From 30a91b58af70af9502cbc8f982e6fa877ae2edfd Mon Sep 17 00:00:00 2001 From: Aaron Louie Date: Thu, 30 Jan 2020 21:21:20 -0500 Subject: [PATCH] Adds remaining unit tests --- .../delete-file-dialog.component.spec.ts | 15 +++++++ ...ete-workflow-spec-dialog.component.spec.ts | 16 +++++++ .../new-file-dialog.component.spec.ts | 19 +++++++- .../open-file-dialog.component.spec.ts | 22 +++++++++ .../workflow-spec-dialog.component.spec.ts | 16 +++++++ src/app/file-list/file-list.component.spec.ts | 30 +++++++++++++ src/app/modeler/modeler.component.spec.ts | 45 +++++++++++++++++-- src/app/modeler/modeler.component.ts | 28 ++++++------ 8 files changed, 171 insertions(+), 20 deletions(-) diff --git a/src/app/_dialogs/delete-file-dialog/delete-file-dialog.component.spec.ts b/src/app/_dialogs/delete-file-dialog/delete-file-dialog.component.spec.ts index e9ca1e2..46704af 100644 --- a/src/app/_dialogs/delete-file-dialog/delete-file-dialog.component.spec.ts +++ b/src/app/_dialogs/delete-file-dialog/delete-file-dialog.component.spec.ts @@ -3,6 +3,7 @@ import {MAT_DIALOG_DATA, MatDialogModule, MatDialogRef} from '@angular/material' import {MatIconModule} from '@angular/material/icon'; import {BrowserAnimationsModule, NoopAnimationsModule} from '@angular/platform-browser/animations'; import {mockFileMeta0} from 'sartography-workflow-lib'; +import {DeleteFileDialogData} from '../../_interfaces/dialog-data'; import { DeleteFileDialogComponent } from './delete-file-dialog.component'; @@ -45,4 +46,18 @@ describe('DeleteFileDialogComponent', () => { it('should create', () => { expect(component).toBeTruthy(); }); + + it('should confirm deletion on submit', () => { + const closeSpy = spyOn(component.dialogRef, 'close').and.stub(); + const expectedData: DeleteFileDialogData = {confirm: true, fileMeta: mockFileMeta0}; + component.data.fileMeta = mockFileMeta0; + component.onSubmit(); + expect(closeSpy).toHaveBeenCalledWith(expectedData); + }); + + it('should not change data on cancel', () => { + const closeSpy = spyOn(component.dialogRef, 'close').and.stub(); + component.onNoClick(); + expect(closeSpy).toHaveBeenCalledWith(); + }); }); diff --git a/src/app/_dialogs/delete-workflow-spec-dialog/delete-workflow-spec-dialog.component.spec.ts b/src/app/_dialogs/delete-workflow-spec-dialog/delete-workflow-spec-dialog.component.spec.ts index b2e58f9..e198cb0 100644 --- a/src/app/_dialogs/delete-workflow-spec-dialog/delete-workflow-spec-dialog.component.spec.ts +++ b/src/app/_dialogs/delete-workflow-spec-dialog/delete-workflow-spec-dialog.component.spec.ts @@ -2,6 +2,8 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing'; import {MAT_DIALOG_DATA, MatDialogModule, MatDialogRef} from '@angular/material'; import {MatIconModule} from '@angular/material/icon'; import {BrowserAnimationsModule, NoopAnimationsModule} from '@angular/platform-browser/animations'; +import {mockWorkflowSpec0} from 'sartography-workflow-lib'; +import {DeleteWorkflowSpecDialogData} from '../../_interfaces/dialog-data'; import { DeleteWorkflowSpecDialogComponent } from './delete-workflow-spec-dialog.component'; @@ -41,4 +43,18 @@ describe('DeleteFileDialogComponent', () => { it('should create', () => { expect(component).toBeTruthy(); }); + + it('should save data on submit', () => { + const closeSpy = spyOn(component.dialogRef, 'close').and.stub(); + const expectedData: DeleteWorkflowSpecDialogData = {confirm: true, workflowSpec: mockWorkflowSpec0}; + component.data.workflowSpec = mockWorkflowSpec0; + component.onSubmit(); + expect(closeSpy).toHaveBeenCalledWith(expectedData); + }); + + it('should not change data on cancel', () => { + const closeSpy = spyOn(component.dialogRef, 'close').and.stub(); + component.onNoClick(); + expect(closeSpy).toHaveBeenCalledWith(); + }); }); diff --git a/src/app/_dialogs/new-file-dialog/new-file-dialog.component.spec.ts b/src/app/_dialogs/new-file-dialog/new-file-dialog.component.spec.ts index 017e63b..c524ea3 100644 --- a/src/app/_dialogs/new-file-dialog/new-file-dialog.component.spec.ts +++ b/src/app/_dialogs/new-file-dialog/new-file-dialog.component.spec.ts @@ -1,10 +1,12 @@ -import { async, ComponentFixture, TestBed } from '@angular/core/testing'; +import {async, ComponentFixture, TestBed} from '@angular/core/testing'; import {MAT_DIALOG_DATA, MatDialog, MatDialogModule, MatDialogRef} from '@angular/material'; import {MatIconModule} from '@angular/material/icon'; import {BrowserAnimationsModule, NoopAnimationsModule} from '@angular/platform-browser/animations'; +import {FileType} from 'sartography-workflow-lib'; +import {NewFileDialogData} from '../../_interfaces/dialog-data'; import {GetIconCodePipe} from '../../_pipes/get-icon-code.pipe'; -import { NewFileDialogComponent } from './new-file-dialog.component'; +import {NewFileDialogComponent} from './new-file-dialog.component'; describe('NewFileDialogComponent', () => { let component: NewFileDialogComponent; @@ -52,4 +54,17 @@ describe('NewFileDialogComponent', () => { it('should create', () => { expect(component).toBeTruthy(); }); + + it('should save data on submit', () => { + const closeSpy = spyOn(component.dialogRef, 'close').and.stub(); + const expectedData: NewFileDialogData = { fileType: FileType.BPMN }; + component.onSubmit(FileType.BPMN); + expect(closeSpy).toHaveBeenCalledWith(expectedData); + }); + + it('should not change data on cancel', () => { + const closeSpy = spyOn(component.dialogRef, 'close').and.stub(); + component.onNoClick(); + expect(closeSpy).toHaveBeenCalledWith(); + }); }); diff --git a/src/app/_dialogs/open-file-dialog/open-file-dialog.component.spec.ts b/src/app/_dialogs/open-file-dialog/open-file-dialog.component.spec.ts index e7c8403..3a37362 100644 --- a/src/app/_dialogs/open-file-dialog/open-file-dialog.component.spec.ts +++ b/src/app/_dialogs/open-file-dialog/open-file-dialog.component.spec.ts @@ -96,4 +96,26 @@ describe('OpenFileDialogComponent', () => { expect(component.diagramFile.name).toEqual(expectedName); expect(onSubmitSpy).toHaveBeenCalled(); }); + + it('should get the diagram file name', () => { + component.diagramFile = undefined; + expect(component.getFileName()).toEqual('Click to select a file'); + + component.diagramFile = mockFileMeta0.file; + expect(component.getFileName()).toEqual(mockFileMeta0.file.name); + }); + + it('should get a file from the file input field event', () => { + const event = {target: {files: [mockFileMeta0.file]}}; + (component as any).onFileSelected(event); + expect(component.diagramFile).toEqual(mockFileMeta0.file); + }); + + it('should determine if a string is a valid URL', () => { + component.url = 'badurl'; + expect(component.isValidUrl()).toEqual(false); + + component.url = 'http://this-is-a.very-excellent-valid-good-url.com:8080/my_file_name.xml'; + expect(component.isValidUrl()).toEqual(true); + }); }); diff --git a/src/app/_dialogs/workflow-spec-dialog/workflow-spec-dialog.component.spec.ts b/src/app/_dialogs/workflow-spec-dialog/workflow-spec-dialog.component.spec.ts index 9c6d042..1149fb6 100644 --- a/src/app/_dialogs/workflow-spec-dialog/workflow-spec-dialog.component.spec.ts +++ b/src/app/_dialogs/workflow-spec-dialog/workflow-spec-dialog.component.spec.ts @@ -7,6 +7,8 @@ import {MatInputModule} from '@angular/material/input'; import {BrowserAnimationsModule, NoopAnimationsModule} from '@angular/platform-browser/animations'; import {FormlyModule} from '@ngx-formly/core'; import {FormlyMaterialModule} from '@ngx-formly/material'; +import {mockWorkflowSpec0} from 'sartography-workflow-lib'; +import {WorkflowSpecDialogData} from '../../_interfaces/dialog-data'; import { WorkflowSpecDialogComponent } from './workflow-spec-dialog.component'; @@ -52,4 +54,18 @@ describe('WorkflowSpecDialogComponent', () => { it('should create', () => { expect(component).toBeTruthy(); }); + + it('should save data on submit', () => { + const closeSpy = spyOn(component.dialogRef, 'close').and.stub(); + const expectedData: WorkflowSpecDialogData = mockWorkflowSpec0 as WorkflowSpecDialogData; + component.model = expectedData; + component.onSubmit(); + expect(closeSpy).toHaveBeenCalledWith(expectedData); + }); + + it('should not change data on cancel', () => { + const closeSpy = spyOn(component.dialogRef, 'close').and.stub(); + component.onNoClick(); + expect(closeSpy).toHaveBeenCalledWith(); + }); }); diff --git a/src/app/file-list/file-list.component.spec.ts b/src/app/file-list/file-list.component.spec.ts index 2c82f8c..da988f2 100644 --- a/src/app/file-list/file-list.component.spec.ts +++ b/src/app/file-list/file-list.component.spec.ts @@ -7,8 +7,10 @@ import {MatSnackBarModule} from '@angular/material/snack-bar'; import {BrowserDynamicTestingModule} from '@angular/platform-browser-dynamic/testing'; import {BrowserAnimationsModule} from '@angular/platform-browser/animations'; import {RouterTestingModule} from '@angular/router/testing'; +import {of} from 'rxjs'; import {ApiService, MockEnvironment, mockFileMeta0, mockFileMetas, mockWorkflowSpec0} from 'sartography-workflow-lib'; import {DeleteFileDialogComponent} from '../_dialogs/delete-file-dialog/delete-file-dialog.component'; +import {DeleteFileDialogData} from '../_interfaces/dialog-data'; import {GetIconCodePipe} from '../_pipes/get-icon-code.pipe'; import {FileListComponent} from './file-list.component'; @@ -77,6 +79,27 @@ describe('FileListComponent', () => { expect(component).toBeTruthy(); }); + + it('should show a confirmation dialog before deleting a file', () => { + const mockConfirmDeleteData: DeleteFileDialogData = { + confirm: false, + fileMeta: mockFileMeta0, + }; + + const _deleteFileSpy = spyOn((component as any), '_deleteFile').and.stub(); + const openDialogSpy = spyOn(component.dialog, 'open') + .and.returnValue({afterClosed: () => of(mockConfirmDeleteData)} as any); + + component.confirmDelete(mockFileMeta0); + expect(openDialogSpy).toHaveBeenCalled(); + expect(_deleteFileSpy).not.toHaveBeenCalled(); + + mockConfirmDeleteData.confirm = true; + component.confirmDelete(mockFileMeta0); + expect(openDialogSpy).toHaveBeenCalled(); + expect(_deleteFileSpy).toHaveBeenCalled(); + }); + it('should delete a file', () => { const loadFileMetasSpy = spyOn((component as any), '_loadFileMetas').and.stub(); (component as any)._deleteFile(mockFileMeta0); @@ -86,4 +109,11 @@ describe('FileListComponent', () => { expect(loadFileMetasSpy).toHaveBeenCalled(); }); + + it('should navigate to modeler to edit a file', () => { + const routerNavigateSpy = spyOn((component as any).router, 'navigate'); + component.workflowSpec = mockWorkflowSpec0; + component.editFile(mockFileMeta0.id); + expect(routerNavigateSpy).toHaveBeenCalledWith([`/modeler/${mockWorkflowSpec0.id}/${mockFileMeta0.id}`]); + }); }); diff --git a/src/app/modeler/modeler.component.spec.ts b/src/app/modeler/modeler.component.spec.ts index 93d8e80..61fa3d2 100644 --- a/src/app/modeler/modeler.component.spec.ts +++ b/src/app/modeler/modeler.component.spec.ts @@ -31,7 +31,7 @@ import {FileMetaDialogComponent} from '../_dialogs/file-meta-dialog/file-meta-di import {NewFileDialogComponent} from '../_dialogs/new-file-dialog/new-file-dialog.component'; import {OpenFileDialogComponent} from '../_dialogs/open-file-dialog/open-file-dialog.component'; import {BpmnWarning} from '../_interfaces/bpmn-warning'; -import {FileMetaDialogData} from '../_interfaces/dialog-data'; +import {FileMetaDialogData, NewFileDialogData, OpenFileDialogData} from '../_interfaces/dialog-data'; import {GetIconCodePipe} from '../_pipes/get-icon-code.pipe'; import {DiagramComponent} from '../diagram/diagram.component'; import {ModelerComponent} from './modeler.component'; @@ -415,10 +415,10 @@ describe('ModelerComponent', () => { }); it('should get file metadata tooltip text', () => { - component.workflowSpecs = []; + component.workflowSpec = undefined; expect(component.getFileMetaTooltipText(mockFileMeta0)).toEqual('Loading...'); - component.workflowSpecs = mockWorkflowSpecs; + component.workflowSpec = mockWorkflowSpec0; const expectedString = ` Workflow spec ID: all_things Workflow name: all_things @@ -432,4 +432,43 @@ describe('ModelerComponent', () => { expect(component.getFileMetaTooltipText(mockFileMeta0)).toEqual(expectedString); }); + it('should display new file dialog', () => { + const data: NewFileDialogData = { + fileType: FileType.BPMN, + }; + + const newDiagramSpy = spyOn(component, 'newDiagram').and.stub(); + const openDialogSpy = spyOn(component.dialog, 'open') + .and.returnValue({afterClosed: () => of(data)}); + component.newFileDialog(); + expect(openDialogSpy).toHaveBeenCalled(); + expect(newDiagramSpy).toHaveBeenCalledWith(data.fileType); + }); + + it('should display open file dialog', () => { + const data: OpenFileDialogData = { + file: mockFileMeta0.file + }; + + const onSubmitFileToOpenSpy = spyOn(component, 'onSubmitFileToOpen').and.stub(); + const openDialogSpy = spyOn(component.dialog, 'open') + .and.returnValue({afterClosed: () => of(data)}); + component.openFileDialog(); + expect(openDialogSpy).toHaveBeenCalled(); + expect(component.diagramFile).toEqual(data.file); + expect(onSubmitFileToOpenSpy).toHaveBeenCalled(); + }); + + it('should trigger open file dialog from query params', () => { + const openFileDialogSpy = spyOn(component, 'openFileDialog').and.stub(); + component._handleAction({action: 'openFile'}); + expect(openFileDialogSpy).toHaveBeenCalled(); + }); + + it('should trigger new file dialog from query params', () => { + const newFileDialogSpy = spyOn(component, 'newFileDialog').and.stub(); + component._handleAction({action: 'newFile'}); + expect(newFileDialogSpy).toHaveBeenCalled(); + }); + }); diff --git a/src/app/modeler/modeler.component.ts b/src/app/modeler/modeler.component.ts index ded53df..982ecc8 100644 --- a/src/app/modeler/modeler.component.ts +++ b/src/app/modeler/modeler.component.ts @@ -2,7 +2,7 @@ import {DatePipe} from '@angular/common'; import {AfterViewInit, Component, ViewChild} from '@angular/core'; import {MatDialog} from '@angular/material/dialog'; import {MatSnackBar} from '@angular/material/snack-bar'; -import {ActivatedRoute, Router} from '@angular/router'; +import {ActivatedRoute, Params, Router} from '@angular/router'; import {ApiService, FileMeta, FileType, WorkflowSpec} from 'sartography-workflow-lib'; import {BpmnWarning} from '../_interfaces/bpmn-warning'; import {FileMetaDialogData, NewFileDialogData, OpenFileDialogData} from '../_interfaces/dialog-data'; @@ -27,7 +27,6 @@ export class ModelerComponent implements AfterViewInit { expandToolbar = false; openMethod: string; diagramFile: File; - workflowSpecs: WorkflowSpec[] = []; workflowSpec: WorkflowSpec; bpmnFiles: FileMeta[] = []; diagramFileMeta: FileMeta; @@ -48,13 +47,7 @@ export class ModelerComponent implements AfterViewInit { private router: Router, ) { this.route.queryParams.subscribe(q => { - if (q && q.action) { - if (q.action === 'openFile') { - this.openFileDialog(); - } else if (q.action === 'newFile') { - this.newFileDialog(); - } - } + this._handleAction(q); }); this.route.paramMap.subscribe(paramMap => { @@ -150,7 +143,6 @@ export class ModelerComponent implements AfterViewInit { loadDbFile(bf: FileMeta) { this.diagramFile = bf.file; this.diagramFileMeta = bf; - this.workflowSpec = this.getWorkflowSpec(bf.workflow_spec_id); this.onSubmitFileToOpen(); } @@ -203,10 +195,6 @@ export class ModelerComponent implements AfterViewInit { }); } - getWorkflowSpec(workflow_spec_id: string): WorkflowSpec { - return this.workflowSpecs.find(wfs => workflow_spec_id === wfs.id); - } - getFileMetaDisplayString(fileMeta: FileMeta) { if (fileMeta) { const lastUpdated = new DatePipe('en-us').transform(fileMeta.last_updated); @@ -217,7 +205,7 @@ export class ModelerComponent implements AfterViewInit { } getFileMetaTooltipText(fileMeta: FileMeta) { - const spec = this.getWorkflowSpec(fileMeta.workflow_spec_id); + const spec = this.workflowSpec; if (spec) { const lastUpdated = new DatePipe('en-us').transform(fileMeta.last_updated); @@ -304,4 +292,14 @@ export class ModelerComponent implements AfterViewInit { this.snackBar.open(`Saved changes to file ${this.diagramFileMeta.name}.`, 'Ok', {duration: 5000}); }); } + + private _handleAction(q: Params) { + if (q && q.action) { + if (q.action === 'openFile') { + this.openFileDialog(); + } else if (q.action === 'newFile') { + this.newFileDialog(); + } + } + } }