// 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 utils = repeaterUtils, loadedEvent = utils.events.loadedEvent, simpleRenderer = utils.simpleRenderer, repeaterClass = "win-repeater", repeaterChildClass = "repeater-child"; function verifyDOM(elem, data, childrenClassQuery) { LiveUnit.LoggingCore.logComment("Verifying the DOM"); var domChildren = elem.querySelectorAll(childrenClassQuery), numberOfDomChildren = domChildren.length; // Verify the number of children elements LiveUnit.Assert.areEqual(data.length, numberOfDomChildren, "The DOM size is not equal to the number of data items"); // Verify that repeater owns the its innerHTML and that no other html elements have been injected into it.. LiveUnit.Assert.areEqual(numberOfDomChildren, elem.childNodes.length, "After initialization, Repeater's innerHTML should only contain the elements its template generated from the data set."); // Verify the DOM order data.forEach(function (item, index) { // Verify the content of the element var child = domChildren[index]; LiveUnit.Assert.areEqual(item, child.textContent, "The data and the DOM element don't match"); }); // Verify the css class LiveUnit.Assert.isTrue(WinJS.Utilities.hasClass(elem, repeaterClass), "The repeater container element doesn't have the expected CSS class"); } export class RepeaterInitTests { // 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 = "RepeaterTests"; document.body.appendChild(newNode); window['RepeaterInitTests'] = {}; } tearDown() { LiveUnit.LoggingCore.logComment("In tearDown"); var element = document.getElementById("RepeaterTests"); if (element) { WinJS.Utilities.disposeSubTree(element); document.body.removeChild(element); } delete window['RepeaterInitTests']; } testReloadWithExternalTemplate = function () { var templateDiv = document.createElement("div"); templateDiv.innerHTML = "
"; var template = new WinJS.Binding.Template(templateDiv); var list = new WinJS.Binding.List([{ value: "value" }]); var repeater = new WinJS.UI.Repeater(document.querySelector("#RepeaterTests")); repeater.template = template; repeater.data = list; document.body.appendChild(repeater.element); // Next line should not cause a crash repeater.template = template; }; testInitJSCtorRendererFunction = function (complete) { var data = utils.createWeekdaysList(), elem = document.getElementById("RepeaterTests"), loadedEventFired = 0; elem.addEventListener(loadedEvent, itemsLoadedHandler); function itemsLoadedHandler(ev) { LiveUnit.LoggingCore.logComment("Inside the itemsLoaded event handler"); loadedEventFired++; } LiveUnit.LoggingCore.logComment("Creating a repeater control"); var repeater = new WinJS.UI.Repeater(elem, { data: data, template: simpleRenderer }); LiveUnit.LoggingCore.logComment("Repeater control created"); verifyDOM(elem, data, "." + repeaterChildClass); // Verify the itemsloaded fired only once LiveUnit.Assert.areEqual(1, loadedEventFired, "itemsloaded event fired unexpected number of times"); // Done complete(); }; testInitJSCtorInlineTemplate = function (complete) { var data = utils.createWeekdaysList(), elem = document.getElementById("RepeaterTests"), loadedEventFired = 0; var str = "
"; elem.innerHTML = str; function itemsLoadedHandler(ev) { LiveUnit.LoggingCore.logComment("Inside the itemsLoaded event handler"); loadedEventFired++; } LiveUnit.LoggingCore.logComment("Creating a repeater control"); var repeater = new WinJS.UI.Repeater(elem, { data: data, onitemsloaded: itemsLoadedHandler }); LiveUnit.LoggingCore.logComment("Repeater control created"); verifyDOM(elem, data, "." + repeaterChildClass); // Verify the itemsloaded fired only once LiveUnit.Assert.areEqual(1, loadedEventFired, "itemsloaded event fired unexpected number of times"); // Done complete(); }; testInitJSCtorBindingTemplate = function (complete) { var data = utils.createWeekdaysList(), root = document.getElementById("RepeaterTests"), loadedEventFired = 0; var templateStr = ""; root.innerHTML = templateStr; var elem = document.createElement("div"); root.appendChild(elem); elem.addEventListener(loadedEvent, itemsLoadedHandler); function itemsLoadedHandler(ev) { LiveUnit.LoggingCore.logComment("Inside the itemsLoaded event handler"); loadedEventFired++; } WinJS.UI.processAll(). then(function () { LiveUnit.LoggingCore.logComment("Creating a repeater control"); var repeater = new WinJS.UI.Repeater(elem, { data: data, template: document.getElementById("template") }); LiveUnit.LoggingCore.logComment("Repeater control created"); verifyDOM(elem, data, "." + repeaterChildClass); // Verify the itemsloaded fired only once LiveUnit.Assert.areEqual(1, loadedEventFired, "itemsloaded event fired unexpected number of times"); }). done(complete); }; testInitJSCtorBindingTemplateWinControl = function (complete) { var data = utils.createWeekdaysList(), root = document.getElementById("RepeaterTests"), loadedEventFired = 0; var templateStr = ""; root.innerHTML = templateStr; var elem = document.createElement("div"); root.appendChild(elem); elem.addEventListener(loadedEvent, itemsLoadedHandler); function itemsLoadedHandler(ev) { LiveUnit.LoggingCore.logComment("Inside the itemsLoaded event handler"); loadedEventFired++; } WinJS.UI.processAll(). then(function () { LiveUnit.LoggingCore.logComment("Creating a repeater control"); var repeater = new WinJS.UI.Repeater(elem, { data: data, template: document.getElementById("template").winControl, }); LiveUnit.LoggingCore.logComment("Repeater control created"); verifyDOM(elem, data, "." + repeaterChildClass); // Verify the itemsloaded fired only once LiveUnit.Assert.areEqual(1, loadedEventFired, "itemsloaded event fired unexpected number of times"); }). done(complete); }; testInitMarkupRendererFunction = function (complete) { var data = utils.createWeekdaysList(), root = document.getElementById("RepeaterTests"), loadedEventFired = 0; function itemsLoadedHandler(ev) { LiveUnit.LoggingCore.logComment("Inside the itemsLoaded event handler"); loadedEventFired++; } WinJS.Utilities.markSupportedForProcessing(itemsLoadedHandler); window['RepeaterInitTests'].data = data; window['RepeaterInitTests'].simpleRenderer = simpleRenderer; window['RepeaterInitTests'].itemsLoadedHandler = itemsLoadedHandler; var str = "
"; root.innerHTML = str; WinJS.UI.processAll(). then(function () { var elem = document.getElementById("myRepeater"); verifyDOM(elem, data, "." + repeaterChildClass); // Verify the itemsloaded fired only once LiveUnit.Assert.areEqual(1, loadedEventFired, "itemsloaded event fired unexpected number of times"); }). done(complete); }; testInitMarkupInlineTemplate = function (complete) { var data = utils.createWeekdaysList(), root = document.getElementById("RepeaterTests"), loadedEventFired = 0; function itemsLoadedHandler(ev) { LiveUnit.LoggingCore.logComment("Inside the itemsLoaded event handler"); loadedEventFired++; } WinJS.Utilities.markSupportedForProcessing(itemsLoadedHandler); window['RepeaterInitTests'].data = data; window['RepeaterInitTests'].itemsLoadedHandler = itemsLoadedHandler; var str = "
" + "
" + "
"; root.innerHTML = str; WinJS.UI.processAll(). then(function () { var elem = document.getElementById("myRepeater"); verifyDOM(elem, data, "." + repeaterChildClass); // Verify the itemsloaded fired only once LiveUnit.Assert.areEqual(1, loadedEventFired, "itemsloaded event fired unexpected number of times"); }). done(complete); }; testInitMarkupBindingTemplate = function (complete) { var data = utils.createWeekdaysList(), root = document.getElementById("RepeaterTests"), loadedEventFired = 0; function itemsLoadedHandler(ev) { LiveUnit.LoggingCore.logComment("Inside the itemsLoaded event handler"); loadedEventFired++; } WinJS.Utilities.markSupportedForProcessing(itemsLoadedHandler); window['RepeaterInitTests'].data = data; window['RepeaterInitTests'].itemsLoadedHandler = itemsLoadedHandler; var str = ""; str += "
"; root.innerHTML = str; WinJS.UI.processAll(). then(function () { var elem = document.getElementById("myRepeater"); verifyDOM(elem, data, "." + repeaterChildClass); // Verify the itemsloaded fired only once LiveUnit.Assert.areEqual(1, loadedEventFired, "itemsloaded event fired unexpected number of times"); }). done(complete); }; testAriaAttributes = function (complete) { var data = utils.createWeekdaysList(), elem = document.getElementById("RepeaterTests"), ariaLabel = "myAwesomeRepeater"; LiveUnit.LoggingCore.logComment("Setting aria attributes on the element"); elem.setAttribute("aria-label", ariaLabel); LiveUnit.LoggingCore.logComment("Creating a repeater control"); var repeater = new WinJS.UI.Repeater(elem, { data: data, template: simpleRenderer }); LiveUnit.LoggingCore.logComment("Repeater control created"); LiveUnit.LoggingCore.logComment("Verifying aria attributes"); function checkAttribute(element, attribute, expectedValue) { var values = element.getAttribute(attribute).match(expectedValue), value = values ? values[0] : null; LiveUnit.Assert.areEqual(value, expectedValue, "Expected " + attribute + ": " + expectedValue + " Actual: " + value); } checkAttribute(elem, "aria-label", ariaLabel); // Done complete(); }; testEmptyCtor = function (complete) { var data = utils.createWeekdaysList(), elem = document.getElementById("RepeaterTests"), loadedEventFired = 0; elem.addEventListener(loadedEvent, itemsLoadedHandler); function itemsLoadedHandler(ev) { LiveUnit.LoggingCore.logComment("Inside the itemsLoaded event handler"); loadedEventFired++; } LiveUnit.LoggingCore.logComment("Creating a repeater control"); var repeater = new WinJS.UI.Repeater(); LiveUnit.LoggingCore.logComment("Repeater control created"); // Verify a div is created for the repeater control, and control is well formed and empty LiveUnit.Assert.isTrue(repeater.element); LiveUnit.Assert.isTrue(repeater.data); LiveUnit.Assert.isTrue(repeater.template); LiveUnit.Assert.isTrue(repeater.elementFromIndex); LiveUnit.Assert.areEqual(0, repeater.element.childElementCount, "Repeater should be empty with no children"); // Add an event handler repeater.addEventListener(loadedEvent, itemsLoadedHandler, false); // Attach data, template and verify that itemsLoaded fires twice. repeater.data = data; repeater.template = simpleRenderer; verifyDOM(repeater.element, data, "." + repeaterChildClass); // Verify itemsLoaded was fired twice LiveUnit.Assert.areEqual(2, loadedEventFired, "itemsloaded event didn't fire expected number of times"); // Done complete(); }; testNoTemplate = function (complete) { var data = utils.createWeekdaysList(), elem = document.getElementById("RepeaterTests"); LiveUnit.LoggingCore.logComment("Creating a repeater control"); var repeater = new WinJS.UI.Repeater(elem, { data: data }); LiveUnit.LoggingCore.logComment("Repeater control created"); // When a template is not provided, repeater is populated with JSON text from the item // wrapped in divs. // Verify the number of children div elements and complete LiveUnit.Assert.areEqual(data.length, elem.childElementCount, "The DOM size is not equal to the number of data items"); complete(); }; // WinBlue: 66929 testNestedRepeaterInlineTemplate = function (complete) { var outerList = createNestedData(), str = "", root = document.getElementById("RepeaterTests"); function createNestedData() { var outerList = new WinJS.Binding.List(), days = repeaterUtils.createWeekdaysList(); days.forEach(function (day) { outerList.push({ title: day, moments: repeaterUtils.getListOfMoments(3) }); }); return outerList; } window['RepeaterInitTests'].data = outerList; str += "
    " + "
  • " + "" + "
      " + "
    • " + "
    • " + "
    " + "
  • " + "
"; root.innerHTML = str; WinJS.UI.processAll(). then(function () { LiveUnit.LoggingCore.logComment("Nested repeaters created"); var outerRepeater = document.getElementById("outerRepeater").winControl; function verifyChildrenCount(element, childrenClassQuery, length) { var domChildren = element.querySelectorAll(childrenClassQuery), numberOfDomChildren = domChildren.length; // Verify the number of children elements LiveUnit.Assert.areEqual(length, numberOfDomChildren, "The DOM size is not equal to the number of data items"); } // Verify the number of elements in outer repeater LiveUnit.LoggingCore.logComment("Verifying item count of outer repeater"); verifyChildrenCount(outerRepeater.element, ".repeater-1-child", outerList.length); outerList.forEach(function (item:any, index) { // Get repeater at given index var innerRepeater = outerRepeater.elementFromIndex(index).querySelector(".innerRepeater").winControl; // Verify the number of elements in inner repeater LiveUnit.LoggingCore.logComment("Verifying item count of inner repeater"); verifyChildrenCount(innerRepeater.element, ".repeater-2-child", item.moments.length); }); }). done(complete); }; testRepeaterDoubleDispose = function (complete) { var elem = document.getElementById("RepeaterTests"); LiveUnit.LoggingCore.logComment("Creating a repeater control"); var repeater:any = new WinJS.UI.Repeater(elem); LiveUnit.LoggingCore.logComment("Repeater control created"); LiveUnit.Assert.isFalse(repeater._disposed); repeater.dispose(); LiveUnit.Assert.isTrue(repeater._disposed); repeater.dispose(); // Done complete(); }; testDuplicateConstructionException = function (complete) { var elem = document.getElementById("RepeaterTests"); LiveUnit.LoggingCore.logComment("Creating a repeater control"); var repeater = new WinJS.UI.Repeater(elem); LiveUnit.LoggingCore.logComment("Repeater control created"); LiveUnit.LoggingCore.logComment("Creating another repeater on the same element"); try { repeater = new WinJS.UI.Repeater(elem); } catch (e) { LiveUnit.Assert.areEqual("Invalid argument: Controls may only be instantiated one time for each DOM element", e.message); } complete(); }; testAsyncTemplateException = function (complete) { var data = utils.createWeekdaysList(), elem = document.getElementById("RepeaterTests"); LiveUnit.LoggingCore.logComment("Creating a repeater control"); var repeater = new WinJS.UI.Repeater(elem, { data: data }); LiveUnit.LoggingCore.logComment("Repeater control created"); // Template returns null try { repeater.template = function (item) { return null; }; } catch (e) { LiveUnit.Assert.areEqual("Top level items must render synchronously", e.message); } // Template returns promise try { repeater.template = function (item) { return WinJS.Promise.wrap(document.createElement("div")); }; } catch (e) { // TODO: What the repeater check for HTMLelement instead of a null check? //LiveUnit.Assert.areEqual("Top level items must render synchronously", e.message); } complete(); }; // Regression test for Windows Blue Bug # 424560 testDeclarativeControlContainerWithItemContainerInlineTemplate = function (complete) { var data = new WinJS.Binding.List([{}]); // Create list of a singular empty object. var itemsLoadedHandler = function () { var repeaterElement = document.getElementById("myRepeater"); LiveUnit.Assert.isTrue(repeaterElement.querySelectorAll(".win-itembox").length === 1, "There should only be 1 itembox generated for a singular ItemContainer.") }; WinJS.Utilities.markSupportedForProcessing(itemsLoadedHandler); var str = "
" + "
Hello
" + "
"; var root = document.getElementById("RepeaterTests"); root.innerHTML = str; WinJS.UI.processAll(root). then(function () { var repeater = document.getElementById("myRepeater").winControl; repeater.onitemsloaded = itemsLoadedHandler; repeater.data = data; }). done(complete); } }; (function () { function generateTest(control) { return function (complete) { var ds = createDS(), elem = document.getElementById("RepeaterTests"); function createDS() { var list = new WinJS.Binding.List(), days = repeaterUtils.createWeekdaysList(); days.forEach(function (day) { list.push({ title: day, moments: repeaterUtils.getListOfMoments(4) }); }); return list.dataSource; } elem.style.width = "500px"; elem.style.height = "500px"; var renderer = function (itemPromise) { return itemPromise.then(function (item) { var root = document.createElement("div"), rep = document.createElement("div"); function repeaterRenderer(itemMoment) { var e = document.createElement("div"); e.textContent = itemMoment.seconds + " " + itemMoment.minutes + " " + itemMoment.hour; return e; } var repeater = new WinJS.UI.Repeater(rep, { data: item.data.moments, template: repeaterRenderer }); root.appendChild(rep); return root; }); }; LiveUnit.LoggingCore.logComment("Creating the control"); var ctrl = new control(elem, { itemDataSource: ds, itemTemplate: renderer }); // Wait till the control is ready and call complete if (control === WinJS.UI.ListView) { // ListView repeaterUtils.waitForReady(ctrl)() .done(function () { LiveUnit.LoggingCore.logComment("ListView with repeater in the template created. Finished"); complete(); }); } else { //FlipView elem.addEventListener("pagecompleted", function (ev) { LiveUnit.LoggingCore.logComment("FlipView with repeater in the template created. Finished"); complete(); }); } }; } RepeaterInitTests.prototype['testRepeaterInListViewTemplate'] = generateTest(WinJS.UI.ListView); RepeaterInitTests.prototype['testRepeaterInFlipViewTemplate'] = generateTest(WinJS.UI.FlipView); } ()); (function () { function generateTest(renderer) { return function (complete) { var data = utils.createWeekdaysList(), elem = document.getElementById("RepeaterTests"), loadedEventFired = 0; elem.addEventListener(loadedEvent, itemsLoadedHandler); function itemsLoadedHandler(ev) { LiveUnit.LoggingCore.logComment("Inside the itemsloaded event handler"); loadedEventFired++; } LiveUnit.LoggingCore.logComment("Creating a repeater control"); var repeater = new WinJS.UI.Repeater(elem, { data: data, template: renderer }); LiveUnit.LoggingCore.logComment("Repeater control created"); // Verify the number of children div elements LiveUnit.Assert.areEqual(data.length, elem.childElementCount, "The DOM size is not equal to the number of data items"); // Repeater should not clear innerHTML when disposed var beforeDisposeCount = elem.childElementCount; repeater.dispose(); LiveUnit.Assert.areEqual(beforeDisposeCount, elem.childElementCount, "Repeater should not lose innerHTML after dispose"); // Verify itemsloaded wasn't fired during/after dispose. LiveUnit.Assert.areEqual(1, loadedEventFired, "itemsloaded event didn't fire expected number of times"); // Done complete(); }; } RepeaterInitTests.prototype['testRepeaterDisposeSimpleRenderer'] = generateTest(simpleRenderer); RepeaterInitTests.prototype['testRepeaterDisposeWinJSRenderer'] = generateTest(utils.winJSCtrlRenderer); RepeaterInitTests.prototype['testRepeaterDisposeDisposableRenderer'] = generateTest(utils.disposableRenderer); })(); } // register the object as a test class by passing in the name LiveUnit.registerTestClass("WinJSTests.RepeaterInitTests");