From 9d3769103dd7d35cc93deda6ea0f354515e8ce6a Mon Sep 17 00:00:00 2001 From: Kristof De Langhe Date: Mon, 2 Jan 2023 17:44:58 +0100 Subject: [PATCH] 93747: Test cases --- ...it-metadata-field-values.component.spec.ts | 135 ++++++++++++++ ...so-edit-metadata-headers.component.spec.ts | 32 ++++ .../dso-edit-metadata-value.component.html | 10 +- .../dso-edit-metadata-value.component.spec.ts | 170 ++++++++++++++++++ .../metadata-field-selector.component.spec.ts | 103 +++++++++++ .../metadata-field-selector.component.ts | 2 +- 6 files changed, 446 insertions(+), 6 deletions(-) create mode 100644 src/app/dso-shared/dso-edit-metadata/dso-edit-metadata-field-values/dso-edit-metadata-field-values.component.spec.ts create mode 100644 src/app/dso-shared/dso-edit-metadata/dso-edit-metadata-headers/dso-edit-metadata-headers.component.spec.ts create mode 100644 src/app/dso-shared/dso-edit-metadata/dso-edit-metadata-value/dso-edit-metadata-value.component.spec.ts create mode 100644 src/app/dso-shared/dso-edit-metadata/metadata-field-selector/metadata-field-selector.component.spec.ts diff --git a/src/app/dso-shared/dso-edit-metadata/dso-edit-metadata-field-values/dso-edit-metadata-field-values.component.spec.ts b/src/app/dso-shared/dso-edit-metadata/dso-edit-metadata-field-values/dso-edit-metadata-field-values.component.spec.ts new file mode 100644 index 0000000000..3ca0dba3b6 --- /dev/null +++ b/src/app/dso-shared/dso-edit-metadata/dso-edit-metadata-field-values/dso-edit-metadata-field-values.component.spec.ts @@ -0,0 +1,135 @@ +import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; +import { VarDirective } from '../../../shared/utils/var.directive'; +import { TranslateModule } from '@ngx-translate/core'; +import { RouterTestingModule } from '@angular/router/testing'; +import { NO_ERRORS_SCHEMA } from '@angular/core'; +import { DsoEditMetadataFieldValuesComponent } from './dso-edit-metadata-field-values.component'; +import { DsoEditMetadataForm } from '../dso-edit-metadata-form'; +import { DSpaceObject } from '../../../core/shared/dspace-object.model'; +import { MetadataValue } from '../../../core/shared/metadata.models'; +import { of } from 'rxjs/internal/observable/of'; +import { BehaviorSubject } from 'rxjs/internal/BehaviorSubject'; +import { By } from '@angular/platform-browser'; + +describe('DsoEditMetadataFieldValuesComponent', () => { + let component: DsoEditMetadataFieldValuesComponent; + let fixture: ComponentFixture; + + let form: DsoEditMetadataForm; + let dso: DSpaceObject; + let mdField: string; + let draggingMdField$: BehaviorSubject; + + beforeEach(waitForAsync(() => { + dso = Object.assign(new DSpaceObject(), { + metadata: { + 'dc.title': [ + Object.assign(new MetadataValue(), { + value: 'Test Title', + language: 'en', + place: 0, + }), + ], + 'dc.subject': [ + Object.assign(new MetadataValue(), { + value: 'Subject One', + language: 'en', + place: 0, + }), + Object.assign(new MetadataValue(), { + value: 'Subject Two', + language: 'en', + place: 1, + }), + Object.assign(new MetadataValue(), { + value: 'Subject Three', + language: 'en', + place: 2, + }), + ], + }, + }); + form = new DsoEditMetadataForm(dso.metadata); + mdField = 'dc.subject'; + draggingMdField$ = new BehaviorSubject(null); + + TestBed.configureTestingModule({ + declarations: [DsoEditMetadataFieldValuesComponent, VarDirective], + imports: [TranslateModule.forRoot(), RouterTestingModule.withRoutes([])], + providers: [ + ], + schemas: [NO_ERRORS_SCHEMA] + }).compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(DsoEditMetadataFieldValuesComponent); + component = fixture.componentInstance; + component.dso = dso; + component.form = form; + component.mdField = mdField; + component.saving$ = of(false); + component.draggingMdField$ = draggingMdField$; + fixture.detectChanges(); + }); + + describe('when draggingMdField$ emits a value equal to mdField', () => { + beforeEach(() => { + draggingMdField$.next(mdField); + fixture.detectChanges(); + }); + + it('should not disable the list', () => { + expect(fixture.debugElement.query(By.css('.ds-drop-list.disabled'))).toBeNull(); + }); + }); + + describe('when draggingMdField$ emits a value different to mdField', () => { + beforeEach(() => { + draggingMdField$.next(`${mdField}.fake`); + fixture.detectChanges(); + }); + + it('should disable the list', () => { + expect(fixture.debugElement.query(By.css('.ds-drop-list.disabled'))).toBeTruthy(); + }); + }); + + describe('when draggingMdField$ emits null', () => { + beforeEach(() => { + draggingMdField$.next(null); + fixture.detectChanges(); + }); + + it('should not disable the list', () => { + expect(fixture.debugElement.query(By.css('.ds-drop-list.disabled'))).toBeNull(); + }); + }); + + describe('dropping a value on a different index', () => { + beforeEach(() => { + component.drop(Object.assign({ + previousIndex: 0, + currentIndex: 2, + })); + }); + + it('should physically move the relevant metadata value within the form', () => { + expect(form.fields[mdField][0].newValue.value).toEqual('Subject Two'); + expect(form.fields[mdField][1].newValue.value).toEqual('Subject Three'); + expect(form.fields[mdField][2].newValue.value).toEqual('Subject One'); + }); + + it('should update the metadata values their new place to match the new physical order', () => { + expect(form.fields[mdField][0].newValue.place).toEqual(0); + expect(form.fields[mdField][1].newValue.place).toEqual(1); + expect(form.fields[mdField][2].newValue.place).toEqual(2); + }); + + it('should maintain the metadata values their original place in their original value so it can be used later to determine the patch operations', () => { + expect(form.fields[mdField][0].originalValue.place).toEqual(1); + expect(form.fields[mdField][1].originalValue.place).toEqual(2); + expect(form.fields[mdField][2].originalValue.place).toEqual(0); + }); + }); +}); diff --git a/src/app/dso-shared/dso-edit-metadata/dso-edit-metadata-headers/dso-edit-metadata-headers.component.spec.ts b/src/app/dso-shared/dso-edit-metadata/dso-edit-metadata-headers/dso-edit-metadata-headers.component.spec.ts new file mode 100644 index 0000000000..a0a1da1f1e --- /dev/null +++ b/src/app/dso-shared/dso-edit-metadata/dso-edit-metadata-headers/dso-edit-metadata-headers.component.spec.ts @@ -0,0 +1,32 @@ +import { DsoEditMetadataHeadersComponent } from './dso-edit-metadata-headers.component'; +import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; +import { VarDirective } from '../../../shared/utils/var.directive'; +import { TranslateModule } from '@ngx-translate/core'; +import { RouterTestingModule } from '@angular/router/testing'; +import { NO_ERRORS_SCHEMA } from '@angular/core'; +import { By } from '@angular/platform-browser'; + +describe('DsoEditMetadataHeadersComponent', () => { + let component: DsoEditMetadataHeadersComponent; + let fixture: ComponentFixture; + + beforeEach(waitForAsync(() => { + TestBed.configureTestingModule({ + declarations: [DsoEditMetadataHeadersComponent, VarDirective], + imports: [TranslateModule.forRoot(), RouterTestingModule.withRoutes([])], + providers: [ + ], + schemas: [NO_ERRORS_SCHEMA] + }).compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(DsoEditMetadataHeadersComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should display three headers', () => { + expect(fixture.debugElement.queryAll(By.css('.ds-flex-cell')).length).toEqual(3); + }); +}); diff --git a/src/app/dso-shared/dso-edit-metadata/dso-edit-metadata-value/dso-edit-metadata-value.component.html b/src/app/dso-shared/dso-edit-metadata/dso-edit-metadata-value/dso-edit-metadata-value.component.html index 4e5890ae7d..ce08eed473 100644 --- a/src/app/dso-shared/dso-edit-metadata/dso-edit-metadata-value/dso-edit-metadata-value.component.html +++ b/src/app/dso-shared/dso-edit-metadata/dso-edit-metadata-value/dso-edit-metadata-value.component.html @@ -18,24 +18,24 @@
- - - -
- diff --git a/src/app/dso-shared/dso-edit-metadata/dso-edit-metadata-value/dso-edit-metadata-value.component.spec.ts b/src/app/dso-shared/dso-edit-metadata/dso-edit-metadata-value/dso-edit-metadata-value.component.spec.ts new file mode 100644 index 0000000000..08f041c4cd --- /dev/null +++ b/src/app/dso-shared/dso-edit-metadata/dso-edit-metadata-value/dso-edit-metadata-value.component.spec.ts @@ -0,0 +1,170 @@ +import { DsoEditMetadataValueComponent } from './dso-edit-metadata-value.component'; +import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; +import { VarDirective } from '../../../shared/utils/var.directive'; +import { TranslateModule } from '@ngx-translate/core'; +import { RouterTestingModule } from '@angular/router/testing'; +import { DebugElement, NO_ERRORS_SCHEMA } from '@angular/core'; +import { RelationshipService } from '../../../core/data/relationship.service'; +import { DSONameService } from '../../../core/breadcrumbs/dso-name.service'; +import { of } from 'rxjs/internal/observable/of'; +import { ItemMetadataRepresentation } from '../../../core/shared/metadata-representation/item/item-metadata-representation.model'; +import { MetadataValue, VIRTUAL_METADATA_PREFIX } from '../../../core/shared/metadata.models'; +import { DsoEditMetadataChangeType, DsoEditMetadataValue } from '../dso-edit-metadata-form'; +import { By } from '@angular/platform-browser'; + +const EDIT_BTN = 'edit'; +const CONFIRM_BTN = 'confirm'; +const REMOVE_BTN = 'remove'; +const UNDO_BTN = 'undo'; +const DRAG_BTN = 'drag'; + +describe('DsoEditMetadataValueComponent', () => { + let component: DsoEditMetadataValueComponent; + let fixture: ComponentFixture; + + let relationshipService: RelationshipService; + let dsoNameService: DSONameService; + + let editMetadataValue: DsoEditMetadataValue; + let metadataValue: MetadataValue; + + function initServices(): void { + relationshipService = jasmine.createSpyObj('relationshipService', { + resolveMetadataRepresentation: of(new ItemMetadataRepresentation(metadataValue)), + }); + dsoNameService = jasmine.createSpyObj('dsoNameService', { + getName: 'Related Name', + }); + } + + beforeEach(waitForAsync(() => { + metadataValue = Object.assign(new MetadataValue(), { + value: 'Regular Name', + language: 'en', + place: 0, + authority: undefined, + }); + editMetadataValue = new DsoEditMetadataValue(metadataValue); + + initServices(); + + TestBed.configureTestingModule({ + declarations: [DsoEditMetadataValueComponent, VarDirective], + imports: [TranslateModule.forRoot(), RouterTestingModule.withRoutes([])], + providers: [ + { provide: RelationshipService, useValue: relationshipService }, + { provide: DSONameService, useValue: dsoNameService }, + ], + schemas: [NO_ERRORS_SCHEMA] + }).compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(DsoEditMetadataValueComponent); + component = fixture.componentInstance; + component.mdValue = editMetadataValue; + component.saving$ = of(false); + fixture.detectChanges(); + }); + + it('should not show a badge', () => { + expect(fixture.debugElement.query(By.css('ds-type-badge'))).toBeNull(); + }); + + describe('when no changes have been made', () => { + assertButton(EDIT_BTN, true, false); + assertButton(CONFIRM_BTN, false); + assertButton(REMOVE_BTN, true, false); + assertButton(UNDO_BTN, true, true); + assertButton(DRAG_BTN, true, false); + }); + + describe('when this is the only metadata value within its field', () => { + beforeEach(() => { + component.isOnlyValue = true; + fixture.detectChanges(); + }); + + assertButton(DRAG_BTN, true, true); + }); + + describe('when the value is marked for removal', () => { + beforeEach(() => { + editMetadataValue.change = DsoEditMetadataChangeType.REMOVE; + fixture.detectChanges(); + }); + + assertButton(REMOVE_BTN, true, true); + assertButton(UNDO_BTN, true, false); + }); + + describe('when the value is being edited', () => { + beforeEach(() => { + editMetadataValue.editing = true; + fixture.detectChanges(); + }); + + assertButton(EDIT_BTN, false); + assertButton(CONFIRM_BTN, true, false); + assertButton(UNDO_BTN, true, false); + }); + + describe('when the value is new', () => { + beforeEach(() => { + editMetadataValue.change = DsoEditMetadataChangeType.ADD; + fixture.detectChanges(); + }); + + assertButton(REMOVE_BTN, true, false); + assertButton(UNDO_BTN, true, false); + }); + + describe('when the metadata value is virtual', () => { + beforeEach(() => { + metadataValue = Object.assign(new MetadataValue(), { + value: 'Virtual Name', + language: 'en', + place: 0, + authority: `${VIRTUAL_METADATA_PREFIX}authority-key`, + }); + editMetadataValue = new DsoEditMetadataValue(metadataValue); + component.mdValue = editMetadataValue; + component.ngOnInit(); + fixture.detectChanges(); + }); + + it('should show a badge', () => { + expect(fixture.debugElement.query(By.css('ds-type-badge'))).toBeTruthy(); + }); + + assertButton(EDIT_BTN, true, true); + assertButton(CONFIRM_BTN, false); + assertButton(REMOVE_BTN, true, true); + assertButton(UNDO_BTN, true, true); + assertButton(DRAG_BTN, true, false); + }); + + function assertButton(name: string, exists: boolean, disabled: boolean = false): void { + describe(`${name} button`, () => { + let btn: DebugElement; + + beforeEach(() => { + btn = fixture.debugElement.query(By.css(`#metadata-${name}-btn`)); + }); + + if (exists) { + it('should exist', () => { + expect(btn).toBeTruthy(); + }); + + it(`should${disabled ? ' ' : ' not '}be disabled`, () => { + expect(btn.nativeElement.disabled).toBe(disabled); + }); + } else { + it('should not exist', () => { + expect(btn).toBeNull(); + }); + } + }); + } +}); diff --git a/src/app/dso-shared/dso-edit-metadata/metadata-field-selector/metadata-field-selector.component.spec.ts b/src/app/dso-shared/dso-edit-metadata/metadata-field-selector/metadata-field-selector.component.spec.ts new file mode 100644 index 0000000000..ee4738a322 --- /dev/null +++ b/src/app/dso-shared/dso-edit-metadata/metadata-field-selector/metadata-field-selector.component.spec.ts @@ -0,0 +1,103 @@ +import { MetadataFieldSelectorComponent } from './metadata-field-selector.component'; +import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; +import { VarDirective } from '../../../shared/utils/var.directive'; +import { TranslateModule } from '@ngx-translate/core'; +import { RouterTestingModule } from '@angular/router/testing'; +import { NO_ERRORS_SCHEMA } from '@angular/core'; +import { RegistryService } from '../../../core/registry/registry.service'; +import { MetadataField } from '../../../core/metadata/metadata-field.model'; +import { MetadataSchema } from '../../../core/metadata/metadata-schema.model'; +import { createSuccessfulRemoteDataObject$ } from '../../../shared/remote-data.utils'; +import { createPaginatedList } from '../../../shared/testing/utils.test'; +import { followLink } from '../../../shared/utils/follow-link-config.model'; +import { By } from '@angular/platform-browser'; + +describe('MetadataFieldSelectorComponent', () => { + let component: MetadataFieldSelectorComponent; + let fixture: ComponentFixture; + + let registryService: RegistryService; + + let metadataSchema: MetadataSchema; + let metadataFields: MetadataField[]; + + beforeEach(waitForAsync(() => { + metadataSchema = Object.assign(new MetadataSchema(), { + id: 0, + prefix: 'dc', + namespace: 'http://dublincore.org/documents/dcmi-terms/', + }); + metadataFields = [ + Object.assign(new MetadataField(), { + id: 0, + element: 'description', + qualifier: undefined, + schema: createSuccessfulRemoteDataObject$(metadataSchema), + }), + Object.assign(new MetadataField(), { + id: 1, + element: 'description', + qualifier: 'abstract', + schema: createSuccessfulRemoteDataObject$(metadataSchema), + }), + ]; + + registryService = jasmine.createSpyObj('registryService', { + queryMetadataFields: createSuccessfulRemoteDataObject$(createPaginatedList(metadataFields)), + }); + + TestBed.configureTestingModule({ + declarations: [MetadataFieldSelectorComponent, VarDirective], + imports: [TranslateModule.forRoot(), RouterTestingModule.withRoutes([])], + providers: [ + { provide: RegistryService, useValue: registryService }, + ], + schemas: [NO_ERRORS_SCHEMA] + }).compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(MetadataFieldSelectorComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + describe('when a query is entered', () => { + const query = 'test query'; + + beforeEach(() => { + component.showInvalid = true; + component.query$.next(query); + }); + + it('should reset showInvalid', () => { + expect(component.showInvalid).toBeFalse(); + }); + + it('should query the registry service for metadata fields and include the schema', () => { + expect(registryService.queryMetadataFields).toHaveBeenCalledWith(query, null, true, false, followLink('schema')); + }); + }); + + describe('validate', () => { + it('should return an observable true and show no feedback if the current mdField exists in registry', (done) => { + component.mdField = 'dc.description.abstract'; + component.validate().subscribe((result) => { + expect(result).toBeTrue(); + fixture.detectChanges(); + expect(fixture.debugElement.query(By.css('.invalid-feedback'))).toBeNull(); + done(); + }); + }); + + it('should return an observable false and show invalid feedback if the current mdField is missing in registry', (done) => { + component.mdField = 'dc.fake.field'; + component.validate().subscribe((result) => { + expect(result).toBeFalse(); + fixture.detectChanges(); + expect(fixture.debugElement.query(By.css('.invalid-feedback'))).toBeTruthy(); + done(); + }); + }); + }); +}); diff --git a/src/app/dso-shared/dso-edit-metadata/metadata-field-selector/metadata-field-selector.component.ts b/src/app/dso-shared/dso-edit-metadata/metadata-field-selector/metadata-field-selector.component.ts index f3f6f15914..2bbe64b3df 100644 --- a/src/app/dso-shared/dso-edit-metadata/metadata-field-selector/metadata-field-selector.component.ts +++ b/src/app/dso-shared/dso-edit-metadata/metadata-field-selector/metadata-field-selector.component.ts @@ -157,7 +157,7 @@ export class MetadataFieldSelectorComponent implements OnInit, OnDestroy, AfterV } /** - * Select a metadata field from the dropdown optipons + * Select a metadata field from the dropdown options * @param mdFieldOption */ select(mdFieldOption: string): void {