Skip to content

17 files changed

+892
-255
lines changed

ddp-workspace/angular.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3051,6 +3051,11 @@
30513051
"projects/ddp-dsm-ui/src/assets/dsm-theme.scss",
30523052
"projects/ddp-dsm-ui/src/styles.scss"
30533053
],
3054+
"stylePreprocessorOptions": {
3055+
"includePaths": [
3056+
"projects/ddp-dsm-ui/src/styles"
3057+
]
3058+
},
30543059
"scripts": [
30553060
"node_modules/jquery/dist/jquery.min.js",
30563061
"node_modules/bootstrap/dist/js/bootstrap.min.js"

ddp-workspace/projects/ddp-dsm-ui/src/app/modals/loading-modal.component.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,7 @@ import {MAT_DIALOG_DATA} from '@angular/material/dialog';
88
<mat-dialog-content>
99
{{ data.message }}
1010
</mat-dialog-content>
11-
`,
12-
styles: [``]
11+
`
1312
})
1413

1514
export class LoadingModalComponent {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import {ConfirmationModalComponent} from './confirmationModal.component';
2+
import {ComponentFixture, TestBed, waitForAsync} from '@angular/core/testing';
3+
import {MAT_DIALOG_DATA, MatDialogRef} from '@angular/material/dialog';
4+
import {DebugElement} from '@angular/core';
5+
import {By} from '@angular/platform-browser';
6+
7+
describe('ConfirmationModalComponent', () => {
8+
let fixture: ComponentFixture<ConfirmationModalComponent>;
9+
let component: ConfirmationModalComponent;
10+
let componentHTML: DebugElement;
11+
12+
beforeEach(waitForAsync(() => {
13+
TestBed.configureTestingModule({
14+
declarations: [ConfirmationModalComponent],
15+
providers: [
16+
{
17+
provide: MatDialogRef,
18+
useValue: jasmine.createSpyObj('MatDialogRef', ['close'])
19+
},
20+
{
21+
provide: MAT_DIALOG_DATA,
22+
useValue: {fileName: 'testFile.pdf'}
23+
}
24+
]
25+
}).compileComponents();
26+
}
27+
));
28+
29+
beforeEach(() => {
30+
fixture = TestBed.createComponent(ConfirmationModalComponent);
31+
component = fixture.debugElement.componentInstance;
32+
componentHTML = fixture.debugElement;
33+
34+
fixture.detectChanges();
35+
});
36+
37+
it('should create component', () => {
38+
expect(component).toBeTruthy('Component has not been instantiated');
39+
});
40+
41+
it('should display file name', () => {
42+
const fileName = componentHTML
43+
.query(By.css('section.confirmationModal-content p'))
44+
.nativeElement.textContent;
45+
46+
expect(fileName).toContain('testFile.pdf', 'File name is not displayed');
47+
});
48+
49+
});

ddp-workspace/projects/ddp-dsm-ui/src/app/sharedLearningUpload/components/filesTable/filesTable.component.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<main id="filesTable" class="filesTable" *ngIf="somaticResultsFiles.length; else noFiles">
2-
<table mat-table [dataSource]="somaticResultsFiles">
2+
<table mat-table [dataSource]="somaticResultsFiles" [trackBy]="trackBy">
33

44
<ng-container matColumnDef="VirusStatus">
55
<th mat-header-cell *matHeaderCellDef> Status </th>
@@ -106,7 +106,7 @@
106106

107107
<ng-template #noFiles>
108108
<div class="noFilesNote">
109-
<p >No files found</p>
109+
<p>No files were found</p>
110110
</div>
111111
</ng-template>
112112

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,233 @@
1+
import {ComponentFixture, TestBed, waitForAsync} from '@angular/core/testing';
2+
import {FilesTableComponent} from './filesTable.component';
3+
import {MatIconModule} from '@angular/material/icon';
4+
import {MatTableModule} from '@angular/material/table';
5+
import {DebugElement} from '@angular/core';
6+
import {MaterialHarnesses} from '../../../test-helpers/MaterialHarnesses';
7+
import {TestbedHarnessEnvironment} from '@angular/cdk/testing/testbed';
8+
import {expect} from '@angular/flex-layout/_private-utils/testing';
9+
import {ConfigurationService} from 'ddp-sdk';
10+
import {By} from '@angular/platform-browser';
11+
import {HttpRequestStatusEnum} from '../../enums/httpRequestStatus-enum';
12+
import {SomaticResultsFileVirusStatusEnum} from '../../enums/somaticResultsFileVirusStatus-enum';
13+
import {MatTooltipModule} from '@angular/material/tooltip';
14+
import {MatProgressSpinnerModule} from '@angular/material/progress-spinner';
15+
import {DatePipe} from '@angular/common';
16+
import { cloneDeep } from 'lodash';
17+
import {SomaticResultsFileWithStatus} from '../../interfaces/somaticResultsFile';
18+
19+
const testDocuments: any = [
20+
// Clean, Sent File
21+
{
22+
somaticDocumentId: 111,
23+
fileName: 'testFileSuccessSent.pdf',
24+
createdAt: 1688476158,
25+
sentAt: 1688476500,
26+
virusStatus: SomaticResultsFileVirusStatusEnum.CLEAN,
27+
sendToParticipantStatus: {
28+
status: HttpRequestStatusEnum.NONE,
29+
message: null
30+
},
31+
deleteStatus: {
32+
status: HttpRequestStatusEnum.NONE,
33+
message: null
34+
}
35+
}
36+
];
37+
38+
enum DocumentIconsEnum {
39+
CLEAN = 'check_circle_outline',
40+
INFECTED = 'bug_report',
41+
SPINNING = 'SPINNING',
42+
UNABLE_TO_SCAN = 'error_outline',
43+
RETRY = 'replay',
44+
FAIL = 'error',
45+
SUCCESS = 'check_circle',
46+
SEND = 'send',
47+
DELETE = 'delete_forever'
48+
}
49+
50+
enum ColumnNameEnum {
51+
STATUS = 'VirusStatus',
52+
FILE = 'Name',
53+
DATE_UPLOADED = 'UploadDate',
54+
SEND_TO_PARTICIPANT = 'SendToParticipant',
55+
DATE_SENT = 'SentDate',
56+
DELETE = 'Delete'
57+
}
58+
59+
describe('FilesTableComponent', () => {
60+
let fixture: ComponentFixture<FilesTableComponent>;
61+
let component: FilesTableComponent;
62+
let componentHTML: DebugElement;
63+
let materialHarnessLoader: MaterialHarnesses;
64+
65+
const dateFormat = 'MM/dd/YYYY h:mm:ss aa';
66+
const datePipe: DatePipe = new DatePipe('en-US');
67+
68+
beforeEach(waitForAsync(() => {
69+
const sdkConfig = new ConfigurationService();
70+
71+
TestBed.configureTestingModule({
72+
declarations: [FilesTableComponent, DatePipe],
73+
imports: [MatIconModule, MatTableModule, MatTooltipModule, MatProgressSpinnerModule],
74+
providers: [{
75+
provide: 'ddp.config',
76+
useValue: sdkConfig
77+
}]
78+
}).compileComponents();
79+
}));
80+
81+
beforeEach(() => {
82+
fixture = TestBed.createComponent(FilesTableComponent);
83+
component = fixture.debugElement.componentInstance;
84+
componentHTML = fixture.debugElement;
85+
materialHarnessLoader = new MaterialHarnesses(TestbedHarnessEnvironment.loader(fixture));
86+
});
87+
88+
it('should create component', () => {
89+
expect(component).toBeTruthy('Component has not been instantiated');
90+
});
91+
92+
it('should display No files found', () => {
93+
fixture.detectChanges();
94+
const noFilesNote = componentHTML.query(By.css('.noFilesNote p'));
95+
expect(noFilesNote.nativeElement.textContent)
96+
.toEqual('No files were found', 'No files found note is not displayed');
97+
});
98+
99+
/* Text data */
100+
101+
it('should display correct file name',async () => {
102+
component.somaticResultsFiles = testDocuments;
103+
fixture.detectChanges();
104+
const fileName = await getDocumentCellData(0, ColumnNameEnum.FILE);
105+
expect(fileName).toEqual('testFileSuccessSent.pdf', 'Wrong file name');
106+
});
107+
108+
it('should display uploaded date in correct format', async () => {
109+
component.somaticResultsFiles = testDocuments;
110+
fixture.detectChanges();
111+
const dateUploaded = await getDocumentCellData(0, ColumnNameEnum.DATE_UPLOADED);
112+
expect(dateUploaded).toEqual(formatDate(1688476158), 'Wrong created at date format');
113+
});
114+
115+
it('should display sent date in correct format', async () => {
116+
component.somaticResultsFiles = testDocuments;
117+
fixture.detectChanges();
118+
const sentDate = await getDocumentCellData(0, ColumnNameEnum.DATE_SENT);
119+
expect(sentDate).toEqual(formatDate(1688476500), 'Wrong sent date format');
120+
});
121+
122+
/* Status icons */
123+
124+
it('should display clean status file', async () => {
125+
component.somaticResultsFiles = testDocuments;
126+
fixture.detectChanges();
127+
const status = await getDocumentCellData(0, ColumnNameEnum.STATUS);
128+
expect(status).toEqual(DocumentIconsEnum.CLEAN, 'Wrong file status');
129+
});
130+
131+
it('should display send icon',async () => {
132+
component.somaticResultsFiles = testDocuments;
133+
fixture.detectChanges();
134+
const sendToParticipant = await getDocumentCellData(0, ColumnNameEnum.SEND_TO_PARTICIPANT);
135+
expect(sendToParticipant).toEqual(DocumentIconsEnum.SEND, 'Wrong send to participant icon');
136+
});
137+
138+
it('should display delete icon',async () => {
139+
component.somaticResultsFiles = testDocuments;
140+
fixture.detectChanges();
141+
const deleteIcon = await getDocumentCellData(0, ColumnNameEnum.DELETE);
142+
expect(deleteIcon).toEqual(DocumentIconsEnum.DELETE, 'Wrong delete icon');
143+
});
144+
145+
it('should display infected status',async () => {
146+
const infectedDocument: SomaticResultsFileWithStatus = cloneDeep(testDocuments[0]);
147+
infectedDocument.virusStatus = SomaticResultsFileVirusStatusEnum.INFECTED;
148+
component.somaticResultsFiles = [infectedDocument];
149+
fixture.detectChanges();
150+
const status = await getDocumentCellData(0, ColumnNameEnum.STATUS);
151+
expect(status).toEqual(DocumentIconsEnum.INFECTED, 'Wrong virus status');
152+
});
153+
154+
it('should display scanning status',async () => {
155+
const scanningDocument: SomaticResultsFileWithStatus = cloneDeep(testDocuments[0]);
156+
scanningDocument.virusStatus = SomaticResultsFileVirusStatusEnum.SCANNING;
157+
component.somaticResultsFiles = [scanningDocument];
158+
fixture.detectChanges();
159+
const status = await getDocumentCellData(0, ColumnNameEnum.STATUS);
160+
expect(status).toEqual(DocumentIconsEnum.SPINNING, 'Wrong virus status');
161+
});
162+
163+
it('should display unable to scan status',async () => {
164+
const unableToScanDocument: SomaticResultsFileWithStatus = cloneDeep(testDocuments[0]);
165+
unableToScanDocument.virusStatus = SomaticResultsFileVirusStatusEnum.UNABLE_TO_SCAN;
166+
component.somaticResultsFiles = [unableToScanDocument];
167+
fixture.detectChanges();
168+
const status = await getDocumentCellData(0, ColumnNameEnum.STATUS);
169+
expect(status).toEqual(DocumentIconsEnum.UNABLE_TO_SCAN, 'Wrong virus status');
170+
});
171+
172+
it('should display send to participant SUCCESS',async () => {
173+
const sendToParticipantSuccessDocument: SomaticResultsFileWithStatus = cloneDeep(testDocuments[0]);
174+
sendToParticipantSuccessDocument.sendToParticipantStatus.status = HttpRequestStatusEnum.SUCCESS;
175+
component.somaticResultsFiles = [sendToParticipantSuccessDocument];
176+
fixture.detectChanges();
177+
const status = await getDocumentCellData(0, ColumnNameEnum.SEND_TO_PARTICIPANT);
178+
expect(status).toEqual(DocumentIconsEnum.SUCCESS, 'Wrong send to participant status');
179+
});
180+
181+
it('should display send to participant FAIL',async () => {
182+
const sendToParticipantFailDocument: SomaticResultsFileWithStatus = cloneDeep(testDocuments[0]);
183+
sendToParticipantFailDocument.sendToParticipantStatus.status = HttpRequestStatusEnum.FAIL;
184+
component.somaticResultsFiles = [sendToParticipantFailDocument];
185+
fixture.detectChanges();
186+
const status = await getDocumentCellData(0, ColumnNameEnum.SEND_TO_PARTICIPANT);
187+
expect(status).toEqual(DocumentIconsEnum.FAIL, 'Wrong send to participant status');
188+
});
189+
190+
it('should display send to participant IN PROGRESS',async () => {
191+
const sendToParticipantInProgressDocument: SomaticResultsFileWithStatus = cloneDeep(testDocuments[0]);
192+
sendToParticipantInProgressDocument.sendToParticipantStatus.status = HttpRequestStatusEnum.IN_PROGRESS;
193+
component.somaticResultsFiles = [sendToParticipantInProgressDocument];
194+
fixture.detectChanges();
195+
const status = await getDocumentCellData(0, ColumnNameEnum.SEND_TO_PARTICIPANT);
196+
expect(status).toEqual(DocumentIconsEnum.SPINNING, 'Wrong send to participant status');
197+
});
198+
199+
it('should display delete IN PROGRESS',async () => {
200+
const deleteInProgressDocument: SomaticResultsFileWithStatus = cloneDeep(testDocuments[0]);
201+
deleteInProgressDocument.deleteStatus.status = HttpRequestStatusEnum.IN_PROGRESS;
202+
component.somaticResultsFiles = [deleteInProgressDocument];
203+
fixture.detectChanges();
204+
const status = await getDocumentCellData(0, ColumnNameEnum.DELETE);
205+
expect(status).toEqual(DocumentIconsEnum.SPINNING, 'Wrong delete status');
206+
});
207+
208+
209+
/* HELPER FUNCTIONS */
210+
211+
const getDocumentCellData = async (rowIndex: number, columName: ColumnNameEnum): Promise<DocumentIconsEnum> => {
212+
const matTableHarness = await materialHarnessLoader.getMatTableHarness();
213+
const rows = await matTableHarness.getRows();
214+
// the status information cell
215+
const cells = await rows[rowIndex].getCells();
216+
// cell data
217+
let cellData = '';
218+
219+
// looking for cell data for the provided column
220+
for(const cell of cells) {
221+
if(await cell.getColumnName() === columName) {
222+
cellData = await cell.getText();
223+
break;
224+
}
225+
}
226+
227+
// returns either matIcon text or SCANNING (matSpinner doesn't have text)
228+
return (cellData || 'SPINNING') as DocumentIconsEnum;
229+
};
230+
231+
const formatDate = (milliseconds: number): string =>
232+
datePipe.transform(milliseconds, dateFormat);
233+
});

ddp-workspace/projects/ddp-dsm-ui/src/app/sharedLearningUpload/components/filesTable/filesTable.component.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,11 @@
11
import {
22
ChangeDetectionStrategy,
3-
ChangeDetectorRef,
43
Component,
54
EventEmitter,
65
Input, Output, Renderer2
76
} from '@angular/core';
87
import {SomaticResultsFileWithStatus} from '../../interfaces/somaticResultsFile';
98
import {HttpRequestStatusEnum} from '../../enums/httpRequestStatus-enum';
10-
import {SharedLearningsHTTPService} from '../../services/sharedLearningsHTTP.service';
119
import {MatIcon} from '@angular/material/icon';
1210
import {SomaticResultsFileVirusStatusEnum} from '../../enums/somaticResultsFileVirusStatus-enum';
1311
import {RoleService} from '../../../services/role.service';
@@ -30,8 +28,6 @@ export class FilesTableComponent {
3028
@Output() delete = new EventEmitter<SomaticResultsFileWithStatus>();
3129

3230
constructor(
33-
private readonly cdr: ChangeDetectorRef,
34-
private readonly sharedLearningsHTTPService: SharedLearningsHTTPService,
3531
private readonly renderer: Renderer2,
3632
private readonly roleService: RoleService
3733
) {}
@@ -50,6 +46,11 @@ export class FilesTableComponent {
5046
}
5147

5248
/* Template methods */
49+
public trackBy(_: number, somaticResultsFile: SomaticResultsFileWithStatus): any {
50+
const {deleteStatus, sendToParticipantStatus, sentAt, virusStatus} = somaticResultsFile;
51+
return deleteStatus.status || sendToParticipantStatus.status || sentAt || virusStatus;
52+
}
53+
5354
public retryOrNot(shouldRetry: boolean, matIcon: MatIcon): void {
5455
const matIconNative = matIcon._elementRef.nativeElement;
5556
matIconNative.innerText = shouldRetry ? 'replay' : 'error';

ddp-workspace/projects/ddp-dsm-ui/src/app/sharedLearningUpload/components/uploadFile/uploadFile.component.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<main id="uploadFile" class="upload" *ngIf="isAllowedToUpload">
2-
<button [disabled]="unauthorized" (click)="browse()" class="upload-selectBtn">Select a PDF</button>
2+
<button (click)="browse()" class="upload-selectBtn">Select a PDF</button>
33
<input type="file" accept=".pdf" #hiddenInput (change)="onFileSelection($event)" class="upload-hiddenInput">
44
<span class="upload-selectedFileName">{{selectedFileName}}</span>
55
<button (mouseleave)="retryOrNot(false)" (mouseover)="retryOrNot(true)"

0 commit comments

Comments
 (0)