// Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. See License.txt in the project root for license information.
//
//
///
///
//
module HubTests {
"use strict";
var HubSection = WinJS.UI.HubSection;
var Hub = WinJS.UI.Hub;
// This is the setup function that will be called at the beginning of each test function.
var hostId = "HubTests";
var hostSelector = "#" + hostId;
var HubUtils = HubTests.Utilities;
function InitTest(testHost, config) {
var control = testHost.querySelector(".win-hub").winControl;
LiveUnit.LoggingCore.logComment("Waiting for control...");
return HubUtils.waitForReady(control)().then(() => {
LiveUnit.LoggingCore.logComment("Verifying...");
HubUtils.verifyOrientation(control, config.orientation);
//use the control's current template if none was defined by config
HubUtils.verifySections(control, config.sectionsArray, config.headerTemplate || control.headerTemplate);
});
}
function LoadingStateChangedTest(testHost, config) {
var control = testHost.querySelector(".win-hub").winControl;
var i = 0;
var sectionsLoadedIndex = i;
var completeIndex = i;
var loadingIndex = i;
LiveUnit.Assert.areEqual(Hub.LoadingState.loading, control.loadingState, "Loading state should start in loading");
i++;
return HubUtils.waitForReady(control)().
then(function () {
completeIndex = i;
LiveUnit.Assert.isTrue(completeIndex > sectionsLoadedIndex, "Expecting complete to fire after sectionsLoaded event");
LiveUnit.Assert.areEqual(Hub.LoadingState.complete, control.loadingState, "Loading state should finish in complete");
}, function () {
LiveUnit.Assert.fail("An error was reported by waitForReady");
}, function () {
if (control.loadingState === Hub.LoadingState.sectionsLoaded) {
sectionsLoadedIndex = i;
LiveUnit.Assert.isTrue(sectionsLoadedIndex > loadingIndex, "Sections loaded Event should fire after loading event");
i++;
} else if (control.loadingState === Hub.LoadingState.loading) {
loadingIndex = i;
i++;
} else {
LiveUnit.Assert.fail("Unrecognized loading state: " + control.loadingState);
}
});
}
function RemoveFromDOMTest(testHost, config) {
return WinJS.Promise.timeout().then(function () {
var control = testHost.querySelector(".win-hub").winControl;
testHost.removeChild(control.element);
testHost.innerHTML = "";
HubUtils.insertHub(testHost, config);
return InitTest(testHost, config);
});
}
function RehydrationTest(testHost, config) {
var control = testHost.querySelector(".win-hub").winControl;
return HubUtils.waitForReady(control)().
then(function () {
//scrollable region
var scrollRange = HubUtils.getScrollRange(control);
var scrollMax = scrollRange.max;
var scrollMin = scrollRange.min;
var scrollDest = 0;
if (scrollMin < scrollMax) {
scrollDest = Math.floor(Math.random() * (scrollMax - scrollMin) + scrollMin);
}
control.scrollPosition = scrollDest;
LiveUnit.Assert.areEqual(scrollDest, control.scrollPosition);
//remove the hub, wait for a layout, then readd it
//this simulates what a navigation would do
testHost.removeChild(control.element);
testHost.innerHTML = "";
return WinJS.Promise.timeout().then(function () { return scrollDest; });
}).
then(function (scrollDest) {
testHost.appendChild(control.element);
control.scrollPosition = scrollDest;
LiveUnit.Assert.areEqual(scrollDest, control.scrollPosition);
HubUtils.verifySections(control, config.sectionsArray, config.headerTemplate || control.headerTemplate);
});
}
function SwapOrientationTest(testHost, config) {
var control = testHost.querySelector(".win-hub").winControl;
return HubUtils.waitForReady(control)().
then(function () {
HubUtils.verifyOrientation(control, config.orientation);
//update the internal representation
if (config.orientation === WinJS.UI.Orientation.vertical) {
config.orientation = WinJS.UI.Orientation.horizontal;
} else {
config.orientation = WinJS.UI.Orientation.vertical;
}
control.orientation = config.orientation;
return HubUtils.waitForReady(control)();
}).
then(function () {
HubUtils.verifyOrientation(control, config.orientation);
});
}
function HeaderInvokedTest(testHost, config) {
var control = testHost.querySelector(".win-hub").winControl;
return new WinJS.Promise(function (c, e, p) {
//grab a map of all headers elements
HubUtils.waitForReady(control)().then(function () {
var headerElements = HubUtils.getAllHeaderElements(control);
LiveUnit.LoggingCore.logComment(headerElements.length + " headers found");
if (headerElements.length > 0) {
var interactiveHeaderCount = 0;
control.addEventListener(Hub._EventName.headerInvoked, function (ev) {
interactiveHeaderCount--;
LiveUnit.Assert.isFalse(config.sectionsArray[ev.detail.index].isHeaderStatic, "Header element " + ev.detail.index + " not expected to be interactive");
});
for (var i = 0; i < headerElements.length; i++) {
var element = headerElements[i];
if (!config.sectionsArray[i].isHeaderStatic) {
LiveUnit.LoggingCore.logComment("Header #" + i + " is interactive!");
interactiveHeaderCount++;
}
element.firstElementChild.click();
}
LiveUnit.Assert.areEqual(0, interactiveHeaderCount, "A header's invoke event was not fired");
c();
} else {
LiveUnit.LoggingCore.logComment("No headers found in this configuration, skipping test");
c();
}
});
});
}
function SwapHeaderTemplateTest(testHost, config) {
var control = testHost.querySelector(".win-hub").winControl;
return new WinJS.Promise(function (c, e, p) {
function myCustomTemplate(item) {
var el = document.createElement("div");
el.textContent = "Test";
return el;
}
var oldTemplate;
HubUtils.waitForReady(control)().then(function () {
oldTemplate = control.headerTemplate;
control.headerTemplate = myCustomTemplate;
return HubUtils.waitForReady(control)();
}).then(function () {
HubUtils.verifySections(control, config.sectionsArray, myCustomTemplate);
control.headerTemplate = null;
//verify that the headerTemplate actually changes
LiveUnit.Assert.areNotEqual(myCustomTemplate, control.headerTemplate);
LiveUnit.Assert.areNotEqual(config.headerTemplate, control.headerTemplate);
return HubUtils.waitForReady(control)();
}).done(function () {
HubUtils.verifySections(control, config.sectionsArray, control.headerTemplate);
//reset the template back to match the input config
control.headerTemplate = oldTemplate;
c();
});
});
}
function SetSectionOnScreenTest(testHost, config) {
var control = testHost.querySelector(".win-hub").winControl;
var sectionsLength = config.sectionsArray.length;
function setAndVerifySectionOnScreen(control, sectionOnScreen) {
return new WinJS.Promise(function (c, e, p) {
control.sectionOnScreen = sectionOnScreen;
HubUtils.waitForReady(control)().done(function () {
function verifySectionOnScreen(control, expectedValue) {
var scrollRange = HubUtils.getScrollRange(control);
var surfaceSpacers = HubUtils.getSurfaceSpacers(control);
var isLTR = (getComputedStyle(control.element).direction === "ltr");
var sectionElement = control.element.querySelectorAll("." + HubSection._ClassName.hubSection)[expectedValue];
var sectionElementRect = sectionElement.getBoundingClientRect();
var viewportRect = control._viewportElement.getBoundingClientRect();
//either the sectionOnScreen was updated successfully or control scrolled as far as possible
if (expectedValue === control.sectionOnScreen) {
//when section on screen is updated successfully, the alignment needs to be correct
if (control.orientation === WinJS.UI.Orientation.horizontal) {
//TODO switch this for RTL
if (isLTR) {
LiveUnit.Assert.isTrue(Math.abs(surfaceSpacers.left + viewportRect.left - sectionElementRect.left) <= .002, "Distance is more than .002 px");
} else {
LiveUnit.Assert.isTrue(Math.abs(viewportRect.right - surfaceSpacers.right - sectionElementRect.right) <= .002, "Distance is more than .002 px");
}
} else {
//vertical Hub
LiveUnit.Assert.isTrue(Math.abs(surfaceSpacers.top + viewportRect.top - sectionElementRect.top) <= .002, "Distance is more than .002 px");
}
} else {
//else the control is scrolled as far as possible
LiveUnit.Assert.isTrue(control.scrollPosition === scrollRange.max || control.scrollPosition === scrollRange.min, "Scroll position should be at max or min");
if (control.orientation === WinJS.UI.Orientation.horizontal) {
if (isLTR) {
LiveUnit.Assert.isTrue(sectionElementRect.left >= surfaceSpacers.left + viewportRect.left, "Left edge should be on screen");
} else {
//RTL
LiveUnit.Assert.isTrue(sectionElementRect.right <= viewportRect.right - surfaceSpacers.right, "Right edge should be on screen");
}
} else { //orientation === WinJS.UI.Orientation.vertical
LiveUnit.Assert.isTrue(sectionElementRect.top >= surfaceSpacers.top + viewportRect.top, "Top edge should be on screen");
}
}
}
verifySectionOnScreen(control, sectionOnScreen);
c();
});
});
}
function iterateAllSections(control, currentSection, decreasing) {
if (currentSection < sectionsLength && currentSection >= 0) {
return setAndVerifySectionOnScreen(control, currentSection).then(function () {
return iterateAllSections(control, decreasing ? currentSection - 1 : currentSection + 1, decreasing);
});
}
}
return HubUtils.waitForReady(control)().
then(function () {
var currentSectionOnScreen = control.sectionOnScreen;
var currentScrollPos = control.scrollPosition;
control.sectionOnScreen = currentSectionOnScreen;
LiveUnit.Assert.areEqual(currentSectionOnScreen, control.sectionOnScreen, "Expecting control to not move");
LiveUnit.Assert.areEqual(currentScrollPos, control.scrollPosition, "Expecting control to not scroll");
return iterateAllSections(control, currentSectionOnScreen, false);
}).then(function () {
var currentSectionOnScreen = control.sectionOnScreen;
return iterateAllSections(control, currentSectionOnScreen, true);
});
}
function GetSectionOnScreenTest(testHost, config) {
var control = testHost.querySelector(".win-hub").winControl;
return HubUtils.waitForReady(control)().
then(function () {
var currentScrollPosition = 42; //starting scroll position for test
var increment = 11; //how far to increment on each iteration
var scrollRange = HubUtils.getScrollRange(control);
var index = HubUtils.findCurrentSectionOnScreen(control);
LiveUnit.Assert.areEqual(index, control.sectionOnScreen);
function loop() {
return new WinJS.Promise(function (c, e, p) {
//set scroll position
currentScrollPosition = Math.min(scrollRange.max, currentScrollPosition + increment);
control.scrollPosition = currentScrollPosition;
WinJS.Utilities._setImmediate(function () {
//hit test for sectionOnScreen
var index = HubUtils.findCurrentSectionOnScreen(control);
LiveUnit.Assert.areEqual(index, control.sectionOnScreen);
c();
});
});
}
function continueCondition() {
return WinJS.Promise.wrap(currentScrollPosition < scrollRange.max);
}
//loop
return Helper.asyncWhile(continueCondition, loop);
});
}
function GetScrollPosTest(testHost, config) {
var control = testHost.querySelector(".win-hub").winControl;
return HubUtils.waitForReady(control)().
then(function () {
var scrollProperty = control.orientation === WinJS.UI.Orientation.horizontal ? "scrollLeft" : "scrollTop";
var scrollRange = HubUtils.getScrollRange(control);
var scroller = control.element.firstElementChild;
var currentScrollPosition = WinJS.Utilities.getScrollPosition(scroller)[scrollProperty];
var increment = 11;
function loop() {
return new WinJS.Promise(function (c) {
currentScrollPosition = Math.min(currentScrollPosition + increment, scrollRange.max);
var newPosition: any = {};
newPosition[scrollProperty] = currentScrollPosition;
WinJS.Utilities.setScrollPosition(scroller, newPosition);
Helper.waitForScroll(control._viewportElement).then(function () {
LiveUnit.Assert.areEqual(currentScrollPosition, control.scrollPosition);
c();
});
});
}
function continueCondition() {
return WinJS.Promise.wrap(currentScrollPosition < scrollRange.max);
}
return Helper.asyncWhile(continueCondition, loop);
});
}
function SetScrollPosTest(testHost, config) {
var control = testHost.querySelector(".win-hub").winControl;
return HubUtils.waitForReady(control)().
then(function () {
var scrollProperty = control.orientation === WinJS.UI.Orientation.horizontal ? "scrollLeft" : "scrollTop";
var scrollRange = HubUtils.getScrollRange(control);
var scroller = control.element.firstElementChild;
var currentScrollPosition = control.scrollPosition;
var increment = 11;
function loop() {
return new WinJS.Promise(function (c) {
currentScrollPosition = Math.min(currentScrollPosition + increment, scrollRange.max);
control.scrollPosition = currentScrollPosition;
Helper.waitForScroll(control._viewportElement).then(function () {
LiveUnit.Assert.areEqual(currentScrollPosition, WinJS.Utilities.getScrollPosition(scroller)[scrollProperty]);
c();
});
});
}
function continueCondition() {
return WinJS.Promise.wrap(currentScrollPosition < scrollRange.max);
}
return Helper.asyncWhile(continueCondition, loop);
});
}
function SwapSectionsTest(testHost, config) {
var control = testHost.querySelector(".win-hub").winControl;
var newSections = [new HubSection()];
var oldSections = control.sections;
return HubUtils.waitForReady(control)().
then(function () {
control.sections = new WinJS.Binding.List(newSections);
return HubUtils.waitForReady(control)();
}).
then(function () {
HubUtils.verifySections(control, newSections, control.headerTemplate);
control.sections = oldSections;
return HubUtils.waitForReady(control)();
}).
then(function () {
HubUtils.verifySections(control, oldSections.slice(), control.headerTemplate);
});
}
function DeleteAllTest(testHost, config) {
var control = testHost.querySelector(".win-hub").winControl;
return HubUtils.waitForReady(control)().
then(function () {
control.sections.length = 0;
return WinJS.Promise.timeout(WinJS.UI._animationTimeAdjustment(3000));
}).
then(function () {
LiveUnit.Assert.areEqual(0, document.body.querySelectorAll('progress').length, "Expecting no progress indicators in DOM");
});
}
export class BasicTests {
setUp() {
LiveUnit.LoggingCore.logComment("In setup");
var newNode = document.createElement("div");
newNode.id = hostId;
newNode.style.minHeight = "1024px";
newNode.style.minWidth = "768px";
newNode.style.height = "100%";
newNode.style.width = "100%";
document.body.appendChild(newNode);
}
tearDown() {
LiveUnit.LoggingCore.logComment("In tearDown");
var element = document.getElementById(hostId);
if (element) {
WinJS.Utilities.disposeSubTree(element);
document.body.removeChild(element);
}
}
// Test functions
}
HubUtils.test(BasicTests.prototype, hostSelector, "Init", InitTest, { priority: 0 });
HubUtils.test(BasicTests.prototype, hostSelector, "LoadingStateChanged", LoadingStateChangedTest), { priority: 0 };
HubUtils.test(BasicTests.prototype, hostSelector, "RemoveFromDOMTest", RemoveFromDOMTest, { priority: 0 });
HubUtils.test(BasicTests.prototype, hostSelector, "RehydrationTest", RehydrationTest, { priority: 0 });
HubUtils.test(BasicTests.prototype, hostSelector, "SwapOrientation", SwapOrientationTest, { priority: 0 });
HubUtils.test(BasicTests.prototype, hostSelector, "SwapHeaderTemplateTest", SwapHeaderTemplateTest, { priority: 0 });
HubUtils.test(BasicTests.prototype, hostSelector, "HeaderInvokedTest", HeaderInvokedTest, { priority: 0 });
HubUtils.test(BasicTests.prototype, hostSelector, "SetSectionOnScreenTest", SetSectionOnScreenTest, { priority: 0 });
HubUtils.test(BasicTests.prototype, hostSelector, "GetSectionOnScreenTest", GetSectionOnScreenTest, { priority: 0 });
HubUtils.test(BasicTests.prototype, hostSelector, "GetScrollPosTest", GetScrollPosTest, { priority: 0 });
HubUtils.test(BasicTests.prototype, hostSelector, "SetScrollPosTest", SetScrollPosTest, { priority: 0 });
HubUtils.test(BasicTests.prototype, hostSelector, "SwapSectionsTest", SwapSectionsTest, { priority: 0 });
HubUtils.test(BasicTests.prototype, hostSelector, "DeleteAll", DeleteAllTest, { priority: 1 });
}
LiveUnit.registerTestClass("HubTests.BasicTests");