Skip to content

Commit

Permalink
share test run (#95)
Browse files Browse the repository at this point in the history
  • Loading branch information
ludeknovy authored Feb 20, 2021
1 parent bdb0b89 commit 1cc302d
Show file tree
Hide file tree
Showing 21 changed files with 513 additions and 16 deletions.
7 changes: 5 additions & 2 deletions src/app/_interceptors/error-interceptor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,21 @@ import { HttpRequest, HttpHandler, HttpEvent, HttpInterceptor } from '@angular/c
import { Observable, throwError } from 'rxjs';
import { catchError } from 'rxjs/operators';
import { AuthenticationService } from '../_services/authentication.service';
import {Router} from '@angular/router';


@Injectable()
export class ErrorInterceptor implements HttpInterceptor {
constructor(private authenticationService: AuthenticationService) { }
constructor(
private authenticationService: AuthenticationService,
private router: Router) { }

intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
return next.handle(request).pipe(catchError(err => {
if (err.status === 401) {
// auto logout if 401 response returned from api
this.authenticationService.logout();
// location.reload(true);
this.router.navigate(['login']);
}

const error = err.error.message || err.statusText;
Expand Down
8 changes: 7 additions & 1 deletion src/app/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@ import { AddNewExternalNotificationComponent } from './scenario/external-notific
// tslint:disable-next-line:max-line-length
import { DeleteExternalNotificationComponent } from './scenario/external-notification/delete-external-notification/delete-external-notification.component';
import { ItemControlsComponent } from './scenario/item-controls/item-controls.component';
import { ShareComponent } from './item-detail/share/share.component';
import { CreateNewShareLinkComponent } from './item-detail/share/create-new-share-link/create-new-share-link.component';
import { DeleteShareLinkComponent } from './item-detail/share/delete-share-link/delete-share-link.component';

const appRoutes: Routes = [
{ path: 'dashboard', component: DashboardComponent, canActivate: [AuthGuard] },
Expand All @@ -78,7 +81,7 @@ const appRoutes: Routes = [
},
{
path: 'project/:projectName/scenario/:scenarioName/item/:id', component: ItemDetailComponent,
runGuardsAndResolvers: 'always', canActivate: [AuthGuard]
runGuardsAndResolvers: 'always', canActivate: [AuthGuard],
},
{
path: 'project/:projectName/scenarios', component: ScenariosComponent,
Expand Down Expand Up @@ -132,6 +135,9 @@ const appRoutes: Routes = [
AddNewExternalNotificationComponent,
DeleteExternalNotificationComponent,
ItemControlsComponent,
ShareComponent,
CreateNewShareLinkComponent,
DeleteShareLinkComponent,
],
imports: [
RouterModule.forRoot(
Expand Down
5 changes: 5 additions & 0 deletions src/app/auth.guard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@ export class AuthGuard implements CanActivate {
) { }

canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {

const { token } = route.queryParams;
if (token) {
return true;
}
if (localStorage.getItem('currentUser')) {
// logged in so return true
this.authService.setLogin(true);
Expand Down
9 changes: 5 additions & 4 deletions src/app/item-detail/item-detail.component.html
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<app-control-panel>
<app-control-panel *ngIf="!isAnonymous">
<ul class="navbar-nav mr-auto">
<li class="nav-item">
<app-breadcrumb></app-breadcrumb>
Expand All @@ -15,6 +15,7 @@
[itemDetailData]="{note: itemData.note, environment: itemData.environment, hostname: itemData.hostname, isBase: itemData.isBase, params: itemParams}"
(itemDetailChange)="itemDetailChanged($event)"></app-edit-item>
<app-attachements [params]="itemParams" [attachements]="itemData.attachements"></app-attachements>
<app-share [params]=itemParams></app-share>
<app-delete-item *ngIf="itemData.reportStatus !== 'in_progress'" [itemData]="itemParams"></app-delete-item>
</div>
</div>
Expand Down Expand Up @@ -266,7 +267,7 @@ <h6 class="card-header bg-transparent">Request Statistics <span class="compare">
(click)="resetStatsData()"><span class="compare-desc-btn">Remove</span>
</button>

<div class="btn-group mr-3">
<div *ngIf="!isAnonymous" class="btn-group mr-3">
<div display="dynamic" [placement]="['bottom-right', 'bottom-left']" class="btn-group" ngbDropdown
role="group" aria-label="Button group with nested dropdown">
<button class="btn btn-sm jtl-no-glow jtl-control-menu hamburger-menu" ngbDropdownToggle><i
Expand Down Expand Up @@ -359,11 +360,11 @@ <h6 class="card-header bg-transparent">Request Statistics <span class="compare">
*ngIf="_.errorRateDiff">{{_.errorRateDiff}}</sup>
</td>
<td>
<app-label-error *ngIf="_.errorRate > 0 && hasErrorsAttachment"
<app-label-error *ngIf="!isAnonymous && _.errorRate > 0 && hasErrorsAttachment"
[labelInput]="{ labelName: _.label, params: itemParams }"></app-label-error>
</td>
<td>
<app-label-trend [trendInput]="{ environment: itemData.environment, labelName: _.label }">
<app-label-trend *ngIf="!isAnonymous" [trendInput]="{ environment: itemData.environment, labelName: _.label }">
</app-label-trend>
</td>
</tr>
Expand Down
17 changes: 15 additions & 2 deletions src/app/item-detail/item-detail.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ export class ItemDetailComponent implements OnInit {
labelsData;
Math: any;
comparisonWarning = [];
token: string;
isAnonymous = false;

constructor(
private route: ActivatedRoute,
Expand All @@ -75,11 +77,22 @@ export class ItemDetailComponent implements OnInit {
return _;
})
).subscribe(_ => this.itemParams = _);
this.route.queryParams.subscribe(_ => {
this.token = _.token;
if (this.token) {
this.isAnonymous = true;
}
});
this.itemsService.fetchItemDetail(
this.itemParams.projectName,
this.itemParams.scenarioName,
this.itemParams.id)
.pipe(catchError(r => of(r)))
this.itemParams.id,
{ token: this.token}
)
.pipe(catchError(r => {
this.spinner.hide();
return of(r);
}))
.subscribe((results) => {
this.itemData = results;
this.labelsData = this.itemData.statistics;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.create-new-link{
margin-bottom: 1.5rem;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<ng-template #content let-modal>
<div class="modal-header">
<h5 class="modal-title" id="modal-basic-title">Add New Link</h5>
<button type="button" class="close" aria-label="Close" (click)="modal.dismiss('Cross click')">
<span aria-hidden="true">&times;</span>
</button>
</div>
<form [formGroup]="newShareLinkForm" (ngSubmit)="onSubmit()">
<div class="modal-body">
<div class="alert alert-primary" role="alert">
<i class="fas fa-info-circle"> </i>
By sharing this link you will grant anonymous access to this test run. Please add note to your link.
</div>
<p class="text-secondary"></p>
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text" id="inputGroup-sizing-default">Note</span>
</div>
<input type="input" class="form-control" formControlName="note" aria-label="Default" aria-describedby="inputGroup-sizing-default">
</div>
<div class="form-control-feedback" *ngIf="note.errors && (note.dirty || note.touched)">
<p class="alert alert-danger" *ngIf="note.errors.maxlength">Note is too long.</p>
</div>
</div>

<div class="modal-footer">
<button type="submit" class="btn btn-primary">Submit</button>
</div>
</form>

</ng-template>

<button class="btn btn-sm jtl-btn-light jtl-no-glow create-new-link" (click)="open(content)">Add new link</button>
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { HttpClientModule } from '@angular/common/http';
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ReactiveFormsModule, FormsModule } from '@angular/forms';

import { CreateNewShareLinkComponent } from './create-new-share-link.component';

describe('CreateNewShareLinkComponent', () => {
let component: CreateNewShareLinkComponent;
let fixture: ComponentFixture<CreateNewShareLinkComponent>;

beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ CreateNewShareLinkComponent ],
imports: [
ReactiveFormsModule,
FormsModule,
HttpClientModule,
]
})
.compileComponents();
}));

beforeEach(() => {
fixture = TestBed.createComponent(CreateNewShareLinkComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

it('should create', () => {
expect(component).toBeTruthy();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import { Component, Input, OnInit } from '@angular/core';
import { FormControl, Validators, FormGroup } from '@angular/forms';
import { NgbActiveModal, NgbModal } from '@ng-bootstrap/ng-bootstrap';
import { of } from 'rxjs';
import { catchError } from 'rxjs/internal/operators/catchError';
import { ItemsApiService } from 'src/app/items-api.service';
import { ItemsService } from 'src/app/items.service';
import { NotificationMessage } from 'src/app/notification/notification-messages';
import { ItemParams } from 'src/app/scenario/item-controls/item-controls.model';


@Component({
selector: 'app-create-new-share-link',
templateUrl: './create-new-share-link.component.html',
styleUrls: ['./create-new-share-link.component.css']
})
export class CreateNewShareLinkComponent implements OnInit {

private note: FormControl;
private newShareLinkForm: FormGroup;
modal: NgbActiveModal;
@Input() params: ItemParams;

constructor(
private modalService: NgbModal,
private notification: NotificationMessage,
private itemApiService: ItemsApiService,
private itemService: ItemsService
) { }

ngOnInit() {
this.createFormControls();
this.createForm();
}

open(content) {
this.modal = this.modalService.open(content, { ariaLabelledBy: 'modal-basic-title' });
}

createFormControls() {
this.note = new FormControl('', [
Validators.maxLength(100),
Validators.required
]);
}

createForm() {
this.newShareLinkForm = new FormGroup({
note: this.note
});
}

onSubmit() {
const { note } = this.newShareLinkForm.value;
const { projectName, scenarioName, id } = this.params;

this.itemApiService.createItemShareToken(projectName, scenarioName, id, { note })
.pipe(catchError(r => of(r)))
.subscribe(_ => {
const message = this.notification.createItemShareLinkNotification(_);
this.itemApiService.setData(message);
this.itemService.fetchItemShareTokens(projectName, scenarioName, id);
});
this.newShareLinkForm.reset();
this.modal.close();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.revoke {
margin-left: 10px;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<ng-template #content let-modal>
<div class="modal-header">
<h5 class="modal-title" id="modal-basic-title">Delete Share Link</h5>
<button type="button" class="close" aria-label="Close" (click)="modal.dismiss('Cross click')">
<span aria-hidden="true">&times;</span>
</button>
</div>
<form [formGroup]="deleteShareLinkForm" (ngSubmit)="onSubmit()">
<div class="modal-body">
<div class="alert alert-danger" role="alert">
<i class="fas fa-info-circle"> </i>
By deleting this link you will immediately revoke its access to this test run.
</div>
<p>Please enter 5 random characters to confirm this action:</p>
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text" id="inputGroup-sizing-default">Delete check</span>
</div>
<input type="deleteCheck" class="form-control" formControlName="deleteCheck" aria-label="Default"
aria-describedby="inputGroup-sizing-default">
</div>
<div class="form-control-feedback" *ngIf="deleteCheck.errors && (deleteCheck.dirty || deleteCheck.touched)">
<p class="alert alert-danger" *ngIf="deleteCheck.errors.minlength">Please enter at least 5 characters...</p>
</div>
</div>
<div class="modal-footer">
<button type="submit" class="btn btn-danger">Delete</button>
</div>
</form>

</ng-template>

<button class="btn btn-sm jtl-btn-light jtl-no-glow revoke" (click)="open(content)">
Delete
</button>
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { HttpClientModule } from '@angular/common/http';
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ReactiveFormsModule, FormsModule } from '@angular/forms';

import { DeleteShareLinkComponent } from './delete-share-link.component';

describe('DeleteShareLinkComponent', () => {
let component: DeleteShareLinkComponent;
let fixture: ComponentFixture<DeleteShareLinkComponent>;

beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ DeleteShareLinkComponent ],
imports: [
ReactiveFormsModule,
FormsModule,
HttpClientModule
]
})
.compileComponents();
}));

beforeEach(() => {
fixture = TestBed.createComponent(DeleteShareLinkComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

it('should create', () => {
expect(component).toBeTruthy();
});
});
Loading

0 comments on commit 1cc302d

Please sign in to comment.