// Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. See License.txt in the project root for license information.
//
//
///
///
//
///
///
module SplitViewTests {
"use strict";
// Horizontal (placement left/right)
var defaultHiddenPaneWidth = 48;
var defaultShownPaneWidth = 320;
// Vertical (placement top/bottom)
var defaultHiddenPaneHeight = 24;
var defaultShownPaneHeight = 60;
var defaultOptions: ISplitViewOptions = {
panePlacement: SplitView.PanePlacement.left,
closedDisplayMode: SplitView.OpenedDisplayMode.inline,
openedDisplayMode: SplitView.OpenedDisplayMode.overlay,
paneOpened: false
};
var defaultLayoutConfig = WinJS.Utilities._merge(defaultOptions, {
//rootWidth: ,
//rootHeight: ,
hiddenPaneWidth: defaultHiddenPaneWidth,
hiddenPaneHeight: defaultHiddenPaneHeight,
shownPaneWidth: defaultShownPaneWidth,
shownPaneHeight: defaultShownPaneHeight,
rtl: false
});
var testRoot: HTMLElement;
var Utils = SplitViewTests.Utilities;
var createSplitView: (options?: any) => WinJS.UI.PrivateSplitView;
interface IRect {
left: number;
top: number;
width: number;
height: number;
}
function measureMarginBox(element: HTMLElement, relativeTo: HTMLElement): IRect {
var style = getComputedStyle(element);
var position = WinJS.Utilities._getPositionRelativeTo(element, relativeTo);
var marginLeft = parseInt(style.marginLeft, 10);
var marginTop = parseInt(style.marginTop, 10);
return {
left: position.left - marginLeft,
top: position.top - marginTop,
width: WinJS.Utilities.getContentWidth(element),
height: WinJS.Utilities.getContentHeight(element),
};
}
function assertAreRectsEqual(expectedRect: IRect, actualRect: IRect, context: string): void {
LiveUnit.Assert.areEqual(expectedRect.left, actualRect.left, context + ": incorrect left");
LiveUnit.Assert.areEqual(expectedRect.top, actualRect.top, context + ": incorrect top");
LiveUnit.Assert.areEqual(expectedRect.width, actualRect.width, context + ": incorrect width");
LiveUnit.Assert.areEqual(expectedRect.height, actualRect.height, context + ": incorrect height");
}
function verifyTabIndicesWithoutCarousel(splitView: WinJS.UI.PrivateSplitView) {
var startPaneTab = splitView._dom.startPaneTab;
var endPaneTab = splitView._dom.endPaneTab;
LiveUnit.Assert.isFalse(startPaneTab.hasAttribute("x-ms-aria-flowfrom"), "startPaneTab shouldn't have x-ms-aria-flowfrom");
LiveUnit.Assert.areEqual(-1, startPaneTab.tabIndex, "startPaneTab should have tabIndex -1");
LiveUnit.Assert.isFalse(endPaneTab.hasAttribute("aria-flowfrom"), "endPaneTab shouldn't have aria-flowto");
LiveUnit.Assert.areEqual(-1, endPaneTab.tabIndex, "endPaneTab should have tabIndex -1");
}
function verifyTabIndicesWithCarousel(splitView: WinJS.UI.PrivateSplitView, lowestTabIndex: number, highestTabIndex: number) {
var startPaneTab = splitView._dom.startPaneTab;
var endPaneTab = splitView._dom.endPaneTab;
LiveUnit.Assert.areEqual(endPaneTab.id, startPaneTab.getAttribute("x-ms-aria-flowfrom"),
"startPaneTab has wrong value for x-ms-aria-flowfrom");
LiveUnit.Assert.areEqual(lowestTabIndex, startPaneTab.tabIndex,
"startPaneTab doesn't match content's lowest tab index");
LiveUnit.Assert.areEqual(startPaneTab.id, endPaneTab.getAttribute("aria-flowto"),
"endPaneTab has wrong value for aria-flowto");
LiveUnit.Assert.areEqual(highestTabIndex, splitView._dom.endPaneTab.tabIndex,
"endPaneTab doesn't match content's highest tab index");
}
interface ILayoutConfig {
rootWidth: number;
rootHeight: number;
hiddenPaneWidth: number;
shownPaneWidth: number;
hiddenPaneHeight: number;
shownPaneHeight: number;
panePlacement: string;
closedDisplayMode: string;
openedDisplayMode: string;
paneOpened: boolean;
rtl: boolean;
}
function expectedPaneRect(config: ILayoutConfig): IRect {
if (!config.paneOpened && config.closedDisplayMode === "none") {
return {
left: 0,
top: 0,
width: 0,
height: 0
};
}
var placementLeft = config.rtl ? SplitView.PanePlacement.right : SplitView.PanePlacement.left;
var placementRight = config.rtl ? SplitView.PanePlacement.left : SplitView.PanePlacement.right;
var paneWidth = config.paneOpened ? config.shownPaneWidth : config.hiddenPaneWidth;
var paneHeight = config.paneOpened ? config.shownPaneHeight : config.hiddenPaneHeight;
var horizontal = config.panePlacement === placementLeft || config.panePlacement === placementRight;
var size = horizontal ? {
width: paneWidth,
height: config.rootHeight
} : {
width: config.rootWidth,
height: paneHeight
};
var pos: { left: number; top: number; }
switch (config.panePlacement) {
case placementLeft:
case SplitView.PanePlacement.top:
pos = { left: 0, top: 0 };
break;
case placementRight:
pos = {
left: config.rootWidth - paneWidth,
top: 0
};
break;
case SplitView.PanePlacement.bottom:
pos = {
left: 0,
top: config.rootHeight - paneHeight
};
break;
}
return {
left: pos.left,
top: pos.top,
width: size.width,
height: size.height
};
}
function expectedContentRect(config: ILayoutConfig): IRect {
var placementLeft = config.rtl ? SplitView.PanePlacement.right : SplitView.PanePlacement.left;
var placementRight = config.rtl ? SplitView.PanePlacement.left : SplitView.PanePlacement.right;
var paneWidth: number;
var paneHeight: number;
if (!config.paneOpened || config.openedDisplayMode === SplitView.OpenedDisplayMode.overlay) {
if (config.closedDisplayMode === "none") {
paneWidth = 0;
paneHeight = 0;
} else {
paneWidth = config.hiddenPaneWidth;
paneHeight = config.hiddenPaneHeight;
}
} else {
paneWidth = config.shownPaneWidth;
paneHeight = config.shownPaneHeight;
}
var horizontal = config.panePlacement === placementLeft || config.panePlacement === placementRight;
var size = horizontal ? {
width: config.rootWidth - paneWidth,
height: config.rootHeight
} : {
width: config.rootWidth,
height: config.rootHeight - paneHeight
};
var pos: { left: number; top: number; }
switch (config.panePlacement) {
case placementLeft:
pos = { left: paneWidth, top: 0 };
break;
case SplitView.PanePlacement.top:
pos = { left: 0, top: paneHeight };
break;
case placementRight:
case SplitView.PanePlacement.bottom:
pos = { left: 0, top: 0 };
break;
}
return {
left: pos.left,
top: pos.top,
width: size.width,
height: size.height
};
}
function assertContentLayoutCorrect(splitView: WinJS.UI.PrivateSplitView, config: ILayoutConfig): void {
var contentRect = measureMarginBox(splitView.contentElement, splitView.element);
assertAreRectsEqual(expectedContentRect(config), contentRect, "Content rect");
}
function assertLayoutCorrect(splitView: WinJS.UI.PrivateSplitView, config: ILayoutConfig): void {
var paneRect = measureMarginBox(splitView.paneElement, splitView.element);
assertAreRectsEqual(expectedPaneRect(config), paneRect, "Pane rect");
assertContentLayoutCorrect(splitView, config);
}
interface ITestLayoutArgs {
rootHeight: number;
rootWidth: number;
hiddenPaneWidth: number;
hiddenPaneHeight: number;
shownPaneWidth: number;
shownPaneHeight: number;
verify?: (splitView: WinJS.UI.PrivateSplitView, config: ILayoutConfig) => void;
}
function testLayout(args: ITestLayoutArgs, splitViewOptions?: any) {
args.verify = args.verify || assertLayoutCorrect;
testRoot.style.height = args.rootHeight + "px";
testRoot.style.width = args.rootWidth + "px";
[true, false].forEach((rtl) => { // rtl
if (rtl) {
document.documentElement.setAttribute("lang", "ar");
} else {
document.documentElement.removeAttribute("lang");
}
var splitView = Utils.useSynchronousAnimations(createSplitView(splitViewOptions));
["left", "right", "top", "bottom"].forEach((panePlacement) => { // panePlacement
["none", "inline"].forEach((closedDisplayMode) => { // closedDisplayMode
["inline", "overlay"].forEach((openedDisplayMode) => { // openedDisplayMode
[true, false].forEach((paneOpened) => { // paneOpened
splitView.panePlacement = panePlacement;
splitView.closedDisplayMode = closedDisplayMode;
splitView.openedDisplayMode = openedDisplayMode;
splitView.paneOpened = paneOpened;
var config = {
panePlacement: panePlacement,
closedDisplayMode: closedDisplayMode,
openedDisplayMode: openedDisplayMode,
paneOpened: paneOpened,
rootWidth: args.rootWidth,
rootHeight: args.rootHeight,
hiddenPaneWidth: args.hiddenPaneWidth,
hiddenPaneHeight: args.hiddenPaneHeight,
shownPaneWidth: args.shownPaneWidth,
shownPaneHeight: args.shownPaneHeight,
rtl: rtl
};
args.verify(splitView, config);
});
});
});
});
Helper.removeElement(splitView.element);
splitView.dispose();
});
}
function assertHasClass(element: HTMLElement, className: string, msg: string): void {
LiveUnit.Assert.isTrue(WinJS.Utilities.hasClass(element, className), msg);
}
function assertProperties(splitView: WinJS.UI.PrivateSplitView, providedOptions) {
providedOptions = providedOptions || {};
var validPropreties = Object.keys(defaultOptions);
Helper.Assert.areKeysValid(providedOptions, validPropreties);
var options: ISplitViewOptions = WinJS.Utilities._merge(defaultOptions, providedOptions);
LiveUnit.Assert.areEqual(options.paneOpened, splitView.paneOpened, "splitView.paneOpened incorrect");
LiveUnit.Assert.areEqual(options.panePlacement, splitView.panePlacement, "splitView.panePlacement incorrect");
LiveUnit.Assert.areEqual(options.closedDisplayMode, splitView.closedDisplayMode, "splitView.closedDisplayMode incorrect");
LiveUnit.Assert.areEqual(options.openedDisplayMode, splitView.openedDisplayMode, "splitView.openedDisplayMode incorrect");
}
// Taking the registration mechanism as a parameter allows us to use this code to test both
// DOM level 0 (e.g. onbeforeopen) and DOM level 2 (e.g. addEventListener) events.
function testEvents(registerForEvent: (splitView: WinJS.UI.PrivateSplitView, eventName: string, handler: Function) => void) {
var splitView = Utils.useSynchronousAnimations(createSplitView());
var counter = 0;
registerForEvent(splitView, "beforeopen", () => {
LiveUnit.Assert.areEqual(1, counter, "beforeopen fired out of order");
counter++;
LiveUnit.Assert.isFalse(splitView.paneOpened, "beforeopen: SplitView should be in hidden state");
});
registerForEvent(splitView, "afteropen", () => {
LiveUnit.Assert.areEqual(2, counter, "afteropen fired out of order");
counter++;
LiveUnit.Assert.isTrue(splitView.paneOpened, "afteropen: SplitView should not be in hidden state");
});
registerForEvent(splitView, "beforeclose", () => {
LiveUnit.Assert.areEqual(4, counter, "beforeclose fired out of order");
counter++;
LiveUnit.Assert.isTrue(splitView.paneOpened, "beforeclose: SplitView should not be in hidden state");
});
registerForEvent(splitView, "afterclose", () => {
LiveUnit.Assert.areEqual(5, counter, "afterclose fired out of order");
counter++;
LiveUnit.Assert.isFalse(splitView.paneOpened, "afterclose: SplitView should be in hidden state");
});
LiveUnit.Assert.areEqual(0, counter, "before openPane: wrong number of events fired");
counter++;
LiveUnit.Assert.isFalse(splitView.paneOpened, "before openPane: SplitView should be in hidden state");
splitView.openPane();
LiveUnit.Assert.areEqual(3, counter, "after openPane: wrong number of events fired");
counter++;
LiveUnit.Assert.isTrue(splitView.paneOpened, "after openPane: SplitView should not be in hidden state");
splitView.closePane();
LiveUnit.Assert.areEqual(6, counter, "after closePane: wrong number of events fired");
LiveUnit.Assert.isFalse(splitView.paneOpened, "after closePane: SplitView should be in hidden state");
}
function testTabIndices(args: {
openedDisplayMode: string;
verifyTabIndicesWhenOpened: (splitView: WinJS.UI.PrivateSplitView, lowestTabIndex: number, highestTabIndex: number) => void;
verifyTabIndicesWhenClosed: (splitView: WinJS.UI.PrivateSplitView, lowestTabIndex: number, highestTabIndex: number) => void;
}) {
var openedDisplayMode = args.openedDisplayMode;
var verifyTabIndicesWhenOpened = args.verifyTabIndicesWhenOpened;
var verifyTabIndicesWhenClosed = args.verifyTabIndicesWhenClosed;
var paneHTML =
'
4
' +
'5
' +
'' +
'
7
' +
'
8
' + // highest
'
6
' +
'
' +
'2
' + // lowest
'3
';
var contentHTML =
'0
' +
'10
';
var lowestTabIndex = 2;
var highestTabIndex = 8;
var splitView = Utils.useSynchronousAnimations(createSplitView({
paneHTML: paneHTML,
contentHTML: contentHTML,
openedDisplayMode: openedDisplayMode
}));
verifyTabIndicesWhenClosed(splitView, lowestTabIndex, highestTabIndex);
splitView.openPane();
verifyTabIndicesWhenOpened(splitView, lowestTabIndex, highestTabIndex);
// Test that SplitView updates its tab indices after the user presses
// the tab key
//
lowestTabIndex = 1;
highestTabIndex = 9;
var newLowest = document.createElement("div");
newLowest.tabIndex = lowestTabIndex;
var newHighest = document.createElement("div");
newHighest.tabIndex = highestTabIndex;
splitView._dom.pane.appendChild(newHighest);
splitView.element.querySelector(".aParent").appendChild(newLowest);
// Tab key should cause the SplitView to update its tab indices
Helper.keydown(splitView._dom.pane, WinJS.Utilities.Key.tab);
verifyTabIndicesWhenOpened(splitView, lowestTabIndex, highestTabIndex);
splitView.closePane();
verifyTabIndicesWhenClosed(splitView, lowestTabIndex, highestTabIndex);
Helper.validateUnhandledErrors();
}
export class BasicTests {
setUp() {
testRoot = document.createElement("div");
// Give it an id so that we can use it in styles to make sure our styles win over the defaults.
// We encourage apps to do the same.
testRoot.id = "test-root";
createSplitView = Utils.makeCreateSplitView(testRoot);
document.body.appendChild(testRoot);
}
tearDown() {
WinJS.Utilities.disposeSubTree(testRoot);
Helper.removeElement(testRoot);
document.documentElement.removeAttribute("lang");
}
testDomLevel0Events() {
testEvents((splitView: WinJS.UI.PrivateSplitView, eventName: string, handler: Function) => {
splitView["on" + eventName] = handler;
});
}
testDomLevel2Events() {
testEvents((splitView: WinJS.UI.PrivateSplitView, eventName: string, handler: Function) => {
splitView.addEventListener(eventName, handler);
});
}
testBeforeOpenIsCancelable() {
var splitView = Utils.useSynchronousAnimations(createSplitView());
splitView.onbeforeopen = function (eventObject) {
eventObject.preventDefault();
};
splitView.onafteropen = function (eventObject) {
LiveUnit.Assert.fail("afteropen shouldn't have fired due to beforeopen being canceled");
};
splitView.onbeforeclose = function (eventObject) {
LiveUnit.Assert.fail("beforeclose shouldn't have fired due to beforeopen being canceled");
};
splitView.onafterclose = function (eventObject) {
LiveUnit.Assert.fail("afterclose shouldn't have fired due to beforeopen being canceled");
};
splitView.openPane();
LiveUnit.Assert.isFalse(splitView.paneOpened, "SplitView should still be hidden");
}
testBeforeCloseIsCancelable() {
var splitView = Utils.useSynchronousAnimations(createSplitView());
splitView.openPane();
splitView.onbeforeclose = function (eventObject) {
eventObject.preventDefault();
};
splitView.onafterclose = function (eventObject) {
LiveUnit.Assert.fail("Hide should have been canceled");
};
splitView.closePane();
LiveUnit.Assert.isTrue(splitView.paneOpened, "SplitView should still be shown");
}
testDispose() {
function failEventHandler(eventName) {
return function () {
LiveUnit.Assert.fail(eventName + ": shouldn't have run due to control being disposed");
};
}
var splitView = Utils.useSynchronousAnimations(createSplitView());
splitView.openPane();
splitView.onbeforeopen = failEventHandler("beforeopen");
splitView.onbeforeclose = failEventHandler("beforeclose");
splitView.onafteropen = failEventHandler("afteropen");
splitView.onafterclose = failEventHandler("afterclose");
splitView.dispose();
LiveUnit.Assert.isTrue(splitView._disposed, "SplitView didn't mark itself as disposed");
LiveUnit.Assert.areEqual("Disposed", splitView._machine._state.name, "SplitView didn't move into the disposed state");
splitView.openPane();
splitView.closePane();
splitView.dispose();
}
testDefaultLayout() {
testLayout({
rootHeight: 500,
rootWidth: 1000,
hiddenPaneWidth: defaultHiddenPaneWidth,
hiddenPaneHeight: defaultHiddenPaneHeight,
shownPaneWidth: defaultShownPaneWidth,
shownPaneHeight: defaultShownPaneHeight
});
}
// Make sure SplitView lays out correctly if the developer uses custom pane dimensions
testCustomLayoutFixedSizes() {
WinJS.Utilities.addClass(testRoot, "file-splitviewstyles-less");
WinJS.Utilities.addClass(testRoot, "custom-sizes-fixed");
testLayout({
rootHeight: 500,
rootWidth: 1000,
hiddenPaneWidth: 321,
hiddenPaneHeight: 123,
shownPaneWidth: 409,
shownPaneHeight: 242
});
}
// Make sure SplitView lays out correctly if the developer configures the pane to size to its content
testCustomLayoutAutoSizes() {
WinJS.Utilities.addClass(testRoot, "file-splitviewstyles-less");
WinJS.Utilities.addClass(testRoot, "custom-sizes-auto");
testLayout({
rootHeight: 500,
rootWidth: 1000,
hiddenPaneWidth: 223,
hiddenPaneHeight: 343,
shownPaneWidth: 303,
shownPaneHeight: 444
}, {
paneHTML: ''
});
}
// Verifies that a percentage sized element (e.g. width/height: 100%) is given the appropriate
// size when placed within the SplitView's content element.
// https://github.com/winjs/winjs/issues/801
testPercentageSizingInContentArea() {
testLayout({
rootHeight: 500,
rootWidth: 1000,
hiddenPaneWidth: defaultHiddenPaneWidth,
hiddenPaneHeight: defaultHiddenPaneHeight,
shownPaneWidth: defaultShownPaneWidth,
shownPaneHeight: defaultShownPaneHeight,
verify: function (splitView, config) {
var percentageSizedEl = splitView.contentElement.querySelector(".percentage-sized");
var percentageSizedRect = measureMarginBox(percentageSizedEl, splitView.element);
var contentRect = measureMarginBox(splitView.contentElement, splitView.element);
assertAreRectsEqual(contentRect, percentageSizedRect,
"Element with width:100% and height:100% should be the same size as the SplitView's content element");
}
}, {
contentHTML: ''
});
}
// Verify that if we don't pass an element to the SplitView's constructor, it creates
// one for us and initializes its DOM structure correctly.
testInitializationWithoutElement() {
var options = null;
var splitView = Utils.useSynchronousAnimations(new SplitView());
assertHasClass(splitView.element, SplitView._ClassNames.splitView, "splitView.element is missing class");
assertHasClass(splitView.paneElement, SplitView._ClassNames.pane, "splitView.paneElement is missing class");
assertHasClass(splitView.contentElement, SplitView._ClassNames.content, "splitView.contentElement is missing class");
assertProperties(splitView, options);
}
// Verify that if we pass an element containing markup to the SplitView's constructor, it correctly
// initializes its DOM and correctly reparents our markup into the pane and content elements.
testInitializationWithElement() {
function assertContainsElementWithClass(element: HTMLElement, className: string, msg: string): void {
LiveUnit.Assert.isNotNull(element.querySelector("." + className), msg);
}
var options = null;
var splitView = Utils.useSynchronousAnimations(createSplitView({
paneHTML: '',
contentHTML: ''
}));
assertHasClass(splitView.element, SplitView._ClassNames.splitView, "splitView.element is missing class");
assertHasClass(splitView.paneElement, SplitView._ClassNames.pane, "splitView.paneElement is missing class");
assertContainsElementWithClass(splitView.paneElement, "pane-element1", "splitView.paneElement is missing a child");
assertContainsElementWithClass(splitView.paneElement, "pane-element2", "splitView.paneElement is missing a child");
assertHasClass(splitView.contentElement, SplitView._ClassNames.content, "splitView.contentElement is missing class");
assertContainsElementWithClass(splitView.contentElement, "content-element1", "splitView.contentElement is missing a child");
assertContainsElementWithClass(splitView.contentElement, "content-element2", "splitView.contentElement is missing a child");
assertProperties(splitView, options);
}
testInitializingProperties() {
var rootHeight = 500;
var rootWidth = 1000;
var optionsRecords = [
undefined,
{ paneOpened: true },
{ panePlacement: "top" },
{ closedDisplayMode: "none" },
{ closedDisplayMode: "inline" },
{ openedDisplayMode: "overlay" },
{ openedDisplayMode: "overlay", paneOpened: true },
{ openedDisplayMode: "inline" },
{ openedDisplayMode: "inline", paneOpened: true },
{ panePlacement: "right", closedDisplayMode: "inline", openedDisplayMode: "inline", paneOpened: true },
{ panePlacement: "left", closedDisplayMode: "none", openedDisplayMode: "inline", paneOpened: false },
{ panePlacement: "bottom", openedDisplayMode: "overlay", paneOpened: true },
{ panePlacement: "bottom", openedDisplayMode: "overlay" }
];
testRoot.style.height = rootHeight + "px";
testRoot.style.width = rootWidth + "px";
optionsRecords.forEach(function (options) {
var element = document.createElement("div");
testRoot.appendChild(element);
var splitView = Utils.useSynchronousAnimations(new SplitView(element, options));
assertProperties(splitView, options);
assertLayoutCorrect(splitView, WinJS.Utilities._mergeAll([defaultLayoutConfig, options || {}, {
rootWidth: rootWidth,
rootHeight: rootHeight
}]));
splitView.dispose();
Helper.removeElement(splitView.element);
});
}
testChangingProperties() {
var rootHeight = 500;
var rootWidth = 1000;
var options: any = {};
var splitView = Utils.useSynchronousAnimations(createSplitView());
function verify() {
assertProperties(splitView, options);
assertLayoutCorrect(splitView, WinJS.Utilities._mergeAll([defaultLayoutConfig, options || {}, {
rootWidth: rootWidth,
rootHeight: rootHeight
}]));
}
testRoot.style.height = rootHeight + "px";
testRoot.style.width = rootWidth + "px";
["left", "right", "top", "bottom"].forEach((panePlacement) => {
options.panePlacement = splitView.panePlacement = panePlacement;
verify();
});
["none", "inline"].forEach((closedDisplayMode) => {
options.closedDisplayMode = splitView.closedDisplayMode = closedDisplayMode;
verify();
});
["overlay", "inline"].forEach((openedDisplayMode) => {
options.openedDisplayMode = splitView.openedDisplayMode = openedDisplayMode;
verify();
});
[false, true].forEach((paneOpened) => {
options.paneOpened = splitView.paneOpened = paneOpened;
verify();
});
}
testTogglingPane() {
var rootHeight = 500;
var rootWidth = 1000;
var splitView = Utils.useSynchronousAnimations(createSplitView());
function verify(args: { paneOpened: boolean }) {
var config = WinJS.Utilities._mergeAll([
defaultLayoutConfig,
args, {
rootWidth: rootWidth,
rootHeight: rootHeight
}
]);
assertProperties(splitView, args);
assertLayoutCorrect(splitView, config);
}
testRoot.style.height = rootHeight + "px";
testRoot.style.width = rootWidth + "px";
// Pane should initially be hidden
verify({ paneOpened: false });
// After toggling pane, pane should be shown
splitView.paneOpened = !splitView.paneOpened;
verify({ paneOpened: true });
// After toggling pane, pane should be hidden
splitView.paneOpened = !splitView.paneOpened;
verify({ paneOpened: false });
}
// Verifies that animations start and end in the correct locations
testAnimations(complete) {
var rootHeight = 500;
var rootWidth = 1000;
var allConfigs = Helper.pairwise({
rtl: [true, false],
panePlacement: ["left", "right", "top", "bottom"],
closedDisplayMode: ["none", "inline"],
openedDisplayMode: ["inline", "overlay"]
});
var testConfig = (index) => {
if (index >= allConfigs.length) {
complete();
} else {
var config = allConfigs[index];
var fullConfig = WinJS.Utilities._merge(config, {
rootHeight: rootHeight,
rootWidth: rootWidth,
hiddenPaneWidth: defaultHiddenPaneWidth,
hiddenPaneHeight: defaultHiddenPaneHeight,
shownPaneWidth: defaultShownPaneWidth,
shownPaneHeight: defaultShownPaneHeight,
paneOpened: true
});
var hooksRan = 0;
if (fullConfig.rtl) {
document.documentElement.setAttribute("lang", "ar");
} else {
document.documentElement.removeAttribute("lang");
}
var splitView = createSplitView({
panePlacement: config.panePlacement,
closedDisplayMode: config.closedDisplayMode,
openedDisplayMode: config.openedDisplayMode
});
var init = () => {
Utils.hookAfterPrepareAnimationOnce(splitView, () => {
hooksRan++;
fullConfig.paneOpened = false;
// It's tricky to verify the layout of the pane at the start of the hidden -> shown transition
// because the pane needs to be at its shown size during the animation but at the start it needs
// to look like it's in its hidden state (off screen)
// So we'll punt and just verify the layout of the content.
assertContentLayoutCorrect(splitView, fullConfig);
});
Utils.hookBeforeClearAnimationOnce(splitView, () => {
hooksRan++;
fullConfig.paneOpened = true;
assertLayoutCorrect(splitView, fullConfig);
});
splitView.openPane();
};
splitView.onafteropen = () => {
Utils.hookAfterPrepareAnimationOnce(splitView, () => {
hooksRan++;
fullConfig.paneOpened = true;
assertLayoutCorrect(splitView, fullConfig);
});
Utils.hookBeforeClearAnimationOnce(splitView, () => {
hooksRan++;
fullConfig.paneOpened = false;
// It's tricky to verify the layout of the pane at the end of the shown -> hidden transition
// because the pane needs to be at its shown size during the animation but at the end it needs
// to look like it's in its hidden state (off screen)
// So we'll punt and just verify the layout of the content.
assertContentLayoutCorrect(splitView, fullConfig);
});
splitView.closePane();
};
splitView.onafterclose = () => {
LiveUnit.Assert.areEqual(4, hooksRan, "Not all of the animations hooks ran");
splitView.dispose();
Helper.removeElement(splitView.element);
testConfig(index + 1);
};
init();
}
}
testRoot.style.height = rootHeight + "px";
testRoot.style.width = rootWidth + "px";
testConfig(0);
}
testTabIndexOfZeroIsHighest() {
var paneHTML =
'4
' +
'5
' +
'' +
'
7
' +
'
8
' +
'
0
' + // highest
'
6
' +
'
' +
'2
' + // lowest
'3
';
var contentHTML =
'0
' +
'10
';
var lowestTabIndex = 2;
var highestTabIndex = 0;
var splitView = Utils.useSynchronousAnimations(createSplitView({
paneHTML: paneHTML,
contentHTML: contentHTML,
openedDisplayMode: WinJS.UI.SplitView.OpenedDisplayMode.overlay
}));
verifyTabIndicesWithoutCarousel(splitView);
splitView.openPane();
verifyTabIndicesWithCarousel(splitView, lowestTabIndex, highestTabIndex);
splitView.closePane();
verifyTabIndicesWithoutCarousel(splitView);
Helper.validateUnhandledErrors();
}
testTabIndicesOpenedDisplayModeInline() {
testTabIndices({
openedDisplayMode: WinJS.UI.SplitView.OpenedDisplayMode.inline,
verifyTabIndicesWhenOpened: (splitView, lowestTabIndex, highestTabIndex) => {
verifyTabIndicesWithoutCarousel(splitView);
},
verifyTabIndicesWhenClosed: (splitView, lowestTabIndex, highestTabIndex) => {
verifyTabIndicesWithoutCarousel(splitView);
}
});
}
testTabIndicesOpenedDisplayModeOverlay() {
testTabIndices({
openedDisplayMode: WinJS.UI.SplitView.OpenedDisplayMode.overlay,
verifyTabIndicesWhenOpened: (splitView, lowestTabIndex, highestTabIndex) => {
verifyTabIndicesWithCarousel(splitView, lowestTabIndex, highestTabIndex);
},
verifyTabIndicesWhenClosed: (splitView, lowestTabIndex, highestTabIndex) => {
verifyTabIndicesWithoutCarousel(splitView);
},
});
}
}
}
LiveUnit.registerTestClass("SplitViewTests.BasicTests");