292 lines
12 KiB
TypeScript
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 {
|
|
} |