From abe4433202a6f559c7617f0ac1333272b6f425c3 Mon Sep 17 00:00:00 2001 From: Ben Lesh Date: Fri, 17 May 2019 12:45:15 -0700 Subject: [PATCH] test(ivy): add tests around directive attribute ghosting (#30544) This battery of tests is to ensure the instructions we are generating have the same behavior in Ivy has they did in ViewEngine. PR Close #30544 --- .../core/test/acceptance/directive_spec.ts | 243 ++++++++++++++++++ 1 file changed, 243 insertions(+) diff --git a/packages/core/test/acceptance/directive_spec.ts b/packages/core/test/acceptance/directive_spec.ts index 0fc8027586..4ff44eb326 100644 --- a/packages/core/test/acceptance/directive_spec.ts +++ b/packages/core/test/acceptance/directive_spec.ts @@ -253,4 +253,247 @@ describe('directives', () => { }); + describe('attribute shadowing behaviors', () => { + /** + * To match ViewEngine, we need to ensure the following behaviors + */ + + @Directive({ + selector: '[dir-with-title]', + }) + class DirWithTitle { + @Input() + title = ''; + } + + it('should set both the div attribute and the directive input for `title="value"`', () => { + @Component({template: `
`}) + class App { + } + + TestBed.configureTestingModule({ + declarations: [App, DirWithTitle], + }); + const fixture = TestBed.createComponent(App); + fixture.detectChanges(); + + const dirWithTitle = + fixture.debugElement.query(By.directive(DirWithTitle)).injector.get(DirWithTitle); + const div = fixture.nativeElement.querySelector('div'); + expect(dirWithTitle.title).toBe('a'); + expect(div.getAttribute('title')).toBe('a'); + }); + + it('should set the directive input only, shadowing the title property of the div, for `[title]="value"`', + () => { + @Component({template: `
`}) + class App { + value = 'a'; + } + + TestBed.configureTestingModule({ + declarations: [App, DirWithTitle], + }); + const fixture = TestBed.createComponent(App); + fixture.detectChanges(); + + const dirWithTitle = + fixture.debugElement.query(By.directive(DirWithTitle)).injector.get(DirWithTitle); + const div = fixture.nativeElement.querySelector('div'); + // We are checking the property here, not the attribute, because in the case of + // [key]="value" we are always setting the property of the instance, and actually setting + // the attribute is just a side-effect of the DOM implementation. + expect(dirWithTitle.title).toBe('a'); + expect(div.title).toBe(''); + }); + + it('should allow setting directive `title` input with `[title]="value"` and a "attr.title" attribute with `attr.title="test"`', + () => { + @Component({template: `
`}) + class App { + value = 'a'; + } + + TestBed.configureTestingModule({ + declarations: [App, DirWithTitle], + }); + const fixture = TestBed.createComponent(App); + fixture.detectChanges(); + + const dirWithTitle = + fixture.debugElement.query(By.directive(DirWithTitle)).injector.get(DirWithTitle); + const div = fixture.nativeElement.querySelector('div'); + expect(dirWithTitle.title).toBe('a'); + expect(div.getAttribute('attr.title')).toBe('test'); + expect(div.title).toBe(''); + }); + + it('should allow setting directive `title` input with `[title]="value1"` and attribute with `[attr.title]="value2"`', + () => { + @Component({template: `
`}) + class App { + value1 = 'a'; + value2 = 'b'; + } + + TestBed.configureTestingModule({ + declarations: [App, DirWithTitle], + }); + const fixture = TestBed.createComponent(App); + fixture.detectChanges(); + + const dirWithTitle = + fixture.debugElement.query(By.directive(DirWithTitle)).injector.get(DirWithTitle); + const div = fixture.nativeElement.querySelector('div'); + expect(dirWithTitle.title).toBe('a'); + expect(div.getAttribute('title')).toBe('b'); + }); + + it('should allow setting directive `title` input with `[title]="value1"` and attribute with `attr.title="{{value2}}"`', + () => { + @Component( + {template: `
`}) + class App { + value1 = 'a'; + value2 = 'b'; + } + + TestBed.configureTestingModule({ + declarations: [App, DirWithTitle], + }); + const fixture = TestBed.createComponent(App); + fixture.detectChanges(); + + const dirWithTitle = + fixture.debugElement.query(By.directive(DirWithTitle)).injector.get(DirWithTitle); + const div = fixture.nativeElement.querySelector('div'); + expect(dirWithTitle.title).toBe('a'); + expect(div.getAttribute('title')).toBe('b'); + }); + + it('should allow setting directive `title` input with `title="{{value}}"` and a "attr.title" attribute with `attr.title="test"`', + () => { + @Component({template: `
`}) + class App { + value = 'a'; + } + + TestBed.configureTestingModule({ + declarations: [App, DirWithTitle], + }); + const fixture = TestBed.createComponent(App); + fixture.detectChanges(); + + const dirWithTitle = + fixture.debugElement.query(By.directive(DirWithTitle)).injector.get(DirWithTitle); + const div = fixture.nativeElement.querySelector('div'); + expect(dirWithTitle.title).toBe('a'); + expect(div.getAttribute('attr.title')).toBe('test'); + expect(div.title).toBe(''); + }); + + it('should allow setting directive `title` input with `title="{{value1}}"` and attribute with `[attr.title]="value2"`', + () => { + @Component( + {template: `
`}) + class App { + value1 = 'a'; + value2 = 'b'; + } + + TestBed.configureTestingModule({ + declarations: [App, DirWithTitle], + }); + const fixture = TestBed.createComponent(App); + fixture.detectChanges(); + + const dirWithTitle = + fixture.debugElement.query(By.directive(DirWithTitle)).injector.get(DirWithTitle); + const div = fixture.nativeElement.querySelector('div'); + expect(dirWithTitle.title).toBe('a'); + expect(div.getAttribute('title')).toBe('b'); + }); + + it('should allow setting directive `title` input with `title="{{value1}}"` and attribute with `attr.title="{{value2}}"`', + () => { + @Component( + {template: `
`}) + class App { + value1 = 'a'; + value2 = 'b'; + } + + TestBed.configureTestingModule({ + declarations: [App, DirWithTitle], + }); + const fixture = TestBed.createComponent(App); + fixture.detectChanges(); + + const dirWithTitle = + fixture.debugElement.query(By.directive(DirWithTitle)).injector.get(DirWithTitle); + const div = fixture.nativeElement.querySelector('div'); + expect(dirWithTitle.title).toBe('a'); + expect(div.getAttribute('title')).toBe('b'); + }); + + it('should set the directive input only, shadowing the title property on the div, for `title="{{value}}"`', + () => { + @Component({template: `
`}) + class App { + value = 'a'; + } + + TestBed.configureTestingModule({ + declarations: [App, DirWithTitle], + }); + const fixture = TestBed.createComponent(App); + fixture.detectChanges(); + + const dirWithTitle = + fixture.debugElement.query(By.directive(DirWithTitle)).injector.get(DirWithTitle); + const div = fixture.nativeElement.querySelector('div'); + expect(dirWithTitle.title).toBe('a'); + expect(div.title).toBe(''); + }); + + it('should set the title attribute only, not directive input, for `attr.title="{{value}}"`', + () => { + @Component({template: `
`}) + class App { + value = 'a'; + } + + TestBed.configureTestingModule({ + declarations: [App, DirWithTitle], + }); + const fixture = TestBed.createComponent(App); + fixture.detectChanges(); + + const dirWithTitle = + fixture.debugElement.query(By.directive(DirWithTitle)).injector.get(DirWithTitle); + const div = fixture.nativeElement.querySelector('div'); + expect(dirWithTitle.title).toBe(''); + expect(div.getAttribute('title')).toBe('a'); + }); + + it('should set the title attribute only, not directive input, for `[attr.title]="value"`', + () => { + @Component({template: `
`}) + class App { + value = 'a'; + } + + TestBed.configureTestingModule({ + declarations: [App, DirWithTitle], + }); + const fixture = TestBed.createComponent(App); + fixture.detectChanges(); + + const dirWithTitle = + fixture.debugElement.query(By.directive(DirWithTitle)).injector.get(DirWithTitle); + const div = fixture.nativeElement.querySelector('div'); + expect(dirWithTitle.title).toBe(''); + expect(div.getAttribute('title')).toBe('a'); + }); + }); });