angular-cn/packages/core/test/acceptance/bootstrap_spec.ts

292 lines
12 KiB
TypeScript

/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {COMPILER_OPTIONS, Component, destroyPlatform, NgModule, ViewEncapsulation} from '@angular/core';
import {BrowserModule} from '@angular/platform-browser';
import {platformBrowserDynamic} from '@angular/platform-browser-dynamic';
import {onlyInIvy, withBody} from '@angular/private/testing';
describe('bootstrap', () => {
beforeEach(destroyPlatform);
afterEach(destroyPlatform);
it('should bootstrap using #id selector',
withBody('<div>before|</div><button id="my-app"></button>', async () => {
try {
const ngModuleRef = await platformBrowserDynamic().bootstrapModule(IdSelectorAppModule);
expect(document.body.textContent).toEqual('before|works!');
ngModuleRef.destroy();
} catch (err) {
console.error(err);
}
}));
it('should bootstrap using one of selectors from the list',
withBody('<div>before|</div><div class="bar"></div>', async () => {
try {
const ngModuleRef =
await platformBrowserDynamic().bootstrapModule(MultipleSelectorsAppModule);
expect(document.body.textContent).toEqual('before|works!');
ngModuleRef.destroy();
} catch (err) {
console.error(err);
}
}));
describe('options', () => {
function createComponentAndModule(
options:
{encapsulation?: ViewEncapsulation; preserveWhitespaces?: boolean;
selector?: string} = {}) {
@Component({
selector: options.selector || 'my-app',
styles: [''],
template: '<span>a b</span>',
encapsulation: options.encapsulation,
preserveWhitespaces: options.preserveWhitespaces,
jit: true,
})
class TestComponent {
}
@NgModule({
imports: [BrowserModule],
declarations: [TestComponent],
bootstrap: [TestComponent],
jit: true,
})
class TestModule {
}
return TestModule;
}
it('should use ViewEncapsulation.Emulated as default',
withBody('<my-app></my-app>', async () => {
const TestModule = createComponentAndModule();
const ngModuleRef = await platformBrowserDynamic().bootstrapModule(TestModule);
expect(document.body.innerHTML).toContain('<span _ngcontent-');
ngModuleRef.destroy();
}));
it('should allow setting defaultEncapsulation using bootstrap option',
withBody('<my-app></my-app>', async () => {
const TestModule = createComponentAndModule();
const ngModuleRef = await platformBrowserDynamic().bootstrapModule(
TestModule, {defaultEncapsulation: ViewEncapsulation.None});
expect(document.body.innerHTML).toContain('<span>');
expect(document.body.innerHTML).not.toContain('_ngcontent-');
ngModuleRef.destroy();
}));
it('should allow setting defaultEncapsulation using compiler option',
withBody('<my-app></my-app>', async () => {
const TestModule = createComponentAndModule();
const ngModuleRef = await platformBrowserDynamic([{
provide: COMPILER_OPTIONS,
useValue: {defaultEncapsulation: ViewEncapsulation.None},
multi: true
}]).bootstrapModule(TestModule);
expect(document.body.innerHTML).toContain('<span>');
expect(document.body.innerHTML).not.toContain('_ngcontent-');
ngModuleRef.destroy();
}));
it('should prefer encapsulation on component over bootstrap option',
withBody('<my-app></my-app>', async () => {
const TestModule = createComponentAndModule({encapsulation: ViewEncapsulation.Emulated});
const ngModuleRef = await platformBrowserDynamic().bootstrapModule(
TestModule, {defaultEncapsulation: ViewEncapsulation.None});
expect(document.body.innerHTML).toContain('<span _ngcontent-');
ngModuleRef.destroy();
}));
it('should use preserveWhitespaces: false as default',
withBody('<my-app></my-app>', async () => {
const TestModule = createComponentAndModule();
const ngModuleRef = await platformBrowserDynamic().bootstrapModule(TestModule);
expect(document.body.innerHTML).toContain('a b');
ngModuleRef.destroy();
}));
it('should allow setting preserveWhitespaces using bootstrap option',
withBody('<my-app></my-app>', async () => {
const TestModule = createComponentAndModule();
const ngModuleRef = await platformBrowserDynamic().bootstrapModule(
TestModule, {preserveWhitespaces: true});
expect(document.body.innerHTML).toContain('a b');
ngModuleRef.destroy();
}));
it('should allow setting preserveWhitespaces using compiler option',
withBody('<my-app></my-app>', async () => {
const TestModule = createComponentAndModule();
const ngModuleRef =
await platformBrowserDynamic([
{provide: COMPILER_OPTIONS, useValue: {preserveWhitespaces: true}, multi: true}
]).bootstrapModule(TestModule);
expect(document.body.innerHTML).toContain('a b');
ngModuleRef.destroy();
}));
it('should prefer preserveWhitespaces on component over bootstrap option',
withBody('<my-app></my-app>', async () => {
const TestModule = createComponentAndModule({preserveWhitespaces: false});
const ngModuleRef = await platformBrowserDynamic().bootstrapModule(
TestModule, {preserveWhitespaces: true});
expect(document.body.innerHTML).toContain('a b');
ngModuleRef.destroy();
}));
onlyInIvy('options cannot be changed in Ivy').describe('changing bootstrap options', () => {
beforeEach(() => {
spyOn(console, 'error');
});
it('should log an error when changing defaultEncapsulation bootstrap options',
withBody('<my-app-a></my-app-a><my-app-b></my-app-b>', async () => {
const platformRef = platformBrowserDynamic();
const TestModuleA = createComponentAndModule({selector: 'my-app-a'});
const ngModuleRefA = await platformRef.bootstrapModule(
TestModuleA, {defaultEncapsulation: ViewEncapsulation.None});
ngModuleRefA.destroy();
const TestModuleB = createComponentAndModule({selector: 'my-app-b'});
const ngModuleRefB = await platformRef.bootstrapModule(
TestModuleB, {defaultEncapsulation: ViewEncapsulation.ShadowDom});
expect(console.error)
.toHaveBeenCalledWith(
'Provided value for `defaultEncapsulation` can not be changed once it has been set.');
// The options should not have been changed
expect(document.body.innerHTML).not.toContain('_ngcontent-');
ngModuleRefB.destroy();
}));
it('should log an error when changing preserveWhitespaces bootstrap options',
withBody('<my-app-a></my-app-a><my-app-b></my-app-b>', async () => {
const platformRef = platformBrowserDynamic();
const TestModuleA = createComponentAndModule({selector: 'my-app-a'});
const ngModuleRefA =
await platformRef.bootstrapModule(TestModuleA, {preserveWhitespaces: true});
ngModuleRefA.destroy();
const TestModuleB = createComponentAndModule({selector: 'my-app-b'});
const ngModuleRefB =
await platformRef.bootstrapModule(TestModuleB, {preserveWhitespaces: false});
expect(console.error)
.toHaveBeenCalledWith(
'Provided value for `preserveWhitespaces` can not be changed once it has been set.');
// The options should not have been changed
expect(document.body.innerHTML).toContain('a b');
ngModuleRefB.destroy();
}));
it('should log an error when changing defaultEncapsulation to its default',
withBody('<my-app-a></my-app-a><my-app-b></my-app-b>', async () => {
const platformRef = platformBrowserDynamic();
const TestModuleA = createComponentAndModule({selector: 'my-app-a'});
const ngModuleRefA = await platformRef.bootstrapModule(TestModuleA);
ngModuleRefA.destroy();
const TestModuleB = createComponentAndModule({selector: 'my-app-b'});
const ngModuleRefB = await platformRef.bootstrapModule(
TestModuleB, {defaultEncapsulation: ViewEncapsulation.Emulated});
// Although the configured value may be identical to the default, the provided set of
// options has still been changed compared to the previously provided options.
expect(console.error)
.toHaveBeenCalledWith(
'Provided value for `defaultEncapsulation` can not be changed once it has been set.');
ngModuleRefB.destroy();
}));
it('should log an error when changing preserveWhitespaces to its default',
withBody('<my-app-a></my-app-a><my-app-b></my-app-b>', async () => {
const platformRef = platformBrowserDynamic();
const TestModuleA = createComponentAndModule({selector: 'my-app-a'});
const ngModuleRefA = await platformRef.bootstrapModule(TestModuleA);
ngModuleRefA.destroy();
const TestModuleB = createComponentAndModule({selector: 'my-app-b'});
const ngModuleRefB =
await platformRef.bootstrapModule(TestModuleB, {preserveWhitespaces: false});
// Although the configured value may be identical to the default, the provided set of
// options has still been changed compared to the previously provided options.
expect(console.error)
.toHaveBeenCalledWith(
'Provided value for `preserveWhitespaces` can not be changed once it has been set.');
ngModuleRefB.destroy();
}));
it('should not log an error when passing identical bootstrap options',
withBody('<my-app-a></my-app-a><my-app-b></my-app-b>', async () => {
const platformRef = platformBrowserDynamic();
const TestModuleA = createComponentAndModule({selector: 'my-app-a'});
const ngModuleRefA = await platformRef.bootstrapModule(
TestModuleA,
{defaultEncapsulation: ViewEncapsulation.None, preserveWhitespaces: true});
ngModuleRefA.destroy();
// Bootstrapping multiple modules using the exact same options should be allowed.
const TestModuleB = createComponentAndModule({selector: 'my-app-b'});
const ngModuleRefB = await platformRef.bootstrapModule(
TestModuleB,
{defaultEncapsulation: ViewEncapsulation.None, preserveWhitespaces: true});
ngModuleRefB.destroy();
}));
});
});
});
@Component({
selector: '#my-app',
template: 'works!',
})
export class IdSelectorAppComponent {
}
@NgModule({
imports: [BrowserModule],
declarations: [IdSelectorAppComponent],
bootstrap: [IdSelectorAppComponent],
})
export class IdSelectorAppModule {
}
@Component({
selector: '[foo],span,.bar',
template: 'works!',
})
export class MultipleSelectorsAppComponent {
}
@NgModule({
imports: [BrowserModule],
declarations: [MultipleSelectorsAppComponent],
bootstrap: [MultipleSelectorsAppComponent],
})
export class MultipleSelectorsAppModule {
}