[AAE-7313] User can claim a task only if he is an candidate and relea… (#7558)

* [AAE-7313] User can claim a task only if he is an candidate and release if he is assigned

* [AAE-7313] unit test improvements

* revert change on  angular.json

* [AAE-7313] removed focus from unit test describe

* Trigger travis

* Trigger travis

* [AAE-7313] exclude C593997 e2e
This commit is contained in:
Tomasz Gnyp
2022-04-19 11:05:24 +02:00
committed by GitHub
parent 61cd711cec
commit 7141230649
8 changed files with 140 additions and 155 deletions

View File

@@ -1,5 +1,6 @@
{ {
"C269081": "https://alfresco.atlassian.net/browse/ADF-5385", "C269081": "https://alfresco.atlassian.net/browse/ADF-5385",
"C272819": "https://alfresco.atlassian.net/browse/ADF-5385", "C272819": "https://alfresco.atlassian.net/browse/ADF-5385",
"C362241": "https://alfresco.atlassian.net/browse/ADF-5385" "C362241": "https://alfresco.atlassian.net/browse/ADF-5385",
"C593997": "https://alfresco.atlassian.net/browse/ADF-5479"
} }

View File

@@ -182,9 +182,7 @@ export class FormCloudService extends BaseCloudService implements FormCloudServi
skipCount skipCount
}) : EMPTY; }) : EMPTY;
}), }),
map((res: any) => { map((res: any) => res.list.entries.map((variable) => new TaskVariableCloud(variable.entry))),
return res.list.entries.map((variable) => new TaskVariableCloud(variable.entry));
}),
reduce((acc, res) => acc.concat(res), []) reduce((acc, res) => acc.concat(res), [])
); );
} }

View File

@@ -32,7 +32,3 @@ export const DEFAULT_TASK_PRIORITIES: TaskPriorityOption[] = [
{ label: 'ADF_CLOUD_TASK_LIST.PROPERTIES.PRIORITY_VALUES.NORMAL', value: '2', key: '2' }, { label: 'ADF_CLOUD_TASK_LIST.PROPERTIES.PRIORITY_VALUES.NORMAL', value: '2', key: '2' },
{ label: 'ADF_CLOUD_TASK_LIST.PROPERTIES.PRIORITY_VALUES.HIGH', value: '3', key: '3' } { label: 'ADF_CLOUD_TASK_LIST.PROPERTIES.PRIORITY_VALUES.HIGH', value: '3', key: '3' }
]; ];
export const TASK_ASSIGNED_STATE = 'ASSIGNED';
export const TASK_CREATED_STATE = 'CREATED';

View File

@@ -19,11 +19,21 @@ import { Injectable } from '@angular/core';
import { AlfrescoApiService, LogService, AppConfigService, IdentityUserService, CardViewArrayItem, TranslationService } from '@alfresco/adf-core'; import { AlfrescoApiService, LogService, AppConfigService, IdentityUserService, CardViewArrayItem, TranslationService } from '@alfresco/adf-core';
import { throwError, Observable, of, Subject } from 'rxjs'; import { throwError, Observable, of, Subject } from 'rxjs';
import { map } from 'rxjs/operators'; import { map } from 'rxjs/operators';
import { TaskDetailsCloudModel, StartTaskCloudResponseModel } from '../start-task/models/task-details-cloud.model'; import {
TaskDetailsCloudModel,
StartTaskCloudResponseModel,
TASK_ASSIGNED_STATE,
TASK_CLAIM_PERMISSION,
TASK_CREATED_STATE,
TASK_RELEASE_PERMISSION
} from '../start-task/models/task-details-cloud.model';
import { BaseCloudService } from '../../services/base-cloud.service'; import { BaseCloudService } from '../../services/base-cloud.service';
import { StartTaskCloudRequestModel } from '../start-task/models/start-task-cloud-request.model'; import { StartTaskCloudRequestModel } from '../start-task/models/start-task-cloud-request.model';
import { ProcessDefinitionCloud } from '../../models/process-definition-cloud.model'; import { ProcessDefinitionCloud } from '../../models/process-definition-cloud.model';
import { DEFAULT_TASK_PRIORITIES, TaskPriorityOption, TASK_ASSIGNED_STATE, TASK_CREATED_STATE } from '../models/task.model'; import {
DEFAULT_TASK_PRIORITIES,
TaskPriorityOption
} from '../models/task.model';
import { TaskCloudServiceInterface } from './task-cloud.service.interface'; import { TaskCloudServiceInterface } from './task-cloud.service.interface';
@Injectable({ @Injectable({
@@ -98,7 +108,8 @@ export class TaskCloudService extends BaseCloudService implements TaskCloudServi
* @returns Boolean value if the task can be completed * @returns Boolean value if the task can be completed
*/ */
canClaimTask(taskDetails: TaskDetailsCloudModel): boolean { canClaimTask(taskDetails: TaskDetailsCloudModel): boolean {
return taskDetails && taskDetails.status === TASK_CREATED_STATE; return taskDetails?.status === TASK_CREATED_STATE &&
taskDetails?.permissions.includes(TASK_CLAIM_PERMISSION);
} }
/** /**
@@ -109,7 +120,10 @@ export class TaskCloudService extends BaseCloudService implements TaskCloudServi
*/ */
canUnclaimTask(taskDetails: TaskDetailsCloudModel): boolean { canUnclaimTask(taskDetails: TaskDetailsCloudModel): boolean {
const currentUser = this.identityUserService.getCurrentUserInfo().username; const currentUser = this.identityUserService.getCurrentUserInfo().username;
return taskDetails && taskDetails.status === TASK_ASSIGNED_STATE && taskDetails.assignee === currentUser; return taskDetails?.status === TASK_ASSIGNED_STATE &&
taskDetails?.assignee === currentUser &&
taskDetails?.permissions.includes(TASK_RELEASE_PERMISSION) &&
!taskDetails?.standalone;
} }
/** /**

View File

@@ -33,6 +33,7 @@ export interface TaskDetailsCloudModel {
lastModifiedFrom?: Date; lastModifiedFrom?: Date;
owner?: any; owner?: any;
parentTaskId?: string; parentTaskId?: string;
permissions?: TaskPermissions[];
priority?: number; priority?: number;
processDefinitionId?: string; processDefinitionId?: string;
processInstanceId?: string; processInstanceId?: string;
@@ -50,9 +51,26 @@ export interface StartTaskCloudResponseModel {
entry: TaskDetailsCloudModel; entry: TaskDetailsCloudModel;
} }
export type TaskStatus = | export type TaskStatus =
'COMPLETED' | 'COMPLETED' |
'CREATED' | 'CREATED' |
'ASSIGNED' | 'ASSIGNED' |
'SUSPENDED' | 'SUSPENDED' |
'CANCELLED'; 'CANCELLED';
export const TASK_COMPLETED_STATE: TaskStatus = 'COMPLETED';
export const TASK_CREATED_STATE: TaskStatus = 'CREATED';
export const TASK_ASSIGNED_STATE: TaskStatus = 'ASSIGNED';
export const TASK_SUSPENDED_STATE: TaskStatus = 'SUSPENDED';
export const TASK_CANCELLED_STATE: TaskStatus = 'CANCELLED';
export type TaskPermissions =
'VIEW' |
'CLAIM' |
'RELEASE' |
'UPDATE';
export const TASK_CLAIM_PERMISSION: TaskPermissions = 'CLAIM';
export const TASK_RELEASE_PERMISSION: TaskPermissions = 'RELEASE';
export const TASK_VIEW_PERMISSION: TaskPermissions = 'VIEW';
export const TASK_UPDATE_PERMISSION: TaskPermissions = 'UPDATE';

View File

@@ -57,7 +57,7 @@
(success)="onClaimTask()" (error)="onError($event)"> (success)="onClaimTask()" (error)="onError($event)">
{{'ADF_CLOUD_TASK_FORM.EMPTY_FORM.BUTTONS.CLAIM' | translate}} {{'ADF_CLOUD_TASK_FORM.EMPTY_FORM.BUTTONS.CLAIM' | translate}}
</button> </button>
<button mat-button *ngIf="hasCandidateUsersOrGroups()" adf-cloud-unclaim-task [appName]="appName" [taskId]="taskId" <button mat-button *ngIf="canUnclaimTask()" adf-cloud-unclaim-task [appName]="appName" [taskId]="taskId"
(success)="onUnclaimTask()" (error)="onError($event)"> (success)="onUnclaimTask()" (error)="onError($event)">
{{'ADF_CLOUD_TASK_FORM.EMPTY_FORM.BUTTONS.UNCLAIM' | translate}} {{'ADF_CLOUD_TASK_FORM.EMPTY_FORM.BUTTONS.UNCLAIM' | translate}}
</button> </button>

View File

@@ -22,7 +22,14 @@ import { ComponentFixture, TestBed } from '@angular/core/testing';
import { IdentityUserService, setupTestBed } from '@alfresco/adf-core'; import { IdentityUserService, setupTestBed } from '@alfresco/adf-core';
import { ProcessServiceCloudTestingModule } from '../../../testing/process-service-cloud.testing.module'; import { ProcessServiceCloudTestingModule } from '../../../testing/process-service-cloud.testing.module';
import { TaskFormCloudComponent } from './task-form-cloud.component'; import { TaskFormCloudComponent } from './task-form-cloud.component';
import { TaskDetailsCloudModel } from '../../start-task/models/task-details-cloud.model'; import {
TaskDetailsCloudModel,
TASK_ASSIGNED_STATE,
TASK_CLAIM_PERMISSION,
TASK_CREATED_STATE,
TASK_RELEASE_PERMISSION,
TASK_VIEW_PERMISSION
} from '../../start-task/models/task-details-cloud.model';
import { TaskCloudService } from '../../services/task-cloud.service'; import { TaskCloudService } from '../../services/task-cloud.service';
import { TranslateModule } from '@ngx-translate/core'; import { TranslateModule } from '@ngx-translate/core';
@@ -36,8 +43,9 @@ const taskDetails: TaskDetailsCloudModel = {
id: 'bd6b1741-6046-11e9-80f0-0a586460040d', id: 'bd6b1741-6046-11e9-80f0-0a586460040d',
name: 'Task1', name: 'Task1',
owner: 'admin.adf', owner: 'admin.adf',
standalone: true, standalone: false,
status: 'ASSIGNED' status: TASK_ASSIGNED_STATE,
permissions: [TASK_VIEW_PERMISSION]
}; };
describe('TaskFormCloudComponent', () => { describe('TaskFormCloudComponent', () => {
@@ -60,7 +68,10 @@ describe('TaskFormCloudComponent', () => {
}); });
beforeEach(() => { beforeEach(() => {
taskDetails.status = 'ASSIGNED'; taskDetails.status = TASK_ASSIGNED_STATE;
taskDetails.permissions = [TASK_VIEW_PERMISSION];
taskDetails.standalone = false;
identityUserService = TestBed.inject(IdentityUserService); identityUserService = TestBed.inject(IdentityUserService);
getCurrentUserSpy = spyOn(identityUserService, 'getCurrentUserInfo').and.returnValue({ username: 'admin.adf' }); getCurrentUserSpy = spyOn(identityUserService, 'getCurrentUserInfo').and.returnValue({ username: 'admin.adf' });
taskCloudService = TestBed.inject(TaskCloudService); taskCloudService = TestBed.inject(TaskCloudService);
@@ -71,47 +82,33 @@ describe('TaskFormCloudComponent', () => {
fixture = TestBed.createComponent(TaskFormCloudComponent); fixture = TestBed.createComponent(TaskFormCloudComponent);
debugElement = fixture.debugElement; debugElement = fixture.debugElement;
component = fixture.componentInstance; component = fixture.componentInstance;
}); });
describe('Complete button', () => { describe('Complete button', () => {
it('should show complete button when status is ASSIGNED', async () => { beforeEach(() => {
component.appName = 'app1';
component.taskId = 'task1'; component.taskId = 'task1';
component.ngOnChanges({ appName: new SimpleChange(null, 'app1', false) });
component.loadTask();
fixture.detectChanges(); fixture.detectChanges();
await fixture.whenStable();
const completeBtn = debugElement.query(By.css('[adf-cloud-complete-task]'));
expect(completeBtn.nativeElement).toBeDefined();
}); });
it('should not show complete button when status is ASSIGNED but assigned to a different person', async () => { it('should show complete button when status is ASSIGNED', () => {
component.appName = 'app1'; const completeBtn = debugElement.query(By.css('[adf-cloud-complete-task]'));
component.taskId = 'task1'; expect(completeBtn.nativeElement).toBeDefined();
expect(completeBtn.nativeElement.innerText.trim()).toEqual('ADF_CLOUD_TASK_FORM.EMPTY_FORM.BUTTONS.COMPLETE');
});
it('should not show complete button when status is ASSIGNED but assigned to a different person', () => {
getCurrentUserSpy.and.returnValue({}); getCurrentUserSpy.and.returnValue({});
component.loadTask();
fixture.detectChanges(); fixture.detectChanges();
await fixture.whenStable();
const completeBtn = debugElement.query(By.css('[adf-cloud-complete-task]')); const completeBtn = debugElement.query(By.css('[adf-cloud-complete-task]'));
expect(completeBtn).toBeNull(); expect(completeBtn).toBeNull();
}); });
it('should not show complete button when showCompleteButton=false', async () => { it('should not show complete button when showCompleteButton=false', () => {
component.appName = 'app1';
component.taskId = 'task1';
component.showCompleteButton = false; component.showCompleteButton = false;
component.loadTask();
fixture.detectChanges(); fixture.detectChanges();
await fixture.whenStable();
const completeBtn = debugElement.query(By.css('[adf-cloud-complete-task]')); const completeBtn = debugElement.query(By.css('[adf-cloud-complete-task]'));
expect(completeBtn).toBeNull(); expect(completeBtn).toBeNull();
@@ -120,88 +117,80 @@ describe('TaskFormCloudComponent', () => {
describe('Claim/Unclaim buttons', () => { describe('Claim/Unclaim buttons', () => {
it('should not show release button for standalone task', async () => { beforeEach(() => {
component.taskId = 'task1';
component.loadTask();
getTaskSpy.and.returnValue(of(taskDetails));
fixture.detectChanges();
await fixture.whenStable();
const unclaimBtn = debugElement.query(By.css('[adf-cloud-unclaim-task]'));
expect(unclaimBtn).toBeNull();
});
it('should show release button when task has candidate users and is assigned to one of these users', async () => {
spyOn(component, 'hasCandidateUsers').and.returnValue(true); spyOn(component, 'hasCandidateUsers').and.returnValue(true);
getTaskSpy.and.returnValue(of(taskDetails));
component.appName = 'app1';
component.taskId = 'task1'; component.taskId = 'task1';
component.ngOnChanges({ appName: new SimpleChange(null, 'app1', false) });
component.loadTask();
fixture.detectChanges(); fixture.detectChanges();
await fixture.whenStable();
const unclaimBtn = debugElement.query(By.css('[adf-cloud-unclaim-task]'));
expect(unclaimBtn).not.toBeNull();
}); });
it('should not show unclaim button when status is ASSIGNED but assigned to different person', async () => { it('should not show release button for standalone task', () => {
component.appName = 'app1'; taskDetails.permissions = [TASK_RELEASE_PERMISSION];
component.taskId = 'task1'; taskDetails.standalone = true;
getTaskSpy.and.returnValue(of(taskDetails));
fixture.detectChanges();
const unclaimBtn = debugElement.query(By.css('[adf-cloud-unclaim-task]'));
expect(unclaimBtn).toBeNull();
});
it('should show release button when task is assigned to one of the candidate users', () => {
taskDetails.permissions = [TASK_RELEASE_PERMISSION];
fixture.detectChanges();
const unclaimBtn = debugElement.query(By.css('[adf-cloud-unclaim-task]'));
expect(unclaimBtn.nativeElement).toBeDefined();
expect(unclaimBtn.nativeElement.innerText.trim()).toEqual('ADF_CLOUD_TASK_FORM.EMPTY_FORM.BUTTONS.UNCLAIM');
});
it('should not show unclaim button when status is ASSIGNED but assigned to different person', () => {
getCurrentUserSpy.and.returnValue({}); getCurrentUserSpy.and.returnValue({});
component.loadTask();
fixture.detectChanges(); fixture.detectChanges();
await fixture.whenStable();
const unclaimBtn = debugElement.query(By.css('[adf-cloud-unclaim-task]')); const unclaimBtn = debugElement.query(By.css('[adf-cloud-unclaim-task]'));
expect(unclaimBtn).toBeNull(); expect(unclaimBtn).toBeNull();
}); });
it('should not show unclaim button when status is not ASSIGNED', async () => { it('should not show unclaim button when status is not ASSIGNED', () => {
component.appName = 'app1';
component.taskId = 'task1';
taskDetails.status = undefined; taskDetails.status = undefined;
getTaskSpy.and.returnValue(of(taskDetails));
component.loadTask();
fixture.detectChanges(); fixture.detectChanges();
await fixture.whenStable();
const unclaimBtn = debugElement.query(By.css('[adf-cloud-unclaim-task]')); const unclaimBtn = debugElement.query(By.css('[adf-cloud-unclaim-task]'));
expect(unclaimBtn).toBeNull(); expect(unclaimBtn).toBeNull();
}); });
it('should show claim button when status is CREATED', async () => { it('should not show unclaim button when status is ASSIGNED and permissions not include RELEASE', () => {
component.appName = 'app1'; taskDetails.status = TASK_ASSIGNED_STATE;
component.taskId = 'task1'; taskDetails.permissions = [TASK_VIEW_PERMISSION];
taskDetails.status = 'CREATED'; fixture.detectChanges();
getTaskSpy.and.returnValue(of(taskDetails));
const unclaimBtn = debugElement.query(By.css('[adf-cloud-unclaim-task]'));
component.loadTask(); expect(unclaimBtn).toBeNull();
});
it('should show claim button when status is CREATED and permission includes CLAIM', () => {
taskDetails.status = TASK_CREATED_STATE;
taskDetails.permissions = [TASK_CLAIM_PERMISSION];
fixture.detectChanges(); fixture.detectChanges();
await fixture.whenStable();
const claimBtn = debugElement.query(By.css('[adf-cloud-claim-task]')); const claimBtn = debugElement.query(By.css('[adf-cloud-claim-task]'));
expect(claimBtn.nativeElement).toBeDefined(); expect(claimBtn.nativeElement).toBeDefined();
expect(claimBtn.nativeElement.innerText.trim()).toEqual('ADF_CLOUD_TASK_FORM.EMPTY_FORM.BUTTONS.CLAIM');
}); });
it('should not show claim button when status is not CREATED', async () => { it('should not show claim button when status is not CREATED', () => {
component.appName = 'app1';
component.taskId = 'task1';
taskDetails.status = undefined; taskDetails.status = undefined;
getTaskSpy.and.returnValue(of(taskDetails));
component.loadTask();
fixture.detectChanges(); fixture.detectChanges();
await fixture.whenStable();
const claimBtn = debugElement.query(By.css('[adf-cloud-claim-task]'));
expect(claimBtn).toBeNull();
});
it('should not show claim button when status is CREATED and permission not includes CLAIM', () => {
taskDetails.status = TASK_CREATED_STATE;
taskDetails.permissions = [TASK_VIEW_PERMISSION];
fixture.detectChanges();
const claimBtn = debugElement.query(By.css('[adf-cloud-claim-task]')); const claimBtn = debugElement.query(By.css('[adf-cloud-claim-task]'));
expect(claimBtn).toBeNull(); expect(claimBtn).toBeNull();
@@ -210,28 +199,23 @@ describe('TaskFormCloudComponent', () => {
describe('Cancel button', () => { describe('Cancel button', () => {
it('should show cancel button by default', async () => { it('should show cancel button by default', () => {
component.appName = 'app1'; component.appName = 'app1';
component.taskId = 'task1'; component.taskId = 'task1';
component.loadTask();
fixture.detectChanges(); fixture.detectChanges();
await fixture.whenStable();
const cancelBtn = debugElement.query(By.css('#adf-cloud-cancel-task')); const cancelBtn = debugElement.query(By.css('#adf-cloud-cancel-task'));
expect(cancelBtn.nativeElement).toBeDefined(); expect(cancelBtn.nativeElement).toBeDefined();
expect(cancelBtn.nativeElement.innerText.trim()).toEqual('ADF_CLOUD_TASK_FORM.EMPTY_FORM.BUTTONS.CANCEL');
}); });
it('should not show cancel button when showCancelButton=false', async () => { it('should not show cancel button when showCancelButton=false', () => {
component.appName = 'app1'; component.appName = 'app1';
component.taskId = 'task1'; component.taskId = 'task1';
component.showCancelButton = false; component.showCancelButton = false;
component.loadTask();
fixture.detectChanges(); fixture.detectChanges();
await fixture.whenStable();
const cancelBtn = debugElement.query(By.css('#adf-cloud-cancel-task')); const cancelBtn = debugElement.query(By.css('#adf-cloud-cancel-task'));
expect(cancelBtn).toBeNull(); expect(cancelBtn).toBeNull();
@@ -240,15 +224,12 @@ describe('TaskFormCloudComponent', () => {
describe('Inputs', () => { describe('Inputs', () => {
it('should not show complete/claim/unclaim buttons when readOnly=true', async () => { it('should not show complete/claim/unclaim buttons when readOnly=true', () => {
component.appName = 'app1'; component.appName = 'app1';
component.taskId = 'task1'; component.taskId = 'task1';
component.readOnly = true; component.readOnly = true;
component.loadTask();
fixture.detectChanges(); fixture.detectChanges();
await fixture.whenStable();
const completeBtn = debugElement.query(By.css('[adf-cloud-complete-task]')); const completeBtn = debugElement.query(By.css('[adf-cloud-complete-task]'));
expect(completeBtn).toBeNull(); expect(completeBtn).toBeNull();
@@ -261,6 +242,7 @@ describe('TaskFormCloudComponent', () => {
const cancelBtn = debugElement.query(By.css('#adf-cloud-cancel-task')); const cancelBtn = debugElement.query(By.css('#adf-cloud-cancel-task'));
expect(cancelBtn.nativeElement).toBeDefined(); expect(cancelBtn.nativeElement).toBeDefined();
expect(cancelBtn.nativeElement.innerText.trim()).toEqual('ADF_CLOUD_TASK_FORM.EMPTY_FORM.BUTTONS.CANCEL');
}); });
it('should load data when appName changes', () => { it('should load data when appName changes', () => {
@@ -288,15 +270,16 @@ describe('TaskFormCloudComponent', () => {
describe('Events', () => { describe('Events', () => {
it('should emit cancelClick when cancel button is clicked', (done) => { beforeEach(() => {
component.appName = 'app1'; component.appName = 'app1';
component.taskId = 'task1'; component.taskId = 'task1';
});
it('should emit cancelClick when cancel button is clicked', (done) => {
component.cancelClick.subscribe(() => { component.cancelClick.subscribe(() => {
done(); done();
}); });
component.loadTask();
fixture.detectChanges(); fixture.detectChanges();
const cancelBtn = debugElement.query(By.css('#adf-cloud-cancel-task')); const cancelBtn = debugElement.query(By.css('#adf-cloud-cancel-task'));
@@ -304,17 +287,13 @@ describe('TaskFormCloudComponent', () => {
}); });
it('should emit taskCompleted when task is completed', (done) => { it('should emit taskCompleted when task is completed', (done) => {
spyOn(taskCloudService, 'completeTask').and.returnValue(of({})); spyOn(taskCloudService, 'completeTask').and.returnValue(of({}));
component.appName = 'app1';
component.taskId = 'task1';
component.taskCompleted.subscribe(() => { component.taskCompleted.subscribe(() => {
done(); done();
}); });
component.loadTask(); component.ngOnChanges({ appName: new SimpleChange(null, 'app1', false) });
fixture.detectChanges(); fixture.detectChanges();
const completeBtn = debugElement.query(By.css('[adf-cloud-complete-task]')); const completeBtn = debugElement.query(By.css('[adf-cloud-complete-task]'));
@@ -323,17 +302,16 @@ describe('TaskFormCloudComponent', () => {
it('should emit taskClaimed when task is claimed', (done) => { it('should emit taskClaimed when task is claimed', (done) => {
spyOn(taskCloudService, 'claimTask').and.returnValue(of({})); spyOn(taskCloudService, 'claimTask').and.returnValue(of({}));
taskDetails.status = 'CREATED'; spyOn(component, 'hasCandidateUsers').and.returnValue(true);
taskDetails.status = TASK_CREATED_STATE;
taskDetails.permissions = [TASK_CLAIM_PERMISSION];
getTaskSpy.and.returnValue(of(taskDetails)); getTaskSpy.and.returnValue(of(taskDetails));
component.appName = 'app1';
component.taskId = 'task1';
component.taskClaimed.subscribe(() => { component.taskClaimed.subscribe(() => {
done(); done();
}); });
component.loadTask(); component.ngOnChanges({ appName: new SimpleChange(null, 'app1', false) });
fixture.detectChanges(); fixture.detectChanges();
const claimBtn = debugElement.query(By.css('[adf-cloud-claim-task]')); const claimBtn = debugElement.query(By.css('[adf-cloud-claim-task]'));
@@ -341,9 +319,6 @@ describe('TaskFormCloudComponent', () => {
}); });
it('should emit error when error occurs', (done) => { it('should emit error when error occurs', (done) => {
component.appName = 'app1';
component.taskId = 'task1';
component.error.subscribe(() => { component.error.subscribe(() => {
done(); done();
}); });
@@ -352,14 +327,10 @@ describe('TaskFormCloudComponent', () => {
}); });
it('should emit taskCompleted when task is completed', () => { it('should emit taskCompleted when task is completed', () => {
spyOn(taskCloudService, 'completeTask').and.returnValue(of({})); spyOn(taskCloudService, 'completeTask').and.returnValue(of({}));
const reloadSpy = spyOn(component, 'loadTask').and.callThrough(); const reloadSpy = spyOn(component, 'ngOnChanges').and.callThrough();
component.appName = 'app1'; component.ngOnChanges({ appName: new SimpleChange(null, 'app1', false) });
component.taskId = 'task1';
component.loadTask();
fixture.detectChanges(); fixture.detectChanges();
const completeBtn = debugElement.query(By.css('[adf-cloud-complete-task]')); const completeBtn = debugElement.query(By.css('[adf-cloud-complete-task]'));
@@ -369,15 +340,13 @@ describe('TaskFormCloudComponent', () => {
it('should emit taskClaimed when task is claimed', () => { it('should emit taskClaimed when task is claimed', () => {
spyOn(taskCloudService, 'claimTask').and.returnValue(of({})); spyOn(taskCloudService, 'claimTask').and.returnValue(of({}));
const reloadSpy = spyOn(component, 'loadTask').and.callThrough(); spyOn(component, 'hasCandidateUsers').and.returnValue(true);
const reloadSpy = spyOn(component, 'ngOnChanges').and.callThrough();
taskDetails.status = 'CREATED'; taskDetails.permissions = [TASK_CLAIM_PERMISSION];
taskDetails.status = TASK_CREATED_STATE;
getTaskSpy.and.returnValue(of(taskDetails)); getTaskSpy.and.returnValue(of(taskDetails));
component.appName = 'app1'; component.ngOnChanges({ appName: new SimpleChange(null, 'app1', false) });
component.taskId = 'task1';
component.loadTask();
fixture.detectChanges(); fixture.detectChanges();
const claimBtn = debugElement.query(By.css('[adf-cloud-claim-task]')); const claimBtn = debugElement.query(By.css('[adf-cloud-claim-task]'));
@@ -387,16 +356,14 @@ describe('TaskFormCloudComponent', () => {
it('should emit taskUnclaimed when task is unclaimed', () => { it('should emit taskUnclaimed when task is unclaimed', () => {
spyOn(taskCloudService, 'unclaimTask').and.returnValue(of({})); spyOn(taskCloudService, 'unclaimTask').and.returnValue(of({}));
const reloadSpy = spyOn(component, 'loadTask').and.callThrough(); const reloadSpy = spyOn(component, 'ngOnChanges').and.callThrough();
spyOn(component, 'hasCandidateUsers').and.returnValue(true); spyOn(component, 'hasCandidateUsers').and.returnValue(true);
taskDetails.status = 'ASSIGNED'; taskDetails.status = TASK_ASSIGNED_STATE;
taskDetails.permissions = [TASK_RELEASE_PERMISSION];
getTaskSpy.and.returnValue(of(taskDetails)); getTaskSpy.and.returnValue(of(taskDetails));
component.appName = 'app1'; component.ngOnChanges({ appName: new SimpleChange(null, 'app1', false) });
component.taskId = 'task1';
component.loadTask();
fixture.detectChanges(); fixture.detectChanges();
const unclaimBtn = debugElement.query(By.css('[adf-cloud-unclaim-task]')); const unclaimBtn = debugElement.query(By.css('[adf-cloud-unclaim-task]'));
@@ -415,10 +382,6 @@ describe('TaskFormCloudComponent', () => {
it('should not show loading template while task data is not being loaded', () => { it('should not show loading template while task data is not being loaded', () => {
component.loading = false; component.loading = false;
component.appName = 'app1';
component.taskId = 'task1';
component.loadTask();
fixture.detectChanges(); fixture.detectChanges();
const loadingTemplate = debugElement.query(By.css('mat-progress-spinner')); const loadingTemplate = debugElement.query(By.css('mat-progress-spinner'));

View File

@@ -133,7 +133,7 @@ export class TaskFormCloudComponent implements OnInit, OnChanges {
} }
} }
loadTask() { private loadTask() {
this.loading = true; this.loading = true;
this.taskCloudService this.taskCloudService
@@ -161,7 +161,7 @@ export class TaskFormCloudComponent implements OnInit, OnChanges {
} }
canClaimTask(): boolean { canClaimTask(): boolean {
return !this.readOnly && this.taskCloudService.canClaimTask(this.taskDetails); return !this.readOnly && this.taskCloudService.canClaimTask(this.taskDetails) && this.hasCandidateUsersOrGroups();
} }
hasCandidateUsers(): boolean { hasCandidateUsers(): boolean {
@@ -173,16 +173,11 @@ export class TaskFormCloudComponent implements OnInit, OnChanges {
} }
hasCandidateUsersOrGroups(): boolean { hasCandidateUsersOrGroups(): boolean {
let hasCandidateUsersOrGroups = false; return this.hasCandidateUsers() || this.hasCandidateGroups();
if (this.taskDetails?.status === 'ASSIGNED') {
hasCandidateUsersOrGroups = this.hasCandidateUsers() || this.hasCandidateGroups();
}
return hasCandidateUsersOrGroups;
} }
canUnclaimTask(): boolean { canUnclaimTask(): boolean {
return !this.readOnly && this.taskCloudService.canUnclaimTask(this.taskDetails); return !this.readOnly && this.taskCloudService.canUnclaimTask(this.taskDetails) && this.hasCandidateUsersOrGroups();
} }
isReadOnly(): boolean { isReadOnly(): boolean {