diff --git a/src/app/shared/mocks/mock-form-models.ts b/src/app/shared/mocks/mock-form-models.ts index f3973abf63..5851da94be 100644 --- a/src/app/shared/mocks/mock-form-models.ts +++ b/src/app/shared/mocks/mock-form-models.ts @@ -242,3 +242,17 @@ export const mockRowGroupModel = new DynamicRowGroupModel({ id: 'mockRowGroupModel', group: [mockInputWithFormFieldValueModel], }); + +export const fileFormEditInputConfig = { + name: 'dc.title', + id: 'dc_title', + readOnly: false, + disabled: false, +}; + +export const mockFileFormEditInputModel = new DsDynamicInputModel(fileFormEditInputConfig); + +export const mockFileFormEditRowGroupModel = new DynamicRowGroupModel({ + id: 'mockRowGroupModel', + group: [mockFileFormEditInputModel] +}); diff --git a/src/app/shared/mocks/mock-form-service.ts b/src/app/shared/mocks/mock-form-service.ts index 4768caadb6..31455f03da 100644 --- a/src/app/shared/mocks/mock-form-service.ts +++ b/src/app/shared/mocks/mock-form-service.ts @@ -7,6 +7,9 @@ export function getMockFormService( ): FormService { return jasmine.createSpyObj('FormService', { getFormData: jasmine.createSpy('getFormData'), + initForm: jasmine.createSpy('initForm'), + removeForm: jasmine.createSpy('removeForm'), + getForm: observableOf({}), getUniqueId: id$, resetForm: {}, validateAllFormFields: {}, diff --git a/src/app/shared/mocks/mock-section-upload.service.ts b/src/app/shared/mocks/mock-section-upload.service.ts new file mode 100644 index 0000000000..6b27c11ac5 --- /dev/null +++ b/src/app/shared/mocks/mock-section-upload.service.ts @@ -0,0 +1,12 @@ +import { SubmissionFormsConfigService } from '../../core/config/submission-forms-config.service'; + +export function getMockSectionUploadService(): SubmissionFormsConfigService { + return jasmine.createSpyObj('SectionUploadService', { + getUploadedFileList: jasmine.createSpy('getUploadedFileList'), + getFileData: jasmine.createSpy('getFileData'), + getDefaultPolicies: jasmine.createSpy('getDefaultPolicies'), + addUploadedFile: jasmine.createSpy('addUploadedFile'), + updateFileData: jasmine.createSpy('updateFileData'), + removeUploadedFile: jasmine.createSpy('removeUploadedFile') + }); +} diff --git a/src/app/shared/mocks/mock-submission.ts b/src/app/shared/mocks/mock-submission.ts index fd1ee27253..81b7bcb144 100644 --- a/src/app/shared/mocks/mock-submission.ts +++ b/src/app/shared/mocks/mock-submission.ts @@ -1080,7 +1080,9 @@ export const mockSubmissionState: SubmissionObjectState = { sectionType: 'upload', collapsed: false, enabled: true, - data: {}, + data: { + files: [] + }, errors: [], isLoading: false, isValid: false @@ -1231,3 +1233,357 @@ export const mockSectionsList = [ sectionType: 'license' } ]; + +export const mockUploadConfigResponse = { + accessConditionOptions: [ + { + name: 'openaccess', + groupUUID: '123456-g', + hasStartDate: false, + hasEndDate: false + }, + { + name: 'lease', + groupUUID: '123456-g', + hasStartDate: false, + hasEndDate: true, + maxEndDate: '2019-07-12T14:40:06.308+0000' + }, + { + name: 'embargo', + groupUUID: '123456-g', + hasStartDate: true, + hasEndDate: false, + maxStartDate: '2022-01-12T14:40:06.308+0000' + }, + { + name: 'administrator', + groupUUID: '0f2773dd-1741-475f-80e7-ccdef153d655', + hasStartDate: false, + hasEndDate: false + } + ], + metadata: { + rows: [ + { + fields: [ + { + input: { + type: 'onebox' + }, + label: 'Title', + mandatory: true, + repeatable: false, + mandatoryMessage: 'You must enter a main title for this item.', + hints: 'Enter the name of the file.', + selectableMetadata: [ + { + metadata: 'dc.title', + label: null, + authority: null, + closed: null + } + ], + languageCodes: [] + } + ] + }, + { + fields: [ + { + input: { + type: 'textarea' + }, + label: 'Description', + mandatory: false, + repeatable: true, + hints: 'Enter a description for the file', + selectableMetadata: [ + { + metadata: 'dc.description', + label: null, + authority: null, + closed: null + } + ], + languageCodes: [] + } + ] + } + ], + name: 'bitstream-metadata', + type: 'submissionform', + _links: { + self: 'https://rest.api/dspace-spring-rest/api/config/submissionforms/bitstream-metadata' + }, + self: 'https://rest.api/dspace-spring-rest/api/config/submissionforms/bitstream-metadata' + }, + required: false, + maxSize: 536870912, + name: 'upload', + type: 'submissionupload', + _links: { + metadata: 'https://rest.api/dspace-spring-rest/api/config/submissionuploads/upload/metadata', + self: 'https://rest.api/dspace-spring-rest/api/config/submissionuploads/upload' + }, + self: 'https://rest.api/dspace-spring-rest/api/config/submissionuploads/upload' +}; + +export const mockAccessConditionOptions = [ + { + name: 'openaccess', + groupUUID: '123456-g', + hasStartDate: false, + hasEndDate: false + }, + { + name: 'lease', + groupUUID: '123456-g', + hasStartDate: false, + hasEndDate: true, + maxEndDate: '2019-07-12T14:40:06.308+0000' + }, + { + name: 'embargo', + groupUUID: '123456-g', + hasStartDate: true, + hasEndDate: false, + maxStartDate: '2022-01-12T14:40:06.308+0000' + }, + { + name: 'administrator', + groupUUID: '0f2773dd-1741-475f-80e7-ccdef153d655', + hasStartDate: false, + hasEndDate: false + } +]; + +export const mockGroup = { + handle: null, + permanent: true, + self: 'https://rest.api/dspace-spring-rest/api/eperson/groups/123456-g1', + id: '123456-g', + uuid: '123456-g', + type: 'group', + name: 'Anonymous', + metadata: [], + _links: { + groups: 'https://rest.api/dspace-spring-rest/api/eperson/groups/123456-g1/groups', + self: 'https://rest.api/dspace-spring-rest/api/eperson/groups/123456-g1' + }, + groups: { + pageInfo: { + elementsPerPage: 0, + totalElements: 0, + totalPages: 1, + currentPage: 1 + }, + page: [] + } +}; + +export const mockUploadFiles = [ + { + uuid: '123456-test-upload', + metadata: { + 'dc.source': [ + { + value: '123456-test-upload.jpg', + language: null, + authority: null, + display: '123456-test-upload.jpg', + confidence: -1, + place: 0, + otherInformation: null + } + ], + 'dc.title': [ + { + value: '123456-test-upload.jpg', + language: null, + authority: null, + display: '123456-test-upload.jpg', + confidence: -1, + place: 0, + otherInformation: null + } + ] + }, + accessConditions: [ + { + id: 3675, + name: 'lease', + rpType: 'TYPE_CUSTOM', + groupUUID: '123456-g', + action: 'READ', + endDate: '2019-01-16', + type: 'resourcePolicy' + }, + { + id: 3676, + name: 'openaccess', + rpType: 'TYPE_CUSTOM', + groupUUID: '123456-g', + action: 'READ', + type: 'resourcePolicy' + } + ], + format: { + id: 16, + shortDescription: 'JPEG', + description: 'Joint Photographic Experts Group/JPEG File Interchange Format (JFIF)', + mimetype: 'image/jpeg', + supportLevel: 0, + internal: false, + extensions: null, + type: 'bitstreamformat' + }, + sizeBytes: 202999, + checkSum: { + checkSumAlgorithm: 'MD5', + value: '5e0996996863d2623439cbb53052bc72' + }, + url: 'https://test-ui.com/api/core/bitstreams/123456-test-upload/content' + } +]; + +export const mockFileFormData = { + metadata: { + 'dc.title': [ + { + value: 'title', + language: null, + authority: null, + display: 'title', + confidence: -1, + place: 0, + otherInformation: null + } + ], + 'dc.description': [ + { + value: 'description', + language: null, + authority: null, + display: 'description', + confidence: -1, + place: 0, + otherInformation: null + } + ] + }, + accessConditions: [ + { + name: [ + { + value: 'openaccess', + language: null, + authority: null, + display: 'openaccess', + confidence: -1, + place: 0, + otherInformation: null + } + ], + groupUUID: [ + { + value: '123456-g', + language: null, + authority: null, + display: '123456-g', + confidence: -1, + place: 0, + otherInformation: null + } + ] + } + , + { + name: [ + { + value: 'lease', + language: null, + authority: null, + display: 'lease', + confidence: -1, + place: 0, + otherInformation: null + } + ], + endDate: [ + { + value: { + year: 2019, + month: 1, + day: 16 + }, + language: null, + authority: null, + display: { + year: 2019, + month: 1, + day: 16 + }, + confidence: -1, + place: 0, + otherInformation: null + } + ], + groupUUID: [ + { + value: '123456-g', + language: null, + authority: null, + display: '123456-g', + confidence: -1, + place: 0, + otherInformation: null + } + ] + } + , + { + name: [ + { + value: 'embargo', + language: null, + authority: null, + display: 'lease', + confidence: -1, + place: 0, + otherInformation: null + } + ], + startDate: [ + { + value: { + year: 2019, + month: 1, + day: 16 + }, + language: null, + authority: null, + display: { + year: 2019, + month: 1, + day: 16 + }, + confidence: -1, + place: 0, + otherInformation: null + } + ], + groupUUID: [ + { + value: '123456-g', + language: null, + authority: null, + display: '123456-g', + confidence: -1, + place: 0, + otherInformation: null + } + ] + } + ] +}; diff --git a/src/app/submission/objects/submission-objects.reducer.spec.ts b/src/app/submission/objects/submission-objects.reducer.spec.ts index 1ca253e03a..23307b3f69 100644 --- a/src/app/submission/objects/submission-objects.reducer.spec.ts +++ b/src/app/submission/objects/submission-objects.reducer.spec.ts @@ -135,7 +135,9 @@ describe('submissionReducer test suite', () => { sectionType: 'upload', collapsed: false, enabled: true, - data: {}, + data: { + files:[] + }, errors: [], isLoading: false, isValid: false @@ -623,10 +625,9 @@ describe('submissionReducer test suite', () => { } ]; - let action: any = new UpdateSectionDataAction(submissionId, 'traditionalpageone', {}, errors); + const action: any = new RemoveSectionErrorsAction(submissionId, 'traditionalpageone'); let newState; - action = new RemoveSectionErrorsAction(submissionId, 'traditionalpageone'); newState = submissionObjectReducer(initState, action); expect(newState[826].sections.traditionalpageone.errors).toEqual([]); diff --git a/src/app/submission/sections/upload/file/edit/file-edit.component.spec.ts b/src/app/submission/sections/upload/file/edit/file-edit.component.spec.ts new file mode 100644 index 0000000000..1ecc5d2721 --- /dev/null +++ b/src/app/submission/sections/upload/file/edit/file-edit.component.spec.ts @@ -0,0 +1,216 @@ +import { ChangeDetectorRef, Component, NO_ERRORS_SCHEMA } from '@angular/core'; +import { async, ComponentFixture, inject, TestBed } from '@angular/core/testing'; +import { BrowserModule } from '@angular/platform-browser'; +import { CommonModule } from '@angular/common'; +import { TranslateModule } from '@ngx-translate/core'; +import { + DynamicFormArrayGroupModel, + DynamicFormArrayModel, + DynamicFormControlEvent, + DynamicFormGroupModel, + DynamicSelectModel +} from '@ng-dynamic-forms/core'; + +import { createTestComponent } from '../../../../../shared/testing/utils'; +import { FormBuilderService } from '../../../../../shared/form/builder/form-builder.service'; +import { SubmissionServiceStub } from '../../../../../shared/testing/submission-service-stub'; +import { SubmissionService } from '../../../../submission.service'; +import { UploadSectionFileEditComponent } from './file-edit.component'; +import { POLICY_DEFAULT_WITH_LIST } from '../../section-upload.component'; +import { + mockGroup, + mockSubmissionCollectionId, + mockSubmissionId, + mockUploadConfigResponse, + mockUploadFiles +} from '../../../../../shared/mocks/mock-submission'; +import { FormsModule, ReactiveFormsModule } from '@angular/forms'; +import { FormComponent } from '../../../../../shared/form/form.component'; +import { FormService } from '../../../../../shared/form/form.service'; +import { GLOBAL_CONFIG } from '../../../../../../config'; +import { MOCK_SUBMISSION_CONFIG } from '../../../../../shared/testing/mock-submission-config'; +import { getMockFormService } from '../../../../../shared/mocks/mock-form-service'; + +describe('UploadSectionFileComponent test suite', () => { + + let comp: UploadSectionFileEditComponent; + let compAsAny: any; + let fixture: ComponentFixture; + let submissionServiceStub: SubmissionServiceStub; + let formbuilderService: any; + + const config = MOCK_SUBMISSION_CONFIG; + const submissionId = mockSubmissionId; + const sectionId = 'upload'; + const collectionId = mockSubmissionCollectionId; + const availableAccessConditionOptions = mockUploadConfigResponse.accessConditionOptions; + const availableGroupsMap = new Map([[mockGroup.id, { name: mockGroup.name, uuid: mockGroup.uuid }]]); + const collectionPolicyType = POLICY_DEFAULT_WITH_LIST; + const configMetadataForm: any = mockUploadConfigResponse.metadata; + const fileIndex = '0'; + const fileId = '123456-test-upload'; + const fileData: any = mockUploadFiles[0]; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + imports: [ + BrowserModule, + CommonModule, + FormsModule, + ReactiveFormsModule, + TranslateModule.forRoot() + ], + declarations: [ + FormComponent, + UploadSectionFileEditComponent, + TestComponent + ], + providers: [ + { provide: GLOBAL_CONFIG, useValue: config }, + { provide: FormService, useValue: getMockFormService() }, + { provide: SubmissionService, useClass: SubmissionServiceStub }, + FormBuilderService, + ChangeDetectorRef, + UploadSectionFileEditComponent + ], + schemas: [NO_ERRORS_SCHEMA] + }).compileComponents().then(); + })); + + describe('', () => { + let testComp: TestComponent; + let testFixture: ComponentFixture; + + // synchronous beforeEach + beforeEach(() => { + const html = ` + `; + + testFixture = createTestComponent(html, TestComponent) as ComponentFixture; + testComp = testFixture.componentInstance; + }); + + afterEach(() => { + testFixture.destroy(); + }); + + it('should create UploadSectionFileEditComponent', inject([UploadSectionFileEditComponent], (app: UploadSectionFileEditComponent) => { + + expect(app).toBeDefined(); + + })); + }); + + describe('', () => { + beforeEach(() => { + fixture = TestBed.createComponent(UploadSectionFileEditComponent); + comp = fixture.componentInstance; + compAsAny = comp; + submissionServiceStub = TestBed.get(SubmissionService); + formbuilderService = TestBed.get(FormBuilderService); + + comp.submissionId = submissionId; + comp.collectionId = collectionId; + comp.sectionId = sectionId; + comp.availableAccessConditionOptions = availableAccessConditionOptions; + comp.availableAccessConditionGroups = availableGroupsMap; + comp.collectionPolicyType = collectionPolicyType; + comp.fileIndex = fileIndex; + comp.fileId = fileId; + comp.configMetadataForm = configMetadataForm; + }); + + afterEach(() => { + fixture.destroy(); + comp = null; + compAsAny = null; + }); + + it('should init form model properly', () => { + comp.fileData = fileData; + comp.formId = 'testFileForm'; + + comp.ngOnChanges(); + + expect(comp.formModel).toBeDefined(); + expect(comp.formModel.length).toBe(2); + expect(comp.formModel[0] instanceof DynamicFormGroupModel).toBeTruthy(); + expect(comp.formModel[1] instanceof DynamicFormArrayModel).toBeTruthy(); + expect((comp.formModel[1] as DynamicFormArrayModel).groups.length).toBe(2); + }); + + it('should call setOptions method onChange', () => { + const dynamicFormControlChangeEvent: DynamicFormControlEvent = { + $event: new Event('change'), + context: null, + control: null, + group: null, + model: {id: 'name'} as any, + type: 'change' + }; + spyOn(comp, 'setOptions'); + + comp.onChange(dynamicFormControlChangeEvent); + + expect(comp.setOptions).toHaveBeenCalled(); + }); + + it('should update form model on group select', () => { + + comp.fileData = fileData; + comp.formId = 'testFileForm'; + + comp.ngOnChanges(); + + const model: DynamicSelectModel = formbuilderService.findById('name', comp.formModel, 0); + const formGroup = formbuilderService.createFormGroup(comp.formModel); + const control = formbuilderService.getFormControlById('name', formGroup, comp.formModel, 0); + + spyOn(formbuilderService, 'findById').and.callThrough(); + + control.value = 'openaccess'; + comp.setOptions(model, control); + expect(formbuilderService.findById).not.toHaveBeenCalledWith('groupUUID', (model.parent as DynamicFormArrayGroupModel).group); + expect(formbuilderService.findById).not.toHaveBeenCalledWith('endDate', (model.parent as DynamicFormArrayGroupModel).group); + expect(formbuilderService.findById).not.toHaveBeenCalledWith('startDate', (model.parent as DynamicFormArrayGroupModel).group); + + control.value = 'lease'; + comp.setOptions(model, control); + expect(formbuilderService.findById).toHaveBeenCalledWith('groupUUID', (model.parent as DynamicFormArrayGroupModel).group); + expect(formbuilderService.findById).toHaveBeenCalledWith('endDate', (model.parent as DynamicFormArrayGroupModel).group); + + control.value = 'embargo'; + comp.setOptions(model, control); + expect(formbuilderService.findById).toHaveBeenCalledWith('groupUUID', (model.parent as DynamicFormArrayGroupModel).group); + expect(formbuilderService.findById).toHaveBeenCalledWith('startDate', (model.parent as DynamicFormArrayGroupModel).group); + }); + }); +}); + +// declare a test component +@Component({ + selector: 'ds-test-cmp', + template: `` +}) +class TestComponent { + + availableGroups; + availableAccessConditionOptions; + collectionId = mockSubmissionCollectionId; + collectionPolicyType; + configMetadataForm$; + fileIndexes = []; + fileList = []; + fileNames = []; + sectionId = 'upload'; + submissionId = mockSubmissionId; +} diff --git a/src/app/submission/sections/upload/file/edit/file-edit.component.ts b/src/app/submission/sections/upload/file/edit/file-edit.component.ts index db9f1dc32f..c44383abc6 100644 --- a/src/app/submission/sections/upload/file/edit/file-edit.component.ts +++ b/src/app/submission/sections/upload/file/edit/file-edit.component.ts @@ -14,18 +14,18 @@ import { } from '@ng-dynamic-forms/core'; import { FormBuilderService } from '../../../../../shared/form/builder/form-builder.service'; import { - BITSTREAM_ACCESS_CONDITIONS_FORM_ARRAY_LAYOUT, BITSTREAM_ACCESS_CONDITIONS_FORM_ARRAY_CONFIG, - BITSTREAM_FORM_ACCESS_CONDITION_END_DATE_LAYOUT, + BITSTREAM_ACCESS_CONDITIONS_FORM_ARRAY_LAYOUT, BITSTREAM_FORM_ACCESS_CONDITION_END_DATE_CONFIG, - BITSTREAM_FORM_ACCESS_CONDITION_GROUPS_LAYOUT, + BITSTREAM_FORM_ACCESS_CONDITION_END_DATE_LAYOUT, BITSTREAM_FORM_ACCESS_CONDITION_GROUPS_CONFIG, - BITSTREAM_FORM_ACCESS_CONDITION_START_DATE_LAYOUT, + BITSTREAM_FORM_ACCESS_CONDITION_GROUPS_LAYOUT, BITSTREAM_FORM_ACCESS_CONDITION_START_DATE_CONFIG, - BITSTREAM_FORM_ACCESS_CONDITION_TYPE_LAYOUT, + BITSTREAM_FORM_ACCESS_CONDITION_START_DATE_LAYOUT, BITSTREAM_FORM_ACCESS_CONDITION_TYPE_CONFIG, - BITSTREAM_METADATA_FORM_GROUP_LAYOUT, - BITSTREAM_METADATA_FORM_GROUP_CONFIG + BITSTREAM_FORM_ACCESS_CONDITION_TYPE_LAYOUT, + BITSTREAM_METADATA_FORM_GROUP_CONFIG, + BITSTREAM_METADATA_FORM_GROUP_LAYOUT } from './files-edit.model'; import { POLICY_DEFAULT_WITH_LIST } from '../../section-upload.component'; import { isNotEmpty, isNotUndefined } from '../../../../../shared/empty.util'; @@ -68,11 +68,11 @@ export class UploadSectionFileEditComponent implements OnChanges { protected buildFileEditForm() { // TODO check in the rest server configuration whether dc.description may be repeatable - const configDescr: FormFieldModel = Object.assign({}, this.configMetadataForm.rows[ 0 ].fields[ 0 ]); + const configDescr: FormFieldModel = Object.assign({}, this.configMetadataForm.rows[0].fields[0]); configDescr.repeatable = false; const configForm = Object.assign({}, this.configMetadataForm, { - fields: Object.assign([], this.configMetadataForm.rows[ 0 ].fields[ 0 ], [ - this.configMetadataForm.rows[ 0 ].fields[ 0 ], + fields: Object.assign([], this.configMetadataForm.rows[0].fields[0], [ + this.configMetadataForm.rows[0].fields[0], configDescr ]) }); @@ -118,9 +118,9 @@ export class UploadSectionFileEditComponent implements OnChanges { hasGroups.push({ id: 'name', value: condition.name }); } }); - const confStart = { relation: [ { action: 'ENABLE', connective: 'OR', when: hasStart } ] }; - const confEnd = { relation: [ { action: 'ENABLE', connective: 'OR', when: hasEnd } ] }; - const confGroup = { relation: [ { action: 'ENABLE', connective: 'OR', when: hasGroups } ] }; + const confStart = { relation: [{ action: 'ENABLE', connective: 'OR', when: hasStart }] }; + const confEnd = { relation: [{ action: 'ENABLE', connective: 'OR', when: hasEnd }] }; + const confGroup = { relation: [{ action: 'ENABLE', connective: 'OR', when: hasGroups }] }; accessConditionsArrayConfig.groupFactory = () => { const type = new DynamicSelectModel(accessConditionTypeModelConfig, BITSTREAM_FORM_ACCESS_CONDITION_TYPE_LAYOUT); @@ -132,7 +132,7 @@ export class UploadSectionFileEditComponent implements OnChanges { const endDate = new DynamicDatePickerModel(endDateConfig, BITSTREAM_FORM_ACCESS_CONDITION_END_DATE_LAYOUT); const groups = new DynamicSelectModel(groupsConfig, BITSTREAM_FORM_ACCESS_CONDITION_GROUPS_LAYOUT); - return [ type, startDate, endDate, groups ]; + return [type, startDate, endDate, groups]; }; // Number of access conditions blocks in form diff --git a/src/app/submission/sections/upload/file/edit/files-edit.model.ts b/src/app/submission/sections/upload/file/edit/files-edit.model.ts index 6640e6da30..185d3a8b89 100644 --- a/src/app/submission/sections/upload/file/edit/files-edit.model.ts +++ b/src/app/submission/sections/upload/file/edit/files-edit.model.ts @@ -49,7 +49,7 @@ export const BITSTREAM_FORM_ACCESS_CONDITION_START_DATE_CONFIG: DynamicDatePicke label: 'submission.sections.upload.form.from-label', placeholder: 'submission.sections.upload.form.from-placeholder', inline: false, - toggleIcon: 'fas fa-calendar', + toggleIcon: 'far fa-calendar-alt', relation: [ { action: 'ENABLE', @@ -73,7 +73,7 @@ export const BITSTREAM_FORM_ACCESS_CONDITION_END_DATE_CONFIG: DynamicDatePickerM label: 'submission.sections.upload.form.until-label', placeholder: 'submission.sections.upload.form.until-placeholder', inline: false, - toggleIcon: 'fas fa-calendar', + toggleIcon: 'far fa-calendar-alt', relation: [ { action: 'ENABLE', diff --git a/src/app/submission/sections/upload/file/file.component.html b/src/app/submission/sections/upload/file/file.component.html index 41768a88aa..a5b89f84a3 100644 --- a/src/app/submission/sections/upload/file/file.component.html +++ b/src/app/submission/sections/upload/file/file.component.html @@ -16,7 +16,7 @@ - + diff --git a/src/app/submission/sections/upload/file/file.component.spec.ts b/src/app/submission/sections/upload/file/file.component.spec.ts new file mode 100644 index 0000000000..8557efd451 --- /dev/null +++ b/src/app/submission/sections/upload/file/file.component.spec.ts @@ -0,0 +1,323 @@ +import { ChangeDetectorRef, Component, NO_ERRORS_SCHEMA } from '@angular/core'; +import { async, ComponentFixture, fakeAsync, inject, TestBed, tick } from '@angular/core/testing'; +import { BrowserModule, By } from '@angular/platform-browser'; +import { CommonModule } from '@angular/common'; + +import { of as observableOf } from 'rxjs'; +import { TranslateModule } from '@ngx-translate/core'; + +import { FileService } from '../../../../core/shared/file.service'; +import { FormService } from '../../../../shared/form/form.service'; +import { getMockFormService } from '../../../../shared/mocks/mock-form-service'; +import { HALEndpointService } from '../../../../core/shared/hal-endpoint.service'; +import { HALEndpointServiceStub } from '../../../../shared/testing/hal-endpoint-service-stub'; +import { NgbModal, NgbModule } from '@ng-bootstrap/ng-bootstrap'; +import { JsonPatchOperationsBuilder } from '../../../../core/json-patch/builder/json-patch-operations-builder'; +import { SubmissionJsonPatchOperationsServiceStub } from '../../../../shared/testing/submission-json-patch-operations-service-stub'; +import { SubmissionJsonPatchOperationsService } from '../../../../core/submission/submission-json-patch-operations.service'; +import { UploadSectionFileComponent } from './file.component'; +import { SubmissionServiceStub } from '../../../../shared/testing/submission-service-stub'; +import { + mockFileFormData, + mockGroup, + mockSubmissionCollectionId, + mockSubmissionId, + mockSubmissionObject, + mockUploadConfigResponse, + mockUploadFiles +} from '../../../../shared/mocks/mock-submission'; + +import { SubmissionService } from '../../../submission.service'; +import { SectionUploadService } from '../section-upload.service'; +import { createTestComponent } from '../../../../shared/testing/utils'; +import { FileSizePipe } from '../../../../shared/utils/file-size-pipe'; +import { POLICY_DEFAULT_WITH_LIST } from '../section-upload.component'; +import { JsonPatchOperationPathCombiner } from '../../../../core/json-patch/builder/json-patch-operation-path-combiner'; +import { getMockSectionUploadService } from '../../../../shared/mocks/mock-section-upload.service'; +import { FormFieldMetadataValueObject } from '../../../../shared/form/builder/models/form-field-metadata-value.model'; + +function getMockFileService(): FileService { + return jasmine.createSpyObj('FileService', { + downloadFile: jasmine.createSpy('downloadFile'), + getFileNameFromResponseContentDisposition: jasmine.createSpy('getFileNameFromResponseContentDisposition') + }); +} + +describe('UploadSectionFileComponent test suite', () => { + + let comp: UploadSectionFileComponent; + let compAsAny: any; + let fixture: ComponentFixture; + let submissionServiceStub: SubmissionServiceStub; + let uploadService: any; + let fileService: any; + let formService: any; + let halService: any; + let operationsBuilder: any; + let operationsService: any; + + const submissionJsonPatchOperationsServiceStub = new SubmissionJsonPatchOperationsServiceStub(); + const submissionId = mockSubmissionId; + const sectionId = 'upload'; + const collectionId = mockSubmissionCollectionId; + const availableAccessConditionOptions = mockUploadConfigResponse.accessConditionOptions; + const availableGroupsMap = new Map([[mockGroup.id, { name: mockGroup.name, uuid: mockGroup.uuid }]]); + const collectionPolicyType = POLICY_DEFAULT_WITH_LIST; + const fileIndex = '0'; + const fileName = '123456-test-upload.jpg'; + const fileId = '123456-test-upload'; + const fileData: any = mockUploadFiles[0]; + const pathCombiner = new JsonPatchOperationPathCombiner('sections', sectionId, 'files', fileIndex); + + const jsonPatchOpBuilder: any = jasmine.createSpyObj('jsonPatchOpBuilder', { + add: jasmine.createSpy('add'), + replace: jasmine.createSpy('replace'), + remove: jasmine.createSpy('remove'), + }); + + beforeEach(async(() => { + TestBed.configureTestingModule({ + imports: [ + BrowserModule, + CommonModule, + NgbModule.forRoot(), + TranslateModule.forRoot() + ], + declarations: [ + FileSizePipe, + UploadSectionFileComponent, + TestComponent + ], + providers: [ + { provide: FileService, useValue: getMockFileService() }, + { provide: FormService, useValue: getMockFormService() }, + { provide: HALEndpointService, useValue: new HALEndpointServiceStub('workspaceitems') }, + { provide: JsonPatchOperationsBuilder, useValue: jsonPatchOpBuilder }, + { provide: SubmissionJsonPatchOperationsService, useValue: submissionJsonPatchOperationsServiceStub }, + { provide: SubmissionService, useClass: SubmissionServiceStub }, + { provide: SectionUploadService, useValue: getMockSectionUploadService() }, + ChangeDetectorRef, + NgbModal, + UploadSectionFileComponent + ], + schemas: [NO_ERRORS_SCHEMA] + }).compileComponents().then(); + })); + + describe('', () => { + let testComp: TestComponent; + let testFixture: ComponentFixture; + + // synchronous beforeEach + beforeEach(() => { + const html = ` + `; + + testFixture = createTestComponent(html, TestComponent) as ComponentFixture; + testComp = testFixture.componentInstance; + }); + + afterEach(() => { + testFixture.destroy(); + }); + + it('should create UploadSectionFileComponent', inject([UploadSectionFileComponent], (app: UploadSectionFileComponent) => { + + expect(app).toBeDefined(); + + })); + }); + + describe('', () => { + beforeEach(() => { + fixture = TestBed.createComponent(UploadSectionFileComponent); + comp = fixture.componentInstance; + compAsAny = comp; + submissionServiceStub = TestBed.get(SubmissionService); + uploadService = TestBed.get(SectionUploadService); + fileService = TestBed.get(FileService); + formService = TestBed.get(FormService); + halService = TestBed.get(HALEndpointService); + operationsBuilder = TestBed.get(JsonPatchOperationsBuilder); + operationsService = TestBed.get(SubmissionJsonPatchOperationsService); + + comp.submissionId = submissionId; + comp.collectionId = collectionId; + comp.sectionId = sectionId; + comp.availableAccessConditionOptions = availableAccessConditionOptions; + comp.availableAccessConditionGroups = availableGroupsMap; + comp.collectionPolicyType = collectionPolicyType; + comp.fileIndex = fileIndex; + comp.fileId = fileId; + comp.fileName = fileName; + }); + + afterEach(() => { + fixture.destroy(); + comp = null; + compAsAny = null; + }); + + it('should init component properly', () => { + fixture.detectChanges(); + + expect(comp.formId).toBeDefined(); + expect(compAsAny.pathCombiner).toEqual(pathCombiner); + }); + + it('should init file data properly', () => { + uploadService.getFileData.and.returnValue(observableOf(fileData)); + + comp.ngOnChanges(); + + expect(comp.fileData).toEqual(fileData); + }); + + it('should call deleteFile on delete confirmation', fakeAsync(() => { + spyOn(compAsAny, 'deleteFile'); + comp.fileData = fileData; + + fixture.detectChanges(); + + const modalBtn = fixture.debugElement.query(By.css('.fa-trash ')); + + modalBtn.nativeElement.click(); + fixture.detectChanges(); + + const confirmBtn: any = ((document as any).querySelector('.btn-danger:nth-child(2)')); + confirmBtn.click(); + + fixture.detectChanges(); + + fixture.whenStable().then(() => { + expect(compAsAny.deleteFile).toHaveBeenCalled(); + }); + })); + + it('should delete file properly', () => { + compAsAny.pathCombiner = pathCombiner; + operationsService.jsonPatchByResourceID.and.returnValue(observableOf({})); + submissionServiceStub.getSubmissionObjectLinkName.and.returnValue('workspaceitems'); + + compAsAny.deleteFile(); + + expect(uploadService.removeUploadedFile).toHaveBeenCalledWith(submissionId, sectionId, fileId); + expect(operationsBuilder.remove).toHaveBeenCalledWith(pathCombiner.getPath()); + expect(operationsService.jsonPatchByResourceID).toHaveBeenCalledWith( + 'workspaceitems', + submissionId, + pathCombiner.rootElement, + pathCombiner.subRootElement); + }); + + it('should download Bitstream File properly', fakeAsync(() => { + comp.fileData = fileData; + comp.downloadBitstreamFile(); + + tick(); + + expect(fileService.downloadFile).toHaveBeenCalled() + })); + + it('should download Bitstream File properly', fakeAsync(() => { + compAsAny.pathCombiner = pathCombiner; + const event = new Event('click', null); + spyOn(comp, 'switchMode'); + formService.getFormData.and.returnValue(observableOf(mockFileFormData)); + + const response = [ + Object.assign(mockSubmissionObject, { + sections: { + upload: { + files: mockUploadFiles + } + } + }) + ]; + operationsService.jsonPatchByResourceID.and.returnValue(observableOf(response)); + + const accessConditionsToSave = [ + { name: 'openaccess', groupUUID: '123456-g' }, + { name: 'lease', endDate: '2019-01-16T00:00:00Z', groupUUID: '123456-g' }, + { name: 'embargo', startDate: '2019-01-16T00:00:00Z', groupUUID: '123456-g' } + ]; + comp.saveBitstreamData(event); + tick(); + + let path = 'metadata/dc.title'; + expect(operationsBuilder.add).toHaveBeenCalledWith( + pathCombiner.getPath(path), + mockFileFormData.metadata['dc.title'], + true + ); + + path = 'metadata/dc.description'; + expect(operationsBuilder.add).toHaveBeenCalledWith( + pathCombiner.getPath(path), + mockFileFormData.metadata['dc.description'], + true + ); + + path = 'accessConditions'; + expect(operationsBuilder.add).toHaveBeenCalledWith( + pathCombiner.getPath(path), + accessConditionsToSave, + true + ); + + expect(comp.switchMode).toHaveBeenCalled(); + expect(uploadService.updateFileData).toHaveBeenCalledWith(submissionId, sectionId, mockUploadFiles[0].uuid, mockUploadFiles[0]); + + })); + + it('should retrieve Value From Field properly', () => { + let field; + expect(compAsAny.retrieveValueFromField(field)).toBeUndefined(); + + field = new FormFieldMetadataValueObject('test'); + expect(compAsAny.retrieveValueFromField(field)).toBe('test'); + + field = [new FormFieldMetadataValueObject('test')]; + expect(compAsAny.retrieveValueFromField(field)).toBe('test'); + }); + + it('should switch read mode', () => { + comp.readMode = false; + + comp.switchMode(); + expect(comp.readMode).toBeTruthy(); + + comp.switchMode(); + + expect(comp.readMode).toBeFalsy(); + }); + }); +}); + +// declare a test component +@Component({ + selector: 'ds-test-cmp', + template: `` +}) +class TestComponent { + + availableGroups; + availableAccessConditionOptions; + collectionId = mockSubmissionCollectionId; + collectionPolicyType; + configMetadataForm$; + fileIndexes = []; + fileList = []; + fileNames = []; + sectionId = 'upload'; + submissionId = mockSubmissionId; +} diff --git a/src/app/submission/sections/upload/file/file.component.ts b/src/app/submission/sections/upload/file/file.component.ts index 0df3a98f00..f23358a09c 100644 --- a/src/app/submission/sections/upload/file/file.component.ts +++ b/src/app/submission/sections/upload/file/file.component.ts @@ -168,13 +168,15 @@ export class UploadSectionFileComponent implements OnChanges, OnInit { this.pathCombiner.subRootElement) }) ).subscribe((result: SubmissionObject[]) => { - Object.keys((result[0].sections.upload as WorkspaceitemSectionUploadObject).files ) - .filter((key) => (result[0].sections.upload as WorkspaceitemSectionUploadObject).files[key].uuid === this.fileId) - .forEach((key) => this.uploadService.updateFileData( - this.submissionId, - this.sectionId, - this.fileId, - (result[0].sections.upload as WorkspaceitemSectionUploadObject).files[key])); + if (result[0].sections.upload) { + Object.keys((result[0].sections.upload as WorkspaceitemSectionUploadObject).files) + .filter((key) => (result[0].sections.upload as WorkspaceitemSectionUploadObject).files[key].uuid === this.fileId) + .forEach((key) => this.uploadService.updateFileData( + this.submissionId, + this.sectionId, + this.fileId, + (result[0].sections.upload as WorkspaceitemSectionUploadObject).files[key])); + } this.switchMode(); })); } diff --git a/src/app/submission/sections/upload/section-upload.component.spec.ts b/src/app/submission/sections/upload/section-upload.component.spec.ts new file mode 100644 index 0000000000..9ea3922226 --- /dev/null +++ b/src/app/submission/sections/upload/section-upload.component.spec.ts @@ -0,0 +1,289 @@ +import { ChangeDetectorRef, Component, NO_ERRORS_SCHEMA } from '@angular/core'; +import { async, ComponentFixture, inject, TestBed } from '@angular/core/testing'; +import { TranslateModule } from '@ngx-translate/core'; + +import { of as observableOf } from 'rxjs'; + +import { createTestComponent } from '../../../shared/testing/utils'; +import { SubmissionService } from '../../submission.service'; +import { SubmissionServiceStub } from '../../../shared/testing/submission-service-stub'; +import { SectionsService } from '../sections.service'; +import { SectionsServiceStub } from '../../../shared/testing/sections-service-stub'; +import { SubmissionFormsConfigService } from '../../../core/config/submission-forms-config.service'; +import { SectionDataObject } from '../models/section-data.model'; +import { SectionsType } from '../sections-type'; +import { + mockGroup, + mockSubmissionCollectionId, + mockSubmissionId, + mockSubmissionState, + mockUploadConfigResponse, + mockUploadFiles +} from '../../../shared/mocks/mock-submission'; +import { BrowserModule } from '@angular/platform-browser'; +import { CommonModule } from '@angular/common'; +import { SubmissionUploadsConfigService } from '../../../core/config/submission-uploads-config.service'; +import { SectionUploadService } from './section-upload.service'; +import { UploadSectionComponent } from './section-upload.component'; +import { CollectionDataService } from '../../../core/data/collection-data.service'; +import { GroupEpersonService } from '../../../core/eperson/group-eperson.service'; +import { cold, hot } from 'jasmine-marbles'; +import { Collection } from '../../../core/shared/collection.model'; +import { ResourcePolicy } from '../../../core/shared/resource-policy.model'; +import { RemoteData } from '../../../core/data/remote-data'; +import { ConfigData } from '../../../core/config/config-data'; +import { PageInfo } from '../../../core/shared/page-info.model'; +import { Group } from '../../../core/eperson/models/group.model'; +import { getMockSectionUploadService } from '../../../shared/mocks/mock-section-upload.service'; + +function getMockSubmissionUploadsConfigService(): SubmissionFormsConfigService { + return jasmine.createSpyObj('SubmissionUploadsConfigService', { + getConfigAll: jasmine.createSpy('getConfigAll'), + getConfigByHref: jasmine.createSpy('getConfigByHref'), + getConfigByName: jasmine.createSpy('getConfigByName'), + getConfigBySearch: jasmine.createSpy('getConfigBySearch') + }); +} + +function getMockCollectionDataService(): CollectionDataService { + return jasmine.createSpyObj('CollectionDataService', { + findById: jasmine.createSpy('findById'), + findByHref: jasmine.createSpy('findByHref') + }); +} + +function getMockGroupEpersonService(): GroupEpersonService { + return jasmine.createSpyObj('GroupEpersonService', { + findById: jasmine.createSpy('findById'), + + }); +} + +const sectionObject: SectionDataObject = { + config: 'https://dspace7.4science.it/or2018/api/config/submissionforms/upload', + mandatory: true, + data: { + files: [] + }, + errors: [], + header: 'submit.progressbar.describe.upload', + id: 'upload', + sectionType: SectionsType.Upload +}; + +describe('UploadSectionComponent test suite', () => { + + let comp: UploadSectionComponent; + let compAsAny: any; + let fixture: ComponentFixture; + let submissionServiceStub: SubmissionServiceStub; + let sectionsServiceStub: SectionsServiceStub; + let collectionDataService: any; + let groupService: any; + let uploadsConfigService: any; + let bitstreamService: any; + + const submissionId = mockSubmissionId; + const collectionId = mockSubmissionCollectionId; + const submissionState = mockSubmissionState[mockSubmissionId]; + const mockCollection = Object.assign(new Collection(), { + name: 'Community 1-Collection 1', + id: collectionId, + metadata: [ + { + key: 'dc.title', + language: 'en_US', + value: 'Community 1-Collection 1' + }], + _links: { + defaultAccessConditions: collectionId + '/defaultAccessConditions' + } + }); + const mockDefaultAccessCondition = Object.assign(new ResourcePolicy(), { + name: null, + groupUUID: '11cc35e5-a11d-4b64-b5b9-0052a5d15509', + id: 20, + uuid: 'resource-policy-20' + }); + + beforeEach(async(() => { + TestBed.configureTestingModule({ + imports: [ + BrowserModule, + CommonModule, + TranslateModule.forRoot() + ], + declarations: [ + UploadSectionComponent, + TestComponent + ], + providers: [ + { provide: CollectionDataService, useValue: getMockCollectionDataService() }, + { provide: GroupEpersonService, useValue: getMockGroupEpersonService() }, + { provide: SubmissionUploadsConfigService, useValue: getMockSubmissionUploadsConfigService() }, + { provide: SectionsService, useClass: SectionsServiceStub }, + { provide: SubmissionService, useClass: SubmissionServiceStub }, + { provide: SectionUploadService, useValue: getMockSectionUploadService() }, + { provide: 'sectionDataProvider', useValue: sectionObject }, + { provide: 'submissionIdProvider', useValue: submissionId }, + ChangeDetectorRef, + UploadSectionComponent + ], + schemas: [NO_ERRORS_SCHEMA] + }).compileComponents().then(); + })); + + describe('', () => { + let testComp: TestComponent; + let testFixture: ComponentFixture; + + // synchronous beforeEach + beforeEach(() => { + const html = ` + `; + + testFixture = createTestComponent(html, TestComponent) as ComponentFixture; + testComp = testFixture.componentInstance; + }); + + afterEach(() => { + testFixture.destroy(); + }); + + it('should create UploadSectionComponent', inject([UploadSectionComponent], (app: UploadSectionComponent) => { + + expect(app).toBeDefined(); + + })); + }); + + describe('', () => { + beforeEach(() => { + fixture = TestBed.createComponent(UploadSectionComponent); + comp = fixture.componentInstance; + compAsAny = comp; + submissionServiceStub = TestBed.get(SubmissionService); + sectionsServiceStub = TestBed.get(SectionsService); + collectionDataService = TestBed.get(CollectionDataService); + groupService = TestBed.get(GroupEpersonService); + uploadsConfigService = TestBed.get(SubmissionUploadsConfigService); + bitstreamService = TestBed.get(SectionUploadService); + }); + + afterEach(() => { + fixture.destroy(); + comp = null; + compAsAny = null; + }); + + it('should init component properly', () => { + + submissionServiceStub.getSubmissionObject.and.returnValue(observableOf(submissionState)); + + collectionDataService.findById.and.returnValue(observableOf( + new RemoteData(false, false, true, + undefined, mockCollection))); + + collectionDataService.findByHref.and.returnValue(observableOf( + new RemoteData(false, false, true, + undefined, mockDefaultAccessCondition) + )); + + uploadsConfigService.getConfigByHref.and.returnValue(observableOf( + new ConfigData(new PageInfo(), mockUploadConfigResponse as any) + )); + + groupService.findById.and.returnValues( + observableOf(new RemoteData(false, false, true, + undefined, Object.assign(new Group(), mockGroup))), + observableOf(new RemoteData(false, false, true, + undefined, Object.assign(new Group(), mockGroup))) + ); + + bitstreamService.getUploadedFileList.and.returnValue(observableOf([])); + + comp.onSectionInit(); + + const expectedGroupsMap = new Map(); + expectedGroupsMap.set(mockGroup.id, { name: mockGroup.name, uuid: mockGroup.uuid }); + + expect(comp.collectionId).toBe(collectionId); + expect(comp.collectionName).toBe(mockCollection.name); + expect(comp.availableAccessConditionOptions.length).toBe(4); + expect(comp.availableAccessConditionOptions).toEqual(mockUploadConfigResponse.accessConditionOptions as any); + expect(compAsAny.subs.length).toBe(2); + expect(compAsAny.availableGroups.size).toBe(1); + expect(compAsAny.availableGroups).toEqual(expectedGroupsMap); + expect(compAsAny.fileList).toEqual([]); + expect(compAsAny.fileIndexes).toEqual([]); + expect(compAsAny.fileNames).toEqual([]); + // this.fileIndexes, this.fileNames).toEqual(expectedGroupsMap); + + }); + + it('should init file list properly', () => { + + submissionServiceStub.getSubmissionObject.and.returnValue(observableOf(submissionState)); + + collectionDataService.findById.and.returnValue(observableOf( + new RemoteData(false, false, true, + undefined, mockCollection))); + + collectionDataService.findByHref.and.returnValue(observableOf( + new RemoteData(false, false, true, + undefined, mockDefaultAccessCondition) + )); + + uploadsConfigService.getConfigByHref.and.returnValue(observableOf( + new ConfigData(new PageInfo(), mockUploadConfigResponse as any) + )); + + groupService.findById.and.returnValues( + observableOf(new RemoteData(false, false, true, + undefined, Object.assign(new Group(), mockGroup))), + observableOf(new RemoteData(false, false, true, + undefined, Object.assign(new Group(), mockGroup))) + ); + + bitstreamService.getUploadedFileList.and.returnValue(observableOf(mockUploadFiles)); + + comp.onSectionInit(); + + const expectedGroupsMap = new Map(); + expectedGroupsMap.set(mockGroup.id, { name: mockGroup.name, uuid: mockGroup.uuid }); + + expect(comp.collectionId).toBe(collectionId); + expect(comp.collectionName).toBe(mockCollection.name); + expect(comp.availableAccessConditionOptions.length).toBe(4); + expect(comp.availableAccessConditionOptions).toEqual(mockUploadConfigResponse.accessConditionOptions as any); + expect(compAsAny.subs.length).toBe(2); + expect(compAsAny.availableGroups.size).toBe(1); + expect(compAsAny.availableGroups).toEqual(expectedGroupsMap); + expect(compAsAny.fileList).toEqual(mockUploadFiles); + expect(compAsAny.fileIndexes).toEqual(['123456-test-upload']); + expect(compAsAny.fileNames).toEqual(['123456-test-upload.jpg']); + + }); + + it('should the properly section status', () => { + bitstreamService.getUploadedFileList.and.returnValue(hot('-a-b', { + a: [], + b: mockUploadFiles + })); + + expect(compAsAny.getSectionStatus()).toBeObservable(cold('-c-d', { + c: false, + d: true + })); + }); + }); +}); + +// declare a test component +@Component({ + selector: 'ds-test-cmp', + template: `` +}) +class TestComponent { + +} diff --git a/src/app/submission/sections/upload/section-upload.component.ts b/src/app/submission/sections/upload/section-upload.component.ts index c2143a3531..5dedc3e7b9 100644 --- a/src/app/submission/sections/upload/section-upload.component.ts +++ b/src/app/submission/sections/upload/section-upload.component.ts @@ -104,7 +104,6 @@ export class UploadSectionComponent extends SectionModelComponent { defaultAccessConditionsRemoteData.hasSucceeded), take(1), tap((defaultAccessConditionsRemoteData: RemoteData) => { - console.log(JSON.stringify(defaultAccessConditionsRemoteData.payload)); if (isNotEmpty(defaultAccessConditionsRemoteData.payload)) { this.collectionDefaultAccessConditions = Array.isArray(defaultAccessConditionsRemoteData.payload) ? defaultAccessConditionsRemoteData.payload : [defaultAccessConditionsRemoteData.payload]; @@ -135,7 +134,6 @@ export class UploadSectionComponent extends SectionModelComponent { }), flatMap((group) => group), reduce((acc: Group[], group: RemoteData) => { - console.log(JSON.stringify(group.payload)); acc.push(group.payload); return acc; }, []), @@ -164,20 +162,21 @@ export class UploadSectionComponent extends SectionModelComponent { }), distinctUntilChanged()) .subscribe(([configMetadataForm, fileList]: [SubmissionFormsModel, any[]]) => { - this.fileList = []; - this.fileIndexes = []; - this.fileNames = []; - this.changeDetectorRef.detectChanges(); - if (isNotUndefined(fileList) && fileList.length > 0) { - fileList.forEach((file) => { - this.fileList.push(file); - this.fileIndexes.push(file.uuid); - this.fileNames.push(this.getFileName(configMetadataForm, file)); - }); - } - this.changeDetectorRef.detectChanges(); + this.fileList = []; + this.fileIndexes = []; + this.fileNames = []; + this.changeDetectorRef.detectChanges(); + if (isNotUndefined(fileList) && fileList.length > 0) { + fileList.forEach((file) => { + this.fileList.push(file); + this.fileIndexes.push(file.uuid); + this.fileNames.push(this.getFileName(configMetadataForm, file)); + }); } - ) + + this.changeDetectorRef.detectChanges(); + } + ) ); }