Skip to content

Commit

Permalink
Adds download zip window (#497)
Browse files Browse the repository at this point in the history
  • Loading branch information
sofyakurilova authored Jun 5, 2024
1 parent 9399e9b commit d436aea
Show file tree
Hide file tree
Showing 22 changed files with 695 additions and 84 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,4 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
<app-download-report
*ngIf="data"
class="download-report-link-zip"
[data]="data"
[href]="getZipLink(data)"
title="Download zip file for Testrun # {{ getTestRunId(data) }}">
<mat-icon class="download-report-icon" fontSet="material-symbols-outlined">
archive
</mat-icon>
</app-download-report>
<ng-content></ng-content>
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/**
* Copyright 2023 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
:host {
cursor: pointer;
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,75 +13,153 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { ComponentFixture, TestBed } from '@angular/core/testing';
import {
ComponentFixture,
fakeAsync,
TestBed,
tick,
} from '@angular/core/testing';

import { DownloadReportZipComponent } from './download-report-zip.component';
import { MOCK_PROGRESS_DATA_COMPLIANT } from '../../mocks/testrun.mock';
import { of } from 'rxjs';
import { MatDialogRef } from '@angular/material/dialog';
import { DownloadZipModalComponent } from '../download-zip-modal/download-zip-modal.component';
import { Router } from '@angular/router';
import { TestRunService } from '../../services/test-run.service';
import { Routes } from '../../model/routes';
import { RouterTestingModule } from '@angular/router/testing';
import { Component } from '@angular/core';

describe('DownloadReportComponent', () => {
describe('DownloadReportZipComponent', () => {
let component: DownloadReportZipComponent;
let fixture: ComponentFixture<DownloadReportZipComponent>;
let compiled: HTMLElement;
let router: Router;

describe('Class tests', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [DownloadReportZipComponent],
});
fixture = TestBed.createComponent(DownloadReportZipComponent);
component = fixture.componentInstance;
});
const testrunServiceMock: jasmine.SpyObj<TestRunService> =
jasmine.createSpyObj('testrunServiceMock', ['downloadZip']);
testrunServiceMock.downloadZip.and.returnValue(of(true));

it('should create', () => {
expect(component).toBeTruthy();
});
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [
RouterTestingModule.withRoutes([
{ path: 'risk-assessment', component: FakeRiskAssessmentComponent },
]),
DownloadReportZipComponent,
],
providers: [{ provide: TestRunService, useValue: testrunServiceMock }],
}).compileComponents();
fixture = TestBed.createComponent(DownloadReportZipComponent);
router = TestBed.get(Router);
compiled = fixture.nativeElement as HTMLElement;
component = fixture.componentInstance;
component.url = 'localhost:8080';
});

describe('DOM tests', () => {
let compiled: HTMLElement;

beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [DownloadReportZipComponent],
}).compileComponents();
fixture = TestBed.createComponent(DownloadReportZipComponent);
compiled = fixture.nativeElement as HTMLElement;
component = fixture.componentInstance;
describe('Class tests', () => {
it('should create', () => {
expect(component).toBeTruthy();
});

describe('with not data provided', () => {
describe('#onClick', () => {
beforeEach(() => {
(component.data as unknown) = null;
fixture.detectChanges();
testrunServiceMock.downloadZip.calls.reset();
});

it('should not have content', () => {
const downloadReportLink = compiled.querySelector(
'.download-report-link'
);
it('should call service if profile is a string', fakeAsync(() => {
const openSpy = spyOn(component.dialog, 'open').and.returnValue({
afterClosed: () => of(''),
} as MatDialogRef<typeof DownloadZipModalComponent>);

expect(downloadReportLink).toBeNull();
});
component.onClick();

expect(openSpy).toHaveBeenCalledWith(DownloadZipModalComponent, {
ariaLabel: 'Download zip',
data: {
hasProfiles: false,
profiles: [],
},
autoFocus: true,
hasBackdrop: true,
disableClose: true,
panelClass: 'initiate-test-run-dialog',
});

tick();

expect(testrunServiceMock.downloadZip).toHaveBeenCalled();
openSpy.calls.reset();
}));

it('should navigate to risk profiles page if profile is null', fakeAsync(() => {
const openSpy = spyOn(component.dialog, 'open').and.returnValue({
afterClosed: () => of(null),
} as MatDialogRef<typeof DownloadZipModalComponent>);

fixture.ngZone?.run(() => {
component.onClick();

expect(openSpy).toHaveBeenCalledWith(DownloadZipModalComponent, {
ariaLabel: 'Download zip',
data: {
hasProfiles: false,
profiles: [],
},
autoFocus: true,
hasBackdrop: true,
disableClose: true,
panelClass: 'initiate-test-run-dialog',
});

tick();

expect(router.url).toBe(Routes.RiskAssessment);
openSpy.calls.reset();
});
}));

it('should do nothing if profile is undefined', fakeAsync(() => {
const openSpy = spyOn(component.dialog, 'open').and.returnValue({
afterClosed: () => of(undefined),
} as MatDialogRef<typeof DownloadZipModalComponent>);

component.onClick();

expect(openSpy).toHaveBeenCalledWith(DownloadZipModalComponent, {
ariaLabel: 'Download zip',
data: {
hasProfiles: false,
profiles: [],
},
autoFocus: true,
hasBackdrop: true,
disableClose: true,
panelClass: 'initiate-test-run-dialog',
});

tick();

expect(testrunServiceMock.downloadZip).not.toHaveBeenCalled();
openSpy.calls.reset();
}));
});
});

describe('with data provided', () => {
beforeEach(() => {
component.data = MOCK_PROGRESS_DATA_COMPLIANT;
fixture.detectChanges();
});
describe('DOM tests', () => {
it('should open risk profiles modal on click', () => {
const openSpy = spyOn(component.dialog, 'open');
compiled.click();

it('should have download report link', () => {
const downloadReportLink = compiled.querySelector(
'.download-report-link'
) as HTMLAnchorElement;

expect(downloadReportLink).not.toBeNull();
expect(downloadReportLink.href).toEqual(
'https://api.testrun.io/export.pdf'
);
expect(downloadReportLink.download).toEqual(
'delta_03-din-cpu_1.2.2_compliant_22_jun_2023_9:20'
);
});
expect(openSpy).toHaveBeenCalled();

openSpy.calls.reset();
});
});
});

@Component({
selector: 'app-fake-risk-assessment-component',
template: '',
})
class FakeRiskAssessmentComponent {}
Original file line number Diff line number Diff line change
Expand Up @@ -13,23 +13,82 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { ChangeDetectionStrategy, Component } from '@angular/core';
import { TestrunStatus } from '../../model/testrun-status';
import { CommonModule, DatePipe } from '@angular/common';
import { DownloadReportComponent } from '../download-report/download-report.component';
import { MatIcon } from '@angular/material/icon';
import { ReportActionComponent } from '../report-action/report-action.component';
import {
ChangeDetectionStrategy,
Component,
HostListener,
Input,
OnDestroy,
} from '@angular/core';
import { CommonModule } from '@angular/common';
import { Profile } from '../../model/profile';
import { MatDialog } from '@angular/material/dialog';
import { Subject, takeUntil } from 'rxjs';
import { Routes } from '../../model/routes';
import { DownloadZipModalComponent } from '../download-zip-modal/download-zip-modal.component';
import { TestRunService } from '../../services/test-run.service';
import { Router } from '@angular/router';

@Component({
selector: 'app-download-report-zip',
templateUrl: './download-report-zip.component.html',
styleUrl: './download-report-zip.component.scss',
standalone: true,
imports: [CommonModule, DownloadReportComponent, MatIcon],
providers: [DatePipe],
imports: [CommonModule],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class DownloadReportZipComponent extends ReportActionComponent {
getZipLink(data: TestrunStatus) {
return data.report?.replace('report', 'export');
export class DownloadReportZipComponent implements OnDestroy {
private destroy$: Subject<boolean> = new Subject<boolean>();
@Input() hasProfiles: boolean = false;
@Input() profiles: Profile[] = [];
@Input() url: string | null | undefined = null;

@HostListener('click', ['$event.target'])
onClick() {
const dialogRef = this.dialog.open(DownloadZipModalComponent, {
ariaLabel: 'Download zip',
data: {
hasProfiles: this.hasProfiles,
profiles: this.profiles,
},
autoFocus: true,
hasBackdrop: true,
disableClose: true,
panelClass: 'initiate-test-run-dialog',
});

dialogRef
?.afterClosed()
.pipe(takeUntil(this.destroy$))
.subscribe(profile => {
if (profile === undefined) {
return;
}
if (profile === null) {
this.route.navigate([Routes.RiskAssessment]);
}

if (this.url != null) {
this.testrunService
.downloadZip(this.getZipLink(this.url), profile)
.pipe(takeUntil(this.destroy$))
.subscribe();
}
});
}

ngOnDestroy() {
this.destroy$.next(true);
this.destroy$.unsubscribe();
}

constructor(
public dialog: MatDialog,
private testrunService: TestRunService,
private route: Router
) {}

private getZipLink(reportURL: string): string {
return reportURL.replace('report', 'export');
}
}
Loading

0 comments on commit d436aea

Please sign in to comment.