/**
* @license
* Copyright Google Inc. 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 {InjectionToken, ViewEncapsulation, defineInjectable, defineInjector} from '../../src/core';
import {AttributeMarker, ComponentFactory, LifecycleHooksFeature, defineComponent, directiveInject, markDirty, template, getRenderedText, ProvidersFeature} from '../../src/render3/index';
import {bind, container, containerRefreshEnd, containerRefreshStart, element, elementEnd, elementProperty, elementStart, embeddedViewEnd, embeddedViewStart, nextContext, text, textBinding, tick} from '../../src/render3/instructions/all';
import {ComponentDef, RenderFlags} from '../../src/render3/interfaces/definition';
import {NgIf} from './common_with_def';
import {getRendererFactory2} from './imported_renderer2';
import {ComponentFixture, MockRendererFactory, containerEl, createComponent, renderComponent, renderToHtml, requestAnimationFrame, toHtml} from './render_util';
import {createInjector} from '../../src/di/r3_injector';
describe('component', () => {
class CounterComponent {
count = 0;
increment() { this.count++; }
static ngComponentDef = defineComponent({
type: CounterComponent,
encapsulation: ViewEncapsulation.None,
selectors: [['counter']],
consts: 1,
vars: 1,
template: function(rf: RenderFlags, ctx: CounterComponent) {
if (rf & RenderFlags.Create) {
text(0);
}
if (rf & RenderFlags.Update) {
textBinding(0, bind(ctx.count));
}
},
factory: () => new CounterComponent,
inputs: {count: 'count'},
});
}
describe('renderComponent', () => {
it('should render on initial call', () => {
renderComponent(CounterComponent);
expect(toHtml(containerEl)).toEqual('0');
});
it('should re-render on input change or method invocation', () => {
const component = renderComponent(CounterComponent);
expect(toHtml(containerEl)).toEqual('0');
component.count = 123;
markDirty(component);
expect(toHtml(containerEl)).toEqual('0');
requestAnimationFrame.flush();
expect(toHtml(containerEl)).toEqual('123');
component.increment();
markDirty(component);
expect(toHtml(containerEl)).toEqual('123');
requestAnimationFrame.flush();
expect(toHtml(containerEl)).toEqual('124');
});
class MyService {
constructor(public value: string) {}
static ngInjectableDef =
defineInjectable({providedIn: 'root', factory: () => new MyService('no-injector')});
}
class MyComponent {
constructor(public myService: MyService) {}
static ngComponentDef = defineComponent({
type: MyComponent,
encapsulation: ViewEncapsulation.None,
selectors: [['my-component']],
factory: () => new MyComponent(directiveInject(MyService)),
consts: 1,
vars: 1,
template: function(fs: RenderFlags, ctx: MyComponent) {
if (fs & RenderFlags.Create) {
text(0);
}
if (fs & RenderFlags.Update) {
textBinding(0, bind(ctx.myService.value));
}
}
});
}
class MyModule {
static ngInjectorDef = defineInjector({
factory: () => new MyModule(),
providers: [{provide: MyService, useValue: new MyService('injector')}]
});
}
it('should support bootstrapping without injector', () => {
const fixture = new ComponentFixture(MyComponent);
expect(fixture.html).toEqual('no-injector');
});
it('should support bootstrapping with injector', () => {
const fixture = new ComponentFixture(MyComponent, {injector: createInjector(MyModule)});
expect(fixture.html).toEqual('injector');
});
});
it('should instantiate components at high indices', () => {
// {{ name }}
class Comp {
// @Input
name = '';
static ngComponentDef = defineComponent({
type: Comp,
selectors: [['comp']],
factory: () => new Comp(),
consts: 1,
vars: 1,
template: (rf: RenderFlags, ctx: Comp) => {
if (rf & RenderFlags.Create) {
text(0);
}
if (rf & RenderFlags.Update) {
textBinding(0, bind(ctx.name));
}
},
inputs: {name: 'name'}
});
}
// Artificially inflating the slot IDs of this app component to mimic an app
// with a very large view
const App = createComponent('app', (rf: RenderFlags, ctx: any) => {
if (rf & RenderFlags.Create) {
element(4097, 'comp');
}
if (rf & RenderFlags.Update) {
elementProperty(4097, 'name', bind(ctx.name));
}
}, 4098, 1, [Comp]);
const fixture = new ComponentFixture(App);
expect(fixture.html).toEqual('