Merge pull request #94 from sartography/412-CallActivity-SanityCheck

412 call activity sanity check
This commit is contained in:
Aaron Louie 2021-08-16 09:12:00 -04:00 committed by GitHub
commit d7d4f0c55c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 140 additions and 20 deletions

16
package-lock.json generated
View File

@ -41,7 +41,7 @@
"ngx-markdown": "^12.0.1",
"protractor": "~7.0.0",
"rxjs": "^6.5.5",
"sartography-workflow-lib": "^0.0.538",
"sartography-workflow-lib": "^0.0.540",
"tslib": "^2.0.0",
"uuid": "^7.0.2",
"zone.js": "~0.11.4"
@ -67,7 +67,7 @@
"@typescript-eslint/eslint-plugin": "4.28.2",
"@typescript-eslint/parser": "4.28.2",
"babel-loader": "^8.2.2",
"eslint": "^7.26.0",
"eslint": "^7.32.0",
"eslint-plugin-import": "latest",
"eslint-plugin-jsdoc": "latest",
"eslint-plugin-prefer-arrow": "latest",
@ -18748,9 +18748,9 @@
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
},
"node_modules/sartography-workflow-lib": {
"version": "0.0.538",
"resolved": "https://registry.npmjs.org/sartography-workflow-lib/-/sartography-workflow-lib-0.0.538.tgz",
"integrity": "sha512-KE6a/ZN9DVlwLXF0A5iq/JYYVIB6T+DaqHQNzGpAAnSSO5vRhQxNeiTqeL30aZhg8js2OzvVivLOAU4i4vKqoQ==",
"version": "0.0.540",
"resolved": "https://registry.npmjs.org/sartography-workflow-lib/-/sartography-workflow-lib-0.0.540.tgz",
"integrity": "sha512-ZYpPfjGDlXX8RalKITN4CiQCo4oDEh2Tk81pJECPw/9s3tUPVgD1rKqAXlDIvoopsjGKshFdY49ldGnjSACJcA==",
"dependencies": {
"tslib": "^2.2.0"
}
@ -36093,9 +36093,9 @@
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
},
"sartography-workflow-lib": {
"version": "0.0.538",
"resolved": "https://registry.npmjs.org/sartography-workflow-lib/-/sartography-workflow-lib-0.0.538.tgz",
"integrity": "sha512-KE6a/ZN9DVlwLXF0A5iq/JYYVIB6T+DaqHQNzGpAAnSSO5vRhQxNeiTqeL30aZhg8js2OzvVivLOAU4i4vKqoQ==",
"version": "0.0.540",
"resolved": "https://registry.npmjs.org/sartography-workflow-lib/-/sartography-workflow-lib-0.0.540.tgz",
"integrity": "sha512-ZYpPfjGDlXX8RalKITN4CiQCo4oDEh2Tk81pJECPw/9s3tUPVgD1rKqAXlDIvoopsjGKshFdY49ldGnjSACJcA==",
"requires": {
"tslib": "^2.2.0"
}

View File

@ -59,7 +59,7 @@
"ngx-markdown": "^12.0.1",
"protractor": "~7.0.0",
"rxjs": "^6.5.5",
"sartography-workflow-lib": "^0.0.538",
"sartography-workflow-lib": "^0.0.540",
"tslib": "^2.0.0",
"uuid": "^7.0.2",
"zone.js": "~0.11.4"
@ -85,7 +85,7 @@
"@typescript-eslint/eslint-plugin": "4.28.2",
"@typescript-eslint/parser": "4.28.2",
"babel-loader": "^8.2.2",
"eslint": "^7.26.0",
"eslint": "^7.32.0",
"eslint-plugin-import": "latest",
"eslint-plugin-jsdoc": "latest",
"eslint-plugin-prefer-arrow": "latest",

View File

@ -37,7 +37,7 @@ import {
import {GetIconCodePipe} from '../_pipes/get-icon-code.pipe';
import {FileListComponent} from '../file-list/file-list.component';
import {WorkflowSpecListComponent} from './workflow-spec-list.component';
import {WorkflowSpecDialogComponent} from '../_dialogs/workflow-spec-dialog/workflow-spec-dialog.component';
export class MdDialogMock {
// When the component calls this.dialog.open(...) we'll return an object
@ -166,8 +166,10 @@ describe('WorkflowSpecListComponent', () => {
.and.stub();
const openDialogSpy = spyOn(component.dialog, 'open')
.and.returnValue({afterClosed: () => of(mockSpecData)} as any);
component.editWorkflowSpec(mockWorkflowSpec0);
component.selectedSpec = mockWorkflowSpec1;
component.selectedSpec.parents = [];
component.selectedSpec.libraries = [];
component.editWorkflowSpec();
expect(openDialogSpy).toHaveBeenCalled();
expect(_upsertWorkflowSpecificationSpy).not.toHaveBeenCalled();
@ -524,11 +526,103 @@ describe('WorkflowSpecListComponent', () => {
it('should call editWorkflowSpec, open Dialog & call _upsertWorkflowSpecification when Edit button is clicked', fakeAsync(() => {
spyOn(dialog, 'open').and.callThrough();
const _upsertWorkflowSpecification = spyOn((component as any), '_upsertWorkflowSpecification').and.stub();
const button = fixture.debugElement.nativeElement.querySelector('#add_spec');
button.click();
const req = httpMock.expectOne(`apiRoot/workflow-specification-category`);
httpMock.expectOne(`apiRoot/workflow-specification-category`);
expect(dialog.open).toHaveBeenCalled();
}
));
it('should disallow deselecting library if being used as library', () => {
let mockSpecData: WorkflowSpecDialogData = {
id: '25',
name: 'name1',
display_name: 'displayname',
description: 'descr',
category_id: 0,
display_order: 0,
standalone: false,
library: false
};
const _upsertWorkflowSpecificationSpy = spyOn((component as any), '_upsertWorkflowSpecification')
.and.stub();
const openDialogSpy = spyOn(component.dialog, 'open')
.and.returnValue({afterClosed: () => of(mockSpecData)} as any);
const canSaveSpy = spyOn(component, 'canSaveWorkflowSpec').and.callThrough();
const snackBarSpy = spyOn((component as any).snackBar, 'open').and.stub();
const localSelectedSpec = cloneDeep(mockWorkflowSpec0);
localSelectedSpec.parents = [
{ id: 1234,
display_name: 'test parent',
name: 'parent1'
}]
component.selectedSpec = localSelectedSpec;
component.editWorkflowSpec(localSelectedSpec);
expect(openDialogSpy).toHaveBeenCalled();
expect(_upsertWorkflowSpecificationSpy).not.toHaveBeenCalled();
expect(canSaveSpy).toHaveBeenCalled();
expect(snackBarSpy).toHaveBeenCalled();
});
it('should disallow saving as both library and standalone', () => {
// we need to have id,name and display_name filled out because there is a conditional
// that fails prior to saving if any of these are blank
let mockSpecData: WorkflowSpecDialogData = {
id: '25',
name: 'name1',
display_name: 'displayname',
description: 'descr',
category_id: 0,
display_order: 0,
standalone: true,
library: true
};
const _upsertWorkflowSpecificationSpy = spyOn((component as any), '_upsertWorkflowSpecification')
.and.stub();
const openDialogSpy = spyOn(component.dialog, 'open')
.and.returnValue({afterClosed: () => of(mockSpecData)} as any);
const canSaveSpy = spyOn(component, 'canSaveWorkflowSpec').and.callThrough();
const snackBarSpy = spyOn((component as any).snackBar, 'open').and.stub();
const localSelectedSpec = cloneDeep(mockWorkflowSpec0);
localSelectedSpec.parents = [
{ id: 1234,
display_name: 'test parent',
name: 'parent1'
}]
component.selectedSpec = localSelectedSpec;
component.editWorkflowSpec(localSelectedSpec);
expect(openDialogSpy).toHaveBeenCalled();
expect(_upsertWorkflowSpecificationSpy).not.toHaveBeenCalled();
expect(canSaveSpy).toHaveBeenCalled();
expect(snackBarSpy).toHaveBeenCalled();
});
it('should not delete a library if it is being used', () => {
const badWorkflowSpec = cloneDeep(mockWorkflowSpec0);
badWorkflowSpec.parents=[
{ id: 1234,
display_name: 'test parent',
name: 'parent1'
}]
badWorkflowSpec.library=true;
const mockConfirmDeleteData: DeleteWorkflowSpecDialogData = {
confirm: false,
workflowSpec: badWorkflowSpec
};
const _deleteWorkflowSpecSpy = spyOn((component as any), '_deleteWorkflowSpec').and.stub();
const openDialogSpy = spyOn(component.dialog, 'open')
.and.returnValue({afterClosed: () => of(mockConfirmDeleteData)} as any);
const snackBarSpy = spyOn((component as any).snackBar, 'open').and.stub();
mockConfirmDeleteData.confirm = true;
component.confirmDeleteWorkflowSpec(badWorkflowSpec);
expect(openDialogSpy).toHaveBeenCalled();
expect(_deleteWorkflowSpecSpy).not.toHaveBeenCalled();
expect(snackBarSpy).toHaveBeenCalled();
});
});

View File

@ -73,7 +73,7 @@ export class WorkflowSpecListComponent implements OnInit {
this._loadWorkflowSpecCategories();
}
});
// this._loadWorkflowLibraries();
this.searchField = new FormControl();
this.searchField.valueChanges.subscribe(value => {
this._loadWorkflowSpecs(null, value);
@ -109,6 +109,18 @@ export class WorkflowSpecListComponent implements OnInit {
return this.selectedSpec != null && this.selectedSpec.category_id === cat.id;
}
canSaveWorkflowSpec(proposed: WorkflowSpecDialogData){
if ((this.selectedSpec.parents.length > 0) && (!proposed.library)){
this.snackBar.open('This Workflow Specification is still being used as a Library. Please remove references first!', 'Ok', { duration: 5000 });
return false;
}
if (proposed.standalone && proposed.library){
this.snackBar.open('A workflow spec cannot be both a standalone and a library!', 'Ok', { duration: 5000 });
return false;
}
return true;
}
editWorkflowSpec(selectedSpec?: WorkflowSpec) {
const hasDisplayOrder = selectedSpec && isNumberDefined(selectedSpec.display_order);
@ -133,8 +145,12 @@ export class WorkflowSpecListComponent implements OnInit {
dialogRef.afterClosed().subscribe((data: WorkflowSpecDialogData) => {
if (data && data.id && data.name && data.display_name && data.description) {
data.display_order = this.categories.filter(function (entry) { return entry.id === data.category_id; }).length;
this._upsertWorkflowSpecification(selectedSpec == null, data);
if (this.canSaveWorkflowSpec(data)) {
data.display_order = this.categories.filter(function (entry) {
return entry.id === data.category_id;
}).length;
this._upsertWorkflowSpecification(selectedSpec == null, data);
}
}
});
}
@ -176,6 +192,16 @@ export class WorkflowSpecListComponent implements OnInit {
});
}
canDeleteWorkflowSpec(wfs){
if ((wfs.parents.length > 0) && (wfs.library)){
this.snackBar.open('This Workflow Specification is still being used as a Library. Please remove references first!', 'Ok', { duration: 5000 });
return false;
}
return true;
}
confirmDeleteWorkflowSpec(wfs: WorkflowSpec) {
const dialogRef = this.dialog.open(DeleteWorkflowSpecDialogComponent, {
data: {
@ -185,7 +211,7 @@ export class WorkflowSpecListComponent implements OnInit {
});
dialogRef.afterClosed().subscribe((data: DeleteWorkflowSpecDialogData) => {
if (data && data.confirm && data.workflowSpec) {
if (data && data.confirm && data.workflowSpec && this.canDeleteWorkflowSpec(data.workflowSpec)) {
this._deleteWorkflowSpec(data.workflowSpec);
if (typeof this.masterStatusSpec !== 'undefined') {
this.selectSpec(this.masterStatusSpec);
@ -391,7 +417,7 @@ export class WorkflowSpecListComponent implements OnInit {
delete newCat.workflow_specs;
newCat.display_order = j;
this.api.updateWorkflowSpecCategory(cat.id, newCat as WorkflowSpecCategory).subscribe(updatedCat => {
this.api.updateWorkflowSpecCategory(cat.id, newCat as WorkflowSpecCategory).subscribe(() => {
numUpdated++;
if (numUpdated === cats.length) {
this._loadWorkflowSpecCategories();