test(upgrade): test injector tree traversal for downgraded components (#27217)

This commit adds tests that verify the current behavior wrt injector
tree traversal for downgraded components, so that it is easier to
contrast with changed behavior is future commits (should we decide
to actually change it).

PR Close #27217
This commit is contained in:
George Kalpakas 2018-11-20 22:08:34 +02:00 committed by Matias Niemelä
parent bc0ee01d09
commit 077a5fb04b
1 changed files with 210 additions and 0 deletions

View File

@ -331,6 +331,216 @@ withEachNg1Version(() => {
expect(multiTrim(element.children[1].textContent)).toBe('Counter:1');
}));
fixmeIvy('FW-714: ng1 projected content is not being rendered')
.it('should correctly traverse the injector tree of downgraded components', async(() => {
@Component({
selector: 'ng2A',
template: 'ng2A(<ng-content></ng-content>)',
providers: [
{provide: 'FOO', useValue: 'CompA-foo'},
{provide: 'BAR', useValue: 'CompA-bar'},
],
})
class Ng2ComponentA {
}
@Component({
selector: 'ng2B',
template: `
FOO:{{ foo }}
BAR:{{ bar }}
BAZ:{{ baz }}
QUX:{{ qux }}
`,
providers: [
{provide: 'FOO', useValue: 'CompB-foo'},
],
})
class Ng2ComponentB {
constructor(
@Inject('FOO') public foo: string, @Inject('BAR') public bar: string,
@Inject('BAZ') public baz: string, @Inject('QUX') public qux: string) {}
}
@NgModule({
declarations: [Ng2ComponentA, Ng2ComponentB],
entryComponents: [Ng2ComponentA, Ng2ComponentB],
imports: [BrowserModule],
providers: [
{provide: 'FOO', useValue: 'Mod-foo'},
{provide: 'BAR', useValue: 'Mod-bar'},
{provide: 'BAZ', useValue: 'Mod-baz'},
],
})
class Ng2Module {
ngDoBootstrap() {}
}
const bootstrapFn = (extraProviders: StaticProvider[]) => {
const platformRef = getPlatform() || platformBrowserDynamic([
...extraProviders,
{provide: 'FOO', useValue: 'Plat-foo'},
{provide: 'BAR', useValue: 'Plat-bar'},
{provide: 'BAZ', useValue: 'Plat-baz'},
{provide: 'QUX', useValue: 'Plat-qux'},
]);
return platformRef.bootstrapModule(Ng2Module);
};
const downMod = downgradeModule(bootstrapFn);
const ng1Module =
angular.module('ng1', [downMod])
.directive(
'ng2A', downgradeComponent({component: Ng2ComponentA, propagateDigest}))
.directive(
'ng2B',
downgradeComponent({component: Ng2ComponentB, propagateDigest}));
const element = html(`
<ng2-a><ng2-b ng-if="showB1"></ng2-b></ng2-a>
<ng2-b ng-if="showB2"></ng2-b>
`);
const $injector = angular.bootstrap(element, [ng1Module.name]);
const $rootScope = $injector.get($ROOT_SCOPE) as angular.IRootScopeService;
// Wait for the module to be bootstrapped.
setTimeout(() => {
expect(multiTrim(element.textContent)).toBe('ng2A()');
// Nested component B.
$rootScope.$apply('showB1 = true');
expect(multiTrim(element.children[0].textContent))
.toBe('ng2A( FOO:CompB-foo BAR:CompA-bar BAZ:Mod-baz QUX:Plat-qux )');
// Standalone component B.
$rootScope.$apply('showB2 = true');
expect(multiTrim(element.children[1].textContent))
.toBe('FOO:CompB-foo BAR:Mod-bar BAZ:Mod-baz QUX:Plat-qux');
});
}));
fixmeIvy('FW-714: ng1 projected content is not being rendered')
.it('should correctly traverse the injector tree of downgraded components (from different modules)',
async(() => {
@Component({
selector: 'ng2A',
template: 'ng2A(<ng-content></ng-content>)',
providers: [
{provide: 'FOO', useValue: 'CompA-foo'},
{provide: 'BAR', useValue: 'CompA-bar'},
],
})
class Ng2ComponentA {
}
@Component({
selector: 'ng2B',
template: `
FOO:{{ foo }}
BAR:{{ bar }}
BAZ:{{ baz }}
QUX:{{ qux }}
QUUX:{{ quux }}
`,
providers: [
{provide: 'FOO', useValue: 'CompB-foo'},
],
})
class Ng2ComponentB {
constructor(
@Inject('FOO') public foo: string, @Inject('BAR') public bar: string,
@Inject('BAZ') public baz: string, @Inject('QUX') public qux: string,
@Inject('QUUX') public quux: string) {}
}
@NgModule({
declarations: [Ng2ComponentA],
entryComponents: [Ng2ComponentA],
imports: [BrowserModule],
providers: [
{provide: 'FOO', useValue: 'ModA-foo'},
{provide: 'BAR', useValue: 'ModA-bar'},
{provide: 'BAZ', useValue: 'ModA-baz'},
{provide: 'QUX', useValue: 'ModA-qux'},
],
})
class Ng2ModuleA {
ngDoBootstrap() {}
}
@NgModule({
declarations: [Ng2ComponentB],
entryComponents: [Ng2ComponentB],
imports: [BrowserModule],
providers: [
{provide: 'FOO', useValue: 'ModB-foo'},
{provide: 'BAR', useValue: 'ModB-bar'},
{provide: 'BAZ', useValue: 'ModB-baz'},
],
})
class Ng2ModuleB {
ngDoBootstrap() {}
}
const doDowngradeModule = (module: Type<any>) => {
const bootstrapFn = (extraProviders: StaticProvider[]) => {
const platformRef = getPlatform() || platformBrowserDynamic([
...extraProviders,
{provide: 'FOO', useValue: 'Plat-foo'},
{provide: 'BAR', useValue: 'Plat-bar'},
{provide: 'BAZ', useValue: 'Plat-baz'},
{provide: 'QUX', useValue: 'Plat-qux'},
{provide: 'QUUX', useValue: 'Plat-quux'},
]);
return platformRef.bootstrapModule(module);
};
return downgradeModule(bootstrapFn);
};
const downModA = doDowngradeModule(Ng2ModuleA);
const downModB = doDowngradeModule(Ng2ModuleB);
const ng1Module = angular.module('ng1', [downModA, downModB])
.directive('ng2A', downgradeComponent({
component: Ng2ComponentA,
downgradedModule: downModA, propagateDigest,
}))
.directive('ng2B', downgradeComponent({
component: Ng2ComponentB,
downgradedModule: downModB, propagateDigest,
}));
const element = html(`
<ng2-a><ng2-b ng-if="showB1"></ng2-b></ng2-a>
<ng2-b ng-if="showB2"></ng2-b>
`);
const $injector = angular.bootstrap(element, [ng1Module.name]);
const $rootScope = $injector.get($ROOT_SCOPE) as angular.IRootScopeService;
// Wait for module A to be bootstrapped.
setTimeout(() => {
expect(multiTrim(element.textContent)).toBe('ng2A()');
// Nested component B.
$rootScope.$apply('showB1 = true');
// Wait for module B to be bootstrapped.
setTimeout(() => {
// It is debatable, whether the order of traversal should be:
// CompB > CompA > ModB > ModA > Plat (similar to how lazy-loaded components
// work)
expect(multiTrim(element.children[0].textContent))
.toBe(
'ng2A( FOO:CompB-foo BAR:CompA-bar BAZ:ModB-baz QUX:Plat-qux QUUX:Plat-quux )');
// Standalone component B.
$rootScope.$apply('showB2 = true');
expect(multiTrim(element.children[1].textContent))
.toBe(
'FOO:CompB-foo BAR:ModB-bar BAZ:ModB-baz QUX:Plat-qux QUUX:Plat-quux');
});
});
}));
it('should support downgrading a component and propagate inputs', async(() => {
@Component(
{selector: 'ng2A', template: 'a({{ value }}) | <ng2B [value]="value"></ng2B>'})