test(ivy): run common tests with ivy on ci (#27071)

PR Close #27071
This commit is contained in:
Pawel Kozlowski 2018-11-13 11:51:02 +01:00 committed by Andrew Kushnir
parent 9741f5b8cf
commit 7695dbd0bd
7 changed files with 378 additions and 391 deletions

View File

@ -15,15 +15,13 @@ ts_library(
"//packages/platform-browser", "//packages/platform-browser",
"//packages/platform-browser-dynamic", "//packages/platform-browser-dynamic",
"//packages/platform-browser/testing", "//packages/platform-browser/testing",
"//packages/private/testing",
], ],
) )
jasmine_node_test( jasmine_node_test(
name = "test", name = "test",
bootstrap = ["angular/tools/testing/init_node_spec.js"], bootstrap = ["angular/tools/testing/init_node_spec.js"],
tags = [
"fixme-ivy-aot",
],
deps = [ deps = [
":test_lib", ":test_lib",
"//tools/testing:node", "//tools/testing:node",
@ -32,9 +30,6 @@ jasmine_node_test(
ts_web_test_suite( ts_web_test_suite(
name = "test_web", name = "test_web",
tags = [
"fixme-ivy-aot",
],
deps = [ deps = [
":test_lib", ":test_lib",
], ],

View File

@ -7,20 +7,17 @@
*/ */
import {DeprecatedI18NPipesModule, Plural} from '@angular/common';
import {DEPRECATED_PLURAL_FN, getPluralCase} from '@angular/common/src/i18n/localization';
import {TestBed, inject} from '@angular/core/testing'; import {TestBed, inject} from '@angular/core/testing';
import {DeprecatedI18NPipesModule} from '../src/common_module';
import {Plural} from '../src/i18n/locale_data_api';
import {DEPRECATED_PLURAL_FN, getPluralCase} from '../src/i18n/localization';
{ describe('DeprecatedI18NPipesModule', () => {
describe('DeprecatedI18NPipesModule', () => { beforeEach(() => { TestBed.configureTestingModule({imports: [DeprecatedI18NPipesModule]}); });
beforeEach(() => { TestBed.configureTestingModule({imports: [DeprecatedI18NPipesModule]}); });
it('should define the token DEPRECATED_PLURAL_FN', it('should define the token DEPRECATED_PLURAL_FN',
inject( inject(
[DEPRECATED_PLURAL_FN], [DEPRECATED_PLURAL_FN],
(injectedGetPluralCase?: (locale: string, value: number | string) => Plural) => { (injectedGetPluralCase?: (locale: string, value: number | string) => Plural) => {
expect(injectedGetPluralCase).toEqual(getPluralCase); expect(injectedGetPluralCase).toEqual(getPluralCase);
})); }));
}); });
}

View File

@ -8,206 +8,211 @@
import {CommonModule} from '@angular/common'; import {CommonModule} from '@angular/common';
import {NgComponentOutlet} from '@angular/common/src/directives/ng_component_outlet'; import {NgComponentOutlet} from '@angular/common/src/directives/ng_component_outlet';
import {Compiler, Component, ComponentRef, Inject, InjectionToken, Injector, NO_ERRORS_SCHEMA, NgModule, NgModuleFactory, Optional, QueryList, StaticProvider, TemplateRef, Type, ViewChild, ViewChildren, ViewContainerRef} from '@angular/core'; import {Compiler, Component, ComponentRef, Inject, InjectionToken, Injector, NO_ERRORS_SCHEMA, NgModule, NgModuleFactory, Optional, QueryList, TemplateRef, Type, ViewChild, ViewChildren, ViewContainerRef} from '@angular/core';
import {TestBed, async, fakeAsync} from '@angular/core/testing'; import {TestBed, async} from '@angular/core/testing';
import {expect} from '@angular/platform-browser/testing/src/matchers'; import {expect} from '@angular/platform-browser/testing/src/matchers';
import {fixmeIvy} from '@angular/private/testing';
{ describe('insert/remove', () => {
describe('insert/remove', () => {
beforeEach(() => { TestBed.configureTestingModule({imports: [TestModule]}); }); beforeEach(() => { TestBed.configureTestingModule({imports: [TestModule]}); });
it('should do nothing if component is null', async(() => { it('should do nothing if component is null', async(() => {
const template = `<ng-template *ngComponentOutlet="currentComponent"></ng-template>`; const template = `<ng-template *ngComponentOutlet="currentComponent"></ng-template>`;
TestBed.overrideComponent(TestComponent, {set: {template: template}}); TestBed.overrideComponent(TestComponent, {set: {template: template}});
let fixture = TestBed.createComponent(TestComponent); let fixture = TestBed.createComponent(TestComponent);
fixture.componentInstance.currentComponent = null; fixture.componentInstance.currentComponent = null;
fixture.detectChanges(); fixture.detectChanges();
expect(fixture.nativeElement).toHaveText(''); expect(fixture.nativeElement).toHaveText('');
})); }));
it('should insert content specified by a component', async(() => { it('should insert content specified by a component', async(() => {
let fixture = TestBed.createComponent(TestComponent); let fixture = TestBed.createComponent(TestComponent);
fixture.detectChanges(); fixture.detectChanges();
expect(fixture.nativeElement).toHaveText(''); expect(fixture.nativeElement).toHaveText('');
fixture.componentInstance.currentComponent = InjectedComponent; fixture.componentInstance.currentComponent = InjectedComponent;
fixture.detectChanges(); fixture.detectChanges();
expect(fixture.nativeElement).toHaveText('foo'); expect(fixture.nativeElement).toHaveText('foo');
})); }));
it('should emit a ComponentRef once a component was created', async(() => { it('should emit a ComponentRef once a component was created', async(() => {
let fixture = TestBed.createComponent(TestComponent); let fixture = TestBed.createComponent(TestComponent);
fixture.detectChanges(); fixture.detectChanges();
expect(fixture.nativeElement).toHaveText(''); expect(fixture.nativeElement).toHaveText('');
fixture.componentInstance.cmpRef = null; fixture.componentInstance.cmpRef = null;
fixture.componentInstance.currentComponent = InjectedComponent; fixture.componentInstance.currentComponent = InjectedComponent;
fixture.detectChanges(); fixture.detectChanges();
expect(fixture.nativeElement).toHaveText('foo'); expect(fixture.nativeElement).toHaveText('foo');
expect(fixture.componentInstance.cmpRef).toBeAnInstanceOf(ComponentRef); expect(fixture.componentInstance.cmpRef).toBeAnInstanceOf(ComponentRef);
expect(fixture.componentInstance.cmpRef !.instance).toBeAnInstanceOf(InjectedComponent); expect(fixture.componentInstance.cmpRef !.instance).toBeAnInstanceOf(InjectedComponent);
})); }));
it('should clear view if component becomes null', async(() => { it('should clear view if component becomes null', async(() => {
let fixture = TestBed.createComponent(TestComponent); let fixture = TestBed.createComponent(TestComponent);
fixture.detectChanges(); fixture.detectChanges();
expect(fixture.nativeElement).toHaveText(''); expect(fixture.nativeElement).toHaveText('');
fixture.componentInstance.currentComponent = InjectedComponent; fixture.componentInstance.currentComponent = InjectedComponent;
fixture.detectChanges(); fixture.detectChanges();
expect(fixture.nativeElement).toHaveText('foo'); expect(fixture.nativeElement).toHaveText('foo');
fixture.componentInstance.currentComponent = null; fixture.componentInstance.currentComponent = null;
fixture.detectChanges(); fixture.detectChanges();
expect(fixture.nativeElement).toHaveText(''); expect(fixture.nativeElement).toHaveText('');
})); }));
it('should swap content if component changes', async(() => { it('should swap content if component changes', async(() => {
let fixture = TestBed.createComponent(TestComponent); let fixture = TestBed.createComponent(TestComponent);
fixture.detectChanges(); fixture.detectChanges();
expect(fixture.nativeElement).toHaveText(''); expect(fixture.nativeElement).toHaveText('');
fixture.componentInstance.currentComponent = InjectedComponent; fixture.componentInstance.currentComponent = InjectedComponent;
fixture.detectChanges(); fixture.detectChanges();
expect(fixture.nativeElement).toHaveText('foo'); expect(fixture.nativeElement).toHaveText('foo');
fixture.componentInstance.currentComponent = InjectedComponentAgain; fixture.componentInstance.currentComponent = InjectedComponentAgain;
fixture.detectChanges(); fixture.detectChanges();
expect(fixture.nativeElement).toHaveText('bar'); expect(fixture.nativeElement).toHaveText('bar');
})); }));
it('should use the injector, if one supplied', async(() => { fixmeIvy('ComponentFactoryResolver not resolved with supplied injector') &&
let fixture = TestBed.createComponent(TestComponent); it('should use the injector, if one supplied', async(() => {
let fixture = TestBed.createComponent(TestComponent);
const uniqueValue = {}; const uniqueValue = {};
fixture.componentInstance.currentComponent = InjectedComponent; fixture.componentInstance.currentComponent = InjectedComponent;
fixture.componentInstance.injector = Injector.create( fixture.componentInstance.injector = Injector.create(
[{provide: TEST_TOKEN, useValue: uniqueValue}], fixture.componentRef.injector); [{provide: TEST_TOKEN, useValue: uniqueValue}], fixture.componentRef.injector);
fixture.detectChanges(); fixture.detectChanges();
let cmpRef: ComponentRef<InjectedComponent> = fixture.componentInstance.cmpRef !; let cmpRef: ComponentRef<InjectedComponent> = fixture.componentInstance.cmpRef !;
expect(cmpRef).toBeAnInstanceOf(ComponentRef); expect(cmpRef).toBeAnInstanceOf(ComponentRef);
expect(cmpRef.instance).toBeAnInstanceOf(InjectedComponent); expect(cmpRef.instance).toBeAnInstanceOf(InjectedComponent);
expect(cmpRef.instance.testToken).toBe(uniqueValue); expect(cmpRef.instance.testToken).toBe(uniqueValue);
})); }));
it('should resolve a with injector', async(() => { it('should resolve a with injector', async(() => {
let fixture = TestBed.createComponent(TestComponent); let fixture = TestBed.createComponent(TestComponent);
fixture.componentInstance.cmpRef = null; fixture.componentInstance.cmpRef = null;
fixture.componentInstance.currentComponent = InjectedComponent; fixture.componentInstance.currentComponent = InjectedComponent;
fixture.detectChanges(); fixture.detectChanges();
let cmpRef: ComponentRef<InjectedComponent> = fixture.componentInstance.cmpRef !; let cmpRef: ComponentRef<InjectedComponent> = fixture.componentInstance.cmpRef !;
expect(cmpRef).toBeAnInstanceOf(ComponentRef); expect(cmpRef).toBeAnInstanceOf(ComponentRef);
expect(cmpRef.instance).toBeAnInstanceOf(InjectedComponent); expect(cmpRef.instance).toBeAnInstanceOf(InjectedComponent);
expect(cmpRef.instance.testToken).toBeNull(); expect(cmpRef.instance.testToken).toBeNull();
})); }));
it('should render projectable nodes, if supplied', async(() => { fixmeIvy('can not pass projectable nodes') &&
const template = `<ng-template>projected foo</ng-template>${TEST_CMP_TEMPLATE}`; it('should render projectable nodes, if supplied', async(() => {
TestBed.overrideComponent(TestComponent, {set: {template: template}}) const template = `<ng-template>projected foo</ng-template>${TEST_CMP_TEMPLATE}`;
.configureTestingModule({schemas: [NO_ERRORS_SCHEMA]}); TestBed.overrideComponent(TestComponent, {set: {template: template}})
.configureTestingModule({schemas: [NO_ERRORS_SCHEMA]});
TestBed TestBed
.overrideComponent(InjectedComponent, {set: {template: `<ng-content></ng-content>`}}) .overrideComponent(InjectedComponent, {set: {template: `<ng-content></ng-content>`}})
.configureTestingModule({schemas: [NO_ERRORS_SCHEMA]}); .configureTestingModule({schemas: [NO_ERRORS_SCHEMA]});
let fixture = TestBed.createComponent(TestComponent); let fixture = TestBed.createComponent(TestComponent);
fixture.detectChanges(); fixture.detectChanges();
expect(fixture.nativeElement).toHaveText(''); expect(fixture.nativeElement).toHaveText('');
fixture.componentInstance.currentComponent = InjectedComponent; fixture.componentInstance.currentComponent = InjectedComponent;
fixture.componentInstance.projectables = fixture.componentInstance.projectables =
[fixture.componentInstance.vcRef [fixture.componentInstance.vcRef
.createEmbeddedView(fixture.componentInstance.tplRefs.first) .createEmbeddedView(fixture.componentInstance.tplRefs.first)
.rootNodes]; .rootNodes];
fixture.detectChanges(); fixture.detectChanges();
expect(fixture.nativeElement).toHaveText('projected foo'); expect(fixture.nativeElement).toHaveText('projected foo');
})); }));
it('should resolve components from other modules, if supplied', async(() => { fixmeIvy('Runtime compiler is not loaded') &&
const compiler = TestBed.get(Compiler) as Compiler; it('should resolve components from other modules, if supplied', async(() => {
let fixture = TestBed.createComponent(TestComponent); const compiler = TestBed.get(Compiler) as Compiler;
let fixture = TestBed.createComponent(TestComponent);
fixture.detectChanges(); fixture.detectChanges();
expect(fixture.nativeElement).toHaveText(''); expect(fixture.nativeElement).toHaveText('');
fixture.componentInstance.module = compiler.compileModuleSync(TestModule2); fixture.componentInstance.module = compiler.compileModuleSync(TestModule2);
fixture.componentInstance.currentComponent = Module2InjectedComponent; fixture.componentInstance.currentComponent = Module2InjectedComponent;
fixture.detectChanges(); fixture.detectChanges();
expect(fixture.nativeElement).toHaveText('baz'); expect(fixture.nativeElement).toHaveText('baz');
})); }));
it('should clean up moduleRef, if supplied', async(() => { fixmeIvy('Runtime compiler is not loaded') &&
let destroyed = false; it('should clean up moduleRef, if supplied', async(() => {
const compiler = TestBed.get(Compiler) as Compiler; let destroyed = false;
const fixture = TestBed.createComponent(TestComponent); const compiler = TestBed.get(Compiler) as Compiler;
fixture.componentInstance.module = compiler.compileModuleSync(TestModule2); const fixture = TestBed.createComponent(TestComponent);
fixture.componentInstance.currentComponent = Module2InjectedComponent; fixture.componentInstance.module = compiler.compileModuleSync(TestModule2);
fixture.detectChanges(); fixture.componentInstance.currentComponent = Module2InjectedComponent;
fixture.detectChanges();
const moduleRef = fixture.componentInstance.ngComponentOutlet['_moduleRef'] !; const moduleRef = fixture.componentInstance.ngComponentOutlet['_moduleRef'] !;
spyOn(moduleRef, 'destroy').and.callThrough(); spyOn(moduleRef, 'destroy').and.callThrough();
expect(moduleRef.destroy).not.toHaveBeenCalled(); expect(moduleRef.destroy).not.toHaveBeenCalled();
fixture.destroy(); fixture.destroy();
expect(moduleRef.destroy).toHaveBeenCalled(); expect(moduleRef.destroy).toHaveBeenCalled();
})); }));
it('should not re-create moduleRef when it didn\'t actually change', async(() => { fixmeIvy('Runtime compiler is not loaded') &&
const compiler = TestBed.get(Compiler) as Compiler; it('should not re-create moduleRef when it didn\'t actually change', async(() => {
const fixture = TestBed.createComponent(TestComponent); const compiler = TestBed.get(Compiler) as Compiler;
const fixture = TestBed.createComponent(TestComponent);
fixture.componentInstance.module = compiler.compileModuleSync(TestModule2); fixture.componentInstance.module = compiler.compileModuleSync(TestModule2);
fixture.componentInstance.currentComponent = Module2InjectedComponent; fixture.componentInstance.currentComponent = Module2InjectedComponent;
fixture.detectChanges(); fixture.detectChanges();
expect(fixture.nativeElement).toHaveText('baz'); expect(fixture.nativeElement).toHaveText('baz');
const moduleRef = fixture.componentInstance.ngComponentOutlet['_moduleRef']; const moduleRef = fixture.componentInstance.ngComponentOutlet['_moduleRef'];
fixture.componentInstance.currentComponent = Module2InjectedComponent2; fixture.componentInstance.currentComponent = Module2InjectedComponent2;
fixture.detectChanges(); fixture.detectChanges();
expect(fixture.nativeElement).toHaveText('baz2'); expect(fixture.nativeElement).toHaveText('baz2');
expect(moduleRef).toBe(fixture.componentInstance.ngComponentOutlet['_moduleRef']); expect(moduleRef).toBe(fixture.componentInstance.ngComponentOutlet['_moduleRef']);
})); }));
it('should re-create moduleRef when changed', async(() => { fixmeIvy('Runtime compiler is not loaded') &&
const compiler = TestBed.get(Compiler) as Compiler; it('should re-create moduleRef when changed', async(() => {
const fixture = TestBed.createComponent(TestComponent); const compiler = TestBed.get(Compiler) as Compiler;
fixture.componentInstance.module = compiler.compileModuleSync(TestModule2); const fixture = TestBed.createComponent(TestComponent);
fixture.componentInstance.currentComponent = Module2InjectedComponent; fixture.componentInstance.module = compiler.compileModuleSync(TestModule2);
fixture.detectChanges(); fixture.componentInstance.currentComponent = Module2InjectedComponent;
fixture.detectChanges();
expect(fixture.nativeElement).toHaveText('baz'); expect(fixture.nativeElement).toHaveText('baz');
fixture.componentInstance.module = compiler.compileModuleSync(TestModule3); fixture.componentInstance.module = compiler.compileModuleSync(TestModule3);
fixture.componentInstance.currentComponent = Module3InjectedComponent; fixture.componentInstance.currentComponent = Module3InjectedComponent;
fixture.detectChanges(); fixture.detectChanges();
expect(fixture.nativeElement).toHaveText('bat'); expect(fixture.nativeElement).toHaveText('bat');
})); }));
}); });
}
const TEST_TOKEN = new InjectionToken('TestToken'); const TEST_TOKEN = new InjectionToken('TestToken');
@Component({selector: 'injected-component', template: 'foo'}) @Component({selector: 'injected-component', template: 'foo'})

View File

@ -10,205 +10,202 @@ import {CommonModule} from '@angular/common';
import {Component, ContentChildren, Directive, Injectable, NO_ERRORS_SCHEMA, OnDestroy, QueryList, TemplateRef} from '@angular/core'; import {Component, ContentChildren, Directive, Injectable, NO_ERRORS_SCHEMA, OnDestroy, QueryList, TemplateRef} from '@angular/core';
import {ComponentFixture, TestBed, async} from '@angular/core/testing'; import {ComponentFixture, TestBed, async} from '@angular/core/testing';
import {expect} from '@angular/platform-browser/testing/src/matchers'; import {expect} from '@angular/platform-browser/testing/src/matchers';
import {fixmeIvy} from '@angular/private/testing';
{ fixmeIvy('expr.visitExpression is not a function - fixed by #26968') && describe('NgTemplateOutlet', () => {
describe('NgTemplateOutlet', () => { let fixture: ComponentFixture<any>;
let fixture: ComponentFixture<any>;
function setTplRef(value: any): void { fixture.componentInstance.currentTplRef = value; } function setTplRef(value: any): void { fixture.componentInstance.currentTplRef = value; }
function detectChangesAndExpectText(text: string): void { function detectChangesAndExpectText(text: string): void {
fixture.detectChanges(); fixture.detectChanges();
expect(fixture.debugElement.nativeElement).toHaveText(text); expect(fixture.debugElement.nativeElement).toHaveText(text);
} }
afterEach(() => { fixture = null as any; }); afterEach(() => { fixture = null as any; });
beforeEach(() => { beforeEach(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
declarations: [TestComponent, CaptureTplRefs, DestroyableCmpt], declarations: [TestComponent, CaptureTplRefs, DestroyableCmpt],
imports: [CommonModule], imports: [CommonModule],
providers: [DestroyedSpyService] providers: [DestroyedSpyService]
});
});
// https://github.com/angular/angular/issues/14778
it('should accept the component as the context', async(() => {
const template = `<ng-container *ngTemplateOutlet="tpl; context: this"></ng-container>` +
`<ng-template #tpl>{{context.foo}}</ng-template>`;
fixture = createTestComponent(template);
detectChangesAndExpectText('bar');
}));
it('should do nothing if templateRef is `null`', async(() => {
const template = `<ng-container [ngTemplateOutlet]="null"></ng-container>`;
fixture = createTestComponent(template);
detectChangesAndExpectText('');
}));
it('should insert content specified by TemplateRef', async(() => {
const template = `<ng-template #tpl>foo</ng-template>` +
`<ng-container [ngTemplateOutlet]="tpl"></ng-container>`;
fixture = createTestComponent(template);
detectChangesAndExpectText('foo');
}));
it('should clear content if TemplateRef becomes `null`', async(() => {
const template = `<tpl-refs #refs="tplRefs"><ng-template>foo</ng-template></tpl-refs>` +
`<ng-container [ngTemplateOutlet]="currentTplRef"></ng-container>`;
fixture = createTestComponent(template);
fixture.detectChanges();
const refs = fixture.debugElement.children[0].references !['refs'];
setTplRef(refs.tplRefs.first);
detectChangesAndExpectText('foo');
setTplRef(null);
detectChangesAndExpectText('');
}));
it('should swap content if TemplateRef changes', async(() => {
const template =
`<tpl-refs #refs="tplRefs"><ng-template>foo</ng-template><ng-template>bar</ng-template></tpl-refs>` +
`<ng-container [ngTemplateOutlet]="currentTplRef"></ng-container>`;
fixture = createTestComponent(template);
fixture.detectChanges();
const refs = fixture.debugElement.children[0].references !['refs'];
setTplRef(refs.tplRefs.first);
detectChangesAndExpectText('foo');
setTplRef(refs.tplRefs.last);
detectChangesAndExpectText('bar');
}));
it('should display template if context is `null`', async(() => {
const template = `<ng-template #tpl>foo</ng-template>` +
`<ng-container *ngTemplateOutlet="tpl; context: null"></ng-container>`;
fixture = createTestComponent(template);
detectChangesAndExpectText('foo');
}));
it('should reflect initial context and changes', async(() => {
const template = `<ng-template let-foo="foo" #tpl>{{foo}}</ng-template>` +
`<ng-container *ngTemplateOutlet="tpl; context: context"></ng-container>`;
fixture = createTestComponent(template);
fixture.detectChanges();
detectChangesAndExpectText('bar');
fixture.componentInstance.context.foo = 'alter-bar';
detectChangesAndExpectText('alter-bar');
}));
it('should reflect user defined `$implicit` property in the context', async(() => {
const template = `<ng-template let-ctx #tpl>{{ctx.foo}}</ng-template>` +
`<ng-container *ngTemplateOutlet="tpl; context: context"></ng-container>`;
fixture = createTestComponent(template);
fixture.componentInstance.context = {$implicit: {foo: 'bra'}};
detectChangesAndExpectText('bra');
}));
it('should reflect context re-binding', async(() => {
const template =
`<ng-template let-shawshank="shawshank" #tpl>{{shawshank}}</ng-template>` +
`<ng-container *ngTemplateOutlet="tpl; context: context"></ng-container>`;
fixture = createTestComponent(template);
fixture.componentInstance.context = {shawshank: 'brooks'};
detectChangesAndExpectText('brooks');
fixture.componentInstance.context = {shawshank: 'was here'};
detectChangesAndExpectText('was here');
}));
it('should update but not destroy embedded view when context values change', () => {
const template =
`<ng-template let-foo="foo" #tpl><destroyable-cmpt></destroyable-cmpt>:{{foo}}</ng-template>` +
`<ng-template [ngTemplateOutlet]="tpl" [ngTemplateOutletContext]="{foo: value}"></ng-template>`;
fixture = createTestComponent(template);
const spyService = fixture.debugElement.injector.get(DestroyedSpyService);
detectChangesAndExpectText('Content to destroy:bar');
expect(spyService.destroyed).toBeFalsy();
fixture.componentInstance.value = 'baz';
detectChangesAndExpectText('Content to destroy:baz');
expect(spyService.destroyed).toBeFalsy();
});
it('should recreate embedded view when context shape changes', () => {
const template =
`<ng-template let-foo="foo" #tpl><destroyable-cmpt></destroyable-cmpt>:{{foo}}</ng-template>` +
`<ng-template [ngTemplateOutlet]="tpl" [ngTemplateOutletContext]="context"></ng-template>`;
fixture = createTestComponent(template);
const spyService = fixture.debugElement.injector.get(DestroyedSpyService);
detectChangesAndExpectText('Content to destroy:bar');
expect(spyService.destroyed).toBeFalsy();
fixture.componentInstance.context = {foo: 'baz', other: true};
detectChangesAndExpectText('Content to destroy:baz');
expect(spyService.destroyed).toBeTruthy();
});
it('should destroy embedded view when context value changes and templateRef becomes undefined',
() => {
const template =
`<ng-template let-foo="foo" #tpl><destroyable-cmpt></destroyable-cmpt>:{{foo}}</ng-template>` +
`<ng-template [ngTemplateOutlet]="value === 'bar' ? tpl : undefined" [ngTemplateOutletContext]="{foo: value}"></ng-template>`;
fixture = createTestComponent(template);
const spyService = fixture.debugElement.injector.get(DestroyedSpyService);
detectChangesAndExpectText('Content to destroy:bar');
expect(spyService.destroyed).toBeFalsy();
fixture.componentInstance.value = 'baz';
detectChangesAndExpectText('');
expect(spyService.destroyed).toBeTruthy();
});
it('should not try to update null / undefined context when context changes but template stays the same',
() => {
const template = `<ng-template let-foo="foo" #tpl>{{foo}}</ng-template>` +
`<ng-template [ngTemplateOutlet]="tpl" [ngTemplateOutletContext]="value === 'bar' ? null : undefined"></ng-template>`;
fixture = createTestComponent(template);
detectChangesAndExpectText('');
fixture.componentInstance.value = 'baz';
detectChangesAndExpectText('');
});
it('should not try to update null / undefined context when template changes', () => {
const template = `<ng-template let-foo="foo" #tpl1>{{foo}}</ng-template>` +
`<ng-template let-foo="foo" #tpl2>{{foo}}</ng-template>` +
`<ng-template [ngTemplateOutlet]="value === 'bar' ? tpl1 : tpl2" [ngTemplateOutletContext]="value === 'bar' ? null : undefined"></ng-template>`;
fixture = createTestComponent(template);
detectChangesAndExpectText('');
fixture.componentInstance.value = 'baz';
detectChangesAndExpectText('');
});
it('should not try to update context on undefined view', () => {
const template = `<ng-template let-foo="foo" #tpl>{{foo}}</ng-template>` +
`<ng-template [ngTemplateOutlet]="value === 'bar' ? null : undefined" [ngTemplateOutletContext]="{foo: value}"></ng-template>`;
fixture = createTestComponent(template);
detectChangesAndExpectText('');
fixture.componentInstance.value = 'baz';
detectChangesAndExpectText('');
}); });
}); });
}
// https://github.com/angular/angular/issues/14778
it('should accept the component as the context', async(() => {
const template = `<ng-container *ngTemplateOutlet="tpl; context: this"></ng-container>` +
`<ng-template #tpl>{{context.foo}}</ng-template>`;
fixture = createTestComponent(template);
detectChangesAndExpectText('bar');
}));
it('should do nothing if templateRef is `null`', async(() => {
const template = `<ng-container [ngTemplateOutlet]="null"></ng-container>`;
fixture = createTestComponent(template);
detectChangesAndExpectText('');
}));
it('should insert content specified by TemplateRef', async(() => {
const template = `<ng-template #tpl>foo</ng-template>` +
`<ng-container [ngTemplateOutlet]="tpl"></ng-container>`;
fixture = createTestComponent(template);
detectChangesAndExpectText('foo');
}));
it('should clear content if TemplateRef becomes `null`', async(() => {
const template = `<tpl-refs #refs="tplRefs"><ng-template>foo</ng-template></tpl-refs>` +
`<ng-container [ngTemplateOutlet]="currentTplRef"></ng-container>`;
fixture = createTestComponent(template);
fixture.detectChanges();
const refs = fixture.debugElement.children[0].references !['refs'];
setTplRef(refs.tplRefs.first);
detectChangesAndExpectText('foo');
setTplRef(null);
detectChangesAndExpectText('');
}));
it('should swap content if TemplateRef changes', async(() => {
const template =
`<tpl-refs #refs="tplRefs"><ng-template>foo</ng-template><ng-template>bar</ng-template></tpl-refs>` +
`<ng-container [ngTemplateOutlet]="currentTplRef"></ng-container>`;
fixture = createTestComponent(template);
fixture.detectChanges();
const refs = fixture.debugElement.children[0].references !['refs'];
setTplRef(refs.tplRefs.first);
detectChangesAndExpectText('foo');
setTplRef(refs.tplRefs.last);
detectChangesAndExpectText('bar');
}));
it('should display template if context is `null`', async(() => {
const template = `<ng-template #tpl>foo</ng-template>` +
`<ng-container *ngTemplateOutlet="tpl; context: null"></ng-container>`;
fixture = createTestComponent(template);
detectChangesAndExpectText('foo');
}));
it('should reflect initial context and changes', async(() => {
const template = `<ng-template let-foo="foo" #tpl>{{foo}}</ng-template>` +
`<ng-container *ngTemplateOutlet="tpl; context: context"></ng-container>`;
fixture = createTestComponent(template);
fixture.detectChanges();
detectChangesAndExpectText('bar');
fixture.componentInstance.context.foo = 'alter-bar';
detectChangesAndExpectText('alter-bar');
}));
it('should reflect user defined `$implicit` property in the context', async(() => {
const template = `<ng-template let-ctx #tpl>{{ctx.foo}}</ng-template>` +
`<ng-container *ngTemplateOutlet="tpl; context: context"></ng-container>`;
fixture = createTestComponent(template);
fixture.componentInstance.context = {$implicit: {foo: 'bra'}};
detectChangesAndExpectText('bra');
}));
it('should reflect context re-binding', async(() => {
const template = `<ng-template let-shawshank="shawshank" #tpl>{{shawshank}}</ng-template>` +
`<ng-container *ngTemplateOutlet="tpl; context: context"></ng-container>`;
fixture = createTestComponent(template);
fixture.componentInstance.context = {shawshank: 'brooks'};
detectChangesAndExpectText('brooks');
fixture.componentInstance.context = {shawshank: 'was here'};
detectChangesAndExpectText('was here');
}));
it('should update but not destroy embedded view when context values change', () => {
const template =
`<ng-template let-foo="foo" #tpl><destroyable-cmpt></destroyable-cmpt>:{{foo}}</ng-template>` +
`<ng-template [ngTemplateOutlet]="tpl" [ngTemplateOutletContext]="{foo: value}"></ng-template>`;
fixture = createTestComponent(template);
const spyService = fixture.debugElement.injector.get(DestroyedSpyService);
detectChangesAndExpectText('Content to destroy:bar');
expect(spyService.destroyed).toBeFalsy();
fixture.componentInstance.value = 'baz';
detectChangesAndExpectText('Content to destroy:baz');
expect(spyService.destroyed).toBeFalsy();
});
it('should recreate embedded view when context shape changes', () => {
const template =
`<ng-template let-foo="foo" #tpl><destroyable-cmpt></destroyable-cmpt>:{{foo}}</ng-template>` +
`<ng-template [ngTemplateOutlet]="tpl" [ngTemplateOutletContext]="context"></ng-template>`;
fixture = createTestComponent(template);
const spyService = fixture.debugElement.injector.get(DestroyedSpyService);
detectChangesAndExpectText('Content to destroy:bar');
expect(spyService.destroyed).toBeFalsy();
fixture.componentInstance.context = {foo: 'baz', other: true};
detectChangesAndExpectText('Content to destroy:baz');
expect(spyService.destroyed).toBeTruthy();
});
it('should destroy embedded view when context value changes and templateRef becomes undefined', () => {
const template =
`<ng-template let-foo="foo" #tpl><destroyable-cmpt></destroyable-cmpt>:{{foo}}</ng-template>` +
`<ng-template [ngTemplateOutlet]="value === 'bar' ? tpl : undefined" [ngTemplateOutletContext]="{foo: value}"></ng-template>`;
fixture = createTestComponent(template);
const spyService = fixture.debugElement.injector.get(DestroyedSpyService);
detectChangesAndExpectText('Content to destroy:bar');
expect(spyService.destroyed).toBeFalsy();
fixture.componentInstance.value = 'baz';
detectChangesAndExpectText('');
expect(spyService.destroyed).toBeTruthy();
});
it('should not try to update null / undefined context when context changes but template stays the same',
() => {
const template = `<ng-template let-foo="foo" #tpl>{{foo}}</ng-template>` +
`<ng-template [ngTemplateOutlet]="tpl" [ngTemplateOutletContext]="value === 'bar' ? null : undefined"></ng-template>`;
fixture = createTestComponent(template);
detectChangesAndExpectText('');
fixture.componentInstance.value = 'baz';
detectChangesAndExpectText('');
});
it('should not try to update null / undefined context when template changes', () => {
const template = `<ng-template let-foo="foo" #tpl1>{{foo}}</ng-template>` +
`<ng-template let-foo="foo" #tpl2>{{foo}}</ng-template>` +
`<ng-template [ngTemplateOutlet]="value === 'bar' ? tpl1 : tpl2" [ngTemplateOutletContext]="value === 'bar' ? null : undefined"></ng-template>`;
fixture = createTestComponent(template);
detectChangesAndExpectText('');
fixture.componentInstance.value = 'baz';
detectChangesAndExpectText('');
});
it('should not try to update context on undefined view', () => {
const template = `<ng-template let-foo="foo" #tpl>{{foo}}</ng-template>` +
`<ng-template [ngTemplateOutlet]="value === 'bar' ? null : undefined" [ngTemplateOutletContext]="{foo: value}"></ng-template>`;
fixture = createTestComponent(template);
detectChangesAndExpectText('');
fixture.componentInstance.value = 'baz';
detectChangesAndExpectText('');
});
});
@Injectable() @Injectable()
class DestroyedSpyService { class DestroyedSpyService {

View File

@ -12,8 +12,8 @@ import localeZgh from '@angular/common/locales/zgh';
import localeFr from '@angular/common/locales/fr'; import localeFr from '@angular/common/locales/fr';
import {LOCALE_ID} from '@angular/core'; import {LOCALE_ID} from '@angular/core';
import {TestBed, inject} from '@angular/core/testing'; import {TestBed, inject} from '@angular/core/testing';
import {NgLocaleLocalization, NgLocalization, getPluralCategory, DEPRECATED_PLURAL_FN, getPluralCase} from '../../src/i18n/localization'; import {NgLocaleLocalization, NgLocalization, getPluralCategory, DEPRECATED_PLURAL_FN, getPluralCase} from '@angular/common/src/i18n/localization';
import {Plural} from '../../src/i18n/locale_data_api'; import {Plural} from '@angular/common';
import {registerLocaleData} from '../../src/i18n/locale_data'; import {registerLocaleData} from '../../src/i18n/locale_data';
{ {

View File

@ -6,37 +6,35 @@
* found in the LICENSE file at https://angular.io/license * found in the LICENSE file at https://angular.io/license
*/ */
import {Location} from '../../src/location/location'; import {Location} from '@angular/common';
{ const baseUrl = '/base';
const baseUrl = '/base';
describe('Location Class', () => { describe('Location Class', () => {
describe('stripTrailingSlash', () => { describe('stripTrailingSlash', () => {
it('should strip single character slash', () => { it('should strip single character slash', () => {
const input = '/'; const input = '/';
expect(Location.stripTrailingSlash(input)).toBe(''); expect(Location.stripTrailingSlash(input)).toBe('');
}); });
it('should normalize strip a trailing slash', () => { it('should normalize strip a trailing slash', () => {
const input = baseUrl + '/'; const input = baseUrl + '/';
expect(Location.stripTrailingSlash(input)).toBe(baseUrl); expect(Location.stripTrailingSlash(input)).toBe(baseUrl);
}); });
it('should ignore query params when stripping a slash', () => { it('should ignore query params when stripping a slash', () => {
const input = baseUrl + '/?param=1'; const input = baseUrl + '/?param=1';
expect(Location.stripTrailingSlash(input)).toBe(baseUrl + '?param=1'); expect(Location.stripTrailingSlash(input)).toBe(baseUrl + '?param=1');
}); });
it('should not remove slashes inside query params', () => { it('should not remove slashes inside query params', () => {
const input = baseUrl + '?test/?=3'; const input = baseUrl + '?test/?=3';
expect(Location.stripTrailingSlash(input)).toBe(input); expect(Location.stripTrailingSlash(input)).toBe(input);
}); });
it('should not remove slashes after a pound sign', () => { it('should not remove slashes after a pound sign', () => {
const input = baseUrl + '#test/?=3'; const input = baseUrl + '#test/?=3';
expect(Location.stripTrailingSlash(input)).toBe(input); expect(Location.stripTrailingSlash(input)).toBe(input);
});
}); });
}); });
} });

View File

@ -7,13 +7,8 @@
*/ */
import {KeyValuePipe} from '@angular/common'; import {KeyValuePipe} from '@angular/common';
import {EventEmitter, KeyValueDiffers, WrappedValue, ɵdefaultKeyValueDiffers as defaultKeyValueDiffers} from '@angular/core'; import {defaultComparator} from '@angular/common/src/pipes/keyvalue_pipe';
import {AsyncTestCompleter, beforeEach, describe, expect, inject, it} from '@angular/core/testing/src/testing_internal'; import {ɵdefaultKeyValueDiffers as defaultKeyValueDiffers} from '@angular/core';
import {getDOM} from '@angular/platform-browser/src/dom/dom_adapter';
import {browserDetection} from '@angular/platform-browser/testing/src/browser_util';
import {defaultComparator} from '../../src/pipes/keyvalue_pipe';
import {SpyChangeDetectorRef} from '../spies';
describe('KeyValuePipe', () => { describe('KeyValuePipe', () => {
it('should return null when given null', () => { it('should return null when given null', () => {