1 import { CdkDragDrop } from '@angular/cdk/drag-drop'
2 import { provideHttpClient, withInterceptorsFromDi } from '@angular/common/http'
3 import { provideHttpClientTesting } from '@angular/common/http/testing'
4 import { ComponentFixture, TestBed } from '@angular/core/testing'
10 } from '@angular/forms'
11 import { NgbActiveModal, NgbModule } from '@ng-bootstrap/ng-bootstrap'
12 import { NgSelectModule } from '@ng-select/ng-select'
13 import { of } from 'rxjs'
14 import { CustomFieldDataType } from 'src/app/data/custom-field'
15 import { MATCHING_ALGORITHMS, MATCH_AUTO } from 'src/app/data/matching-model'
16 import { Workflow } from 'src/app/data/workflow'
20 } from 'src/app/data/workflow-action'
24 } from 'src/app/data/workflow-trigger'
25 import { IfOwnerDirective } from 'src/app/directives/if-owner.directive'
26 import { IfPermissionsDirective } from 'src/app/directives/if-permissions.directive'
27 import { SafeHtmlPipe } from 'src/app/pipes/safehtml.pipe'
28 import { CorrespondentService } from 'src/app/services/rest/correspondent.service'
29 import { CustomFieldsService } from 'src/app/services/rest/custom-fields.service'
30 import { DocumentTypeService } from 'src/app/services/rest/document-type.service'
31 import { MailRuleService } from 'src/app/services/rest/mail-rule.service'
32 import { StoragePathService } from 'src/app/services/rest/storage-path.service'
33 import { SettingsService } from 'src/app/services/settings.service'
34 import { ConfirmButtonComponent } from '../../confirm-button/confirm-button.component'
35 import { NumberComponent } from '../../input/number/number.component'
36 import { PermissionsGroupComponent } from '../../input/permissions/permissions-group/permissions-group.component'
37 import { PermissionsUserComponent } from '../../input/permissions/permissions-user/permissions-user.component'
38 import { SelectComponent } from '../../input/select/select.component'
39 import { SwitchComponent } from '../../input/switch/switch.component'
40 import { TagsComponent } from '../../input/tags/tags.component'
41 import { TextComponent } from '../../input/text/text.component'
42 import { EditDialogMode } from '../edit-dialog.component'
44 DOCUMENT_SOURCE_OPTIONS,
45 SCHEDULE_DATE_FIELD_OPTIONS,
46 WORKFLOW_ACTION_OPTIONS,
47 WORKFLOW_TYPE_OPTIONS,
48 WorkflowEditDialogComponent,
49 } from './workflow-edit-dialog.component'
51 const workflow: Workflow = {
59 type: WorkflowTriggerType.Consumption,
60 sources: [DocumentSource.ConsumeFolder],
67 type: WorkflowActionType.Assignment,
72 type: WorkflowActionType.Assignment,
78 describe('WorkflowEditDialogComponent', () => {
79 let component: WorkflowEditDialogComponent
80 let settingsService: SettingsService
81 let fixture: ComponentFixture<WorkflowEditDialogComponent>
84 TestBed.configureTestingModule({
90 WorkflowEditDialogComponent,
91 IfPermissionsDirective,
98 PermissionsUserComponent,
99 PermissionsGroupComponent,
101 ConfirmButtonComponent,
106 provide: CorrespondentService,
120 provide: DocumentTypeService,
134 provide: StoragePathService,
148 provide: MailRuleService,
157 provide: CustomFieldsService,
165 data_type: CustomFieldDataType.String,
170 data_type: CustomFieldDataType.Date,
176 provideHttpClient(withInterceptorsFromDi()),
177 provideHttpClientTesting(),
179 }).compileComponents()
181 fixture = TestBed.createComponent(WorkflowEditDialogComponent)
182 settingsService = TestBed.inject(SettingsService)
183 settingsService.currentUser = { id: 99, username: 'user99' }
184 component = fixture.componentInstance
186 fixture.detectChanges()
189 it('should support create and edit modes, support adding triggers and actions on new workflow', () => {
190 component.dialogMode = EditDialogMode.CREATE
191 const createTitleSpy = jest.spyOn(component, 'getCreateTitle')
192 const editTitleSpy = jest.spyOn(component, 'getEditTitle')
193 fixture.detectChanges()
194 expect(createTitleSpy).toHaveBeenCalled()
195 expect(editTitleSpy).not.toHaveBeenCalled()
196 expect(component.object).toBeUndefined()
197 component.addAction()
198 expect(component.object).not.toBeUndefined()
199 expect(component.object.actions).toHaveLength(1)
200 component.object = undefined
201 component.addTrigger()
202 expect(component.object).not.toBeUndefined()
203 expect(component.object.triggers).toHaveLength(1)
205 component.dialogMode = EditDialogMode.EDIT
206 fixture.detectChanges()
207 expect(editTitleSpy).toHaveBeenCalled()
210 it('should return source options, type options, type name, schedule date field options', () => {
211 jest.spyOn(settingsService, 'get').mockReturnValue(true)
213 expect(component.sourceOptions).toEqual(DOCUMENT_SOURCE_OPTIONS)
214 expect(component.triggerTypeOptions).toEqual(WORKFLOW_TYPE_OPTIONS)
216 component.getTriggerTypeOptionName(WorkflowTriggerType.DocumentAdded)
217 ).toEqual('Document Added')
218 expect(component.getTriggerTypeOptionName(null)).toEqual('')
219 expect(component.sourceOptions).toEqual(DOCUMENT_SOURCE_OPTIONS)
220 expect(component.actionTypeOptions).toEqual(WORKFLOW_ACTION_OPTIONS)
222 component.getActionTypeOptionName(WorkflowActionType.Assignment)
223 ).toEqual('Assignment')
224 expect(component.getActionTypeOptionName(null)).toEqual('')
225 expect(component.scheduleDateFieldOptions).toEqual(
226 SCHEDULE_DATE_FIELD_OPTIONS
230 jest.spyOn(settingsService, 'get').mockReturnValue(false)
232 expect(component.actionTypeOptions).toEqual(
233 WORKFLOW_ACTION_OPTIONS.filter((a) => a.id !== WorkflowActionType.Email)
237 it('should support add and remove triggers and actions', () => {
238 component.object = workflow
239 component.addTrigger()
240 expect(component.object.triggers.length).toEqual(2)
241 component.addAction()
242 expect(component.object.actions.length).toEqual(3)
243 component.removeTrigger(1)
244 expect(component.object.triggers.length).toEqual(1)
245 component.removeAction(1)
246 expect(component.object.actions.length).toEqual(2)
249 it('should update order and remove ids from actions on drag n drop', () => {
250 const action1 = workflow.actions[0]
251 const action2 = workflow.actions[1]
252 component.object = workflow
254 component.onActionDrop({ previousIndex: 0, currentIndex: 1 } as CdkDragDrop<
257 expect(component.object.actions).toEqual([action2, action1])
258 expect(action1.id).toBeNull()
259 expect(action2.id).toBeNull()
262 it('should not include auto matching in algorithms', () => {
263 expect(component.getMatchingAlgorithms()).not.toContain(
264 MATCHING_ALGORITHMS.find((a) => a.id === MATCH_AUTO)
268 it('should disable or enable action fields based on removal action type', () => {
269 const workflow: Workflow = {
278 type: WorkflowActionType.Removal,
279 remove_all_tags: true,
280 remove_all_document_types: true,
281 remove_all_correspondents: true,
282 remove_all_storage_paths: true,
283 remove_all_custom_fields: true,
284 remove_all_owners: true,
285 remove_all_permissions: true,
289 component.object = workflow
292 component['checkRemovalActionFields'](workflow)
294 // Assert that the action fields are disabled or enabled correctly
296 component.actionFields.at(0).get('remove_tags').disabled
299 component.actionFields.at(0).get('remove_document_types').disabled
302 component.actionFields.at(0).get('remove_correspondents').disabled
305 component.actionFields.at(0).get('remove_storage_paths').disabled
308 component.actionFields.at(0).get('remove_custom_fields').disabled
311 component.actionFields.at(0).get('remove_owners').disabled
314 component.actionFields.at(0).get('remove_view_users').disabled
317 component.actionFields.at(0).get('remove_view_groups').disabled
320 component.actionFields.at(0).get('remove_change_users').disabled
323 component.actionFields.at(0).get('remove_change_groups').disabled
326 workflow.actions[0].remove_all_tags = false
327 workflow.actions[0].remove_all_document_types = false
328 workflow.actions[0].remove_all_correspondents = false
329 workflow.actions[0].remove_all_storage_paths = false
330 workflow.actions[0].remove_all_custom_fields = false
331 workflow.actions[0].remove_all_owners = false
332 workflow.actions[0].remove_all_permissions = false
334 component['checkRemovalActionFields'](workflow)
336 // Assert that the action fields are disabled or enabled correctly
337 expect(component.actionFields.at(0).get('remove_tags').disabled).toBeFalsy()
339 component.actionFields.at(0).get('remove_document_types').disabled
342 component.actionFields.at(0).get('remove_correspondents').disabled
345 component.actionFields.at(0).get('remove_storage_paths').disabled
348 component.actionFields.at(0).get('remove_custom_fields').disabled
351 component.actionFields.at(0).get('remove_owners').disabled
354 component.actionFields.at(0).get('remove_view_users').disabled
357 component.actionFields.at(0).get('remove_view_groups').disabled
360 component.actionFields.at(0).get('remove_change_users').disabled
363 component.actionFields.at(0).get('remove_change_groups').disabled
367 it('should prune empty nested objects on save', () => {
368 component.object = workflow
369 component.addTrigger()
370 component.addAction()
371 expect(component.objectForm.get('actions').value[0].email).not.toBeNull()
372 expect(component.objectForm.get('actions').value[0].webhook).not.toBeNull()
374 expect(component.objectForm.get('actions').value[0].email).toBeNull()
375 expect(component.objectForm.get('actions').value[0].webhook).toBeNull()
378 it('should remove selected custom field from the form group', () => {
379 const formGroup = new FormGroup({
380 assign_custom_fields: new FormControl([1, 2, 3]),
383 component.removeSelectedCustomField(2, formGroup)
384 expect(formGroup.get('assign_custom_fields').value).toEqual([1, 3])
386 component.removeSelectedCustomField(1, formGroup)
387 expect(formGroup.get('assign_custom_fields').value).toEqual([3])
389 component.removeSelectedCustomField(3, formGroup)
390 expect(formGroup.get('assign_custom_fields').value).toEqual([])