diff --git a/projects/dsp-ui/src/lib/viewer/values/link-value/link-value.component.html b/projects/dsp-ui/src/lib/viewer/values/link-value/link-value.component.html index 5e811ca5e..2511ef23c 100644 --- a/projects/dsp-ui/src/lib/viewer/values/link-value/link-value.component.html +++ b/projects/dsp-ui/src/lib/viewer/values/link-value/link-value.component.html @@ -16,7 +16,7 @@ New value must be different than the current value. - + New value must be a valid resource type. diff --git a/projects/dsp-ui/src/lib/viewer/values/link-value/link-value.component.spec.ts b/projects/dsp-ui/src/lib/viewer/values/link-value/link-value.component.spec.ts index 6800c940c..d518ee46f 100644 --- a/projects/dsp-ui/src/lib/viewer/values/link-value/link-value.component.spec.ts +++ b/projects/dsp-ui/src/lib/viewer/values/link-value/link-value.component.spec.ts @@ -22,564 +22,622 @@ import { LinkValueComponent } from './link-value.component'; * Test host component to simulate parent component. */ @Component({ - template: ` + template: ` ` }) class TestHostDisplayValueComponent implements OnInit { - @ViewChild('inputVal') inputValueComponent: LinkValueComponent; + @ViewChild('inputVal') inputValueComponent: LinkValueComponent; - displayInputVal: ReadLinkValue; - parentResource: ReadResource; - propIri: string; - mode: 'read' | 'update' | 'create' | 'search'; - linkValueClicked: ReadLinkValue; - linkValueHovered: ReadLinkValue; + displayInputVal: ReadLinkValue; + parentResource: ReadResource; + propIri: string; + mode: 'read' | 'update' | 'create' | 'search'; + linkValueClicked: ReadLinkValue; + linkValueHovered: ReadLinkValue; - ngOnInit() { + ngOnInit() { - MockResource.getTestThing().subscribe(res => { - const inputVal: ReadLinkValue = - res.getValuesAs('http://0.0.0.0:3333/ontology/0001/anything/v2#hasOtherThingValue', ReadLinkValue)[0]; + MockResource.getTestThing().subscribe(res => { + const inputVal: ReadLinkValue = + res.getValuesAs('http://0.0.0.0:3333/ontology/0001/anything/v2#hasOtherThingValue', ReadLinkValue)[0]; - this.displayInputVal = inputVal; - this.propIri = this.displayInputVal.property; - this.parentResource = res; - this.mode = 'read'; - }); + this.displayInputVal = inputVal; + this.propIri = this.displayInputVal.property; + this.parentResource = res; + this.mode = 'read'; + }); - } + } - refResClicked(readLinkValue: ReadLinkValue) { - this.linkValueClicked = readLinkValue; - } + refResClicked(readLinkValue: ReadLinkValue) { + this.linkValueClicked = readLinkValue; + } - refResHovered(readLinkValue: ReadLinkValue) { - this.linkValueHovered = readLinkValue; - } + refResHovered(readLinkValue: ReadLinkValue) { + this.linkValueHovered = readLinkValue; + } } /** * Test host component to simulate parent component. */ @Component({ - template: ` + template: ` ` }) class TestHostCreateValueComponent implements OnInit { - @ViewChild('inputVal') inputValueComponent: LinkValueComponent; - parentResource: ReadResource; - propIri: string; - mode: 'read' | 'update' | 'create' | 'search'; + @ViewChild('inputVal') inputValueComponent: LinkValueComponent; + parentResource: ReadResource; + propIri: string; + mode: 'read' | 'update' | 'create' | 'search'; - ngOnInit() { + ngOnInit() { - MockResource.getTestThing().subscribe(res => { - this.propIri = 'http://0.0.0.0:3333/ontology/0001/anything/v2#hasOtherThingValue'; - this.parentResource = res; - this.mode = 'create'; - }); - } + MockResource.getTestThing().subscribe(res => { + this.propIri = 'http://0.0.0.0:3333/ontology/0001/anything/v2#hasOtherThingValue'; + this.parentResource = res; + this.mode = 'create'; + }); + } +} + +/** + * Test host component to simulate parent component. + */ +@Component({ + template: ` + ` +}) +class TestHostCreateValueNoValueRequiredComponent implements OnInit { + + @ViewChild('inputVal') inputValueComponent: LinkValueComponent; + parentResource: ReadResource; + propIri: string; + mode: 'read' | 'update' | 'create' | 'search'; + + ngOnInit() { + MockResource.getTestThing().subscribe(res => { + this.propIri = 'http://0.0.0.0:3333/ontology/0001/anything/v2#hasOtherThingValue'; + this.parentResource = res; + this.mode = 'create'; + }); + } } describe('LinkValueComponent', () => { - beforeEach(async(() => { - const valuesSpyObj = { - v2: { - search: jasmine.createSpyObj('search', ['doSearchByLabel']), - } - }; - TestBed.configureTestingModule({ - declarations: [ - LinkValueComponent, - TestHostDisplayValueComponent, - TestHostCreateValueComponent - ], - imports: [ - ReactiveFormsModule, - MatInputModule, - MatAutocompleteModule, - BrowserAnimationsModule - ], - providers: [ - { - provide: DspApiConnectionToken, - useValue: valuesSpyObj - } - ] - }) - .compileComponents(); - })); - - describe('display and edit a link value', () => { - let testHostComponent: TestHostDisplayValueComponent; - let testHostFixture: ComponentFixture; - let valueComponentDe: DebugElement; - let valueInputDebugElement: DebugElement; - let valueInputNativeElement; - let valueReadModeDebugElement: DebugElement; - let valueReadModeNativeElement; - let commentInputDebugElement: DebugElement; - let commentInputNativeElement; - - beforeEach(() => { - testHostFixture = TestBed.createComponent(TestHostDisplayValueComponent); - testHostComponent = testHostFixture.componentInstance; - testHostFixture.detectChanges(); - - expect(testHostComponent).toBeTruthy(); - expect(testHostComponent.inputValueComponent).toBeTruthy(); - - const hostCompDe = testHostFixture.debugElement; - - valueComponentDe = hostCompDe.query(By.directive(LinkValueComponent)); - valueReadModeDebugElement = valueComponentDe.query(By.css('.rm-value')); - valueReadModeNativeElement = valueReadModeDebugElement.nativeElement; + beforeEach(async(() => { + const valuesSpyObj = { + v2: { + search: jasmine.createSpyObj('search', ['doSearchByLabel']), + } + }; + TestBed.configureTestingModule({ + declarations: [ + LinkValueComponent, + TestHostDisplayValueComponent, + TestHostCreateValueComponent, + TestHostCreateValueNoValueRequiredComponent + ], + imports: [ + ReactiveFormsModule, + MatInputModule, + MatAutocompleteModule, + BrowserAnimationsModule + ], + providers: [ + { + provide: DspApiConnectionToken, + useValue: valuesSpyObj + } + ] + }) + .compileComponents(); + })); - }); + describe('display and edit a link value', () => { + let testHostComponent: TestHostDisplayValueComponent; + let testHostFixture: ComponentFixture; + let valueComponentDe: DebugElement; + let valueInputDebugElement: DebugElement; + let valueInputNativeElement; + let valueReadModeDebugElement: DebugElement; + let valueReadModeNativeElement; + let commentInputDebugElement: DebugElement; + let commentInputNativeElement; - it('should display an existing value', fakeAsync(() => { + beforeEach(() => { + testHostFixture = TestBed.createComponent(TestHostDisplayValueComponent); + testHostComponent = testHostFixture.componentInstance; + testHostFixture.detectChanges(); - expect(testHostComponent.inputValueComponent.displayValue.linkedResourceIri).toEqual('http://rdfh.ch/0001/0C-0L1kORryKzJAJxxRyRQ'); - expect(testHostComponent.inputValueComponent.displayValue.linkedResource.label).toEqual('Sierra'); + expect(testHostComponent).toBeTruthy(); + expect(testHostComponent.inputValueComponent).toBeTruthy(); - expect(testHostComponent.inputValueComponent.form.valid).toBeTruthy(); + const hostCompDe = testHostFixture.debugElement; - expect(testHostComponent.inputValueComponent.mode).toEqual('read'); + valueComponentDe = hostCompDe.query(By.directive(LinkValueComponent)); + valueReadModeDebugElement = valueComponentDe.query(By.css('.rm-value')); + valueReadModeNativeElement = valueReadModeDebugElement.nativeElement; - expect(testHostComponent.inputValueComponent.valueFormControl.value instanceof ReadResource).toBe(true); - expect(testHostComponent.inputValueComponent.valueFormControl.value.label).toEqual('Sierra'); + }); - // setValue has to be called, otherwise the native input field does not get the label via the displayWith function - const res = testHostComponent.inputValueComponent.valueFormControl.value; - testHostComponent.inputValueComponent.valueFormControl.setValue(res); + it('should display an existing value', fakeAsync(() => { - // https://github.com/angular/components/blob/29e74eb9431ba01d951ee33df554f465609b59fa/src/material/autocomplete/autocomplete.spec.ts#L2577-L2580 - testHostFixture.detectChanges(); - tick(); - testHostFixture.detectChanges(); + expect(testHostComponent.inputValueComponent.displayValue.linkedResourceIri).toEqual('http://rdfh.ch/0001/0C-0L1kORryKzJAJxxRyRQ'); + expect(testHostComponent.inputValueComponent.displayValue.linkedResource.label).toEqual('Sierra'); - expect(valueReadModeNativeElement.innerText).toEqual('Sierra'); + expect(testHostComponent.inputValueComponent.form.valid).toBeTruthy(); - const anchorDebugElement = valueReadModeDebugElement.query(By.css('a')); - expect(anchorDebugElement.nativeElement).toBeDefined(); + expect(testHostComponent.inputValueComponent.mode).toEqual('read'); - })); + expect(testHostComponent.inputValueComponent.valueFormControl.value instanceof ReadResource).toBe(true); + expect(testHostComponent.inputValueComponent.valueFormControl.value.label).toEqual('Sierra'); - it('should make a link value editable', fakeAsync(() => { + // setValue has to be called, otherwise the native input field does not get the label via the displayWith function + const res = testHostComponent.inputValueComponent.valueFormControl.value; + testHostComponent.inputValueComponent.valueFormControl.setValue(res); - testHostComponent.mode = 'update'; - testHostFixture.detectChanges(); - valueInputDebugElement = valueComponentDe.query(By.css('input.value')); - valueInputNativeElement = valueInputDebugElement.nativeElement; + // https://github.com/angular/components/blob/29e74eb9431ba01d951ee33df554f465609b59fa/src/material/autocomplete/autocomplete.spec.ts#L2577-L2580 + testHostFixture.detectChanges(); + tick(); + testHostFixture.detectChanges(); - expect(testHostComponent.inputValueComponent.mode).toEqual('update'); - expect(testHostComponent.inputValueComponent.form.valid).toBeFalsy(); + expect(valueReadModeNativeElement.innerText).toEqual('Sierra'); - const update = new ReadResource(); - update.id = 'newId'; - update.label = 'new target'; + const anchorDebugElement = valueReadModeDebugElement.query(By.css('a')); + expect(anchorDebugElement.nativeElement).toBeDefined(); - testHostComponent.inputValueComponent.valueFormControl.setValue(update); + })); - // https://github.com/angular/components/blob/29e74eb9431ba01d951ee33df554f465609b59fa/src/material/autocomplete/autocomplete.spec.ts#L2577-L2580 - testHostFixture.detectChanges(); - tick(); - testHostFixture.detectChanges(); + it('should make a link value editable', fakeAsync(() => { - expect(valueInputNativeElement.value).toEqual('new target'); + testHostComponent.mode = 'update'; + testHostFixture.detectChanges(); + valueInputDebugElement = valueComponentDe.query(By.css('input.value')); + valueInputNativeElement = valueInputDebugElement.nativeElement; - expect(testHostComponent.inputValueComponent.form.valid).toBeTruthy(); + expect(testHostComponent.inputValueComponent.mode).toEqual('update'); + expect(testHostComponent.inputValueComponent.form.valid).toBeFalsy(); - const updatedValue = testHostComponent.inputValueComponent.getUpdatedValue(); + const update = new ReadResource(); + update.id = 'newId'; + update.label = 'new target'; - expect(updatedValue instanceof UpdateLinkValue).toBeTruthy(); + testHostComponent.inputValueComponent.valueFormControl.setValue(update); - expect((updatedValue as UpdateLinkValue).linkedResourceIri).toEqual('newId'); + // https://github.com/angular/components/blob/29e74eb9431ba01d951ee33df554f465609b59fa/src/material/autocomplete/autocomplete.spec.ts#L2577-L2580 + testHostFixture.detectChanges(); + tick(); + testHostFixture.detectChanges(); - })); + expect(valueInputNativeElement.value).toEqual('new target'); - it('should compare the existing version of a link to the user input', () => { + expect(testHostComponent.inputValueComponent.form.valid).toBeTruthy(); - // Sierra, http://rdfh.ch/0001/0C-0L1kORryKzJAJxxRyRQ - const initValue: ReadResource = testHostComponent.inputValueComponent.getInitValue(); + const updatedValue = testHostComponent.inputValueComponent.getUpdatedValue(); - const readRes1 = new ReadResource(); - readRes1.id = 'http://rdfh.ch/0001/0C-0L1kORryKzJAJxxRyRQ'; - readRes1.label = 'Sierra'; + expect(updatedValue instanceof UpdateLinkValue).toBeTruthy(); - expect( - testHostComponent.inputValueComponent.standardValueComparisonFunc( - initValue, readRes1 - ) - ).toBeTruthy(); + expect((updatedValue as UpdateLinkValue).linkedResourceIri).toEqual('newId'); - const readRes2 = new ReadResource(); - readRes2.id = 'newId'; - readRes2.label = 'new target'; + })); - expect( - testHostComponent.inputValueComponent.standardValueComparisonFunc( - initValue, readRes2 - ) - ).toBeFalsy(); + it('should compare the existing version of a link to the user input', () => { - expect( - testHostComponent.inputValueComponent.standardValueComparisonFunc( - initValue, null - ) - ).toBeFalsy(); + // Sierra, http://rdfh.ch/0001/0C-0L1kORryKzJAJxxRyRQ + const initValue: ReadResource = testHostComponent.inputValueComponent.getInitValue(); - expect( - testHostComponent.inputValueComponent.standardValueComparisonFunc( - initValue, 'searchlabel' - ) - ).toBeFalsy(); + const readRes1 = new ReadResource(); + readRes1.id = 'http://rdfh.ch/0001/0C-0L1kORryKzJAJxxRyRQ'; + readRes1.label = 'Sierra'; - }); + expect( + testHostComponent.inputValueComponent.standardValueComparisonFunc( + initValue, readRes1 + ) + ).toBeTruthy(); - it('should search for resources by their label', () => { + const readRes2 = new ReadResource(); + readRes2.id = 'newId'; + readRes2.label = 'new target'; - const valuesSpy = TestBed.inject(DspApiConnectionToken); - (valuesSpy.v2.search as jasmine.SpyObj).doSearchByLabel.and.callFake( - () => { - const res = new ReadResource(); - res.id = 'http://rdfh.ch/0001/IwMDbs0KQsaxSRUTl2cAIQ'; - res.label = 'hidden thing'; - return of(new ReadResourceSequence([res])); - } - ); + expect( + testHostComponent.inputValueComponent.standardValueComparisonFunc( + initValue, readRes2 + ) + ).toBeFalsy(); - // simulate user searching for label 'thing' - testHostComponent.inputValueComponent.valueFormControl.setValue('thing'); + expect( + testHostComponent.inputValueComponent.standardValueComparisonFunc( + initValue, null + ) + ).toBeFalsy(); - expect(valuesSpy.v2.search.doSearchByLabel).toHaveBeenCalledWith('thing', 0, { limitToResourceClass: 'http://0.0.0.0:3333/ontology/0001/anything/v2#Thing' }); - expect(testHostComponent.inputValueComponent.resources.length).toEqual(1); - expect(testHostComponent.inputValueComponent.resources[0].id).toEqual('http://rdfh.ch/0001/IwMDbs0KQsaxSRUTl2cAIQ'); - }); + expect( + testHostComponent.inputValueComponent.standardValueComparisonFunc( + initValue, 'searchlabel' + ) + ).toBeFalsy(); - it('should not return an invalid update value (string)', () => { + }); - const valuesSpy = TestBed.inject(DspApiConnectionToken); + it('should search for resources by their label', () => { - (valuesSpy.v2.search as jasmine.SpyObj).doSearchByLabel.and.callFake( - () => { - const res = new ReadResource(); - res.id = 'http://rdfh.ch/0001/IwMDbs0KQsaxSRUTl2cAIQ'; - res.label = 'hidden thing'; - return of(new ReadResourceSequence([res])); - } - ); + const valuesSpy = TestBed.inject(DspApiConnectionToken); + (valuesSpy.v2.search as jasmine.SpyObj).doSearchByLabel.and.callFake( + () => { + const res = new ReadResource(); + res.id = 'http://rdfh.ch/0001/IwMDbs0KQsaxSRUTl2cAIQ'; + res.label = 'hidden thing'; + return of(new ReadResourceSequence([res])); + } + ); - testHostComponent.mode = 'update'; - testHostFixture.detectChanges(); - valueInputDebugElement = valueComponentDe.query(By.css('input.value')); - valueInputNativeElement = valueInputDebugElement.nativeElement; + // simulate user searching for label 'thing' + testHostComponent.inputValueComponent.valueFormControl.setValue('thing'); - expect(testHostComponent.inputValueComponent.mode).toEqual('update'); - expect(testHostComponent.inputValueComponent.form.valid).toBeFalsy(); + expect(valuesSpy.v2.search.doSearchByLabel).toHaveBeenCalledWith('thing', 0, { limitToResourceClass: 'http://0.0.0.0:3333/ontology/0001/anything/v2#Thing' }); + expect(testHostComponent.inputValueComponent.resources.length).toEqual(1); + expect(testHostComponent.inputValueComponent.resources[0].id).toEqual('http://rdfh.ch/0001/IwMDbs0KQsaxSRUTl2cAIQ'); + }); - testHostComponent.inputValueComponent.valueFormControl.setValue('my string'); + it('should not return an invalid update value (string)', () => { - expect(testHostComponent.inputValueComponent.form.valid).toBeFalsy(); + const valuesSpy = TestBed.inject(DspApiConnectionToken); - const updatedValue = testHostComponent.inputValueComponent.getUpdatedValue(); + (valuesSpy.v2.search as jasmine.SpyObj).doSearchByLabel.and.callFake( + () => { + const res = new ReadResource(); + res.id = 'http://rdfh.ch/0001/IwMDbs0KQsaxSRUTl2cAIQ'; + res.label = 'hidden thing'; + return of(new ReadResourceSequence([res])); + } + ); - expect(updatedValue).toBeFalsy(); + testHostComponent.mode = 'update'; + testHostFixture.detectChanges(); + valueInputDebugElement = valueComponentDe.query(By.css('input.value')); + valueInputNativeElement = valueInputDebugElement.nativeElement; - }); + expect(testHostComponent.inputValueComponent.mode).toEqual('update'); + expect(testHostComponent.inputValueComponent.form.valid).toBeFalsy(); - it('should not return an invalid update value (no value)', () => { + testHostComponent.inputValueComponent.valueFormControl.setValue('my string'); - const valuesSpy = TestBed.inject(DspApiConnectionToken); + expect(testHostComponent.inputValueComponent.form.valid).toBeFalsy(); - (valuesSpy.v2.search as jasmine.SpyObj).doSearchByLabel.and.callFake( - () => { - const res = new ReadResource(); - res.id = 'http://rdfh.ch/0001/IwMDbs0KQsaxSRUTl2cAIQ'; - res.label = 'hidden thing'; - return of(new ReadResourceSequence([res])); - } - ); + const updatedValue = testHostComponent.inputValueComponent.getUpdatedValue(); - testHostComponent.mode = 'update'; - testHostFixture.detectChanges(); - valueInputDebugElement = valueComponentDe.query(By.css('input.value')); - valueInputNativeElement = valueInputDebugElement.nativeElement; + expect(updatedValue).toBeFalsy(); - expect(testHostComponent.inputValueComponent.mode).toEqual('update'); - expect(testHostComponent.inputValueComponent.form.valid).toBeFalsy(); + }); - testHostComponent.inputValueComponent.valueFormControl.setValue(null); + it('should not return an invalid update value (no value)', () => { - expect(testHostComponent.inputValueComponent.form.valid).toBeFalsy(); + const valuesSpy = TestBed.inject(DspApiConnectionToken); - const updatedValue = testHostComponent.inputValueComponent.getUpdatedValue(); + (valuesSpy.v2.search as jasmine.SpyObj).doSearchByLabel.and.callFake( + () => { + const res = new ReadResource(); + res.id = 'http://rdfh.ch/0001/IwMDbs0KQsaxSRUTl2cAIQ'; + res.label = 'hidden thing'; + return of(new ReadResourceSequence([res])); + } + ); - expect(updatedValue).toBeFalsy(); + testHostComponent.mode = 'update'; + testHostFixture.detectChanges(); + valueInputDebugElement = valueComponentDe.query(By.css('input.value')); + valueInputNativeElement = valueInputDebugElement.nativeElement; - }); + expect(testHostComponent.inputValueComponent.mode).toEqual('update'); + expect(testHostComponent.inputValueComponent.form.valid).toBeFalsy(); - it('should validate an existing value with an added comment', () => { + testHostComponent.inputValueComponent.valueFormControl.setValue(null); - testHostComponent.mode = 'update'; - testHostFixture.detectChanges(); - valueInputDebugElement = valueComponentDe.query(By.css('input.value')); - valueInputNativeElement = valueInputDebugElement.nativeElement; + expect(testHostComponent.inputValueComponent.form.valid).toBeFalsy(); - commentInputDebugElement = valueComponentDe.query(By.css('textarea.comment')); - commentInputNativeElement = commentInputDebugElement.nativeElement; + const updatedValue = testHostComponent.inputValueComponent.getUpdatedValue(); - expect(testHostComponent.inputValueComponent.mode).toEqual('update'); - expect(testHostComponent.inputValueComponent.form.valid).toBeFalsy(); + expect(updatedValue).toBeFalsy(); - commentInputNativeElement.value = 'this is a comment'; - commentInputNativeElement.dispatchEvent(new Event('input')); - testHostFixture.detectChanges(); + }); - expect(testHostComponent.inputValueComponent.form.valid).toBeTruthy(); - const updatedValue = testHostComponent.inputValueComponent.getUpdatedValue(); - expect(updatedValue instanceof UpdateLinkValue).toBeTruthy(); - expect((updatedValue as UpdateLinkValue).valueHasComment).toEqual('this is a comment'); + it('should validate an existing value with an added comment', () => { - }); + testHostComponent.mode = 'update'; + testHostFixture.detectChanges(); + valueInputDebugElement = valueComponentDe.query(By.css('input.value')); + valueInputNativeElement = valueInputDebugElement.nativeElement; - it('should restore the initially displayed value', fakeAsync(() => { + commentInputDebugElement = valueComponentDe.query(By.css('textarea.comment')); + commentInputNativeElement = commentInputDebugElement.nativeElement; - testHostComponent.mode = 'update'; + expect(testHostComponent.inputValueComponent.mode).toEqual('update'); + expect(testHostComponent.inputValueComponent.form.valid).toBeFalsy(); - testHostFixture.detectChanges(); + commentInputNativeElement.value = 'this is a comment'; + commentInputNativeElement.dispatchEvent(new Event('input')); + testHostFixture.detectChanges(); - valueInputDebugElement = valueComponentDe.query(By.css('input.value')); - valueInputNativeElement = valueInputDebugElement.nativeElement; + expect(testHostComponent.inputValueComponent.form.valid).toBeTruthy(); + const updatedValue = testHostComponent.inputValueComponent.getUpdatedValue(); + expect(updatedValue instanceof UpdateLinkValue).toBeTruthy(); + expect((updatedValue as UpdateLinkValue).valueHasComment).toEqual('this is a comment'); - expect(testHostComponent.inputValueComponent.mode).toEqual('update'); + }); - expect(testHostComponent.inputValueComponent.form.valid).toBeFalsy(); + it('should restore the initially displayed value', fakeAsync(() => { - // simulate user input - const update = new ReadResource(); - update.id = 'newId'; - update.label = 'new target'; + testHostComponent.mode = 'update'; - testHostComponent.inputValueComponent.valueFormControl.setValue(update); + testHostFixture.detectChanges(); - // https://github.com/angular/components/blob/29e74eb9431ba01d951ee33df554f465609b59fa/src/material/autocomplete/autocomplete.spec.ts#L2577-L2580 - testHostFixture.detectChanges(); - tick(); - testHostFixture.detectChanges(); + valueInputDebugElement = valueComponentDe.query(By.css('input.value')); + valueInputNativeElement = valueInputDebugElement.nativeElement; - expect(valueInputNativeElement.value).toEqual('new target'); + expect(testHostComponent.inputValueComponent.mode).toEqual('update'); - expect(testHostComponent.inputValueComponent.form.valid).toBeTruthy(); + expect(testHostComponent.inputValueComponent.form.valid).toBeFalsy(); - testHostComponent.inputValueComponent.resetFormControl(); + // simulate user input + const update = new ReadResource(); + update.id = 'newId'; + update.label = 'new target'; - testHostFixture.detectChanges(); - tick(); - testHostFixture.detectChanges(); + testHostComponent.inputValueComponent.valueFormControl.setValue(update); - expect(valueInputNativeElement.value).toEqual('Sierra'); + // https://github.com/angular/components/blob/29e74eb9431ba01d951ee33df554f465609b59fa/src/material/autocomplete/autocomplete.spec.ts#L2577-L2580 + testHostFixture.detectChanges(); + tick(); + testHostFixture.detectChanges(); - expect(testHostComponent.inputValueComponent.form.valid).toBeFalsy(); + expect(valueInputNativeElement.value).toEqual('new target'); - })); + expect(testHostComponent.inputValueComponent.form.valid).toBeTruthy(); - it('should set a new display value', fakeAsync(() => { + testHostComponent.inputValueComponent.resetFormControl(); - // setValue has to be called, otherwise the native input field does not get the label via the displayWith function - const res = testHostComponent.inputValueComponent.valueFormControl.value; - testHostComponent.inputValueComponent.valueFormControl.setValue(res); + testHostFixture.detectChanges(); + tick(); + testHostFixture.detectChanges(); - // https://github.com/angular/components/blob/29e74eb9431ba01d951ee33df554f465609b59fa/src/material/autocomplete/autocomplete.spec.ts#L2577-L2580 - testHostFixture.detectChanges(); - tick(); - testHostFixture.detectChanges(); + expect(valueInputNativeElement.value).toEqual('Sierra'); - expect(testHostComponent.inputValueComponent.valueFormControl.value.label).toEqual('Sierra'); + expect(testHostComponent.inputValueComponent.form.valid).toBeFalsy(); - const linkedRes = new ReadResource(); - linkedRes.id = 'newId'; - linkedRes.label = 'new target'; + })); - const newLink = new ReadLinkValue(); - newLink.id = 'updatedId'; - newLink.linkedResourceIri = 'newId'; - newLink.linkedResource = linkedRes; + it('should set a new display value', fakeAsync(() => { - testHostComponent.displayInputVal = newLink; + // setValue has to be called, otherwise the native input field does not get the label via the displayWith function + const res = testHostComponent.inputValueComponent.valueFormControl.value; + testHostComponent.inputValueComponent.valueFormControl.setValue(res); - testHostFixture.detectChanges(); - tick(); - testHostFixture.detectChanges(); + // https://github.com/angular/components/blob/29e74eb9431ba01d951ee33df554f465609b59fa/src/material/autocomplete/autocomplete.spec.ts#L2577-L2580 + testHostFixture.detectChanges(); + tick(); + testHostFixture.detectChanges(); - expect(valueReadModeNativeElement.innerText).toEqual('new target'); + expect(testHostComponent.inputValueComponent.valueFormControl.value.label).toEqual('Sierra'); - })); + const linkedRes = new ReadResource(); + linkedRes.id = 'newId'; + linkedRes.label = 'new target'; - it('should emit the displayValue when the value is clicked on', () => { + const newLink = new ReadLinkValue(); + newLink.id = 'updatedId'; + newLink.linkedResourceIri = 'newId'; + newLink.linkedResource = linkedRes; - expect(testHostComponent.linkValueClicked).toBeUndefined(); + testHostComponent.displayInputVal = newLink; - valueReadModeNativeElement.click(); + testHostFixture.detectChanges(); + tick(); + testHostFixture.detectChanges(); - expect(testHostComponent.linkValueClicked).toEqual(testHostComponent.displayInputVal); - }); + expect(valueReadModeNativeElement.innerText).toEqual('new target'); + + })); - it('should emit the displayValue when the value is hovered', () => { + it('should emit the displayValue when the value is clicked on', () => { - expect(testHostComponent.linkValueHovered).toBeUndefined(); + expect(testHostComponent.linkValueClicked).toBeUndefined(); - valueReadModeNativeElement.dispatchEvent( - new MouseEvent('mouseover', { - view: window, - bubbles: true, - cancelable: true - }) - ); + valueReadModeNativeElement.click(); + + expect(testHostComponent.linkValueClicked).toEqual(testHostComponent.displayInputVal); + }); + + it('should emit the displayValue when the value is hovered', () => { + + expect(testHostComponent.linkValueHovered).toBeUndefined(); + + valueReadModeNativeElement.dispatchEvent( + new MouseEvent('mouseover', { + view: window, + bubbles: true, + cancelable: true + }) + ); + + expect(testHostComponent.linkValueHovered).toEqual(testHostComponent.displayInputVal); + }); - expect(testHostComponent.linkValueHovered).toEqual(testHostComponent.displayInputVal); }); - }); + describe('create a new link value', () => { + let testHostComponent: TestHostCreateValueComponent; + let testHostFixture: ComponentFixture; - describe('create a new link value', () => { - let testHostComponent: TestHostCreateValueComponent; - let testHostFixture: ComponentFixture; + let valueComponentDe: DebugElement; - let valueComponentDe: DebugElement; + let valueInputDebugElement: DebugElement; + let valueInputNativeElement; + let commentInputDebugElement: DebugElement; + let commentInputNativeElement; - let valueInputDebugElement: DebugElement; - let valueInputNativeElement; - let commentInputDebugElement: DebugElement; - let commentInputNativeElement; + beforeEach(() => { - beforeEach(() => { + testHostFixture = TestBed.createComponent(TestHostCreateValueComponent); + testHostComponent = testHostFixture.componentInstance; + testHostFixture.detectChanges(); - testHostFixture = TestBed.createComponent(TestHostCreateValueComponent); - testHostComponent = testHostFixture.componentInstance; - testHostFixture.detectChanges(); + expect(testHostComponent).toBeTruthy(); + expect(testHostComponent.inputValueComponent).toBeTruthy(); - expect(testHostComponent).toBeTruthy(); - expect(testHostComponent.inputValueComponent).toBeTruthy(); + const hostCompDe = testHostFixture.debugElement; - const hostCompDe = testHostFixture.debugElement; + valueComponentDe = hostCompDe.query(By.directive(LinkValueComponent)); - valueComponentDe = hostCompDe.query(By.directive(LinkValueComponent)); + valueInputDebugElement = valueComponentDe.query(By.css('input.value')); + valueInputNativeElement = valueInputDebugElement.nativeElement; - valueInputDebugElement = valueComponentDe.query(By.css('input.value')); - valueInputNativeElement = valueInputDebugElement.nativeElement; + commentInputDebugElement = valueComponentDe.query(By.css('textarea.comment')); + commentInputNativeElement = commentInputDebugElement.nativeElement; + }); - commentInputDebugElement = valueComponentDe.query(By.css('textarea.comment')); - commentInputNativeElement = commentInputDebugElement.nativeElement; - }); + it('should search a new value', () => { + const valuesSpy = TestBed.inject(DspApiConnectionToken); - it('should search a new value', () => { - const valuesSpy = TestBed.inject(DspApiConnectionToken); + (valuesSpy.v2.search as jasmine.SpyObj).doSearchByLabel.and.callFake( + () => { + const res = new ReadResource(); + res.id = 'http://rdfh.ch/0001/IwMDbs0KQsaxSRUTl2cAIQ'; + res.label = 'hidden thing'; + return of(new ReadResourceSequence([res])); + } + ); - (valuesSpy.v2.search as jasmine.SpyObj).doSearchByLabel.and.callFake( - () => { - const res = new ReadResource(); - res.id = 'http://rdfh.ch/0001/IwMDbs0KQsaxSRUTl2cAIQ'; - res.label = 'hidden thing'; - return of(new ReadResourceSequence([res])); - } - ); + testHostComponent.inputValueComponent.searchByLabel('thing'); + testHostFixture.detectChanges(); - testHostComponent.inputValueComponent.searchByLabel('thing'); - testHostFixture.detectChanges(); + expect(testHostComponent.inputValueComponent.mode).toEqual('create'); + expect(valuesSpy.v2.search.doSearchByLabel).toHaveBeenCalledWith('thing', 0, { limitToResourceClass: 'http://0.0.0.0:3333/ontology/0001/anything/v2#Thing' }); + expect(testHostComponent.inputValueComponent.resources.length).toEqual(1); + }); - expect(testHostComponent.inputValueComponent.mode).toEqual('create'); - expect(valuesSpy.v2.search.doSearchByLabel).toHaveBeenCalledWith('thing', 0, { limitToResourceClass: 'http://0.0.0.0:3333/ontology/0001/anything/v2#Thing' }); - expect(testHostComponent.inputValueComponent.resources.length).toEqual(1); - }); + it('should create a value', () => { - it('should create a value', () => { + // simulate user input + const res = new ReadResource(); + res.id = 'http://rdfh.ch/0001/IwMDbs0KQsaxSRUTl2cAIQ'; + res.label = 'hidden thing'; - // simulate user input - const res = new ReadResource(); - res.id = 'http://rdfh.ch/0001/IwMDbs0KQsaxSRUTl2cAIQ'; - res.label = 'hidden thing'; + expect(testHostComponent.inputValueComponent.form.valid).toBeFalsy(); - expect(testHostComponent.inputValueComponent.form.valid).toBeFalsy(); + testHostComponent.inputValueComponent.valueFormControl.setValue(res); - testHostComponent.inputValueComponent.valueFormControl.setValue(res); + expect(testHostComponent.inputValueComponent.form.valid).toBeTruthy(); - expect(testHostComponent.inputValueComponent.form.valid).toBeTruthy(); + expect(testHostComponent.inputValueComponent.valueFormControl.value instanceof ReadResource).toBeTruthy(); - expect(testHostComponent.inputValueComponent.valueFormControl.value instanceof ReadResource).toBeTruthy(); + const newValue = testHostComponent.inputValueComponent.getNewValue(); + expect(newValue instanceof CreateLinkValue).toBeTruthy(); + expect((newValue as CreateLinkValue).linkedResourceIri).toEqual('http://rdfh.ch/0001/IwMDbs0KQsaxSRUTl2cAIQ'); + }); - const newValue = testHostComponent.inputValueComponent.getNewValue(); - expect(newValue instanceof CreateLinkValue).toBeTruthy(); - expect((newValue as CreateLinkValue).linkedResourceIri).toEqual('http://rdfh.ch/0001/IwMDbs0KQsaxSRUTl2cAIQ'); - }); + it('should only create a new value if input is a resource', () => { + // simulate user input + const valuesSpy = TestBed.inject(DspApiConnectionToken); - it('should only create a new value if input is a resource', () => { - // simulate user input - const valuesSpy = TestBed.inject(DspApiConnectionToken); + (valuesSpy.v2.search as jasmine.SpyObj).doSearchByLabel.and.callFake( + () => { + const res = new ReadResource(); + res.id = 'http://rdfh.ch/0001/IwMDbs0KQsaxSRUTl2cAIQ'; + res.label = 'hidden thing'; + return of(new ReadResourceSequence([res])); + } + ); + expect(testHostComponent.inputValueComponent.form.valid).toBeFalsy(); - (valuesSpy.v2.search as jasmine.SpyObj).doSearchByLabel.and.callFake( - () => { - const res = new ReadResource(); - res.id = 'http://rdfh.ch/0001/IwMDbs0KQsaxSRUTl2cAIQ'; - res.label = 'hidden thing'; - return of(new ReadResourceSequence([res])); - } - ); - expect(testHostComponent.inputValueComponent.form.valid).toBeFalsy(); + const label = 'thing'; + testHostComponent.inputValueComponent.valueFormControl.setValue(label); - const label = 'thing'; - testHostComponent.inputValueComponent.valueFormControl.setValue(label); + expect(testHostComponent.inputValueComponent.valueFormControl.value instanceof ReadResource).toBeFalsy(); + expect(testHostComponent.inputValueComponent.form.valid).toBeFalsy(); - expect(testHostComponent.inputValueComponent.valueFormControl.value instanceof ReadResource).toBeFalsy(); - expect(testHostComponent.inputValueComponent.form.valid).toBeFalsy(); + const newValue = testHostComponent.inputValueComponent.getNewValue(); - const newValue = testHostComponent.inputValueComponent.getNewValue(); + expect(newValue instanceof CreateLinkValue).toBeFalsy(); + }); - expect(newValue instanceof CreateLinkValue).toBeFalsy(); - }); + it('should reset form after cancellation', fakeAsync(() => { - it('should reset form after cancellation', fakeAsync(() => { + // simulate user input + const res = new ReadResource(); + res.id = 'http://rdfh.ch/0001/IwMDbs0KQsaxSRUTl2cAIQ'; + res.label = 'hidden thing'; + testHostComponent.inputValueComponent.valueFormControl.setValue(res); - // simulate user input - const res = new ReadResource(); - res.id = 'http://rdfh.ch/0001/IwMDbs0KQsaxSRUTl2cAIQ'; - res.label = 'hidden thing'; - testHostComponent.inputValueComponent.valueFormControl.setValue(res); + // https://github.com/angular/components/blob/29e74eb9431ba01d951ee33df554f465609b59fa/src/material/autocomplete/autocomplete.spec.ts#L2577-L2580 + testHostFixture.detectChanges(); + tick(); + testHostFixture.detectChanges(); - // https://github.com/angular/components/blob/29e74eb9431ba01d951ee33df554f465609b59fa/src/material/autocomplete/autocomplete.spec.ts#L2577-L2580 - testHostFixture.detectChanges(); - tick(); - testHostFixture.detectChanges(); + expect(valueInputNativeElement.value).toEqual('hidden thing'); - expect(valueInputNativeElement.value).toEqual('hidden thing'); + commentInputNativeElement.value = 'created comment'; - commentInputNativeElement.value = 'created comment'; + commentInputNativeElement.dispatchEvent(new Event('input')); - commentInputNativeElement.dispatchEvent(new Event('input')); + testHostFixture.detectChanges(); - testHostFixture.detectChanges(); + expect(testHostComponent.inputValueComponent.mode).toEqual('create'); - expect(testHostComponent.inputValueComponent.mode).toEqual('create'); + expect(testHostComponent.inputValueComponent.form.valid).toBeTruthy(); - expect(testHostComponent.inputValueComponent.form.valid).toBeTruthy(); + testHostComponent.inputValueComponent.resetFormControl(); - testHostComponent.inputValueComponent.resetFormControl(); + testHostFixture.detectChanges(); + tick(); + testHostFixture.detectChanges(); - testHostFixture.detectChanges(); - tick(); - testHostFixture.detectChanges(); + expect(testHostComponent.inputValueComponent.form.valid).toBeFalsy(); - expect(testHostComponent.inputValueComponent.form.valid).toBeFalsy(); + expect(testHostComponent.inputValueComponent.valueFormControl.value).toEqual(null); - expect(testHostComponent.inputValueComponent.valueFormControl.value).toEqual(null); + expect(valueInputNativeElement.value).toEqual(''); + expect(commentInputNativeElement.value).toEqual(''); - expect(valueInputNativeElement.value).toEqual(''); - expect(commentInputNativeElement.value).toEqual(''); + })); + }); - })); - }); + describe('create a new link value no value required', () => { + let testHostComponent: TestHostCreateValueNoValueRequiredComponent; + let testHostFixture: ComponentFixture; + + beforeEach(() => { + + testHostFixture = TestBed.createComponent(TestHostCreateValueNoValueRequiredComponent); + testHostComponent = testHostFixture.componentInstance; + testHostFixture.detectChanges(); + + expect(testHostComponent).toBeTruthy(); + }); + + it('should create a value', () => { + + // simulate user input + const res = new ReadResource(); + res.id = 'http://rdfh.ch/0001/IwMDbs0KQsaxSRUTl2cAIQ'; + res.label = 'hidden thing'; + + expect(testHostComponent.inputValueComponent.form.valid).toBeTruthy(); + + testHostComponent.inputValueComponent.valueFormControl.setValue(res); + + expect(testHostComponent.inputValueComponent.form.valid).toBeTruthy(); + + expect(testHostComponent.inputValueComponent.valueFormControl.value instanceof ReadResource).toBeTruthy(); + + const newValue = testHostComponent.inputValueComponent.getNewValue(); + expect(newValue instanceof CreateLinkValue).toBeTruthy(); + expect((newValue as CreateLinkValue).linkedResourceIri).toEqual('http://rdfh.ch/0001/IwMDbs0KQsaxSRUTl2cAIQ'); + }); + }); }); diff --git a/projects/dsp-ui/src/lib/viewer/values/link-value/link-value.component.ts b/projects/dsp-ui/src/lib/viewer/values/link-value/link-value.component.ts index c68cf1f55..c722f72f7 100644 --- a/projects/dsp-ui/src/lib/viewer/values/link-value/link-value.component.ts +++ b/projects/dsp-ui/src/lib/viewer/values/link-value/link-value.component.ts @@ -23,7 +23,7 @@ import { DspApiConnectionToken } from '../../../core/core.module'; import { BaseValueComponent } from '../base-value.component'; export function resourceValidator(control: AbstractControl) { - const invalid = !(control.value instanceof ReadResource); + const invalid = !(control.value === null || control.value === '' || control.value instanceof ReadResource); return invalid ? { invalidType: { value: control.value } } : null; }