2017-12-01 17:23:03 -05:00
|
|
|
/**
|
|
|
|
* @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
|
|
|
|
*/
|
|
|
|
|
2018-01-03 05:42:48 -05:00
|
|
|
import {stringifyElement} from '@angular/platform-browser/testing/src/browser_util';
|
2018-01-09 19:43:12 -05:00
|
|
|
|
2017-12-19 10:51:42 -05:00
|
|
|
import {ComponentTemplate, ComponentType, DirectiveType, PublicFeature, defineComponent, defineDirective, renderComponent as _renderComponent} from '../../src/render3/index';
|
2018-01-08 23:17:13 -05:00
|
|
|
import {NG_HOST_SYMBOL, createLNode, createLView, renderTemplate} from '../../src/render3/instructions';
|
2018-01-09 19:43:12 -05:00
|
|
|
import {DirectiveDefArgs} from '../../src/render3/interfaces/definition';
|
2018-01-09 21:38:17 -05:00
|
|
|
import {LElementNode, LNodeFlags} from '../../src/render3/interfaces/node';
|
|
|
|
import {RElement, RText, Renderer3, RendererFactory3, domRendererFactory3} from '../../src/render3/interfaces/renderer';
|
2018-01-09 19:43:12 -05:00
|
|
|
|
2017-12-11 10:30:46 -05:00
|
|
|
import {getRendererFactory2} from './imported_renderer2';
|
2017-12-01 17:23:03 -05:00
|
|
|
|
|
|
|
export const document = ((global || window) as any).document;
|
|
|
|
export let containerEl: HTMLElement = null !;
|
2018-01-08 23:17:13 -05:00
|
|
|
let host: LElementNode|null;
|
2017-12-27 13:54:19 -05:00
|
|
|
const isRenderer2 =
|
|
|
|
typeof process == 'object' && process.argv[3] && process.argv[3] === '--r=renderer2';
|
2017-12-01 17:23:03 -05:00
|
|
|
// tslint:disable-next-line:no-console
|
2017-12-11 10:30:46 -05:00
|
|
|
console.log(`Running tests with ${!isRenderer2 ? 'document' : 'Renderer2'} renderer...`);
|
|
|
|
const testRendererFactory: RendererFactory3 =
|
|
|
|
isRenderer2 ? getRendererFactory2(document) : domRendererFactory3;
|
2017-12-01 17:23:03 -05:00
|
|
|
|
|
|
|
export const requestAnimationFrame:
|
|
|
|
{(fn: () => void): void; flush(): void; queue: (() => void)[];} = function(fn: () => void) {
|
|
|
|
requestAnimationFrame.queue.push(fn);
|
|
|
|
} as any;
|
|
|
|
requestAnimationFrame.flush = function() {
|
|
|
|
while (requestAnimationFrame.queue.length) {
|
|
|
|
requestAnimationFrame.queue.shift() !();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
export function resetDOM() {
|
|
|
|
requestAnimationFrame.queue = [];
|
2017-12-15 11:50:54 -05:00
|
|
|
if (containerEl) {
|
2018-01-03 04:45:09 -05:00
|
|
|
try {
|
|
|
|
document.body.removeChild(containerEl);
|
|
|
|
} catch (e) {
|
|
|
|
}
|
2017-12-15 11:50:54 -05:00
|
|
|
}
|
2017-12-01 17:23:03 -05:00
|
|
|
containerEl = document.createElement('div');
|
|
|
|
containerEl.setAttribute('host', '');
|
2017-12-15 11:50:54 -05:00
|
|
|
document.body.appendChild(containerEl);
|
2017-12-11 10:30:46 -05:00
|
|
|
host = null;
|
2017-12-01 17:23:03 -05:00
|
|
|
// TODO: assert that the global state is clean (e.g. ngData, previousOrParentNode, etc)
|
|
|
|
}
|
|
|
|
|
2017-12-11 10:30:46 -05:00
|
|
|
export function renderToHtml(
|
|
|
|
template: ComponentTemplate<any>, ctx: any, providedRendererFactory?: RendererFactory3) {
|
|
|
|
host = renderTemplate(
|
|
|
|
containerEl, template, ctx, providedRendererFactory || testRendererFactory, host);
|
|
|
|
return toHtml(containerEl);
|
2017-12-01 17:23:03 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
beforeEach(resetDOM);
|
|
|
|
|
2017-12-11 10:30:46 -05:00
|
|
|
export function renderComponent<T>(type: ComponentType<T>, rendererFactory?: RendererFactory3): T {
|
|
|
|
return _renderComponent(
|
|
|
|
type, {rendererFactory: rendererFactory || testRendererFactory, host: containerEl});
|
2017-12-01 17:23:03 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
export function toHtml<T>(componentOrElement: T | RElement): string {
|
2018-01-08 23:17:13 -05:00
|
|
|
const node = (componentOrElement as any)[NG_HOST_SYMBOL] as LElementNode;
|
2017-12-01 17:23:03 -05:00
|
|
|
if (node) {
|
|
|
|
return toHtml(node.native);
|
|
|
|
} else {
|
2018-01-03 05:42:48 -05:00
|
|
|
return stringifyElement(componentOrElement)
|
|
|
|
.replace(/^<div host="">/, '')
|
|
|
|
.replace(/<\/div>$/, '')
|
|
|
|
.replace(' style=""', '')
|
|
|
|
.replace(/<!--[\w]*-->/g, '');
|
2017-12-01 17:23:03 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
export function createComponent(
|
|
|
|
name: string, template: ComponentTemplate<any>): ComponentType<any> {
|
|
|
|
return class Component {
|
|
|
|
value: any;
|
2018-01-22 18:27:21 -05:00
|
|
|
static ngComponentDef = defineComponent({
|
|
|
|
type: Component,
|
|
|
|
tag: name,
|
|
|
|
factory: () => new Component,
|
|
|
|
template: template,
|
|
|
|
features: [PublicFeature]
|
|
|
|
});
|
2017-12-01 17:23:03 -05:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2018-01-09 00:57:50 -05:00
|
|
|
export function createDirective({exportAs}: {exportAs?: string} = {}): DirectiveType<any> {
|
2017-12-19 10:51:42 -05:00
|
|
|
return class Directive {
|
|
|
|
static ngDirectiveDef = defineDirective({
|
2018-01-22 18:27:21 -05:00
|
|
|
type: Directive,
|
2017-12-19 10:51:42 -05:00
|
|
|
factory: () => new Directive(),
|
2017-12-20 06:19:59 -05:00
|
|
|
features: [PublicFeature],
|
2018-01-09 00:57:50 -05:00
|
|
|
exportAs: exportAs,
|
2017-12-19 10:51:42 -05:00
|
|
|
});
|
|
|
|
};
|
|
|
|
}
|
2017-12-01 17:23:03 -05:00
|
|
|
|
|
|
|
|
|
|
|
// Verify that DOM is a type of render. This is here for error checking only and has no use.
|
|
|
|
export const renderer: Renderer3 = null as any as Document;
|
|
|
|
export const element: RElement = null as any as HTMLElement;
|
|
|
|
export const text: RText = null as any as Text;
|