// Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. See License.txt in the project root for license information.
//
//
///
///
module WinJSTests {
"use strict";
var ITEMS_COUNT = 5;
var ListView = WinJS.UI.ListView;
function getDataSource(count = ITEMS_COUNT) {
var rawData = [];
for (var i = 0; i < count; i++) {
rawData.push({ itemInfo: "Tile" + i });
}
return new WinJS.Binding.List(rawData).dataSource;
}
function basicRenderer(itemPromise) {
var element = document.createElement("div");
element.style.width = "50px";
element.style.height = "50px";
return {
element: element,
renderComplete: itemPromise.then(function (item) {
element.textContent = item.data.itemInfo;
})
};
}
function verifyListLayout(listView) {
var list = listView.itemDataSource.list;
for (var i = 0; i < list.length; i++) {
var element = listView.elementFromIndex(i),
container = Helper.ListView.containerFrom(element);
LiveUnit.Assert.areEqual(list.getItem(i).data.itemInfo, element.textContent);
LiveUnit.Assert.areEqual(i * 50, Helper.ListView.offsetTopFromSurface(listView, container));
LiveUnit.Assert.areEqual(0, Helper.ListView.offsetLeftFromSurface(listView, container));
}
}
function verifyGridLayout(listView, expectedRows) {
var list = listView.itemDataSource.list,
row = 0,
col = 0,
rtl = (listView._element.style.direction === "rtl");
if (!expectedRows) {
expectedRows = 3;
}
for (var i = 0; i < list.length; i++) {
var element = listView.elementFromIndex(i),
container = Helper.ListView.containerFrom(element);
LiveUnit.Assert.areEqual(list.getItem(i).data.itemInfo, element.textContent);
var expectedLeft = col * 50;
if (rtl) {
expectedLeft = listView._canvas.offsetWidth - expectedLeft - container.offsetWidth;
}
LiveUnit.Assert.areEqual(row * 50, Helper.ListView.offsetTopFromSurface(listView, container));
LiveUnit.Assert.areEqual(expectedLeft, Helper.ListView.offsetLeftFromSurface(listView, container));
row++;
row = row % expectedRows;
if (row == 0) {
col++;
}
}
}
export class ListViewAnimationTest {
// This is the setup function that will be called at the beginning of each test function.
setUp() {
LiveUnit.LoggingCore.logComment("In setup");
var newNode = document.createElement("div");
newNode.id = "AnimationTest";
newNode.style.width = "500px";
newNode.style.height = "500px";
document.body.appendChild(newNode);
}
tearDown() {
LiveUnit.LoggingCore.logComment("In tearDown");
var element = document.getElementById("AnimationTest");
if (element) {
WinJS.Utilities.disposeSubTree(element);
document.body.removeChild(element);
}
}
};
function generateDelayedEntranceAnimation(layoutName) {
ListViewAnimationTest.prototype["testDelayedEntranceAnimation" + layoutName] = function (complete) {
// This test is only useful on a machine that has animations enabled.
if (!WinJS.UI.isAnimationEnabled()) {
complete();
return;
}
var element = document.getElementById("AnimationTest");
element.style.height = "150px";
element.style.direction = "ltr";
var entranceAnimationCount = 0;
WinJS.Utilities["_addEventListener"](element, "animationstart", function (e) {
if (e.animationName.indexOf("enterContent") !== -1) {
entranceAnimationCount++;
}
});
var countAnimationHandlerCalled = 0,
delayedPromiseDone = false;
var animationEventHandler = function (e) {
countAnimationHandlerCalled++;
LiveUnit.Assert.areEqual(1, countAnimationHandlerCalled);
LiveUnit.Assert.areEqual(WinJS.UI.ListViewAnimationType.entrance, e.detail.type);
var delayPromise = WinJS.Promise.timeout(1000).then(function () {
LiveUnit.Assert.areEqual(0, entranceAnimationCount);
delayedPromiseDone = true;
});
e.detail.setPromise(delayPromise);
};
var listView;
var viewCompleteEventHandler = function (e) {
if (listView && listView.loadingState === "complete") {
LiveUnit.Assert.areEqual(1, countAnimationHandlerCalled);
LiveUnit.Assert.areEqual(1, entranceAnimationCount);
element.removeEventListener("contentanimating", animationEventHandler, false);
element.removeEventListener("loadingstatechanged", viewCompleteEventHandler, false);
complete();
}
};
element.addEventListener("contentanimating", animationEventHandler, false);
element.addEventListener("loadingstatechanged", viewCompleteEventHandler, false);
listView = new WinJS.UI.ListView(element, { itemDataSource: getDataSource(), itemTemplate: basicRenderer, layout: new WinJS.UI[layoutName]() });
};
};
function generateSkippedEntranceAnimation(layoutName) {
ListViewAnimationTest.prototype["testSkippedEntranceAnimation" + layoutName] = function (complete) {
// This test is only useful on a machine that has animations enabled.
if (!WinJS.UI.isAnimationEnabled()) {
complete();
return;
}
var element = document.getElementById("AnimationTest");
element.style.height = "150px";
element.style.direction = "ltr";
var entranceAnimationCount = 0;
WinJS.Utilities["_addEventListener"](element, "animationstart", function (e) {
if (e.animationName.indexOf("enterContent") !== -1) {
entranceAnimationCount++;
}
});
var countAnimationHandlerCalled = 0,
delayedPromiseDone = false;
var animationEventHandler = function (e) {
countAnimationHandlerCalled++;
LiveUnit.Assert.areEqual(1, countAnimationHandlerCalled);
LiveUnit.Assert.areEqual(WinJS.UI.ListViewAnimationType.entrance, e.detail.type);
e.preventDefault();
};
var listView;
var viewCompleteEventHandler = function (e) {
if (listView && listView.loadingState === "complete") {
LiveUnit.Assert.areEqual(1, countAnimationHandlerCalled);
LiveUnit.Assert.areEqual(0, entranceAnimationCount);
element.removeEventListener("contentanimating", animationEventHandler, false);
element.removeEventListener("loadingstatechanged", viewCompleteEventHandler, false);
complete();
}
};
element.addEventListener("contentanimating", animationEventHandler, false);
element.addEventListener("loadingstatechanged", viewCompleteEventHandler, false);
listView = new WinJS.UI.ListView(element, { itemDataSource: getDataSource(), itemTemplate: basicRenderer, layout: new WinJS.UI[layoutName]() });
};
};
function generateSkippedContentTransition(layoutName) {
ListViewAnimationTest.prototype["testSkippedContentTransition" + layoutName] = function (complete) {
// This test is only useful on a machine that has animations enabled.
if (!WinJS.UI.isAnimationEnabled()) {
complete();
return;
}
var element = document.getElementById("AnimationTest");
element.style.height = "150px";
element.style.direction = "ltr";
var entranceAnimationCount = 0;
WinJS.Utilities["_addEventListener"](element, "animationstart", function (e) {
if (e.animationName.indexOf("enterContent") !== -1) {
entranceAnimationCount++;
}
});
var countAnimationHandlerCalled = 0,
delayedPromiseDone = false;
var animationEventHandler = function (e) {
countAnimationHandlerCalled++;
if (e.detail.type === WinJS.UI.ListViewAnimationType.entrance) {
LiveUnit.Assert.areEqual(1, countAnimationHandlerCalled);
} else if (e.detail.type === WinJS.UI.ListViewAnimationType.contentTransition) {
LiveUnit.Assert.areEqual(2, countAnimationHandlerCalled);
e.preventDefault();
} else {
LiveUnit.Assert.fail("Got an animation event with an unexpected type");
}
};
element.addEventListener("contentanimating", animationEventHandler, false);
var listView = new WinJS.UI.ListView(element, { itemDataSource: getDataSource(), itemTemplate: basicRenderer, layout: new WinJS.UI[layoutName]() });
var tests = [
function () {
LiveUnit.Assert.areEqual(1, countAnimationHandlerCalled);
LiveUnit.Assert.areEqual(1, entranceAnimationCount);
listView.itemDataSource = getDataSource();
return true;
},
function () {
LiveUnit.Assert.areEqual(2, countAnimationHandlerCalled);
LiveUnit.Assert.areEqual(1, entranceAnimationCount);
element.removeEventListener("contentanimating", animationEventHandler, false);
complete();
}
];
Helper.ListView.runTests(listView, tests);
};
};
function generateInterruptedEntranceAnimationWithContentTransitionPlayed(layoutName) {
ListViewAnimationTest.prototype["testInterruptedEntranceAnimationWithContentTransitionPlayed" + layoutName] = function (complete) {
// This test is only useful on a machine that has animations enabled.
if (!WinJS.UI.isAnimationEnabled()) {
complete();
return;
}
var element = document.getElementById("AnimationTest");
element.style.height = "150px";
element.style.direction = "ltr";
var entranceAnimationCount = 0;
WinJS.Utilities["_addEventListener"](element, "animationstart", function (e) {
if (e.animationName.indexOf("enterContent") !== -1) {
entranceAnimationCount++;
}
});
var countAnimationHandlerCalled = 0,
delayedPromiseDone = false;
var animationEventHandler = function (e) {
countAnimationHandlerCalled++;
if (e.detail.type === WinJS.UI.ListViewAnimationType.entrance) {
LiveUnit.Assert.areEqual(1, countAnimationHandlerCalled);
e.detail.setPromise(WinJS.Promise.timeout(6000).then(function () {
delayedPromiseDone = true;
}));
} else if (e.detail.type === WinJS.UI.ListViewAnimationType.contentTransition) {
LiveUnit.Assert.areEqual(2, countAnimationHandlerCalled);
LiveUnit.Assert.isFalse(delayedPromiseDone);
} else {
LiveUnit.Assert.fail("Got an animation event with an unexpected type");
}
};
var listView,
interruptionDone = false;
var viewCompleteEventHandler = function (e) {
if (listView && listView.loadingState === "complete") {
LiveUnit.Assert.isTrue(interruptionDone);
LiveUnit.Assert.isFalse(delayedPromiseDone);
LiveUnit.Assert.areEqual(2, countAnimationHandlerCalled);
LiveUnit.Assert.areEqual(1, entranceAnimationCount);
element.removeEventListener("contentanimating", animationEventHandler, false);
element.removeEventListener("loadingstatechanged", viewCompleteEventHandler, false);
complete();
}
};
element.addEventListener("contentanimating", animationEventHandler, false);
element.addEventListener("loadingstatechanged", viewCompleteEventHandler, false);
listView = new WinJS.UI.ListView(element, { itemDataSource: getDataSource(), itemTemplate: basicRenderer, layout: new WinJS.UI[layoutName]() });
WinJS.Promise.timeout(1000).then(function () {
interruptionDone = true;
listView.itemDataSource = getDataSource();
});
};
};
function generateInterruptedEntranceAnimationWithNoContentTransitionPlayed(layoutName) {
ListViewAnimationTest.prototype["testInterruptedEntranceAnimationWithNoContentTransitionPlayed" + layoutName] = function (complete) {
// This test is only useful on a machine that has animations enabled.
if (!WinJS.UI.isAnimationEnabled()) {
complete();
return;
}
var element = document.getElementById("AnimationTest");
element.style.height = "150px";
element.style.direction = "ltr";
var entranceAnimationCount = 0;
WinJS.Utilities["_addEventListener"](element, "animationstart", function (e) {
if (e.animationName.indexOf("enterContent") !== -1) {
entranceAnimationCount++;
}
});
var countAnimationHandlerCalled = 0,
delayedPromiseDone = false;
var animationEventHandler = function (e) {
countAnimationHandlerCalled++;
if (e.detail.type === WinJS.UI.ListViewAnimationType.entrance) {
LiveUnit.Assert.areEqual(1, countAnimationHandlerCalled);
e.detail.setPromise(WinJS.Promise.timeout(6000).then(function () {
delayedPromiseDone = true;
}));
} else if (e.detail.type === WinJS.UI.ListViewAnimationType.contentTransition) {
LiveUnit.Assert.areEqual(2, countAnimationHandlerCalled);
LiveUnit.Assert.isFalse(delayedPromiseDone);
e.preventDefault();
} else {
LiveUnit.Assert.fail("Got an animation event with an unexpected type");
}
};
var listView,
interruptionDone = false;
var viewCompleteEventHandler = function (e) {
if (listView && listView.loadingState === "complete") {
LiveUnit.Assert.isTrue(interruptionDone);
LiveUnit.Assert.isFalse(delayedPromiseDone);
LiveUnit.Assert.areEqual(2, countAnimationHandlerCalled);
LiveUnit.Assert.areEqual(0, entranceAnimationCount);
element.removeEventListener("contentanimating", animationEventHandler, false);
element.removeEventListener("loadingstatechanged", viewCompleteEventHandler, false);
complete();
}
};
element.addEventListener("contentanimating", animationEventHandler, false);
element.addEventListener("loadingstatechanged", viewCompleteEventHandler, false);
listView = new WinJS.UI.ListView(element, { itemDataSource: getDataSource(), itemTemplate: basicRenderer, layout: new WinJS.UI[layoutName]() });
WinJS.Promise.timeout(1000).then(function () {
interruptionDone = true;
listView.itemDataSource = getDataSource();
});
};
};
if (!WinJS.Utilities.isPhone) {
generateDelayedEntranceAnimation("GridLayout");
generateSkippedEntranceAnimation("GridLayout");
generateSkippedContentTransition("GridLayout");
generateInterruptedEntranceAnimationWithContentTransitionPlayed("GridLayout");
generateInterruptedEntranceAnimationWithNoContentTransitionPlayed("GridLayout");
}
function generateAnimationEventsWithAnimationsDisabled(layoutName) {
ListViewAnimationTest.prototype["testAnimationEventsWithAnimationsDisabled" + layoutName] = function (complete) {
var element = document.getElementById("AnimationTest");
element.style.height = "150px";
element.style.direction = "ltr";
var entranceAnimationCount = 0;
WinJS.Utilities["_addEventListener"](element, "animationstart", function (e) {
if (e.animationName.indexOf("enterContent") !== -1) {
entranceAnimationCount++;
}
});
var countAnimationHandlerCalled = 0,
// Since we're hacking the ListView's animations disabled function via setting _animationsDisabled below, it's possible that a synchronous listview will
// complete and fire viewstatecomplete + entrance animation events before we've had a chance to override animations disabled. If that happens a couple counts
// will be off by one, so this boolean is used to account for that error
offByOne = false,
delayedPromiseDone = false;
var initializationComplete = false;
var animationEventHandler = function (e) {
countAnimationHandlerCalled++;
if (!initializationComplete) {
offByOne = true;
}
};
element.addEventListener("contentanimating", animationEventHandler, false);
var listView = new ListView(element, { itemDataSource: getDataSource(), itemTemplate: basicRenderer, layout: new WinJS.UI[layoutName]() });
listView._animationsDisabled = function () {
return true;
}
initializationComplete = true;
var tests = [
function () {
LiveUnit.Assert.areEqual((offByOne ? 1 : 0), entranceAnimationCount);
LiveUnit.Assert.areEqual((offByOne ? 1 : 0), countAnimationHandlerCalled);
listView.itemDataSource = getDataSource();
return true;
},
function () {
LiveUnit.Assert.areEqual((offByOne ? 1 : 0), entranceAnimationCount);
LiveUnit.Assert.areEqual((offByOne ? 1 : 0), countAnimationHandlerCalled);
complete();
}
];
Helper.ListView.runTests(listView, tests);
};
};
generateAnimationEventsWithAnimationsDisabled("GridLayout");
}
LiveUnit.registerTestClass("WinJSTests.ListViewAnimationTest");