Skip to content
This repository has been archived by the owner on Jul 30, 2018. It is now read-only.

Commit

Permalink
Fix Edge failures (#680)
Browse files Browse the repository at this point in the history
* change to stubs

* comment out async

* fixed timing for tests

* resolve raf

* make tests sync

* remove comments

* fix assertions
  • Loading branch information
tomdye authored Sep 15, 2017
1 parent 0f7f45e commit 16d1d33
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 94 deletions.
54 changes: 22 additions & 32 deletions src/WidgetBase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,8 @@ export class WidgetBase<P = WidgetProperties, C extends DNode = DNode> extends E

private _numRootNodes = 0;

private _rootNodeKeys: object[];

/**
* @constructor
*/
Expand Down Expand Up @@ -239,16 +241,6 @@ export class WidgetBase<P = WidgetProperties, C extends DNode = DNode> extends E
projectionOptions: ProjectionOptions,
vnodeSelector: string,
properties: VNodeProperties
): void {
this._nodeHandler.add(element, properties);
this.onElementCreated(element, String(properties.key));
}

private _afterRootCreateCallback(
element: HTMLElement,
projectionOptions: ProjectionOptions,
vnodeSelector: string,
properties: VNodeProperties
): void {
this._addElementToNodeHandler(element, projectionOptions, properties);
this.onElementCreated(element, String(properties.key));
Expand All @@ -262,36 +254,32 @@ export class WidgetBase<P = WidgetProperties, C extends DNode = DNode> extends E
projectionOptions: ProjectionOptions,
vnodeSelector: string,
properties: VNodeProperties
): void {
this._nodeHandler.add(element, properties);
this.onElementUpdated(element, String(properties.key));
}

private _afterRootUpdateCallback(
element: HTMLElement,
projectionOptions: ProjectionOptions,
vnodeSelector: string,
properties: VNodeProperties
): void {
this._addElementToNodeHandler(element, projectionOptions, properties);
this.onElementUpdated(element, String(properties.key));
}

private _addElementToNodeHandler(element: HTMLElement, projectionOptions: ProjectionOptions, properties: VNodeProperties) {
this._currentRootNode++;
const isLastRootNode = (this._currentRootNode === this._numRootNodes);

if (this._projectorAttachEvent === undefined) {
this._projectorAttachEvent = projectionOptions.nodeEvent.on('rendered', () => {
this._nodeHandler.addProjector();
});
this.own(this._projectorAttachEvent);
const isRootNode = !properties.key || this._rootNodeKeys.indexOf(properties.key) > -1;
const hasKey = !!properties.key;
let isLastRootNode = false;

if (isRootNode) {
this._currentRootNode++;
isLastRootNode = (this._currentRootNode === this._numRootNodes);

if (this._projectorAttachEvent === undefined) {
this._projectorAttachEvent = projectionOptions.nodeEvent.on('rendered', () => {
this._nodeHandler.addProjector();
});
this.own(this._projectorAttachEvent);
}
}

if (isLastRootNode) {
this._nodeHandler.addRoot(element, properties);
}
else {
else if (hasKey) {
this._nodeHandler.add(element, properties);
}
}
Expand Down Expand Up @@ -466,13 +454,15 @@ export class WidgetBase<P = WidgetProperties, C extends DNode = DNode> extends E
this._numRootNodes = nodes.length;
this._currentRootNode = 0;
const rootNodes: DNode[] = [];
this._rootNodeKeys = [];

nodes.forEach(node => {
if (isHNode(node)) {
rootNodes.push(node);
node.properties = node.properties || {};
node.properties.afterCreate = this._afterRootCreateCallback;
node.properties.afterUpdate = this._afterRootUpdateCallback;
if (node.properties.key) {
this._rootNodeKeys.push(node.properties.key);
}
}
});

Expand All @@ -481,7 +471,7 @@ export class WidgetBase<P = WidgetProperties, C extends DNode = DNode> extends E
if (isHNode(node) || isWNode(node)) {
node.properties = node.properties || {};
if (isHNode(node)) {
if (rootNodes.indexOf(node) === -1 && node.properties.key) {
if (rootNodes.indexOf(node) === -1 || node.properties.key) {
node.properties.afterCreate = this._afterCreateCallback;
node.properties.afterUpdate = this._afterUpdateCallback;
}
Expand Down
11 changes: 7 additions & 4 deletions tests/unit/WidgetBase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -572,19 +572,22 @@ registerSuite({
assert.lengthOf(qux.children, 1);
const bar = qux.children[0];
assert.equal(bar.vnodeSelector, 'bar');
assert.deepEqual(bar.properties, { bind: widget, foo: 'bar' });
assert.deepEqual(bar.properties.bind, widget);
assert.deepEqual(bar.properties.foo, 'bar');
assert.lengthOf(bar.children, 2);
const foo = bar.children[0];
assert.equal(foo.vnodeSelector, 'foo');
assert.deepEqual(foo.properties, { bind: widget });
assert.deepEqual(foo.properties.bind, widget);
assert.lengthOf(foo.children, 1);
const baz1 = foo.children[0];
assert.equal(baz1.vnodeSelector, 'baz');
assert.deepEqual(baz1.properties, { bind: widget, baz: 'qux' });
assert.deepEqual(baz1.properties.bind, widget);
assert.deepEqual(baz1.properties.baz, 'qux');
assert.lengthOf(baz1.children, 0);
const baz2 = bar.children[1];
assert.equal(baz2.vnodeSelector, 'baz');
assert.deepEqual(baz2.properties, { bind: widget, baz: 'qux' });
assert.deepEqual(baz2.properties.bind, widget);
assert.deepEqual(baz2.properties.baz, 'qux');
assert.lengthOf(baz2.children, 0);
},
'class level decorator'() {
Expand Down
16 changes: 8 additions & 8 deletions tests/unit/lifecycle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ registerSuite({
const Projector = ProjectorMixin(WidgetA);
const projector = new Projector();
const handle = projector.append(root);
assert.strictEqual(projector.lifeCycleCreated.length, 2);
assert.strictEqual(projector.lifeCycleCreated.length, 3);
assert.strictEqual(projector.lifeCycleUpdated.length, 0);
handle.destroy();
},
Expand All @@ -162,18 +162,18 @@ registerSuite({
const projector = new Projector();
const handle = projector.append(root);
assert.strictEqual(projector.lifeCycleCreated[0].key, 'div2');
assert.strictEqual(projector.lifeCycleCreated[1].key, 'div1');
assert.strictEqual(projector.lifeCycleCreated[2].key, 'div1');
handle.destroy();
},

'on create with afterCreate'() {
const Projector = ProjectorMixin(WidgetB);
const projector = new Projector();
const handle = projector.append(root);
assert.strictEqual(projector.lifeCycleCreated.length, 2);
// afterCreateCounter will be 1 because the other two afterCreate callbacks will be replaced in
assert.strictEqual(projector.lifeCycleCreated.length, 3);
// afterCreateCounter will be 0 because all afterCreate callbacks will be replaced in
// WidgetBase.
assert.strictEqual(afterCreateCounter, 1);
assert.strictEqual(afterCreateCounter, 0);
assert.strictEqual(afterUpdateCounter, 0);
assert.strictEqual(projector.lifeCycleUpdated.length, 0);
handle.destroy();
Expand All @@ -195,7 +195,7 @@ registerSuite({
}, 'DOM update did not occur', 10);

assert.strictEqual(projector.lifeCycleCreated.length, 1, 'Unexpected number of created nodes.');
assert.strictEqual(projector.lifeCycleUpdated.length, 2, 'Unexpected number of updated nodes.');
assert.strictEqual(projector.lifeCycleUpdated.length, 3, 'Unexpected number of updated nodes.');
},

async 'on update with afterUpdate'() {
Expand All @@ -215,9 +215,9 @@ registerSuite({
}, 'DOM update did not occur', 10);

assert.strictEqual(projector.lifeCycleCreated.length, 1, 'Unexpected number of created nodes.');
assert.strictEqual(projector.lifeCycleUpdated.length, 2, 'Unexpected number of updated nodes.');
assert.strictEqual(projector.lifeCycleUpdated.length, 3, 'Unexpected number of updated nodes.');
assert.strictEqual(afterCreateCounter, 0); // afterCreate callback is replaced in WidgetBase.
assert.strictEqual(afterUpdateCounter, 1); // afterUpdate callback is replaced in WidgetBase.
assert.strictEqual(afterUpdateCounter, 0); // afterUpdate callback is replaced in WidgetBase.
},

async 'basic widget that always re-renders'() {
Expand Down
82 changes: 32 additions & 50 deletions tests/unit/mixins/Projector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,10 @@ import '@dojo/shim/Promise';
import { VNode } from '@dojo/interfaces/vdom';
import * as registerSuite from 'intern!object';
import * as assert from 'intern/chai!assert';
import { spy } from 'sinon';
import { spy, stub, SinonStub } from 'sinon';
import { v } from '../../../src/d';
import { ProjectorMixin, ProjectorAttachState } from '../../../src/mixins/Projector';
import { beforeRender, WidgetBase } from '../../../src/WidgetBase';
import { waitFor } from '../waitFor';

const Event = global.window.Event;

Expand Down Expand Up @@ -44,26 +43,27 @@ function sendAnimationEndEvents(element: Element) {
dispatchEvent(element, 'animationend');
}

let rafSpy: any;
let cancelRafSpy: any;
let rafStub: SinonStub;
let cancelRafStub: SinonStub;
let projector: BaseTestWidget | MyWidget;

registerSuite({
name: 'mixins/projectorMixin',

beforeEach() {
result = null;
rafSpy = spy(global, 'requestAnimationFrame');
cancelRafSpy = spy(global, 'cancelAnimationFrame');
rafStub = stub(global, 'requestAnimationFrame').returns(1);
rafStub.yields();
cancelRafStub = stub(global, 'cancelAnimationFrame');
},

afterEach() {
if (projector) {
projector.destroy();
projector = <any> undefined;
}
rafSpy.restore();
cancelRafSpy.restore();
rafStub.restore();
cancelRafStub.restore();
},
'attach to projector': {
'append': {
Expand Down Expand Up @@ -636,7 +636,7 @@ registerSuite({

projector.pause();
projector.scheduleRender();
assert.isFalse(rafSpy.called);
assert.isFalse(rafStub.called);
},
'pause cancels animation frame if scheduled'() {
const projector = new BaseTestWidget();
Expand All @@ -645,7 +645,7 @@ registerSuite({

projector.scheduleRender();
projector.pause();
assert.isTrue(cancelRafSpy.called);
assert.isTrue(cancelRafStub.called);
},
'resume'() {
const projector = new BaseTestWidget();
Expand Down Expand Up @@ -786,14 +786,14 @@ registerSuite({

projector.invalidate();

assert.isFalse(rafSpy.called);
assert.isFalse(rafStub.called);
},
'invalidate after attached'() {
const projector: any = new BaseTestWidget();

projector.append();
projector.invalidate();
assert.isTrue(rafSpy.called);
assert.isTrue(rafStub.called);
},
'reattach'() {
const root = document.createElement('div');
Expand Down Expand Up @@ -869,8 +869,8 @@ registerSuite({
}

const projector = new TestProjector();

await projector.append();
projector.async = false;
projector.append();

children.push(v('div', {
id: 'test-element',
Expand All @@ -880,25 +880,19 @@ registerSuite({

projector.callInvalidate();

await waitFor(() => {
return document.getElementById('test-element') !== null;
}, 'Element was never added');

const domNode = document.getElementById('test-element')!;

await waitFor(() => {
return domNode.classList.contains('fade-in') && domNode.classList.contains('fade-in-active');
}, 'fade-in classes never got added to element');
assert.isNotNull(domNode);
assert.isTrue(domNode.classList.contains('fade-in'));
assert.isTrue(domNode.classList.contains('fade-in-active'));

// manually fire the transition end events
sendAnimationEndEvents(domNode);
sendAnimationEndEvents(domNode!);

children = [];
projector.callInvalidate();

await waitFor(() => {
return domNode.classList.contains('fade-out') && domNode.classList.contains('fade-out-active');
}, 'fade-out classes never got added to element');
assert.isTrue(domNode.classList.contains('fade-out'));
assert.isTrue(domNode.classList.contains('fade-out-active'));

domNode.parentElement!.removeChild(domNode);
},
Expand All @@ -918,8 +912,8 @@ registerSuite({
}

const projector = new TestProjector();

await projector.append();
projector.async = false;
projector.append();

children.push(v('div', {
id: 'test-element',
Expand All @@ -931,25 +925,19 @@ registerSuite({

projector.callInvalidate();

await waitFor(() => {
return document.getElementById('test-element') !== null;
}, 'Element was never added');

const domNode = document.getElementById('test-element')!;

await waitFor(() => {
return domNode.classList.contains('fade-in') && domNode.classList.contains('active-fade-in');
}, 'fade-in classes never got added to element');
assert.isNotNull(domNode);
assert.isTrue(domNode.classList.contains('fade-in'));
assert.isTrue(domNode.classList.contains('active-fade-in'));

// manually fire the transition end events
sendAnimationEndEvents(domNode);

children = [];
projector.callInvalidate();

await waitFor(() => {
return domNode.classList.contains('fade-out') && domNode.classList.contains('active-fade-out');
}, 'fade-out classes never got added to element');
assert.isTrue(domNode.classList.contains('fade-out'));
assert.isTrue(domNode.classList.contains('active-fade-out'));

domNode.parentElement!.removeChild(domNode);
},
Expand All @@ -976,27 +964,21 @@ registerSuite({
}

const projector = new TestProjector();

projector.async = false;
await projector.append();

await waitFor(() => {
return document.getElementById('test-element') !== null;
}, 'Element was never added');

const domNode = document.getElementById('test-element')!;
assert.isNotNull(domNode);

children = [];
projector.callInvalidate();

await waitFor(() => {
return domNode.classList.contains('fade-out') && domNode.classList.contains('fade-out-active');
}, 'fade-out classes never got added to element');
assert.isTrue(domNode.classList.contains('fade-out'));
assert.isTrue(domNode.classList.contains('fade-out-active'));

// manually fire the transition end events
sendAnimationEndEvents(domNode);

await waitFor(() => {
return document.getElementById('test-element') === null;
}, 'Element never got removed');
assert.isNull(document.getElementById('test-element'));
}
});

0 comments on commit 16d1d33

Please sign in to comment.