// 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 ListView = WinJS.UI.ListView;
var _oldMaxTimePerCreateContainers;
var testRootEl,
smallGroups = [],
bigGroups = [],
LAST_LETTER = 26,
SMALL_GROUPS_COUNT = LAST_LETTER * 5,
BIG_GROUPS_COUNT = LAST_LETTER * 15;
function firstLetter(index, count) {
var pom = index * LAST_LETTER / count,
letterIndex = Math.floor(pom);
return String.fromCharCode("A".charCodeAt(0) + letterIndex);
}
function createDataSource(array, async = false) {
var dataSource = {
itemsFromIndex: function (index, countBefore, countAfter) {
return new WinJS.Promise(function (complete, error) {
if (index >= 0 && index < array.length) {
var startIndex = Math.max(0, index - countBefore),
endIndex = Math.min(index + countAfter, array.length - 1),
size = endIndex - startIndex + 1;
var items = [];
for (var i = startIndex; i < startIndex + size; i++) {
items.push({
key: i.toString(),
data: array[i]
});
}
var retVal = {
items: items,
offset: index - startIndex,
totalCount: array.length,
absoluteIndex: index
};
if (async) {
WinJS.Promise.timeout(50).then(function () {
complete(retVal);
});
} else {
complete(retVal);
}
} else {
complete({});
}
});
},
getCount: function () {
return new WinJS.Promise(function (complete) {
if (async) {
WinJS.Promise.timeout(50).then(function () {
complete(array.length);
});
} else {
complete(array.length);
}
});
}
};
return new WinJS.UI.ListDataSource(dataSource);
}
function checkTile(listView, groupIndex, index, left, top, caption?) {
var tile = listView.elementFromIndex(index),
container = Helper.ListView.containerFrom(tile),
offsetXFromSurface = listView._rtl() ? Helper.ListView.offsetRightFromSurface : Helper.ListView.offsetLeftFromSurface;
LiveUnit.Assert.areEqual(caption ? caption : (String.fromCharCode("A".charCodeAt(0) + groupIndex) + " tile " + index), tile.textContent.trim());
LiveUnit.Assert.areEqual(left, offsetXFromSurface(listView, container));
LiveUnit.Assert.areEqual(top, Helper.ListView.offsetTopFromSurface(listView, container));
}
function checkHeader(listView, groupIndex, left, top, id, caption?) {
var tile = document.getElementById(id + groupIndex),
container = Helper.ListView.headerContainerFrom(listView, tile),
offsetXFromSurface = listView._rtl() ? Helper.ListView.offsetRightFromSurface : Helper.ListView.offsetLeftFromSurface;
LiveUnit.Assert.areEqual(caption ? caption : String.fromCharCode("A".charCodeAt(0) + groupIndex), tile.textContent.trim());
LiveUnit.Assert.areEqual(left, offsetXFromSurface(listView, container));
LiveUnit.Assert.areEqual(top, Helper.ListView.offsetTopFromSurface(listView, container));
return container;
}
function createListView(dataSource, options, id?, elementId?) {
function firstLetter(item) {
return item.data.text.toUpperCase().charAt(0);
}
function groupKey(item) {
return firstLetter(item);
}
function groupData(item) {
return {
title: firstLetter(item)
};
}
var element = document.getElementById(elementId ? elementId : "groupTestList"),
itemDataSource = WinJS.UI.computeDataSourceGroups(dataSource, groupKey, groupData),
listView = new ListView(element,
Helper.ListView.extend(options, {
layout: Helper.ListView.extend(options.layout, { groupHeaderPosition: WinJS.UI.HeaderPosition.left }),
itemDataSource: itemDataSource,
itemTemplate: Helper.ListView.createRenderer("groupTestTemplate"),
groupDataSource: itemDataSource.groups,
groupHeaderTemplate: Helper.ListView.createRenderer("groupHeaderTemplate", id)
}));
return listView;
}
function trackState(element) {
var listViewComplete,
listViewCompletePromise = new WinJS.Promise(function (complete) {
listViewComplete = complete;
});
var listViewLoaded,
listViewLoadedPromise = new WinJS.Promise(function (complete) {
listViewLoaded = complete;
});
var state: any = {
states: []
};
function loadingStateChanged(eventObject) {
var control = eventObject.target.winControl;
state.states.push(control.loadingState);
if (control.loadingState === "itemsLoaded") {
listViewLoaded();
} else if (control.loadingState === "complete") {
listViewComplete();
}
}
element.addEventListener("loadingstatechanged", loadingStateChanged, false);
state.loadedPromise = listViewLoadedPromise;
state.completePromise = WinJS.Promise.join([WinJS.Promise.timeout(500), listViewCompletePromise]).then(function () {
element.removeEventListener("loadingstatechanged", loadingStateChanged, false);
return state.states;
});
return state;
}
export class GroupsTests {
// This is the setup function that will be called at the beginning of each test function.
setUp() {
LiveUnit.LoggingCore.logComment("In setup");
smallGroups = [];
bigGroups = [];
for (var i = 0; i < SMALL_GROUPS_COUNT; ++i) {
smallGroups.push({
text: firstLetter(i, SMALL_GROUPS_COUNT) + " tile " + i
});
}
for (i = 0; i < BIG_GROUPS_COUNT; ++i) {
bigGroups.push({
text: firstLetter(i, BIG_GROUPS_COUNT) + " tile " + i
});
}
testRootEl = document.createElement("div");
testRootEl.className = "file-listview-css";
var newNode = document.createElement("div");
newNode.id = "GroupsTests";
newNode.innerHTML =
"" +
"" +
"" +
"" +
"";
testRootEl.appendChild(newNode);
document.body.appendChild(testRootEl);
_oldMaxTimePerCreateContainers = WinJS.UI._VirtualizeContentsView._maxTimePerCreateContainers;
WinJS.UI._VirtualizeContentsView._maxTimePerCreateContainers = Number.MAX_VALUE;
}
tearDown() {
LiveUnit.LoggingCore.logComment("In tearDown");
WinJS.UI._VirtualizeContentsView._maxTimePerCreateContainers = _oldMaxTimePerCreateContainers;
WinJS.Utilities.disposeSubTree(testRootEl);
document.body.removeChild(testRootEl);
WinJS.Utilities.stopLog();
Helper.cleanupUnhandledErrors();
}
// Verifies that when you read indexOfFirstVisible after setting it, it returns the
// value that you set it to. It verifies this under the following conditions:
// - win-groupleader has no margins
// - win-container has margins
// This permits the first group on screen to not have any of its items' contents on
// screen which is what triggered WinBlue#246863.
testIndexOfFirstVisibleWithoutGroupMargins = function (complete) {
var dataSource = Helper.ItemsManager.simpleSynchronousArrayDataSource(bigGroups);
var listView = createListView(dataSource, {
layout: { type: WinJS.UI.GridLayout, groupHeaderPosition: WinJS.UI.HeaderPosition.top },
groupHeaderTemplate: Helper.ListView.createRenderer("smallGroupHeaderTemplate", "groupScrollTo")
});
WinJS.Utilities.addClass(listView.element, "noGroupMargins");
var itemsPerGroup = 15,
firstIndexOfGroup10 = itemsPerGroup * 10;
Helper.ListView.runTests(listView, [
function () {
// Verify the conditions required for triggering the bug.
var groupHeaderContainer = listView.element.querySelector(".win-groupheadercontainer");
var itemsContainer = listView.element.querySelector(".win-itemscontainer");
var container = listView.element.querySelector(".win-container");
LiveUnit.Assert.areEqual("0px", getComputedStyle(groupHeaderContainer).marginLeft, "win-groupleader should have margin-left set to 0");
LiveUnit.Assert.areEqual("0px", getComputedStyle(itemsContainer).marginLeft, "win-groupleader should have margin-left set to 0");
LiveUnit.Assert.areEqual("5px", getComputedStyle(container).marginRight, "win-container should have a margin right of 5px");
listView.indexOfFirstVisible = firstIndexOfGroup10;
},
function () {
LiveUnit.Assert.areEqual(firstIndexOfGroup10, listView.indexOfFirstVisible,
"indexOfFirstVisible returned a value different from the one it was set to");
complete();
}
]);
};
// Verifies that indexOfLastVisible returns the correct value when the ListView
// is scrolled such that the last visible thing is the last column of a partially
// filled group.
// Regression test for WinBlue#259740.
testIndexOfLastVisibleInLastColumnOfAGroup = function (complete) {
var dataSource = Helper.ItemsManager.simpleSynchronousArrayDataSource(bigGroups);
var listView = createListView(dataSource, {
layout: { type: WinJS.UI.GridLayout, groupHeaderPosition: WinJS.UI.HeaderPosition.top },
groupHeaderTemplate: Helper.ListView.createRenderer("groupHeaderTemplate", "groupScrollTo")
});
var itemsPerGroup = 15,
lastIndexOfGroup9 = itemsPerGroup * 10 - 1;
Helper.ListView.runTests(listView, [
function () {
// Verify the conditions required for triggering the bug.
LiveUnit.Assert.isTrue(itemsPerGroup % listView.layout['_itemsPerBar'] > 0, "The last column should have some empty rows");
// Ensure lastIndexOfGroup9 is visible so that we can inspect its offsetLeft and offsetWidth
listView.ensureVisible(lastIndexOfGroup9);
},
function () {
// Scroll the ListView so that the last thing visible is the last column of group 9.
var container = Helper.ListView.containerFrom(listView.elementFromIndex(lastIndexOfGroup9));
listView.scrollPosition = container.offsetLeft + container.offsetWidth - listView._getViewportLength();
},
function () {
LiveUnit.Assert.areEqual(lastIndexOfGroup9, listView.indexOfLastVisible, "indexOfLastVisible is incorrect");
complete();
}
]);
};
// Regression test for WinBlue:212689
testSwitchingFromNoStructureNodesToStructureNodesWithGroups = function (complete) {
var list = new WinJS.Binding.List<{ startDate: Date; text: string; }>();
var element = document.getElementById("groupTestList");
element.style.width = "700px"
var listView = new WinJS.UI.ListView(element);
listView.itemTemplate = function (itemPromise) {
return itemPromise.then(function (data) {
var item = document.createElement("div");
item.textContent = data.data.text;
item.style.height = "400px";
item.style.width = "100px";
return item;
});
};
var groupTimelineList = list.createGrouped(
function (event) {
var startDate = event.startDate;
var year = startDate.getFullYear();
var month = startDate.getMonth();
var day = startDate.getDate();
return "" + year + (month < 10 ? "0" + month : month.toString()) + (day < 10 ? "0" + day : day.toString());
},
function (event) {
return event.startDate;
},
function (leftKey, rightKey) {
return leftKey.localeCompare(rightKey);
});
listView.itemDataSource = groupTimelineList.dataSource;
listView.groupDataSource = groupTimelineList.groups.dataSource;
Helper.ListView.waitForDeferredAction(listView)().then(function () {
WinJS.Utilities._setImmediate(function () {
list.splice(0, 1, { startDate: new Date(2013, 4, 12, 5), text: "Fri 5am" }),
list.splice(1, 1, { startDate: new Date(2013, 4, 12, 6), text: "Fri 6am" }),
list.splice(2, 1, { startDate: new Date(2013, 4, 12, 10), text: "Fri 10am" }),
list.splice(3, 1, { startDate: new Date(2013, 4, 12, 12), text: "Fri 12am" }),
list.splice(4, 1, { startDate: new Date(2013, 4, 13, 8), text: "Sat 8am" }),
list.splice(5, 1, { startDate: new Date(2013, 4, 13, 10), text: "Sat 10am" }),
list.splice(6, 1, { startDate: new Date(2013, 4, 13, 16), text: "Sat 4pm" }),
list.splice(7, 1, { startDate: new Date(2013, 4, 13, 17), text: "Sat 5pm" })
list.splice(8, 1, { startDate: new Date(2013, 4, 14, 15), text: "Sat 3pm" })
list.splice(9, 1, { startDate: new Date(2013, 4, 14, 14), text: "Sat 2pm" })
list.splice(10, 1, { startDate: new Date(2013, 4, 14, 13), text: "Sat 1pm" })
list.splice(11, 1, { startDate: new Date(2013, 4, 15, 14), text: "Sat 2pm" })
list.splice(12, 1, { startDate: new Date(2013, 4, 16, 15), text: "Sat 3pm" })
list.splice(13, 1, { startDate: new Date(2013, 4, 17, 16), text: "Sat 4pm" })
list.splice(14, 1, { startDate: new Date(2013, 4, 18, 17), text: "Sat 5pm" })
list.splice(15, 1, { startDate: new Date(2013, 4, 19, 18), text: "Sat 6pm" })
list.splice(16, 1, { startDate: new Date(2013, 4, 20, 19), text: "Sat 7pm" })
list.splice(17, 1, { startDate: new Date(2013, 4, 21, 20), text: "Sat 8pm" })
list.splice(18, 1, { startDate: new Date(2013, 4, 22, 21), text: "Sat 9pm" })
});
Helper.ListView.waitForDeferredAction(listView)().then(function () {
list.splice(5, 1);
Helper.ListView.waitForDeferredAction(listView)(400).then(function () {
list.splice(2, 0, { startDate: new Date(2013, 4, 12, 11), text: "Fri 11am" })
Helper.ListView.waitForDeferredAction(listView)(400).then(complete);
});
});
});
};
testCustomGroupDataSource = function (complete) {
var flavors = [
{ text: "Banana Blast", kind: "IC" },
{ text: "Lavish Lemon Ice", kind: "ST" },
{ text: "Marvelous Mint", kind: "IC" },
{ text: "Creamy Orange", kind: "IC" },
{ text: "Succulent Strawberry", kind: "ST" },
{ text: "Very Vanilla", kind: "IC" },
{ text: "Banana Blast", kind: "FY" },
{ text: "Lavish Lemon Ice", kind: "ST" },
{ text: "Marvelous Mint", kind: "GO" },
{ text: "Creamy Orange", kind: "ST" },
{ text: "Succulent Strawberry", kind: "IC" },
];
var desertTypes: any = [
{ key: "IC", title: "Ice Cream" },
{ key: "FY", title: "Low-fat frozen yogurt" },
{ key: "ST", title: "Sorbet" },
{ key: "GO", title: "Gelato" }
];
//
// Flavors Data Adapter
//
// Data adapter for items. Follows the same pattern as the Bing Search adapter. The main concerns when
// creating a data adapter for grouping are:
// * Listview works on an item-first mechanism, so the items need to be sorted and already arranged by group.
// * Supply the key for the group using the groupKey property for each item
//
var flavorsDataAdapter = WinJS.Class.define(
function (data) {
// Constructor
this._itemData = data;
},
// Data Adapter interface methods
// These define the contract between the virtualized datasource and the data adapter.
// These methods will be called by virtualized datasource to fetch items, count etc.
{
// This example only implements the itemsFromIndex and count methods
// Called to get a count of the items, result should be a promise for the items
getCount: function () {
var that = this;
return WinJS.Promise.wrap(that._itemData.length);
},
// Called by the virtualized datasource to fetch items
// It will request a specific item index and hints for a number of items either side of it
// The implementation should return the specific item, and can choose how many either side.
// to also send back. It can be more or less than those requested.
//
// Must return back an object containing fields:
// items: The array of items of the form:
// [{ key: key1, groupKey: group1, data : { field1: value, field2: value, ... }}, { key: key2, groupKey: group1, data : {...}}, ...]
// offset: The offset into the array for the requested item
// totalCount: (optional) Update the count for the collection
itemsFromIndex: function (requestIndex, countBefore, countAfter) {
var that = this;
if (requestIndex >= that._itemData.length) {
return WinJS.Promise.wrapError(new WinJS.ErrorFromName(WinJS.UI.FetchError.doesNotExist.toString()));
}
var lastFetchIndex = Math.min(requestIndex + countAfter, that._itemData.length - 1);
var fetchIndex = Math.max(requestIndex - countBefore, 0);
var results = [];
// iterate and form the collection of items
for (var i = fetchIndex; i <= lastFetchIndex; i++) {
var item = that._itemData[i];
results.push({
key: i.toString(), // the key for the item itself
groupKey: item.kind, // the key for the group for the item
data: item // the data fields for the item
});
}
// return a promise for the results
return WinJS.Promise.wrap({
items: results, // The array of items
offset: requestIndex - fetchIndex, // The offset into the array for the requested item
totalCount: that._itemData.length // the total count
});
}
});
// Create a DataSource by deriving and wrapping the data adapter with a VirtualizedDataSource
var flavorsDataSource = WinJS.Class.derive(WinJS.UI.VirtualizedDataSource, function (data) {
this._baseDataSourceConstructor(new flavorsDataAdapter(data));
});
//
// Groups Data Adapter
//
// Data adapter for the groups. Follows the same pattern as the items data adapter, but each item is a group.
// The main concerns when creating a data adapter for groups are:
// * Groups can be enumerated by key or index, so the adapter needs to implement both itemsFromKey and itemsFromIndex
// * Each group should supply a firstItemIndexHint which is the index of the first item in the group. This enables listview
// to figure out the position of an item in the group so it can get the columns correct.
//
var desertsDataAdapter = WinJS.Class.define(
function (groupData) {
// Constructor
this._groupData = groupData;
},
// Data Adapter interface methods
// These define the contract between the virtualized datasource and the data adapter.
// These methods will be called by virtualized datasource to fetch items, count etc.
{
// This example only implements the itemsFromIndex, itemsFromKey and count methods
// Called to get a count of the items, this can be async so return a promise for the count
getCount: function () {
var that = this;
return WinJS.Promise.wrap(that._groupData.length);
},
// Called by the virtualized datasource to fetch a list of the groups based on group index
// It will request a specific group and hints for a number of groups either side of it
// The implementation should return the specific group, and can choose how many either side
// to also send back. It can be more or less than those requested.
//
// Must return back an object containing fields:
// items: The array of groups of the form:
// [{ key: groupkey1, firstItemIndexHint: 0, data : { field1: value, field2: value, ... }}, { key: groupkey2, firstItemIndexHint: 27, data : {...}}, ...
// offset: The offset into the array for the requested group
// totalCount: (optional) an update of the count of items
itemsFromIndex: function (requestIndex, countBefore, countAfter) {
var that = this;
if (requestIndex >= that._groupData.length) {
return WinJS.Promise.wrapError(new WinJS.ErrorFromName(WinJS.UI.FetchError.doesNotExist.toString()));
}
var lastFetchIndex = Math.min(requestIndex + countAfter, that._groupData.length - 1);
var fetchIndex = Math.max(requestIndex - countBefore, 0);
var results = [];
// form the array of groups
for (var i = fetchIndex; i <= lastFetchIndex; i++) {
var group = that._groupData[i];
results.push({
key: group.key,
firstItemIndexHint: group.firstItemIndex,
data: group
});
}
return WinJS.Promise.wrap({
items: results, // The array of items
offset: requestIndex - fetchIndex, // The offset into the array for the requested item
totalCount: that._groupData.length // The total count
});
},
// Called by the virtualized datasource to fetch groups based on the group's key
// It will request a specific group and hints for a number of groups either side of it
// The implementation should return the specific group, and can choose how many either side
// to also send back. It can be more or less than those requested.
//
// Must return back an object containing fields:
// [{ key: groupkey1, firstItemIndexHint: 0, data : { field1: value, field2: value, ... }}, { key: groupkey2, firstItemIndexHint: 27, data : {...}}, ...
// offset: The offset into the array for the requested group
// absoluteIndex: the index into the list of groups of the requested group
// totalCount: (optional) an update of the count of items
itemsFromKey: function (requestKey, countBefore, countAfter) {
var that = this;
var requestIndex = null;
// Find the group in the collection
for (var i = 0, len = that._groupData.length; i < len; i++) {
if (that._groupData[i].key === requestKey) {
requestIndex = i;
break;
}
}
if (requestIndex === null) {
return WinJS.Promise.wrapError(new WinJS.ErrorFromName(WinJS.UI.FetchError.doesNotExist.toString()));
}
var lastFetchIndex = Math.min(requestIndex + countAfter, that._groupData.length - 1);
var fetchIndex = Math.max(requestIndex - countBefore, 0);
var results = [];
//iterate and form the collection of the results
for (var j = fetchIndex; j <= lastFetchIndex; j++) {
var group = that._groupData[j];
results.push({
key: group.key, // The key for the group
firstItemIndexHint: group.firstItemIndex, // The index into the items for the first item in the group
data: group // The data for the specific group
});
}
// Results can be async so the result is supplied as a promise
return WinJS.Promise.wrap({
items: results, // The array of items
offset: requestIndex - fetchIndex, // The offset into the array for the requested item
absoluteIndex: requestIndex, // The index into the collection of the item referenced by key
totalCount: that._groupData.length // The total length of the collection
});
},
});
// Create a DataSource by deriving and wrapping the data adapter with a VirtualizedDataSource
var desertsDataSource = WinJS.Class.derive(WinJS.UI.VirtualizedDataSource, function (data) {
this._baseDataSourceConstructor(new desertsDataAdapter(data));
});
// form an array of the keys to help with the sort
var groupKeys = [];
for (var i = 0; i < desertTypes.length; i++) {
groupKeys[i] = desertTypes[i].key;
}
var itemData = flavors;
itemData.sort(function CompareForSort(item1, item2) {
var first = groupKeys.indexOf(item1.kind), second = groupKeys.indexOf(item2.kind);
if (first === second) { return item1.text.localeCompare(item2.text); }
else if (first < second) { return -1; }
else { return 1; }
});
// Calculate the indexes of the first item for each group, ideally this should also be done at the source of the data
var itemIndex = 0;
for (var j = 0, len = desertTypes.length; j < len; j++) {
desertTypes[j].firstItemIndex = itemIndex;
var key = desertTypes[j].key;
for (var k = itemIndex, len2 = itemData.length; k < len2; k++) {
if (itemData[k].kind !== key) {
itemIndex = k;
break;
}
}
}
// Create the datasources that will then be set on the datasource
var itemDataSource = new flavorsDataSource(itemData);
var groupDataSource = new desertsDataSource(desertTypes);
var listView = new WinJS.UI.ListView(document.getElementById("groupTestList"), {
itemDataSource: itemDataSource,
groupDataSource: groupDataSource,
itemTemplate: Helper.ListView.createRenderer("groupTestTemplate"),
groupHeaderTemplate: Helper.ListView.createRenderer("groupHeaderTemplate")
});
return Helper.ListView.waitForReady(listView, -1)().then(function () {
checkTile(listView, 0, 0, 50, 200, "Banana Blast");
complete();
});
};
testRequestGroupBeforeListViewReady = function (complete) {
var data = [];
for (var i = 0; i < 100; i++) {
data.push({ data: i + "" });
}
var list = new WinJS.Binding.List(data);
var glist = list.createGrouped(function (item) {
return Math.floor(item.data / 10) + "";
}, function (item) {
return { data: Math.floor(item.data / 10) + "" };
});
var lv = new ListView();
lv.itemDataSource = glist.dataSource;
lv.groupDataSource = glist.groups.dataSource;
testRootEl.appendChild(lv.element);
lv._groups.requestHeader(0).then(function () {
testRootEl.removeChild(lv.element);
complete();
});
};
};
function generateSimpleLayout(layout) {
GroupsTests.prototype["testSimpleLayout" + (layout == "GridLayout" ? "" : layout)] = function (complete) {
var listView = createListView(createDataSource(smallGroups), { layout: { type: WinJS.UI[layout] } }, "groupSimpleLayout");
Helper.ListView.whenLoadingComplete(listView, function () {
// first group
checkHeader(listView, 0, 50, 0, "groupSimpleLayout");
checkTile(listView, 0, 0, 250, 0);
checkTile(listView, 0, 1, 250, 100);
checkTile(listView, 0, 4, 350, 0);
// second group
checkHeader(listView, 1, 500, 0, "groupSimpleLayout");
checkTile(listView, 1, 5, 700, 0);
checkTile(listView, 1, 6, 700, 100);
checkTile(listView, 1, 9, 800, 0);
complete();
});
};
};
generateSimpleLayout("GridLayout");
function generateSimpleLayoutAsyncDataSource(layout) {
GroupsTests.prototype["testSimpleLayoutAsyncDataSource" + (layout == "GridLayout" ? "" : layout)] = function (complete) {
var listView = createListView(createDataSource(smallGroups, true), { layout: { type: WinJS.UI[layout] } }, "groupSimpleLayoutAsyncDataSource");
Helper.ListView.whenLoadingComplete(listView, function () {
// first group
checkHeader(listView, 0, 50, 0, "groupSimpleLayoutAsyncDataSource");
checkTile(listView, 0, 0, 250, 0);
checkTile(listView, 0, 1, 250, 100);
checkTile(listView, 0, 4, 350, 0);
// second group
checkHeader(listView, 1, 500, 0, "groupSimpleLayoutAsyncDataSource");
checkTile(listView, 1, 5, 700, 0);
checkTile(listView, 1, 6, 700, 100);
checkTile(listView, 1, 9, 800, 0);
complete();
});
};
};
generateSimpleLayoutAsyncDataSource("GridLayout");
function generateSimpleLayoutAsyncRenderer(layout) {
GroupsTests.prototype["testSimpleLayoutAsyncRenderer" + (layout == "GridLayout" ? "" : layout)] = function (complete) {
var listView = createListView(createDataSource(smallGroups, true), {
layout: { type: WinJS.UI[layout] },
itemTemplate: Helper.ListView.createAsyncRenderer("groupTestTemplate", 100, 100),
groupHeaderTemplate: Helper.ListView.createAsyncRenderer("groupHeaderTemplate", 200, 200, "groupSimpleLayoutAsyncRenderer")
});
Helper.ListView.whenLoadingComplete(listView, function () {
// first group
checkHeader(listView, 0, 50, 0, "groupSimpleLayoutAsyncRenderer");
checkTile(listView, 0, 0, 250, 0);
checkTile(listView, 0, 1, 250, 100);
checkTile(listView, 0, 4, 350, 0);
// second group
checkHeader(listView, 1, 500, 0, "groupSimpleLayoutAsyncRenderer");
checkTile(listView, 1, 5, 700, 0);
checkTile(listView, 1, 6, 700, 100);
checkTile(listView, 1, 9, 800, 0);
complete();
});
};
};
generateSimpleLayoutAsyncRenderer("GridLayout");
function generateHeaderAbove(layout) {
GroupsTests.prototype["testHeaderAbove" + (layout == "GridLayout" ? "" : layout)] = function (complete) {
var myData = [],
c = 0;
function addGroup(letter, count) {
for (var i = 0; i < count; ++i) {
myData.push({
text: letter + " tile " + c
});
c++;
}
}
addGroup("A", 5);
addGroup("B", 5);
addGroup("C", 1);
addGroup("D", 4);
addGroup("E", 10);
var dataSource = Helper.ItemsManager.simpleSynchronousArrayDataSource(myData);
var listView = createListView(dataSource, { layout: { type: WinJS.UI[layout], groupHeaderPosition: WinJS.UI.HeaderPosition.top } }, "groupHeaderAbove");
Helper.ListView.whenLoadingComplete(listView, function () {
// first group
var header = checkHeader(listView, 0, 50, 0, "groupHeaderAbove");
LiveUnit.Assert.areEqual(300, header.offsetWidth);
checkTile(listView, 0, 0, 50, 200);
checkTile(listView, 0, 1, 50, 300);
checkTile(listView, 0, 4, 250, 200);
// second group
checkHeader(listView, 1, 400, 0, "groupHeaderAbove");
checkTile(listView, 1, 5, 400, 200);
checkTile(listView, 1, 6, 400, 300);
checkTile(listView, 1, 9, 600, 200);
header = checkHeader(listView, 2, 750, 0, "groupHeaderAbove");
LiveUnit.Assert.areEqual(100, header.offsetWidth);
header = checkHeader(listView, 3, 900, 0, "groupHeaderAbove");
LiveUnit.Assert.areEqual(200, header.offsetWidth);
complete();
});
};
};
generateHeaderAbove("GridLayout");
function generateRtl(layout) {
GroupsTests.prototype["testRtl" + (layout == "GridLayout" ? "" : layout)] = function (complete) {
var dataSource = Helper.ItemsManager.simpleSynchronousArrayDataSource(smallGroups);
var listView = createListView(dataSource, { layout: { type: WinJS.UI[layout] } }, "groupRtlTestList", "groupRtlTestList");
Helper.ListView.whenLoadingComplete(listView, function () {
// first group
checkHeader(listView, 0, 50, 0, "groupRtlTestList");
checkTile(listView, 0, 0, 250, 0);
checkTile(listView, 0, 1, 250, 100);
checkTile(listView, 0, 4, 350, 0);
// second group
checkHeader(listView, 1, 500, 0, "groupRtlTestList");
checkTile(listView, 1, 5, 700, 0);
checkTile(listView, 1, 6, 700, 100);
checkTile(listView, 1, 9, 800, 0);
complete();
});
};
};
generateRtl("GridLayout");
function generateScrollTo(layout) {
GroupsTests.prototype["testScrollTo" + (layout == "GridLayout" ? "" : layout)] = function (complete) {
var dataSource = Helper.ItemsManager.simpleSynchronousArrayDataSource(bigGroups);
var listView = createListView(dataSource, {
layout: { type: WinJS.UI[layout] },
groupHeaderTemplate: Helper.ListView.createRenderer("smallGroupHeaderTemplate", "groupScrollTo")
});
Helper.ListView.runTests(listView, [
function () {
checkHeader(listView, 0, 50, 0, "groupScrollTo");
checkTile(listView, 0, 0, 150, 0);
listView.indexOfFirstVisible = 106;
},
function () {
var element = document.getElementById("groupTestList"),
viewportElement = Helper.ListView.viewport(element),
scrollOffset = WinJS.Utilities.getScrollPosition(viewportElement).scrollLeft;
checkHeader(listView, 7, scrollOffset - 50, 0, "groupScrollTo");
checkTile(listView, 7, 105, scrollOffset + 50, 0);
checkTile(listView, 7, 106, scrollOffset + 50, 100);
checkTile(listView, 7, 109, scrollOffset + 150, 0);
complete();
}
]);
};
};
generateScrollTo("GridLayout");
function generateScrollLeft(layout) {
GroupsTests.prototype["testScrollLeft" + (layout == "GridLayout" ? "" : layout)] = function (complete) {
var dataSource = Helper.ItemsManager.simpleSynchronousArrayDataSource(bigGroups);
var listView = createListView(dataSource, {
layout: { type: WinJS.UI[layout] },
groupHeaderTemplate: Helper.ListView.createRenderer("smallGroupHeaderTemplate", "groupScrollLeft")
}),
element = document.getElementById("groupTestList"),
viewportElement = Helper.ListView.viewport(element);
Helper.ListView.runTests(listView, [
function () {
checkHeader(listView, 0, 50, 0, "groupScrollLeft");
checkTile(listView, 0, 0, 150, 0);
listView.indexOfFirstVisible = 340;
return true;
},
function () {
var position = WinJS.Utilities.getScrollPosition(viewportElement);
position.scrollLeft = position.scrollLeft - viewportElement.offsetWidth;
LiveUnit.Assert.areEqual(338, listView.indexOfFirstVisible);
// Verify that we have realized content for the item
checkTile(listView, 22, 338, 12450, 0);
LiveUnit.LoggingCore.logComment("scrolling from " + WinJS.Utilities.getScrollPosition(viewportElement).scrollLeft + " to " + position.scrollLeft);
WinJS.Utilities.setScrollPosition(viewportElement, position);
return true;
},
function () {
//LiveUnit.Assert.areEqual(337, listView.lastVisible());
LiveUnit.LoggingCore.logComment("scrollPos=" + WinJS.Utilities.getScrollPosition(viewportElement).scrollLeft + " lastVisible=" + listView.indexOfLastVisible);
complete();
}
]);
};
};
generateScrollLeft("GridLayout");
function generateAdd(layout) {
GroupsTests.prototype["testAdd" + (layout == "GridLayout" ? "" : layout)] = function (complete) {
var dataSource = Helper.ItemsManager.simpleSynchronousArrayDataSource(smallGroups);
var listView = createListView(dataSource, { layout: { type: WinJS.UI[layout] } }, "groupAdd");
Helper.ListView.runTests(listView, [
function () {
// first group
checkHeader(listView, 0, 50, 0, "groupAdd");
checkTile(listView, 0, 0, 250, 0);
checkTile(listView, 0, 1, 250, 100);
checkTile(listView, 0, 4, 350, 0);
// second group
checkHeader(listView, 1, 500, 0, "groupAdd");
checkTile(listView, 1, 5, 700, 0);
checkTile(listView, 1, 6, 700, 100);
checkTile(listView, 1, 9, 800, 0);
Helper.ListView.getDataObjects(listView.itemDataSource, [5]).done(function (dataObjects) {
listView.itemDataSource.beginEdits();
listView.itemDataSource.insertBefore(null, { text: "A NewTile" }, dataObjects[0].key);
listView.itemDataSource.insertBefore(null, { text: "A NewTile" }, dataObjects[0].key);
listView.itemDataSource.insertBefore(null, { text: "A NewTile" }, dataObjects[0].key);
listView.itemDataSource.insertBefore(null, { text: "A NewTile" }, dataObjects[0].key);
listView.itemDataSource.endEdits();
});
return true;
},
function () {
checkHeader(listView, 0, 50, 0, "groupAdd");
checkTile(listView, 0, 0, 250, 0);
checkTile(listView, 0, 1, 250, 100);
checkTile(listView, 0, 4, 350, 0);
checkTile(listView, 0, 5, 350, 100, "A NewTile");
checkTile(listView, 0, 6, 350, 200, "A NewTile");
checkTile(listView, 0, 7, 350, 300, "A NewTile");
checkTile(listView, 0, 8, 450, 0, "A NewTile");
// second group
checkHeader(listView, 1, 600, 0, "groupAdd");
checkTile(listView, 1, 9, 800, 0, "B tile 5");
checkTile(listView, 1, 10, 800, 100, "B tile 6");
complete();
}
]);
};
};
generateAdd("GridLayout");
function generateAddGroup(layout) {
GroupsTests.prototype["testAddGroup" + (layout == "GridLayout" ? "" : layout)] = function (complete) {
function test(itemDataSource, groupDataSource, edit) {
return new WinJS.Promise(function (testComplete) {
var listView = new WinJS.UI.ListView(document.getElementById("groupTestList"), {
layout: { type: WinJS.UI[layout] },
itemDataSource: itemDataSource,
itemTemplate: Helper.ListView.createRenderer("groupTestTemplate"),
groupDataSource: groupDataSource,
groupHeaderTemplate: Helper.ListView.createRenderer("smallGroupHeaderTemplate", "groupAddGroup")
});
Helper.ListView.runTests(listView, [
function () {
// first group
checkHeader(listView, 0, 50, 0, "groupAddGroup");
checkTile(listView, 0, 0, 50, 100);
checkTile(listView, 0, 1, 50, 200);
checkTile(listView, 0, 2, 50, 300);
checkTile(listView, 0, 3, 150, 100);
checkTile(listView, 0, 4, 150, 200);
// second group
checkHeader(listView, 1, 300, 0, "groupAddGroup", "C");
checkTile(listView, 1, 5, 300, 100, "C tile 5");
edit();
return true;
},
function () {
// first group
checkHeader(listView, 0, 50, 0, "groupAddGroup");
checkTile(listView, 0, 0, 50, 100);
checkTile(listView, 0, 1, 50, 200);
checkTile(listView, 0, 2, 50, 300);
checkTile(listView, 0, 3, 150, 100);
checkTile(listView, 0, 4, 150, 200);
// new group
checkHeader(listView, 1, 300, 0, "groupAddGroup", "B");
checkTile(listView, 1, 5, 300, 100, "B New tile");
// third group
checkHeader(listView, 2, 450, 0, "groupAddGroup", "C");
checkTile(listView, 2, 6, 450, 100, "C tile 5");
listView.forceLayout();
return true;
},
function () {
// first group
checkHeader(listView, 0, 50, 0, "groupAddGroup");
checkTile(listView, 0, 0, 50, 100);
// new group
checkHeader(listView, 1, 300, 0, "groupAddGroup", "B");
checkTile(listView, 1, 5, 300, 100, "B New tile");
testComplete();
}
]);
});
}
function getData() {
var myData = [],
c = 0;
function addGroup(letter, count) {
for (var i = 0; i < count; ++i) {
myData.push({
text: letter + " tile " + c
});
c++;
}
}
addGroup("A", 5);
addGroup("C", 5);
addGroup("D", 5);
return myData;
}
var list = (new WinJS.Binding.List(getData())).createGrouped(function (item) {
return item.text.charAt(0);
}, function (item) {
return { title: item.text.charAt(0) };
});
var dataSource = WinJS.UI.computeDataSourceGroups(Helper.ItemsManager.simpleSynchronousArrayDataSource(getData()), function (item) {
return item.data.text.charAt(0);
}, function (item) {
return { title: item.data.text.charAt(0) };
});
function editList() {
list.splice(5, 0, { text: "B New tile" });
}
function editDataSource() {
Helper.ListView.getDataObjects(dataSource, [5]).then(function (dataObjects) {
dataSource.insertBefore(null, { text: "B New tile" }, dataObjects[0].key);
});
}
test(list.dataSource, list.groups.dataSource, editList).then(function () {
return test(dataSource, dataSource.groups, editDataSource);
}).then(function () {
complete();
});
};
};
generateAddGroup("GridLayout");
function generateDelete(layout) {
GroupsTests.prototype["testDelete" + (layout == "GridLayout" ? "" : layout)] = function (complete) {
var dataSource = Helper.ItemsManager.simpleSynchronousArrayDataSource(smallGroups);
var i, listView = createListView(dataSource, { layout: { type: WinJS.UI[layout] } }, "groupDelete");
Helper.ListView.waitForReady(listView, -1)().then(function () {
// first group
checkHeader(listView, 0, 50, 0, "groupDelete");
checkTile(listView, 0, 0, 250, 0);
checkTile(listView, 0, 1, 250, 100);
checkTile(listView, 0, 4, 350, 0);
// second group
checkHeader(listView, 1, 500, 0, "groupDelete");
checkTile(listView, 1, 5, 700, 0);
checkTile(listView, 1, 6, 700, 100);
checkTile(listView, 1, 9, 800, 0);
Helper.ListView.getDataObjects(listView.itemDataSource, [1, 2, 3, 4]).then(function (dataObjects) {
listView.itemDataSource.beginEdits();
for (i = 0; i < dataObjects.length; ++i) {
listView.itemDataSource.remove(dataObjects[i].key);
}
listView.itemDataSource.endEdits();
});
return Helper.ListView.waitForState(listView, "viewPortLoaded", -1)()
}).then(function () {
var headerContainer = listView.element.querySelector(".win-groupheadercontainer");
LiveUnit.Assert.areEqual(1, headerContainer.children.length);
return Helper.ListView.waitForReady(listView, -1)();
}).then(function () {
// first group
checkHeader(listView, 0, 50, 0, "groupDelete");
checkTile(listView, 0, 0, 250, 0);
// second group
checkHeader(listView, 1, 400, 0, "groupDelete");
checkTile(listView, null, 1, 600, 0, "B tile 5");
checkTile(listView, null, 2, 600, 100, "B tile 6");
checkTile(listView, null, 5, 700, 0, "B tile 9");
Helper.ListView.getDataObjects(listView.itemDataSource, [0]).then(function (dataObjects) {
listView.itemDataSource.remove(dataObjects[0].key);
});
listView._raiseViewLoading();
return Helper.ListView.waitForReady(listView, -1)();
}).then(function () {
checkHeader(listView, 0, 50, 0, "groupDelete", "B");
checkTile(listView, null, 0, 250, 0, "B tile 5");
checkTile(listView, null, 1, 250, 100, "B tile 6");
checkTile(listView, null, 4, 350, 0, "B tile 9");
complete();
});
};
};
generateDelete("GridLayout");
function generateDeleteAll(layout) {
GroupsTests.prototype["testDeleteAll" + (layout == "GridLayout" ? "" : layout)] = function (complete) {
function test(itemDataSource, groupDataSource) {
return new WinJS.Promise(function (testComplete) {
var listView = new WinJS.UI.ListView(document.getElementById("groupTestList"), {
layout: { type: WinJS.UI[layout], groupHeaderPosition: WinJS.UI.HeaderPosition.left },
itemDataSource: itemDataSource,
itemTemplate: Helper.ListView.createRenderer("groupTestTemplate"),
groupDataSource: groupDataSource,
groupHeaderTemplate: Helper.ListView.createRenderer("groupHeaderTemplate", "groupDeleteAll")
});
Helper.ListView.runTests(listView, [
function () {
// first group
checkHeader(listView, 0, 50, 0, "groupDeleteAll");
checkTile(listView, 0, 0, 250, 0);
checkTile(listView, 0, 1, 250, 100);
// second group
checkHeader(listView, 1, 400, 0, "groupDeleteAll");
checkTile(listView, 1, 2, 600, 0);
Helper.ListView.getDataObjects(listView.itemDataSource, [0, 1, 2]).then(function (dataObjects) {
listView.itemDataSource.beginEdits();
for (var i = 0; i < dataObjects.length; ++i) {
listView.itemDataSource.remove(dataObjects[i].key);
}
listView.itemDataSource.endEdits();
});
return true;
},
function () {
LiveUnit.Assert.areEqual(0, listView.element.querySelectorAll(".win-container").length);
LiveUnit.Assert.areEqual(0, listView.element.querySelectorAll(".win-groupheader").length);
testComplete();
}
]);
});
}
function getData() {
return [
{ text: "A tile 0" },
{ text: "A tile 1" },
{ text: "B tile 2" }
];
}
var list = (new WinJS.Binding.List(getData())).createGrouped(function (item) {
return item.text.charAt(0);
}, function (item) {
return { title: item.text.charAt(0) };
});
test(list.dataSource, list.groups.dataSource).then(function () {
var dataSource = WinJS.UI.computeDataSourceGroups(Helper.ItemsManager.simpleSynchronousArrayDataSource(getData()), function (item) {
return item.data.text.charAt(0);
}, function (item) {
return { title: item.data.text.charAt(0) };
});
return test(dataSource, dataSource.groups);
}).then(function () {
complete();
});
};
};
generateDeleteAll("GridLayout");
function generateReload(layout) {
GroupsTests.prototype["testReload" + (layout == "GridLayout" ? "" : layout)] = function (complete) {
function checkTileLabel(listView, index, caption) {
var tile = listView.elementFromIndex(index);
LiveUnit.Assert.areEqual(caption, tile.textContent.trim());
}
function checkHeaderLabel(listView, id, groupIndex, caption) {
var tile = document.getElementById(id + groupIndex);
LiveUnit.Assert.areEqual(caption, tile.textContent.trim());
}
var myData = [],
c = 0;
function addGroup(letter, count) {
for (var i = 0; i < count; ++i) {
myData.push({
text: letter + " tile " + c
});
c++;
}
}
addGroup("A", 3);
addGroup("B", 3);
var dataSource = Helper.ItemsManager.simpleSynchronousArrayDataSource(myData);
var listView = createListView(dataSource, { layout: { type: WinJS.UI[layout] } }, "groupReload");
var tests = [
function () {
listView.currentItem = { index: 4 };
LiveUnit.Assert.areEqual(4, listView.currentItem.index, "ListView's currentItem wasn't set properly");
checkTileLabel(listView, 0, "A tile 0");
checkTileLabel(listView, 3, "B tile 3");
checkHeaderLabel(listView, "groupReload", 0, "A");
checkHeaderLabel(listView, "groupReload", 1, "B");
myData = [];
c = 0;
addGroup("C", 2);
addGroup("D", 2);
var items = [];
for (var i = 0; i < myData.length; i++) {
items.push({
key: i.toString(),
data: myData[i]
});
}
listView.itemDataSource['testDataAdapter'].replaceItems(items);
listView.itemDataSource['testDataAdapter'].reload();
},
function () {
Helper.ListView.validateResetFocusState(listView, "after calling reload");
checkTileLabel(listView, 0, "C tile 0");
checkTileLabel(listView, 2, "D tile 2");
checkHeaderLabel(listView, "groupReload", 0, "C");
checkHeaderLabel(listView, "groupReload", 1, "D");
complete();
}
];
Helper.ListView.runTests(listView, tests);
};
};
generateReload("GridLayout");
var correctStates = ["itemsLoading", "viewPortLoaded", "itemsLoaded", "complete"];
function generateLoadingStateEmpty(layout) {
GroupsTests.prototype["testLoadingStateEmpty" + (layout == "GridLayout" ? "" : layout)] = function (complete) {
var element = document.getElementById("groupTestList");
var state = trackState(element);
var list = new WinJS.Binding.List([]);
var listView = new WinJS.UI.ListView(element, {
layout: { type: WinJS.UI[layout] },
itemDataSource: list.dataSource,
itemTemplate: Helper.ListView.createRenderer("groupTestTemplate")
});
state.completePromise.then(function (states) {
Helper.ListView.elementsEqual(correctStates, states);
complete();
});
};
};
generateLoadingStateEmpty("GridLayout");
function generateLoadingStateSync(layout) {
GroupsTests.prototype["testLoadingStateSync" + (layout == "GridLayout" ? "" : layout)] = function (complete) {
WinJS.Utilities.startLog({
action: function (message, tag, type) {
LiveUnit.LoggingCore.logComment(type + ": " + message + " (" + tag + ")");
}
});
var element = document.getElementById("groupTestList");
var state = trackState(element);
var listView = new ListView(element, {
layout: { type: WinJS.UI[layout] },
itemDataSource: createDataSource(smallGroups),
itemTemplate: Helper.ListView.createRenderer("groupTestTemplate")
});
state.completePromise.then(function (states) {
Helper.ListView.elementsEqual(correctStates, states);
var state = trackState(listView._element);
listView.indexOfFirstVisible = 70;
return state.completePromise;
}).then(function (states) {
Helper.ListView.elementsEqual(correctStates, states);
var state = trackState(listView._element);
listView.scrollPosition = listView.scrollPosition + 5;
return state.completePromise;
}).then(function (states) {
Helper.ListView.elementsEqual(correctStates, states);
WinJS.Utilities.stopLog();
}).then(null, function () { WinJS.Utilities.stopLog(); }).
done(complete);
};
};
generateLoadingStateSync("GridLayout");
function generateLoadingStateAsync(layout) {
GroupsTests.prototype["testLoadingStateAsync" + (layout == "GridLayout" ? "" : layout)] = function (complete) {
WinJS.Utilities.startLog({
action: function (message, tag, type) {
LiveUnit.LoggingCore.logComment(type + ": " + message + " (" + tag + ")");
}
});
var element = document.getElementById("groupTestList");
var state = trackState(element);
var listView = new WinJS.UI.ListView(element, {
layout: { type: WinJS.UI[layout] },
itemDataSource: createDataSource(smallGroups, true),
itemTemplate: Helper.ListView.createAsyncRenderer("groupTestTemplate", 100, 100, "", 500)
});
state.loadedPromise.then(function (states) {
//checkTile(listView, 0, 1, 0, 100, "Loading");
return state.completePromise;
}).then(function (states) {
Helper.ListView.elementsEqual(correctStates, states);
checkTile(listView, 0, 1, 0, 100);
WinJS.Utilities.stopLog();
}).
then(null, function () { WinJS.Utilities.stopLog(); }).
done(complete);
};
};
generateLoadingStateAsync("GridLayout");
function generateGroupFocusAfterDataSourceMutation(layout) {
GroupsTests.prototype["testGroupFocusAfterDataSourceMutation" + (layout == "GridLayout" ? "" : layout)] = function (complete) {
var data = [];
for (var i = 0; i < 100; i++) {
data.push({ data: i + "" });
}
var list = new WinJS.Binding.List(data);
var glist = list.createGrouped(function (item) {
return Math.floor(item.data / 10) + "";
}, function (item) {
return { data: Math.floor(item.data / 10) + "" };
});
var element = document.getElementById("groupTestList");
var listView = new WinJS.UI.ListView(element, {
layout: { type: WinJS.UI[layout] },
itemDataSource: glist.dataSource,
groupDataSource: glist.groups.dataSource
});
var header = null;
Helper.ListView.waitForReady(listView)().
then(function () {
listView.currentItem = { type: WinJS.UI.ObjectType.groupHeader, index: 0, hasFocus: true };
header = listView.element.querySelector(".win-groupheader");
LiveUnit.Assert.areEqual(header, document.activeElement);
listView.itemDataSource.remove("8");
return Helper.ListView.waitForReady(listView, -1)();
}).done(function () {
LiveUnit.Assert.isTrue(document.activeElement && document.activeElement !== header && document.activeElement === listView.element.querySelector(".win-groupheader"));
complete();
});
};
};
generateGroupFocusAfterDataSourceMutation("GridLayout");
function generateRealizeRenderDuringScrolling(layout) {
var testName = "testRealizeRenderAndResetDuringScrolling" + (layout == "GridLayout" ? "" : layout);
GroupsTests.prototype[testName] = function (complete) {
Helper.initUnhandledErrors();
var refItems = {};
var stopScrolling = false;
var failures = 0;
var scrollPosition = 0;
WinJS.Utilities.startLog({
action: function (message, tag, type) {
LiveUnit.LoggingCore.logComment(type + ": " + message + " (" + tag + ")");
}
});
function getItemTemplate() {
var realRenderer = Helper.ListView.createAsyncRenderer("groupTestTemplate", 200, 200, "", 1000);
return function (itemPromise) {
itemPromise.then(function (item) {
if (item.key) {
if (refItems[item.key]) {
failures++;
} else {
refItems[item.key] = item;
}
}
});
return realRenderer(itemPromise);
};
}
var element = document.getElementById("groupTestList");
var state = trackState(element);
var listView = new ListView(element, {
layout: new WinJS.UI[layout](),
itemDataSource: createDataSource(bigGroups, true),
itemTemplate: getItemTemplate()
});
function scrollListView() {
if (!stopScrolling && document.body.contains(listView.element)) {
var scrollProperty = listView.layout.orientation === WinJS.UI.Orientation.horizontal ? "scrollLeft" : "scrollTop";
scrollPosition += 10;
var newPos: any = {};
newPos[scrollProperty] = scrollPosition;
WinJS.Utilities.setScrollPosition(listView._viewport, newPos);
setTimeout(scrollListView, 16);
}
}
scrollListView();
state.loadedPromise.
then(function (states) {
return state.completePromise;
}).
then(function () {
return WinJS.Promise.timeout(16).then(function () {
scrollPosition = listView.scrollPosition = 4000;
});
}).
then(function () {
LiveUnit.Assert.areEqual(0, failures);
}).
then(function () {
return WinJS.Promise.timeout(16).then(function () {
scrollPosition = listView.scrollPosition = 14100;
});
}).
then(function () {
return WinJS.Promise.timeout(16).then(function () {
scrollPosition = listView.scrollPosition = 14400;
});
}).
then(function () {
return WinJS.Promise.timeout(16).then(function () {
scrollPosition = listView.scrollPosition = 14150;
stopScrolling = true;
});
}).
then(Helper.validateUnhandledErrorsOnIdle).
done(function () {
WinJS.Utilities.stopLog();
complete();
});
};
GroupsTests.prototype[testName].timeout = 60000;
};
generateRealizeRenderDuringScrolling("GridLayout");
function generateLoadingStateScrolling(layout) {
var testName = "testLoadingStateScrolling" + (layout == "GridLayout" ? "" : layout);
GroupsTests.prototype[testName] = function (complete) {
WinJS.Utilities.startLog({
action: function (message, tag, type) {
LiveUnit.LoggingCore.logComment(type + ": " + message + " (" + tag + ")");
}
});
var element = document.getElementById("groupTestList");
var state = trackState(element);
var listView = new ListView(element, {
layout: { type: WinJS.UI[layout] },
itemDataSource: createDataSource(smallGroups, true),
itemTemplate: Helper.ListView.createRenderer("groupTestTemplate")
});
var stopScrolling = false;
var failedEvents = 0;
var scrollPosition = 0;
function scrollListView() {
if (!stopScrolling && document.body.contains(listView.element)) {
var scrollProperty = listView.layout.orientation === WinJS.UI.Orientation.horizontal ? "scrollLeft" : "scrollTop";
scrollPosition += 5;
var newPos: any = {};
newPos[scrollProperty] = scrollPosition;
WinJS.Utilities.setScrollPosition(listView._viewport, newPos);
setTimeout(scrollListView, 16);
}
}
scrollListView();
listView.addEventListener("loadingstatechanged", function () {
if (!stopScrolling) {
if (listView.loadingState !== 'itemsLoading') {
var indexOfFirstVisible = listView.indexOfFirstVisible;
var indexOfLastVisible = listView.indexOfLastVisible;
var firstElement = listView.elementFromIndex(indexOfFirstVisible);
var lastElement = listView.elementFromIndex(indexOfLastVisible);
if (!firstElement || !lastElement) {
failedEvents++;
}
}
}
});
state.loadedPromise.
then(function (states) {
stopScrolling = true;
return state.completePromise;
}).
then(function (states) {
LiveUnit.Assert.areEqual(0, failedEvents);
}).
then(Helper.validateUnhandledErrorsOnIdle)
.done(function () {
WinJS.Utilities.stopLog();
complete();
});
};
GroupsTests.prototype[testName].timeout = 60000;
};
generateLoadingStateScrolling("GridLayout");
}
// register the object as a test class by passing in the name
LiveUnit.registerTestClass("WinJSTests.GroupsTests");