diff --git a/packages/core/test/render3/BUILD.bazel b/packages/core/test/render3/BUILD.bazel
index a27837958e..ccbb26d6f5 100644
--- a/packages/core/test/render3/BUILD.bazel
+++ b/packages/core/test/render3/BUILD.bazel
@@ -15,6 +15,10 @@ ts_library(
"//packages:types",
"//packages/core",
"//packages/platform-browser",
+ "//packages/platform-browser/animations",
+ "//packages/animations",
+ "//packages/animations/browser",
+ "//packages/animations/browser/testing",
],
)
diff --git a/packages/core/test/render3/component_spec.ts b/packages/core/test/render3/component_spec.ts
index e23285c60f..0089db882d 100644
--- a/packages/core/test/render3/component_spec.ts
+++ b/packages/core/test/render3/component_spec.ts
@@ -170,6 +170,6 @@ describe('encapsulation', () => {
renderComponent(WrapperComponentWith, getRendererFactory2(document));
expect(containerEl.outerHTML)
.toEqual(
- '
bar
');
+ 'bar
');
});
});
diff --git a/packages/core/test/render3/imported_renderer2.ts b/packages/core/test/render3/imported_renderer2.ts
index b2858cceb2..09742807bc 100644
--- a/packages/core/test/render3/imported_renderer2.ts
+++ b/packages/core/test/render3/imported_renderer2.ts
@@ -6,8 +6,12 @@
* found in the LICENSE file at https://angular.io/license
*/
+import {ɵAnimationEngine, ɵNoopAnimationStyleNormalizer} from '@angular/animations/browser';
+import {MockAnimationDriver} from '@angular/animations/browser/testing';
import {EventEmitter, NgZone, RendererFactory2} from '@angular/core';
import {EventManager, ɵDomEventsPlugin, ɵDomRendererFactory2, ɵDomSharedStylesHost} from '@angular/platform-browser';
+import {ɵAnimationRendererFactory} from '@angular/platform-browser/animations';
+
// Adapted renderer: it creates a Renderer2 instance and adapts it to Renderer3
// TODO: remove once this code is in angular/angular
@@ -52,3 +56,11 @@ export function getRendererFactory2(document: any): RendererFactory2 {
new EventManager([new SimpleDomEventsPlugin(document, fakeNgZone)], fakeNgZone);
return new ɵDomRendererFactory2(eventManager, new ɵDomSharedStylesHost(document));
}
+
+export function getAnimationRendererFactory2(document: any): RendererFactory2 {
+ const fakeNgZone: NgZone = new NoopNgZone();
+ return new ɵAnimationRendererFactory(
+ getRendererFactory2(document),
+ new ɵAnimationEngine(new MockAnimationDriver(), new ɵNoopAnimationStyleNormalizer()),
+ fakeNgZone);
+}
diff --git a/packages/core/test/render3/load_domino.ts b/packages/core/test/render3/load_domino.ts
index 5857630e34..e07ef10a9c 100644
--- a/packages/core/test/render3/load_domino.ts
+++ b/packages/core/test/render3/load_domino.ts
@@ -6,8 +6,12 @@
* found in the LICENSE file at https://angular.io/license
*/
+// Needed to run animation tests
+require('zone.js/dist/zone-node.js');
+
if (typeof window == 'undefined') {
- const createWindow = require('domino').createWindow;
+ const domino = require('domino');
+ const createWindow = domino.createWindow;
const window = createWindow('', 'http://localhost');
(global as any).document = window.document;
@@ -16,4 +20,8 @@ if (typeof window == 'undefined') {
// It fails with Domino with TypeError: Cannot assign to read only property
// 'stopImmediatePropagation' of object '#'
(global as any).Event = null;
+
+ // For animation tests, see
+ // https://github.com/angular/angular/blob/master/packages/animations/browser/src/render/shared.ts#L140
+ (global as any).Element = domino.impl.Element;
}
diff --git a/packages/core/test/render3/render_util.ts b/packages/core/test/render3/render_util.ts
index 88c9c0942c..573eee1735 100644
--- a/packages/core/test/render3/render_util.ts
+++ b/packages/core/test/render3/render_util.ts
@@ -33,8 +33,12 @@ requestAnimationFrame.flush = function() {
export function resetDOM() {
requestAnimationFrame.queue = [];
+ if (containerEl) {
+ document.body.removeChild(containerEl);
+ }
containerEl = document.createElement('div');
containerEl.setAttribute('host', '');
+ document.body.appendChild(containerEl);
host = null;
// TODO: assert that the global state is clean (e.g. ngData, previousOrParentNode, etc)
}
diff --git a/packages/core/test/render3/renderer_factory_spec.ts b/packages/core/test/render3/renderer_factory_spec.ts
index 0efe207c61..3c21761a42 100644
--- a/packages/core/test/render3/renderer_factory_spec.ts
+++ b/packages/core/test/render3/renderer_factory_spec.ts
@@ -6,13 +6,15 @@
* found in the LICENSE file at https://angular.io/license
*/
-import {RendererType2} from '@angular/core';
+import {AnimationEvent} from '@angular/animations';
+import {MockAnimationDriver, MockAnimationPlayer} from '@angular/animations/browser/testing';
-import {D, E, e} from '../../src/render3';
-import {T, defineComponent, detectChanges} from '../../src/render3/index';
+import {RendererType2, ViewEncapsulation} from '../../src/core';
+import {D, E, L, T, b, defineComponent, detectChanges, e, p} from '../../src/render3';
+import {createRendererType2} from '../../src/view';
-import {getRendererFactory2} from './imported_renderer2';
-import {document, renderComponent, renderToHtml, resetDOM} from './render_util';
+import {getAnimationRendererFactory2, getRendererFactory2} from './imported_renderer2';
+import {containerEl, document, renderComponent, renderToHtml} from './render_util';
describe('renderer factory lifecycle', () => {
let logs: string[] = [];
@@ -104,3 +106,99 @@ describe('renderer factory lifecycle', () => {
});
});
+
+describe('animation renderer factory', () => {
+ let eventLogs: string[] = [];
+ function getLog(): MockAnimationPlayer[] {
+ return MockAnimationDriver.log as MockAnimationPlayer[];
+ }
+
+ function resetLog() { MockAnimationDriver.log = []; }
+
+ beforeEach(() => {
+ eventLogs = [];
+ resetLog();
+ });
+
+ class SomeComponent {
+ static ngComponentDef = defineComponent({
+ type: SomeComponent,
+ tag: 'some-component',
+ template: function(ctx: SomeComponent, cm: boolean) {
+ if (cm) {
+ T(0, 'foo');
+ }
+ },
+ factory: () => new SomeComponent
+ });
+ }
+
+ class SomeComponentWithAnimation {
+ exp: string;
+ callback(event: AnimationEvent) {
+ eventLogs.push(`${event.fromState ? event.fromState : event.toState} - ${event.phaseName}`);
+ }
+ static ngComponentDef = defineComponent({
+ type: SomeComponentWithAnimation,
+ tag: 'some-component',
+ template: function(ctx: SomeComponentWithAnimation, cm: boolean) {
+ if (cm) {
+ E(0, 'div');
+ {
+ L('@myAnimation.start', ctx.callback.bind(ctx));
+ L('@myAnimation.done', ctx.callback.bind(ctx));
+ T(1, 'foo');
+ }
+ e();
+ }
+ p(0, '@myAnimation', b(ctx.exp));
+ },
+ factory: () => new SomeComponentWithAnimation,
+ rendererType: createRendererType2({
+ encapsulation: ViewEncapsulation.None,
+ styles: [],
+ data: {
+ animation: [{
+ type: 7,
+ name: 'myAnimation',
+ definitions: [{
+ type: 1,
+ expr: '* => on',
+ animation:
+ [{type: 4, styles: {type: 6, styles: {opacity: 1}, offset: null}, timings: 10}],
+ options: null
+ }],
+ options: {}
+ }]
+ }
+ }),
+ });
+ }
+
+ it('should work with components without animations', () => {
+ renderComponent(SomeComponent, getAnimationRendererFactory2(document));
+ expect(containerEl.innerHTML).toEqual('foo');
+ });
+
+ it('should work with animated components', (done) => {
+ const factory = getAnimationRendererFactory2(document);
+ const component = renderComponent(SomeComponentWithAnimation, factory);
+ expect(containerEl.innerHTML)
+ .toEqual('foo
');
+
+ component.exp = 'on';
+ detectChanges(component);
+
+ const [player] = getLog();
+ expect(player.keyframes).toEqual([
+ {opacity: '*', offset: 0},
+ {opacity: 1, offset: 1},
+ ]);
+ player.finish();
+
+ factory.whenRenderingDone !().then(() => {
+ expect(eventLogs).toEqual(['void - start', 'void - done', 'on - start', 'on - done']);
+ done();
+ });
+ });
+});