feat(ivy): support host properties in DebugElement.properties (#28355)

DebugElement.properties should contain a map of element
property names to element property values, with entries
for both normal property bindings and host bindings.
Many Angular core tests depend on this map being present.

This commit adds support for host property bindings in
DebugElement.properties, which fixes the Angular core tests.
There is still work to be done for normal property bindings.

PR Close #28355
This commit is contained in:
Kara Erickson
2019-01-22 15:02:52 -08:00
committed by Jason Aden
parent c522e03fe9
commit 46aec4a58f
7 changed files with 213 additions and 175 deletions

View File

@ -924,26 +924,24 @@ function declareTests(config?: {useJit: boolean}) {
expect(getDOM().getProperty(tc.nativeElement, 'id')).toEqual('newId');
});
fixmeIvy('FW-681: not possible to retrieve host property bindings from TView')
.it('should not use template variables for expressions in hostProperties', () => {
@Directive(
{selector: '[host-properties]', host: {'[id]': 'id', '[title]': 'unknownProp'}})
class DirectiveWithHostProps {
id = 'one';
}
it('should not use template variables for expressions in hostProperties', () => {
@Directive({selector: '[host-properties]', host: {'[id]': 'id', '[title]': 'unknownProp'}})
class DirectiveWithHostProps {
id = 'one';
}
const fixture =
TestBed.configureTestingModule({declarations: [MyComp, DirectiveWithHostProps]})
.overrideComponent(MyComp, {
set: {template: `<div *ngFor="let id of ['forId']" host-properties></div>`}
})
.createComponent(MyComp);
fixture.detectChanges();
const fixture =
TestBed.configureTestingModule({declarations: [MyComp, DirectiveWithHostProps]})
.overrideComponent(
MyComp,
{set: {template: `<div *ngFor="let id of ['forId']" host-properties></div>`}})
.createComponent(MyComp);
fixture.detectChanges();
const tc = fixture.debugElement.children[0];
expect(tc.properties['id']).toBe('one');
expect(tc.properties['title']).toBe(undefined);
});
const tc = fixture.debugElement.children[0];
expect(tc.properties['id']).toBe('one');
expect(tc.properties['title']).toBe(undefined);
});
fixmeIvy('FW-725: Pipes in host bindings fail with a cryptic error')
.it('should not allow pipes in hostProperties', () => {

View File

@ -423,163 +423,155 @@ function declareTests(config?: {useJit: boolean}) {
});
describe('directives and pipes', () => {
fixmeIvy('FW-681: not possible to retrieve host property bindings from TView')
.describe('declarations', () => {
it('should be supported in root modules', () => {
@NgModule({
declarations: [CompUsingModuleDirectiveAndPipe, SomeDirective, SomePipe],
entryComponents: [CompUsingModuleDirectiveAndPipe]
})
class SomeModule {
}
describe('declarations', () => {
it('should be supported in root modules', () => {
@NgModule({
declarations: [CompUsingModuleDirectiveAndPipe, SomeDirective, SomePipe],
entryComponents: [CompUsingModuleDirectiveAndPipe]
})
class SomeModule {
}
const compFixture = createComp(CompUsingModuleDirectiveAndPipe, SomeModule);
const compFixture = createComp(CompUsingModuleDirectiveAndPipe, SomeModule);
compFixture.detectChanges();
expect(compFixture.debugElement.children[0].properties['title'])
.toBe('transformed someValue');
});
compFixture.detectChanges();
expect(compFixture.debugElement.children[0].properties['title'])
.toBe('transformed someValue');
});
it('should be supported in imported modules', () => {
@NgModule({
declarations: [CompUsingModuleDirectiveAndPipe, SomeDirective, SomePipe],
entryComponents: [CompUsingModuleDirectiveAndPipe]
})
class SomeImportedModule {
}
it('should be supported in imported modules', () => {
@NgModule({
declarations: [CompUsingModuleDirectiveAndPipe, SomeDirective, SomePipe],
entryComponents: [CompUsingModuleDirectiveAndPipe]
})
class SomeImportedModule {
}
@NgModule({imports: [SomeImportedModule]})
class SomeModule {
}
@NgModule({imports: [SomeImportedModule]})
class SomeModule {
}
const compFixture = createComp(CompUsingModuleDirectiveAndPipe, SomeModule);
compFixture.detectChanges();
expect(compFixture.debugElement.children[0].properties['title'])
.toBe('transformed someValue');
});
const compFixture = createComp(CompUsingModuleDirectiveAndPipe, SomeModule);
compFixture.detectChanges();
expect(compFixture.debugElement.children[0].properties['title'])
.toBe('transformed someValue');
});
it('should be supported in nested components', () => {
@Component({
selector: 'parent',
template: '<comp></comp>',
})
class ParentCompUsingModuleDirectiveAndPipe {
}
it('should be supported in nested components', () => {
@Component({
selector: 'parent',
template: '<comp></comp>',
})
class ParentCompUsingModuleDirectiveAndPipe {
}
@NgModule({
declarations: [
ParentCompUsingModuleDirectiveAndPipe, CompUsingModuleDirectiveAndPipe,
SomeDirective, SomePipe
],
entryComponents: [ParentCompUsingModuleDirectiveAndPipe]
})
class SomeModule {
}
@NgModule({
declarations: [
ParentCompUsingModuleDirectiveAndPipe, CompUsingModuleDirectiveAndPipe, SomeDirective,
SomePipe
],
entryComponents: [ParentCompUsingModuleDirectiveAndPipe]
})
class SomeModule {
}
const compFixture = createComp(ParentCompUsingModuleDirectiveAndPipe, SomeModule);
compFixture.detectChanges();
expect(compFixture.debugElement.children[0].children[0].properties['title'])
.toBe('transformed someValue');
});
});
const compFixture = createComp(ParentCompUsingModuleDirectiveAndPipe, SomeModule);
compFixture.detectChanges();
expect(compFixture.debugElement.children[0].children[0].properties['title'])
.toBe('transformed someValue');
});
});
describe('import/export', () => {
fixmeIvy('FW-681: not possible to retrieve host property bindings from TView')
.it('should support exported directives and pipes', () => {
@NgModule(
{declarations: [SomeDirective, SomePipe], exports: [SomeDirective, SomePipe]})
class SomeImportedModule {
}
it('should support exported directives and pipes', () => {
@NgModule({declarations: [SomeDirective, SomePipe], exports: [SomeDirective, SomePipe]})
class SomeImportedModule {
}
@NgModule({
declarations: [CompUsingModuleDirectiveAndPipe],
imports: [SomeImportedModule],
entryComponents: [CompUsingModuleDirectiveAndPipe]
})
class SomeModule {
}
@NgModule({
declarations: [CompUsingModuleDirectiveAndPipe],
imports: [SomeImportedModule],
entryComponents: [CompUsingModuleDirectiveAndPipe]
})
class SomeModule {
}
const compFixture = createComp(CompUsingModuleDirectiveAndPipe, SomeModule);
compFixture.detectChanges();
expect(compFixture.debugElement.children[0].properties['title'])
.toBe('transformed someValue');
});
const compFixture = createComp(CompUsingModuleDirectiveAndPipe, SomeModule);
compFixture.detectChanges();
expect(compFixture.debugElement.children[0].properties['title'])
.toBe('transformed someValue');
});
fixmeIvy('FW-681: not possible to retrieve host property bindings from TView')
.it('should support exported directives and pipes if the module is wrapped into an `ModuleWithProviders`',
() => {
@NgModule(
{declarations: [SomeDirective, SomePipe], exports: [SomeDirective, SomePipe]})
class SomeImportedModule {
}
it('should support exported directives and pipes if the module is wrapped into an `ModuleWithProviders`',
() => {
@NgModule(
{declarations: [SomeDirective, SomePipe], exports: [SomeDirective, SomePipe]})
class SomeImportedModule {
}
@NgModule({
declarations: [CompUsingModuleDirectiveAndPipe],
imports: [{ngModule: SomeImportedModule}],
entryComponents: [CompUsingModuleDirectiveAndPipe]
})
class SomeModule {
}
@NgModule({
declarations: [CompUsingModuleDirectiveAndPipe],
imports: [{ngModule: SomeImportedModule}],
entryComponents: [CompUsingModuleDirectiveAndPipe]
})
class SomeModule {
}
const compFixture = createComp(CompUsingModuleDirectiveAndPipe, SomeModule);
compFixture.detectChanges();
expect(compFixture.debugElement.children[0].properties['title'])
.toBe('transformed someValue');
});
const compFixture = createComp(CompUsingModuleDirectiveAndPipe, SomeModule);
compFixture.detectChanges();
expect(compFixture.debugElement.children[0].properties['title'])
.toBe('transformed someValue');
});
fixmeIvy('FW-681: not possible to retrieve host property bindings from TView')
.it('should support reexported modules', () => {
@NgModule(
{declarations: [SomeDirective, SomePipe], exports: [SomeDirective, SomePipe]})
class SomeReexportedModule {
}
it('should support reexported modules', () => {
@NgModule({declarations: [SomeDirective, SomePipe], exports: [SomeDirective, SomePipe]})
class SomeReexportedModule {
}
@NgModule({exports: [SomeReexportedModule]})
class SomeImportedModule {
}
@NgModule({exports: [SomeReexportedModule]})
class SomeImportedModule {
}
@NgModule({
declarations: [CompUsingModuleDirectiveAndPipe],
imports: [SomeImportedModule],
entryComponents: [CompUsingModuleDirectiveAndPipe]
})
class SomeModule {
}
@NgModule({
declarations: [CompUsingModuleDirectiveAndPipe],
imports: [SomeImportedModule],
entryComponents: [CompUsingModuleDirectiveAndPipe]
})
class SomeModule {
}
const compFixture = createComp(CompUsingModuleDirectiveAndPipe, SomeModule);
compFixture.detectChanges();
expect(compFixture.debugElement.children[0].properties['title'])
.toBe('transformed someValue');
});
const compFixture = createComp(CompUsingModuleDirectiveAndPipe, SomeModule);
compFixture.detectChanges();
expect(compFixture.debugElement.children[0].properties['title'])
.toBe('transformed someValue');
});
fixmeIvy('FW-681: not possible to retrieve host property bindings from TView')
.it('should support exporting individual directives of an imported module', () => {
@NgModule(
{declarations: [SomeDirective, SomePipe], exports: [SomeDirective, SomePipe]})
class SomeReexportedModule {
}
it('should support exporting individual directives of an imported module', () => {
@NgModule({declarations: [SomeDirective, SomePipe], exports: [SomeDirective, SomePipe]})
class SomeReexportedModule {
}
@NgModule({imports: [SomeReexportedModule], exports: [SomeDirective, SomePipe]})
class SomeImportedModule {
}
@NgModule({imports: [SomeReexportedModule], exports: [SomeDirective, SomePipe]})
class SomeImportedModule {
}
@NgModule({
declarations: [CompUsingModuleDirectiveAndPipe],
imports: [SomeImportedModule],
entryComponents: [CompUsingModuleDirectiveAndPipe]
})
class SomeModule {
}
@NgModule({
declarations: [CompUsingModuleDirectiveAndPipe],
imports: [SomeImportedModule],
entryComponents: [CompUsingModuleDirectiveAndPipe]
})
class SomeModule {
}
const compFixture = createComp(CompUsingModuleDirectiveAndPipe, SomeModule);
compFixture.detectChanges();
expect(compFixture.debugElement.children[0].properties['title'])
.toBe('transformed someValue');
});
const compFixture = createComp(CompUsingModuleDirectiveAndPipe, SomeModule);
compFixture.detectChanges();
expect(compFixture.debugElement.children[0].properties['title'])
.toBe('transformed someValue');
});
it('should not use non exported pipes of an imported module', () => {
@NgModule({