// Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. See License.txt in the project root for license information.
///
//
module CorsicaTests {
"use strict";
var Keys = WinJS.Utilities.Key;
function waitForScrollDone(element: HTMLElement) {
return new WinJS.Promise(c => {
element.addEventListener("MSManipulationStateChanged", function handler(e: MSManipulationEvent) {
if (e.currentState !== MSManipulationEvent.MS_MANIPULATION_STATE_STOPPED) {
return;
}
element.removeEventListener("MSManipulationStateChanged", handler);
c();
});
});
}
export class ScrollViewerTests {
leftButton: HTMLButtonElement;
rightButton: HTMLButtonElement;
sv: WinJS.UI.ScrollViewer;
setUp() {
var testRoot = document.createElement("div");
testRoot.id = "testRoot";
testRoot.style.position = "relative";
testRoot.style.width = "100%";
testRoot.style.height = "100%";
document.body.appendChild(testRoot);
this.leftButton = document.createElement("button");
this.leftButton.style.position = "absolute";
this.leftButton.style.width = "100px";
this.leftButton.style.height = "20px";
this.leftButton.style.left = "0";
this.leftButton.style.top = "0";
testRoot.appendChild(this.leftButton);
var el = document.createElement("div");
el.id = "testScrollViewer";
el.style.position = "absolute";
el.style.left = "100px";
el.style.top = "0";
el.style.width = "300px";
el.style.height = "400px";
var child = document.createElement("div");
child.tabIndex = 0;
child.style.height = "10000px";
child.style.width = "100%";
el.appendChild(child);
testRoot.appendChild(el);
this.rightButton = document.createElement("button");
this.rightButton.style.position = "absolute";
this.rightButton.style.width = "100px";
this.rightButton.style.height = "20px";
this.rightButton.style.left = "400px";
this.rightButton.style.top = "0";
testRoot.appendChild(this.rightButton);
this.sv = new WinJS.UI.ScrollViewer(el);
}
tearDown() {
var testRoot = document.querySelector("#testRoot");
if (testRoot) {
WinJS.Utilities.disposeSubTree(testRoot);
testRoot.parentElement.removeChild(testRoot);
}
}
testEmptyConstructor() {
new WinJS.UI.ScrollViewer();
}
testTextMode(complete) {
if (!HTMLElement.prototype.setActive) {
LiveUnit.LoggingCore.logComment("This test relies on IE specific focus APIs.");
complete();
return;
}
this.sv._refreshDone = () => {
this.sv._refreshDone = null;
var origScrollPosition = this.sv._scrollingContainer.scrollTop;
LiveUnit.Assert.isTrue(this.sv.element.classList.contains("win-scrollviewer-scrollmode-text"));
LiveUnit.Assert.isTrue(this.sv._scrollingContainer.classList.contains("win-xyfocus-togglemode"));
LiveUnit.Assert.isFalse(this.sv._scrollingContainer.classList.contains("win-xyfocus-togglemode-active"));
// Normal text mode should not auto-activate on focus
this.sv._scrollingContainer.focus();
WinJS.Promise.timeout(200)
.then(() => {
LiveUnit.Assert.areEqual(this.sv._scrollingContainer, document.activeElement);
LiveUnit.Assert.isFalse(this.sv._scrollingContainer.classList.contains("win-xyfocus-togglemode-active"));
// Try scrolling while SV is inactive
Helper.keydown(document.activeElement, Keys.downArrow);
Helper.keydown(document.activeElement, Keys.pageDown);
return WinJS.Promise.timeout(200);
}).then(() => {
LiveUnit.Assert.areEqual(origScrollPosition, this.sv._scrollingContainer.scrollTop, "Should not scroll since the SV is not yet active");
this.sv._setActive();
LiveUnit.Assert.isTrue(this.sv._scrollingContainer.classList.contains("win-xyfocus-togglemode-active"));
// Try scrolling down by a small amount
Helper.keydown(document.activeElement, Keys.downArrow);
return waitForScrollDone(this.sv._scrollingContainer);
}).done(() => {
LiveUnit.Assert.isTrue(this.sv._scrollingContainer.scrollTop > origScrollPosition);
complete();
});
};
}
testNonModalTextMode(complete) {
if (!HTMLElement.prototype.setActive) {
LiveUnit.LoggingCore.logComment("This test relies on IE specific focus APIs.");
complete();
return;
}
this.sv._refreshDone = () => {
this.sv._refreshDone = null;
this.sv.scrollMode = WinJS.UI.ScrollMode.nonModalText;
var origScrollPosition = this.sv._scrollingContainer.scrollTop;
LiveUnit.Assert.isTrue(this.sv.element.classList.contains("win-scrollviewer-scrollmode-text"));
LiveUnit.Assert.isTrue(this.sv._scrollingContainer.classList.contains("win-xyfocus-togglemode"));
LiveUnit.Assert.isFalse(this.sv._scrollingContainer.classList.contains("win-xyfocus-togglemode-active"));
// Non-modal text mode should auto-activate on focus
this.sv._scrollingContainer.focus();
WinJS.Promise.timeout(200)
.then(() => {
LiveUnit.Assert.areEqual(this.sv._scrollingContainer, document.activeElement);
LiveUnit.Assert.isTrue(this.sv._scrollingContainer.classList.contains("win-xyfocus-togglemode-active"));
// Try scrolling by a small amount
Helper.keydown(document.activeElement, Keys.downArrow);
return waitForScrollDone(this.sv._scrollingContainer);
}).done(() => {
LiveUnit.Assert.isTrue(this.sv._scrollingContainer.scrollTop > origScrollPosition);
complete();
});
};
}
testListMode(complete) {
if (!HTMLElement.prototype.setActive) {
LiveUnit.LoggingCore.logComment("This test relies on IE specific focus APIs.");
complete();
return;
}
this.sv._refreshDone = () => {
this.sv._refreshDone = null;
this.sv.scrollMode = WinJS.UI.ScrollMode.list;
var origScrollPosition = this.sv._scrollingContainer.scrollTop;
LiveUnit.Assert.isTrue(this.sv.element.classList.contains("win-scrollviewer-scrollmode-list"));
LiveUnit.Assert.isFalse(this.sv._scrollingContainer.classList.contains("win-xyfocus-togglemode"));
LiveUnit.Assert.isFalse(this.sv._scrollingContainer.classList.contains("win-xyfocus-togglemode-active"));
// Focusing the ScrollViewer in List mode should delegate focus to the first focusable element within it
this.sv._scrollingContainer.focus();
WinJS.Promise.timeout(200)
.then(() => {
LiveUnit.Assert.areEqual(this.sv._scrollingContainer.firstElementChild, document.activeElement);
// Try scrolling by a small amount, should not work
Helper.keydown(document.activeElement, Keys.downArrow);
return WinJS.Promise.timeout(200);
}).then(() => {
LiveUnit.Assert.areEqual(origScrollPosition, this.sv._scrollingContainer.scrollTop);
// Try scrolling by a large amount, should not work
origScrollPosition = this.sv._scrollingContainer.scrollTop;
Helper.keydown(document.activeElement, Keys.pageDown);
return WinJS.Promise.timeout(200);
}).done(() => {
LiveUnit.Assert.areEqual(origScrollPosition, this.sv._scrollingContainer.scrollTop);
complete();
});
};
}
testScrolling(complete) {
if (!HTMLElement.prototype.setActive) {
LiveUnit.LoggingCore.logComment("This test relies on IE specific focus APIs.");
complete();
return;
}
this.sv._refreshDone = () => {
this.sv._refreshDone = null;
// The scrolling indicators should show up-disabled, down-enabled
LiveUnit.Assert.isFalse(this.sv._scrollingIndicatorElement.classList.contains("win-scrollable-up"));
LiveUnit.Assert.isTrue(this.sv._scrollingIndicatorElement.classList.contains("win-scrollable-down"));
this.sv._scrollingContainer.focus();
this.sv._setActive();
var origScrollPosition = this.sv._scrollingContainer.scrollTop;
var smallDelta = 0;
var largeDelta = 0;
// Try scrolling down by a small amount
Helper.keydown(document.activeElement, Keys.downArrow);
waitForScrollDone(this.sv._scrollingContainer)
.then(() => {
smallDelta = this.sv._scrollingContainer.scrollTop - origScrollPosition;
LiveUnit.Assert.isTrue(this.sv._scrollingContainer.scrollTop > origScrollPosition);
LiveUnit.Assert.isTrue(this.sv._scrollingIndicatorElement.classList.contains("win-scrollable-up"));
LiveUnit.Assert.isTrue(this.sv._scrollingIndicatorElement.classList.contains("win-scrollable-down"));
// Try scrolling down by a large amount
origScrollPosition = this.sv._scrollingContainer.scrollTop;
Helper.keydown(document.activeElement, Keys.pageDown);
return waitForScrollDone(this.sv._scrollingContainer);
}).then(() => {
largeDelta = this.sv._scrollingContainer.scrollTop - origScrollPosition;
LiveUnit.Assert.isTrue(largeDelta > smallDelta);
LiveUnit.Assert.isTrue(this.sv._scrollingIndicatorElement.classList.contains("win-scrollable-up"));
LiveUnit.Assert.isTrue(this.sv._scrollingIndicatorElement.classList.contains("win-scrollable-down"));
// Try scrolling up by a small amount
origScrollPosition = this.sv._scrollingContainer.scrollTop;
Helper.keydown(document.activeElement, Keys.upArrow);
return waitForScrollDone(this.sv._scrollingContainer);
}).then(() => {
LiveUnit.Assert.areEqual(-smallDelta, this.sv._scrollingContainer.scrollTop - origScrollPosition);
LiveUnit.Assert.isTrue(this.sv._scrollingIndicatorElement.classList.contains("win-scrollable-up"));
LiveUnit.Assert.isTrue(this.sv._scrollingIndicatorElement.classList.contains("win-scrollable-down"));
// Try scrolling up by a large amount
origScrollPosition = this.sv._scrollingContainer.scrollTop;
Helper.keydown(document.activeElement, Keys.pageUp);
return waitForScrollDone(this.sv._scrollingContainer);
}).then(() => {
LiveUnit.Assert.areEqual(-largeDelta, this.sv._scrollingContainer.scrollTop - origScrollPosition);
LiveUnit.Assert.isFalse(this.sv._scrollingIndicatorElement.classList.contains("win-scrollable-up"));
LiveUnit.Assert.isTrue(this.sv._scrollingIndicatorElement.classList.contains("win-scrollable-down"));
// Scroll to end, indcators should show up-enabled, down-disabled
this.sv._scrollingContainer.scrollTop = this.sv._scrollingContainer.scrollHeight - this.sv.element.offsetHeight;
return WinJS.Promise.timeout(100);
}).then(() => {
LiveUnit.Assert.isTrue(this.sv._scrollingIndicatorElement.classList.contains("win-scrollable-up"));
LiveUnit.Assert.isFalse(this.sv._scrollingIndicatorElement.classList.contains("win-scrollable-down"));
// ScrollViewer should deactivate on focus loss
this.rightButton.focus();
return WinJS.Promise.timeout(100);
}).done(() => {
LiveUnit.Assert.isFalse(this.sv._scrollingContainer.classList.contains("win-xyfocus-togglemode-active"));
complete();
});
};
}
testLeftRightKeysExitsActiveMode(complete) {
if (!HTMLElement.prototype.setActive) {
LiveUnit.LoggingCore.logComment("This test relies on IE specific focus APIs.");
complete();
return;
}
this.sv._refreshDone = () => {
this.sv._refreshDone = null;
this.sv._scrollingContainer.focus();
LiveUnit.Assert.areEqual(this.sv._scrollingContainer, document.activeElement);
this.sv._setActive();
// Exit the ScrollViewer to the left
Helper.keydown(document.activeElement, Keys.leftArrow);
LiveUnit.Assert.areEqual(this.leftButton, document.activeElement);
this.sv._scrollingContainer.focus();
LiveUnit.Assert.areEqual(this.sv._scrollingContainer, document.activeElement);
this.sv._setActive();
// Exit the ScrollViewer to the right
Helper.keydown(document.activeElement, Keys.rightArrow);
LiveUnit.Assert.areEqual(this.rightButton, document.activeElement);
complete();
};
}
testVUIActivation(complete) {
if (!HTMLElement.prototype.setActive) {
LiveUnit.LoggingCore.logComment("This test relies on IE specific focus APIs.");
complete();
return;
}
this.sv._refreshDone = () => {
this.sv._refreshDone = null;
// VUI should start off disabled
LiveUnit.Assert.isFalse(this.sv.element.classList.contains("win-voice-voicemodeactive"));
// VUI should be active in active state
var evt = document.createEvent("CustomEvent");
evt["state"] = "active";
evt.initCustomEvent("listeningstatechanged", true, false, null);
this.sv._scrollingIndicatorElement.dispatchEvent(evt);
LiveUnit.Assert.isTrue(this.sv.element.classList.contains("win-voice-voicemodeactive"));
// VUI should remain active in disambig state
var evt = document.createEvent("CustomEvent");
evt["state"] = "disambiguation";
evt.initCustomEvent("listeningstatechanged", true, false, null);
this.sv._scrollingIndicatorElement.dispatchEvent(evt);
LiveUnit.Assert.isTrue(this.sv.element.classList.contains("win-voice-voicemodeactive"));
// VUI should be disabled in inactive state
var evt = document.createEvent("CustomEvent");
evt["state"] = "inactive";
evt.initCustomEvent("listeningstatechanged", true, false, null);
this.sv._scrollingIndicatorElement.dispatchEvent(evt);
LiveUnit.Assert.isFalse(this.sv.element.classList.contains("win-voice-voicemodeactive"));
complete();
};
}
testVUIScrolling(complete) {
if (!HTMLElement.prototype.setActive) {
LiveUnit.LoggingCore.logComment("This test relies on IE specific focus APIs.");
complete();
return;
}
this.sv._refreshDone = () => {
this.sv._refreshDone = null;
// Make sure the scroller is focused and the ScrollViewer is still inactive
this.sv._scrollingContainer.focus();
LiveUnit.Assert.areEqual(this.sv._scrollingContainer, document.activeElement);
LiveUnit.Assert.isFalse(this.sv._scrollingContainer.classList.contains("win-xyfocus-togglemode-active"));
// Try scrolling by large amounts, should fail
var origScrollPosition = this.sv._scrollingContainer.scrollTop;
Helper.keydown(document.activeElement, Keys.pageDown);
Helper.keydown(document.activeElement, Keys.pageDown);
Helper.keydown(document.activeElement, Keys.pageUp);
WinJS.Promise.timeout(200)
.then(() => {
LiveUnit.Assert.areEqual(origScrollPosition, this.sv._scrollingContainer.scrollTop);
// Simulate VUI active
this.sv._vuiActive = true;
// Try scrolling by a small amounts, should not work
origScrollPosition = this.sv._scrollingContainer.scrollTop;
Helper.keydown(document.activeElement, Keys.downArrow);
Helper.keydown(document.activeElement, Keys.downArrow);
Helper.keydown(document.activeElement, Keys.upArrow);
return WinJS.Promise.timeout(200);
}).then(() => {
LiveUnit.Assert.areEqual(origScrollPosition, this.sv._scrollingContainer.scrollTop);
// Try scrolling by a large amount, should work
origScrollPosition = this.sv._scrollingContainer.scrollTop;
Helper.keydown(document.activeElement, Keys.pageDown);
return waitForScrollDone(this.sv._scrollingContainer);
}).then(() => {
LiveUnit.Assert.areNotEqual(origScrollPosition, this.sv._scrollingContainer.scrollTop);
// Try scrolling by a large amount, should work
origScrollPosition = this.sv._scrollingContainer.scrollTop;
Helper.keydown(document.activeElement, Keys.pageUp);
return waitForScrollDone(this.sv._scrollingContainer);
}).done(() => {
LiveUnit.Assert.areNotEqual(origScrollPosition, this.sv._scrollingContainer.scrollTop);
complete();
});
};
}
}
}
LiveUnit.registerTestClass("CorsicaTests.ScrollViewerTests");