// Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. See License.txt in the project root for license information. // // /// /// /// /// /// module CorsicaTests { var _Constants = Helper.require("WinJS/Controls/CommandingSurface/_Constants"); var _CommandingSurface = Helper.require("WinJS/Controls/CommandingSurface/_CommandingSurface")._CommandingSurface; var Command = WinJS.UI.AppBarCommand; var Util = WinJS.Utilities; // 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(testElement, registerForEvent: (commandingSurface: WinJS.UI.PrivateCommandingSurface, eventName: string, handler: Function) => void) { var commandingSurface = new _CommandingSurface(testElement); Helper._CommandingSurface.useSynchronousAnimations(commandingSurface); var counter = 0; registerForEvent(commandingSurface, _Constants.EventNames.beforeOpen, () => { LiveUnit.Assert.areEqual(1, counter, _Constants.EventNames.beforeOpen + " fired out of order"); counter++; LiveUnit.Assert.isFalse(commandingSurface.opened, _Constants.EventNames.beforeOpen + ": CommandingSurface should not be in opened state"); }); registerForEvent(commandingSurface, _Constants.EventNames.afterOpen, () => { LiveUnit.Assert.areEqual(2, counter, _Constants.EventNames.afterOpen + " fired out of order"); counter++; LiveUnit.Assert.isTrue(commandingSurface.opened, _Constants.EventNames.afterOpen + ": CommandingSurface should be in opened state"); }); registerForEvent(commandingSurface, _Constants.EventNames.beforeClose, () => { LiveUnit.Assert.areEqual(4, counter, _Constants.EventNames.beforeClose + " fired out of order"); counter++; LiveUnit.Assert.isTrue(commandingSurface.opened, _Constants.EventNames.beforeClose + ": CommandingSurface should be in opened state"); }); registerForEvent(commandingSurface, _Constants.EventNames.afterClose, () => { LiveUnit.Assert.areEqual(5, counter, _Constants.EventNames.afterClose + " fired out of order"); counter++; LiveUnit.Assert.isFalse(commandingSurface.opened, _Constants.EventNames.afterClose + ": CommandingSurface should not be in opened state"); }); LiveUnit.Assert.areEqual(0, counter, "before open: wrong number of events fired"); counter++; LiveUnit.Assert.isFalse(commandingSurface.opened, "before open: CommandingSurface should not be in opened state"); commandingSurface.open(); LiveUnit.Assert.areEqual(3, counter, "after open: wrong number of events fired"); counter++; LiveUnit.Assert.isTrue(commandingSurface.opened, "after open: CommandingSurface should be in opened state"); commandingSurface.close(); LiveUnit.Assert.areEqual(6, counter, "after close: wrong number of events fired"); LiveUnit.Assert.isFalse(commandingSurface.opened, "after close: CommandingSurface should not be in opened state"); } function verifyTabIndices(commandingSurface: WinJS.UI.PrivateCommandingSurface, firstTabStopIndex: number, finalTabStopIndex: number) { // first tab stop LiveUnit.Assert.areEqual(firstTabStopIndex, commandingSurface._dom.firstTabStop.tabIndex, "firstTabStop doesn't match expected tab index"); // last tab stop LiveUnit.Assert.areEqual(finalTabStopIndex, commandingSurface._dom.finalTabStop.tabIndex, "finalTabStop doesn't match expected tab index"); } function failEventHandler(eventName: string, msg?: string) { return function () { LiveUnit.Assert.fail("Failure, " + eventName + " dectected: " + msg); }; } function disposeAndRemoveElement(element: HTMLElement) { if (element.winControl) { element.winControl.dispose(); } WinJS.Utilities.disposeSubTree(element); if (element.parentElement) { element.parentElement.removeChild(element); } } interface IOverflowButtonVisibilityTestCase { name: string; commands: Array; expectsOverflowCommands: boolean; } var visibleOverflowButton_Helpers = { verifyOverflowButton: function verifyOverflowButton(commandingSurface: WinJS.UI.PrivateCommandingSurface) { // PRECONDITION: this helper expects the commandingSurface param to be using Synchronous Animations. // Inspects the _CommandingSurface DOM and verifies that the appearance of the overflow button, // while the control is opened and closed, is in alignment with our expectations. var mode = commandingSurface.closedDisplayMode; var isRendered = (mode !== _CommandingSurface.ClosedDisplayMode.none); // Test is a Nop is the control isn't rendered. if (isRendered) { // Some closedDisplayModes can't do a full layout while closed, but still need to be able to // Set visibility on the overflowButton correctly. Record the style of the button before the control // is ever opened since opening the control can cause another layout to run and we want to make sure // that the overflow button was correctly laid out and visible to a user while the control was closed. var hadVisibleOverflowButtonBeforeOpening = this.isOverflowButtonVisible(commandingSurface); // Record where the visible commands are when the control is opened. commandingSurface.open(); var hasVisibleActionAreaCommands = this.areVisibleCommandsInActionArea(commandingSurface); var hasVisibleOverflowAreaCommands = this.areVisibleCommandsInOverflowArea(commandingSurface); var hadVisibleOverflowButtonAfterOpening = this.isOverflowButtonVisible(commandingSurface); commandingSurface.close(); var hasVisibleCommands = (hasVisibleActionAreaCommands || hasVisibleOverflowAreaCommands); var hasExandableActionArea = this.isActionAreaExpandable(commandingSurface); LiveUnit.Assert.areEqual(hadVisibleOverflowButtonBeforeOpening, hadVisibleOverflowButtonAfterOpening, "Overflow button visibility should not change just because the control was opened or closed.") if (!hasVisibleCommands) { LiveUnit.Assert.isFalse(hadVisibleOverflowButtonBeforeOpening, "Overflow button should always be hidden if there are no commands visible."); } else { if (hasExandableActionArea) { // Should always have an overflow button. LiveUnit.Assert.isTrue(hadVisibleOverflowButtonBeforeOpening, "Overflow button should be visible when there is at least one visible command and closedDisplayMode = " + mode); } else { // Should only have an overflow button if there are commands in the overflowarea. if (hasVisibleOverflowAreaCommands) { LiveUnit.Assert.isTrue(hadVisibleOverflowButtonBeforeOpening, "Overflow button should be visible when closedDisplayMode = " + mode + ", and there ARE commands in the overflowArea"); } else { LiveUnit.Assert.isFalse(hadVisibleOverflowButtonBeforeOpening, "Overflow button should be hidden when closedDisplayMode = " + mode + ", and there are NO commands in the overflowArea"); } } } } }, isOverflowButtonVisible: function isOverflowButtonVisible(commandingSurface: WinJS.UI.PrivateCommandingSurface) { var overflowButton = commandingSurface._dom.overflowButton; return overflowButton.style.display !== "none"; }, areVisibleCommandsInActionArea: function areCommandsVisibleInActionArea(commandingSurface: WinJS.UI.PrivateCommandingSurface) { var actionArea = commandingSurface._dom.actionArea; var actionAreaCommands = Helper._CommandingSurface.getVisibleCommandsInElement(actionArea); return actionAreaCommands.length > 0; }, areVisibleCommandsInOverflowArea: function areVisibleCommandsInOverflowArea(commandingSurface: WinJS.UI.PrivateCommandingSurface) { var overflowArea = commandingSurface._dom.overflowArea; var overflowAreaCommands = Helper._CommandingSurface.getVisibleCommandsInElement(overflowArea); return overflowAreaCommands.length > 0; }, isActionAreaExpandable: function isActionAreaExpandable(commandingSurface: WinJS.UI.PrivateCommandingSurface) { return Helper._CommandingSurface.isActionAreaExpandable(commandingSurface.closedDisplayMode); }, } export class _CommandingSurfaceTests { "use strict"; _element: HTMLElement; setUp() { LiveUnit.LoggingCore.logComment("In setup"); var newNode = document.createElement("div"); newNode.id = "host"; document.body.appendChild(newNode); this._element = newNode; } tearDown() { if (this._element) { disposeAndRemoveElement(this._element) this._element = null; } } testConstruction() { var commandingSurface = new _CommandingSurface(this._element); LiveUnit.Assert.isTrue(Util.hasClass(commandingSurface.element, _Constants.ClassNames.controlCssClass), "CommandingSurface missing control css class"); LiveUnit.Assert.isTrue(Util.hasClass(commandingSurface.element, _Constants.ClassNames.disposableCssClass), "CommandingSurface missing disposable css class"); } testAppendToDomAfterConstruction(complete) { this._element.style.width = "1000px"; var data = new WinJS.Binding.List([ new Command(null, { type: _Constants.typeButton, label: "opt 1" }), new Command(null, { type: _Constants.typeButton, label: "opt 2" }) ]); var commandingSurface = new _CommandingSurface(null, { data: data, }); var insertedHandler = function () { commandingSurface.element.removeEventListener("WinJSNodeInserted", insertedHandler); LiveUnit.Assert.areEqual(data.length, commandingSurface._primaryCommands.length, "Primary commands array has an invalid length"); LiveUnit.Assert.areEqual(0, Helper._CommandingSurface.getVisibleCommandsInElement(commandingSurface._dom.overflowArea).length, "Menu commands list has an invalid length"); complete(); } commandingSurface.element.addEventListener("WinJSNodeInserted", insertedHandler); this._element.appendChild(commandingSurface.element); } testElementProperty() { var el = document.createElement("div"); var commandingSurface = new _CommandingSurface(el); LiveUnit.Assert.areEqual(Util._uniqueID(el), Util._uniqueID(commandingSurface.element), "The element passed in the constructor should be the commandingSurface element"); commandingSurface = new _CommandingSurface(); LiveUnit.Assert.isNotNull(commandingSurface.element, "An element should be created when one is not passed to the constructor"); } testDataProperty() { // Verify default (empty) var commandingSurface = new _CommandingSurface(this._element); LiveUnit.Assert.areEqual(0, commandingSurface.data.length, "Empty CommandingSurface should have length 0"); // Add some data var data = new WinJS.Binding.List([ new Command(null, { type: _Constants.typeButton, label: "opt 1" }), new Command(null, { type: _Constants.typeButton, label: "opt 2" }) ]); commandingSurface.data = data; LiveUnit.Assert.areEqual(2, commandingSurface.data.length, "CommandingSurface data has an invalid length"); } testBadData() { var data = new WinJS.Binding.List([ new Command(null, { type: _Constants.typeButton, label: "opt 1" }), new Command(null, { type: _Constants.typeButton, label: "opt 2" }) ]); var commandingSurface = new _CommandingSurface(this._element, { data: data }); // set data to invalid value var property = "data"; try { commandingSurface[property] = { invalid: 1 }; } catch (e) { LiveUnit.Assert.areEqual("WinJS.UI._CommandingSurface.BadData", e.name); // Ensure the value of data did not change LiveUnit.Assert.areEqual(2, commandingSurface.data.length, "CommandingSurface data has an invalid length"); } } testDeclarativeData() { // Verify that if the CommandingSurface element contains children elements at construction, those elements are parsed as data. var el = document.createElement("div"); var child = document.createElement("table"); el.appendChild(child); var commandingSurface: WinJS.UI.PrivateCommandingSurface; try { new _CommandingSurface(el); } catch (e) { LiveUnit.Assert.areEqual("WinJS.UI._CommandingSurface.MustContainCommands", e.name, "Toobar should have thrown MustContainCommands exception"); } finally { } el = document.createElement("div"); var commandEl: HTMLElement; var numberOfCommands = 5; for (var i = 0; i < numberOfCommands; i++) { commandEl = document.createElement("button"); commandEl.setAttribute("data-win-control", "WinJS.UI.AppBarCommand"); el.appendChild(commandEl); } commandingSurface = new _CommandingSurface(el); LiveUnit.Assert.areEqual(numberOfCommands, commandingSurface.data.length, "CommandingSurface declarative commands were not parsed as data."); } testDispose() { this._element.style.width = "10px"; var data = new WinJS.Binding.List([ new Command(null, { type: _Constants.typeButton, label: "opt 1", section: 'primary' }), new Command(null, { type: _Constants.typeButton, label: "opt 2", section: 'secondary' }) ]); var commandingSurface = new _CommandingSurface(this._element, { data: data }); Helper._CommandingSurface.useSynchronousAnimations(commandingSurface); commandingSurface.open(); var msg = "Shouldn't have fired due to control being disposed"; commandingSurface.onbeforeopen = failEventHandler(_Constants.EventNames.beforeOpen, msg); commandingSurface.onbeforeclose = failEventHandler(_Constants.EventNames.beforeClose, msg); commandingSurface.onafteropen = failEventHandler(_Constants.EventNames.afterOpen, msg); commandingSurface.onafterclose = failEventHandler(_Constants.EventNames.afterClose, msg); var menuCommandProjections = Helper._CommandingSurface.getVisibleCommandsInElement(commandingSurface._dom.overflowArea).map(function (element) { return element.winControl; }); commandingSurface.dispose(); LiveUnit.Assert.isTrue(commandingSurface._disposed, "CommandingSurface didn't mark itself as disposed"); LiveUnit.Assert.areEqual("Disposed", commandingSurface._machine._state.name, "CommandingSurface didn't move into the disposed state"); LiveUnit.Assert.isTrue(menuCommandProjections.every(function (menuCommand) { return menuCommand._disposed; }), "Disposing the CommandingSurface should have disposed all the overflowarea MenuCommands."); LiveUnit.Assert.isTrue(commandingSurface.data.every(function (command) { var privateCommand = command; return privateCommand._disposed; }), "Disposing the CommandingSurface should have disposed all of its commands."); // Events should not fire. commandingSurface.close(); commandingSurface.open(); } testDoubleDispose() { var commandingSurface = new _CommandingSurface(); LiveUnit.Assert.isTrue(commandingSurface.dispose); LiveUnit.Assert.isFalse(commandingSurface._disposed); // Double dispose sentinel var sentinel: any = document.createElement("div"); sentinel.disposed = false; WinJS.Utilities.addClass(sentinel, "win-disposable"); commandingSurface.element.appendChild(sentinel); sentinel.dispose = function () { if (sentinel.disposed) { LiveUnit.Assert.fail("Unexpected double dispose occured."); } sentinel.disposed = true; }; commandingSurface.dispose(); LiveUnit.Assert.isTrue(sentinel.disposed); LiveUnit.Assert.isTrue(commandingSurface._disposed); commandingSurface.dispose(); } testVerifyDefaultTabIndex() { var commandingSurface = new _CommandingSurface(); LiveUnit.Assert.areEqual("-1", commandingSurface.element.getAttribute("tabIndex"), "CommandingSurface should've assigned a default tabIndex"); var el = document.createElement("div"); el.setAttribute("tabIndex", "4"); commandingSurface = new _CommandingSurface(el); LiveUnit.Assert.areEqual("4", commandingSurface.element.getAttribute("tabIndex"), "CommandingSurface should have not assigned a default tabIndex"); } testOverflowButtonAriaLabel() { var commandingSurface = new _CommandingSurface(); LiveUnit.Assert.areEqual("View more", commandingSurface._dom.overflowButton.getAttribute("aria-label"), "Missing overflowButton aria label"); } testOverflowButtonVisibilityWhenChangingData() { // Verifies that for each closed display mode, changing the data in the CommandingSurface // will update the visibility of the overflow button accordingly function verifyPreCondition(commandingSurface: WinJS.UI.PrivateCommandingSurface, testCase: IOverflowButtonVisibilityTestCase) { var hasOverflowAreaCommands = visibleOverflowButton_Helpers.areVisibleCommandsInOverflowArea(commandingSurface); var mode = commandingSurface.closedDisplayMode; switch (mode) { case _CommandingSurface.ClosedDisplayMode.compact: case _CommandingSurface.ClosedDisplayMode.full: LiveUnit.Assert.isTrue(commandingSurface._canMeasure(), "TEST ERROR: Closed CommandingSurface with closedDisplayMode:" + mode + " is unable to measure. Layout is blocked."); LiveUnit.Assert.areEqual(testCase.expectsOverflowCommands, hasOverflowAreaCommands, "TEST ERROR: Configuration for test: " + testCase.name + " with closedDisplayMode: " + mode + " has incorrect presence of commands in overflowarea"); break; case _CommandingSurface.ClosedDisplayMode.minimal: case _CommandingSurface.ClosedDisplayMode.none: LiveUnit.Assert.isFalse(commandingSurface._canMeasure(), "TEST ERROR: Test expects that a closed CommandingSurface with closedDisplayMode: " + mode + " can't measure or peform layout. Update the test to include '" + mode + "' with the closedDisplayModes" + " that can be measured while closed."); break; default: LiveUnit.Assert.fail("TEST ERROR: Unknown ClosedDisplayMode enum value: " + mode); break; } } var commandingSurface = new _CommandingSurface(this._element, {}); var controlWidth = 500; // More than wide enough to fit our primary command + overflow button. this._element.style.width = controlWidth + "px"; var primaryCommand = new Command(null, { section: 'primary', type: 'button', label: 'primary command', icon: '1' }); var secondaryCommand = new Command(null, { section: 'secondary', type: 'button', label: 'secondary command' }); var overflowCommand = new Command(null, { section: 'primary', type: 'content', label: 'overflow command', }); // Make the 'content' command wide enough to always force overflow. overflowCommand.element.style.width = (controlWidth + 5) + "px"; var hiddenPrimaryCommand = new Command(null, { section: 'primary', type: 'button', label: 'hidden primary command', icon: 'H', hidden: true }); var hiddenSecondaryCommand = new Command(null, { section: 'secondary', type: 'button', label: 'hidden secondary command', hidden: true }); var dataTestCases: Array = [ { name: "NoCommands", commands: [], expectsOverflowCommands: false }, { name: "PrimayCommandsOnly_NoOverflow", commands: [primaryCommand], expectsOverflowCommands: false }, { name: "PrimaryCommandsOnly_SomeOverflow", commands: [primaryCommand, overflowCommand], expectsOverflowCommands: true }, { name: "SecondaryCommandsOnly", commands: [secondaryCommand], expectsOverflowCommands: true }, { name: "PrimaryAndSecondaryCommands", commands: [primaryCommand, secondaryCommand], expectsOverflowCommands: true }, { name: "HiddenCommands", commands: [hiddenPrimaryCommand, hiddenSecondaryCommand], expectsOverflowCommands: false }, ]; Helper._CommandingSurface.useSynchronousAnimations(commandingSurface); Helper._CommandingSurface.useSynchronousDataRendering(commandingSurface); Object.keys(_CommandingSurface.ClosedDisplayMode).forEach((mode) => { commandingSurface.closedDisplayMode = mode; dataTestCases.forEach((testCase) => { commandingSurface.data = new WinJS.Binding.List(testCase.commands); // PRECONDITION: Sanity test that the testCase's expected configuration for overflow commands // has been met. verifyPreCondition(commandingSurface, testCase); visibleOverflowButton_Helpers.verifyOverflowButton(commandingSurface); }); }); } testOverflowButtonVisibilityWhenChangingClosedDisplayModes() { // The visibility of the overflow button can depend on the closedDisplay mode. // Specifically, closedDisplayMode 'full' should not show an overflow button if there are // visible commands in the action area, but no visible commands of any sort in the overflow area // Verify that changing the closedDisplayMode under these circumstances updates the visibility // of the overflow button var initControl = (closedDisplayMode) => { var controlElement = document.createElement("DIV"); this._element.appendChild(controlElement); var commandingSurface = new _CommandingSurface(controlElement, { closedDisplayMode: closedDisplayMode }); commandingSurface.data = new WinJS.Binding.List([new Command(null, { section: 'primary' })]); Helper._CommandingSurface.useSynchronousAnimations(commandingSurface); return commandingSurface; } for (var beginningMode in _CommandingSurface.ClosedDisplayMode) { for (var endingMode in _CommandingSurface.ClosedDisplayMode) { var commandingSurface = initControl(beginningMode); visibleOverflowButton_Helpers.verifyOverflowButton(commandingSurface); commandingSurface.closedDisplayMode = endingMode; visibleOverflowButton_Helpers.verifyOverflowButton(commandingSurface); } } } testForceLayout() { // Verify that force layout will correctly update commands layout when: // 1. The CommandingSurface constructor could not measure any of the commands because the CommandingSurface element was originally display "none". // 2. The width of the CommandingSurface itself has changed. // 3. The width of content commands in the CommandingSurface have changed var customContentBoxWidth = 100; var customEl = document.createElement("div"); customEl.style.width = customContentBoxWidth + "px"; customEl.style.height = "50px"; this._element.style.display = "none"; this._element.style.width = "1000px"; var data = new WinJS.Binding.List([ new Command(null, { type: _Constants.typeButton, label: "opt 1" }), new Command(customEl, { type: _Constants.typeContent, label: "opt 2" }), new Command(null, { type: _Constants.typeButton, label: "sec opt 1", section: _Constants.secondaryCommandSection }) ]); var commandingSurface = new _CommandingSurface(this._element, { data: data, closedDisplayMode: _CommandingSurface.ClosedDisplayMode.compact, }); // The measurement stage of the CommandLayoutPipeline should have failed because our element was display "none". // Therefore, the layout stage should not have been reached and not even secondary commands will have made it into the overflow area yet. // Sanity check our test expectations before we begin. LiveUnit.Assert.areEqual(2, commandingSurface._primaryCommands.length, "TEST ERROR: Primary commands array has an invalid length"); LiveUnit.Assert.areEqual(1, commandingSurface._secondaryCommands.length, "TEST ERROR: Secondary commands array has an invalid length"); LiveUnit.Assert.areEqual(3, Helper._CommandingSurface.getVisibleCommandsInElement(commandingSurface._dom.actionArea).length, "TEST ERROR: until a layout can occur, actionarea should have 3 commands"); LiveUnit.Assert.areEqual(0, Helper._CommandingSurface.getVisibleCommandsInElement(commandingSurface._dom.overflowArea).length, "TEST ERROR: until a layout can occur, overflowarea should have 0 commands"); // Restore the display, then test forceLayout this._element.style.display = ""; commandingSurface.forceLayout(); LiveUnit.Assert.areEqual(2, Helper._CommandingSurface.getVisibleCommandsInElement(commandingSurface._dom.actionArea).length, "actionarea should have 2 commands"); LiveUnit.Assert.areEqual(1, Helper._CommandingSurface.getVisibleCommandsInElement(commandingSurface._dom.overflowArea).length, "overflowarea should have 1 commands"); // Decrease the width of the CommandingSurface so that it is 1px too thin to fit both primary commands, then test forceLayout. var customContentTotalWidth = commandingSurface._getCommandWidth(data.getAt(1)); var args: Helper._CommandingSurface.ISizeForCommandsArgs = { closedDisplayMode: commandingSurface.closedDisplayMode, numStandardCommandsShownInActionArea: 1, numSeparatorsShownInActionArea: 0, widthOfContentCommandsShownInActionArea: 0, isACommandVisbleInTheOverflowArea: true, additionalFreeSpace: customContentTotalWidth - 1, }; Helper._CommandingSurface.sizeForCommands(this._element, args); commandingSurface.forceLayout(); LiveUnit.Assert.areEqual(1, Helper._CommandingSurface.getVisibleCommandsInElement(commandingSurface._dom.actionArea).length, "actionarea should have 1 commands"); LiveUnit.Assert.areEqual(3 /* 1 primary command + 1 separator + 1 secondary command */, Helper._CommandingSurface.getVisibleCommandsInElement(commandingSurface._dom.overflowArea).length, "overflowarea should have 3 commands"); // Decrease width of content command by 1px so that both primary commands will fit in the action area, then test forceLayout customContentBoxWidth--; customEl.style.width = customContentBoxWidth + "px" commandingSurface.forceLayout(); LiveUnit.Assert.areEqual(2, Helper._CommandingSurface.getVisibleCommandsInElement(commandingSurface._dom.actionArea).length, "actionarea should have 2 commands"); LiveUnit.Assert.areEqual(1, Helper._CommandingSurface.getVisibleCommandsInElement(commandingSurface._dom.overflowArea).length, "overflowarea should have 1 command"); } testResizeHandler() { // Verify that the resize handler knows how to correctly re-layout commands if the CommandingSurface width has changed. // - while the control is closed. // - while the control is opened. // Typically the resizeHandler is only called by the window resize event. // Test all closedDisplayModes https://github.com/winjs/winjs/issues/1183 Object.keys(_CommandingSurface.ClosedDisplayMode).forEach((mode) => { var prefix = "closedDisplayMode: " + mode + ", "; // ClosedDisplayMode: "none" can't measure or layout commands while closed because element.style.display is none. // ClosedDisplayMode: "minimal" can't layout commands correctly while closed because all commands are display: "none". var doesModeSupportVisibleCommandsWhileClosed = (mode === _CommandingSurface.ClosedDisplayMode.compact || mode === _CommandingSurface.ClosedDisplayMode.full); // Make sure everything will fit. var commandingSurfaceElement = document.createElement("DIV"); commandingSurfaceElement.style.width = "1000px"; this._element.appendChild(commandingSurfaceElement); var data = new WinJS.Binding.List([ new Command(null, { type: _Constants.typeButton, label: "opt 1" }), new Command(null, { type: _Constants.typeButton, label: "opt 2" }), new Command(null, { type: _Constants.typeButton, label: "sec opt 1", section: _Constants.secondaryCommandSection }) ]); var commandingSurface = new _CommandingSurface(commandingSurfaceElement, { data: data, opened: false, closedDisplayMode: mode, }); Helper._CommandingSurface.useSynchronousAnimations(commandingSurface); if (doesModeSupportVisibleCommandsWhileClosed) { LiveUnit.Assert.areEqual(2, Helper._CommandingSurface.getVisibleCommandsInElement(commandingSurface._dom.actionArea).length, "TEST ERROR: " + prefix + "Test expects actionarea should have 2 commands at start"); LiveUnit.Assert.areEqual(1, Helper._CommandingSurface.getVisibleCommandsInElement(commandingSurface._dom.overflowArea).length, "TEST ERROR: " + prefix + "Test expects overflowarea should have 1 command at start"); } // Decrease the width of our control to fit exactly 1 command + the overflow button in the actionarea. var args: Helper._CommandingSurface.ISizeForCommandsArgs = { closedDisplayMode: commandingSurface.closedDisplayMode, numStandardCommandsShownInActionArea: 1, numSeparatorsShownInActionArea: 0, widthOfContentCommandsShownInActionArea: 0, isACommandVisbleInTheOverflowArea: true, additionalFreeSpace: 0, }; Helper._CommandingSurface.sizeForCommands(commandingSurfaceElement, args); // Ensure that the resizeHandler will have overflowed all but one primary command into the overflowarea WinJS.Utilities._resizeNotifier._handleResize(); if (doesModeSupportVisibleCommandsWhileClosed) { // Verify commands laid our correctly while closed. LiveUnit.Assert.areEqual(1, Helper._CommandingSurface.getVisibleCommandsInElement(commandingSurface._dom.actionArea).length, prefix + "closed actionarea should have 1 command after width decrease"); LiveUnit.Assert.areEqual(3 /* 1 primary command + 1 separator + 1 secondary command */, Helper._CommandingSurface.getVisibleCommandsInElement(commandingSurface._dom.overflowArea).length, prefix + "closed overflowarea should have 3 commands after width decrease"); } // Verify commands are laid out correctly, the first time the control is opened following a resize. commandingSurface.open(); LiveUnit.Assert.areEqual(1, Helper._CommandingSurface.getVisibleCommandsInElement(commandingSurface._dom.actionArea).length, prefix + "actionarea should have 1 command after opening"); LiveUnit.Assert.areEqual(3 /* 1 primary command + 1 separator + 1 secondary command */, Helper._CommandingSurface.getVisibleCommandsInElement(commandingSurface._dom.overflowArea).length, prefix + "overflowarea should have 3 commands after opening"); // Increase element size while opened, and verify the resizeHandler has reflowed all primary commands // back into the action area. commandingSurfaceElement.style.width = "1000px"; WinJS.Utilities._resizeNotifier._handleResize(); LiveUnit.Assert.areEqual(2, Helper._CommandingSurface.getVisibleCommandsInElement(commandingSurface._dom.actionArea).length, prefix + "opened actionarea should have 2 commands after width increase"); LiveUnit.Assert.areEqual(1, Helper._CommandingSurface.getVisibleCommandsInElement(commandingSurface._dom.overflowArea).length, prefix + "opened overflowarea should have 1 command after width increase"); disposeAndRemoveElement(commandingSurface.element); }); } testSeparatorAddedBetweenPrimaryAndSecondary() { this._element.style.width = "10px"; var data = new WinJS.Binding.List([ new Command(null, { type: _Constants.typeButton, label: "opt 1" }), new Command(null, { type: _Constants.typeButton, label: "opt 2", section: _Constants.secondaryCommandSection }) ]); var commandingSurface = new _CommandingSurface(this._element, { data: data }); var overflowCommands = Helper._CommandingSurface.getVisibleCommandsInElement(commandingSurface._dom.overflowArea); LiveUnit.Assert.areEqual(3, overflowCommands.length, "Menu commands list has an invalid length"); LiveUnit.Assert.areEqual("opt 1", overflowCommands[0].winControl.label); LiveUnit.Assert.areEqual(_Constants.typeSeparator, overflowCommands[1].winControl.type); LiveUnit.Assert.areEqual("opt 2", overflowCommands[2].winControl.label); } testOverflowBehaviorOfCustomContent() { var customEl = document.createElement("div"); customEl.style.width = "2000px"; customEl.style.height = "50px"; var data = new WinJS.Binding.List([ new Command(customEl, { type: _Constants.typeContent, label: "1", extraClass: "c1" }), ]); this._element.style.width = "200px"; var commandingSurface = new _CommandingSurface(this._element, { data: data }); LiveUnit.Assert.areEqual(0, Helper._CommandingSurface.getVisibleCommandsInElement(commandingSurface._dom.actionArea).length, "Invalid number of commands in the actionarea"); LiveUnit.Assert.areEqual(1, Helper._CommandingSurface.getVisibleCommandsInElement(commandingSurface._dom.overflowArea).length, "Menu commands list has an invalid length"); // Custom content should overflow as a flyout menu item var menuCommand = (Helper._CommandingSurface.getVisibleCommandsInElement(commandingSurface._dom.overflowArea)[0]["winControl"]); LiveUnit.Assert.areEqual(_Constants.typeFlyout, menuCommand.type, "Custom content should overflow with type flyout"); LiveUnit.Assert.areEqual(commandingSurface._contentFlyout, menuCommand.flyout, "Invalid flyout target for custom command in the overflowarea"); LiveUnit.Assert.areEqual("1", menuCommand.label, "Invalid label for custom command in the overflowarea"); LiveUnit.Assert.areEqual("c1", menuCommand.extraClass, "Invalid extraClass for custom command in the overflowarea"); } testOverflowBehaviorOfButtonCommand(complete) { WinJS.Utilities.markSupportedForProcessing(complete); var data = new WinJS.Binding.List([ new Command(null, { type: _Constants.typeButton, label: "1", extraClass: "c1", disabled: true, onclick: Helper._CommandingSurface.getVisibleCommandsInElement }), new Command(null, { type: _Constants.typeButton, label: "2", extraClass: "c2", disabled: false, onclick: complete }), ]); this._element.style.width = "10px"; var commandingSurface = new _CommandingSurface(this._element, { data: data }); LiveUnit.Assert.areEqual(0, Helper._CommandingSurface.getVisibleCommandsInElement(commandingSurface._dom.actionArea).length, "Invalid number of commands in the actionarea"); LiveUnit.Assert.areEqual(2, Helper._CommandingSurface.getVisibleCommandsInElement(commandingSurface._dom.overflowArea).length, "Menu commands list has an invalid length"); var menuCommand = (Helper._CommandingSurface.getVisibleCommandsInElement(commandingSurface._dom.overflowArea)[0]["winControl"]); LiveUnit.Assert.areEqual(_Constants.typeButton, menuCommand.type, "Invalid menuCommand type"); LiveUnit.Assert.isNull(menuCommand.flyout, "Flyout target for button should be null"); LiveUnit.Assert.areEqual("1", menuCommand.label, "Invalid menuCommand label"); LiveUnit.Assert.areEqual("c1", menuCommand.extraClass, "Invalid menuCommand extraClass"); LiveUnit.Assert.isTrue(menuCommand.disabled, "Invalid menuCommand disabled property value"); LiveUnit.Assert.areEqual(Helper._CommandingSurface.getVisibleCommandsInElement, menuCommand.onclick, "Invalid menuCommand onclick property value"); menuCommand = (Helper._CommandingSurface.getVisibleCommandsInElement(commandingSurface._dom.overflowArea)[1]["winControl"]); LiveUnit.Assert.areEqual(_Constants.typeButton, menuCommand.type, "Invalid menuCommand type"); LiveUnit.Assert.isNull(menuCommand.flyout, "Flyout target for button should be null"); LiveUnit.Assert.areEqual("2", menuCommand.label, "Invalid menuCommand label"); LiveUnit.Assert.areEqual("c2", menuCommand.extraClass, "Invalid menuCommand extraClass"); LiveUnit.Assert.isFalse(menuCommand.disabled, "Invalid menuCommand disabled property value"); LiveUnit.Assert.areEqual(complete, menuCommand.onclick, "Invalid menuCommand onclick property value"); // Verify onclick calls complete menuCommand.element.click(); } testOverflowBehaviorOfToggleCommand() { var clickWasHandled = false; function test_handleClick(event) { clickWasHandled = true; LiveUnit.Assert.isFalse(event.target.winControl.selected, "Invalid menuCommand selected property value"); } WinJS.Utilities.markSupportedForProcessing(test_handleClick); var data = new WinJS.Binding.List([ new Command(null, { type: _Constants.typeToggle, label: "1", extraClass: "c1", selected: true, onclick: test_handleClick }), new Command(null, { type: _Constants.typeButton, label: "2", extraClass: "c2", disabled: true, onclick: test_handleClick }), ]); this._element.style.width = "10px"; var commandingSurface = new _CommandingSurface(this._element, { data: data }); LiveUnit.Assert.areEqual(0, Helper._CommandingSurface.getVisibleCommandsInElement(commandingSurface._dom.actionArea).length, "Invalid number of commands in the actionarea") LiveUnit.Assert.areEqual(2, Helper._CommandingSurface.getVisibleCommandsInElement(commandingSurface._dom.overflowArea).length, "Menu commands list has an invalid length"); var menuCommand = (Helper._CommandingSurface.getVisibleCommandsInElement(commandingSurface._dom.overflowArea)[0]["winControl"]); LiveUnit.Assert.areEqual(_Constants.typeToggle, menuCommand.type, "Invalid menuCommand type"); LiveUnit.Assert.isNull(menuCommand.flyout, "Flyout target for button should be null"); LiveUnit.Assert.areEqual("1", menuCommand.label, "Invalid menuCommand label"); LiveUnit.Assert.areEqual("c1", menuCommand.extraClass, "Invalid menuCommand extraClass"); LiveUnit.Assert.isFalse(menuCommand.disabled, "Invalid menuCommand disabled property value"); LiveUnit.Assert.isTrue(menuCommand.selected, "Invalid menuCommand selected property value"); LiveUnit.Assert.areEqual(test_handleClick, menuCommand.onclick, "Invalid menuCommand onclick property value"); menuCommand.element.click(); LiveUnit.Assert.isTrue(clickWasHandled, "menuCommand click behavior not functioning"); } testOverflowBehaviorOfToggleCommandChangingValues() { var data = new WinJS.Binding.List([ new Command(null, { type: _Constants.typeToggle, label: "1", extraClass: "c1", selected: true }), new Command(null, { type: _Constants.typeButton, label: "2", extraClass: "c2", disabled: true }), ]); this._element.style.width = "10px"; var commandingSurface = new _CommandingSurface(this._element, { data: data, closedDisplayMode: _CommandingSurface.ClosedDisplayMode.compact, }); var menuCommand = (Helper._CommandingSurface.getVisibleCommandsInElement(commandingSurface._dom.overflowArea)[0]["winControl"]); LiveUnit.Assert.isTrue(menuCommand.selected, "Invalid menuCommand selected property value"); // Deselect the toggle button in the menu var menuCommandEl = ( commandingSurface._dom.overflowArea.children[0]); menuCommandEl.click(); // Increase the size of the control to fit both commands. var args: Helper._CommandingSurface.ISizeForCommandsArgs = { closedDisplayMode: commandingSurface.closedDisplayMode, numStandardCommandsShownInActionArea: 2, numSeparatorsShownInActionArea: 0, widthOfContentCommandsShownInActionArea: 0, isACommandVisbleInTheOverflowArea: false, additionalFreeSpace: 0, }; Helper._CommandingSurface.sizeForCommands(this._element, args); commandingSurface.forceLayout(); // Ensure that the command in the actionarea now has the toggle de-selected var command = Helper._CommandingSurface.getVisibleCommandsInElement(commandingSurface._dom.actionArea)[0]; LiveUnit.Assert.isFalse(command.winControl.selected, "Invalid menuCommand selected property value"); } testOverflowBehaviorOfFlyoutCommand(complete) { var flyout = new WinJS.UI.Flyout(); this._element.parentElement.appendChild(flyout.element); var data = new WinJS.Binding.List([ new Command(null, { type: _Constants.typeFlyout, label: "1", extraClass: "c1", flyout: flyout }), new Command(null, { type: _Constants.typeButton, label: "2", extraClass: "c2", disabled: true }), ]); this._element.style.width = "10px"; var commandingSurface = new _CommandingSurface(this._element, { data: data }); LiveUnit.Assert.areEqual(0, Helper._CommandingSurface.getVisibleCommandsInElement(commandingSurface._dom.actionArea).length, "Invalid number of commands in the actionarea"); LiveUnit.Assert.areEqual(2, Helper._CommandingSurface.getVisibleCommandsInElement(commandingSurface._dom.overflowArea).length, "Menu commands list has an invalid length"); var menuCommand = (Helper._CommandingSurface.getVisibleCommandsInElement(commandingSurface._dom.overflowArea)[0]["winControl"]); LiveUnit.Assert.areEqual(_Constants.typeFlyout, menuCommand.type, "Invalid menuCommand type"); LiveUnit.Assert.areEqual(flyout, menuCommand.flyout, "Invalid menuCommand flyout property value"); LiveUnit.Assert.areEqual("1", menuCommand.label, "Invalid menuCommand label"); LiveUnit.Assert.areEqual("c1", menuCommand.extraClass, "Invalid menuCommand extraClass"); LiveUnit.Assert.isFalse(menuCommand.disabled, "Invalid menuCommand disabled property value"); menuCommand.element.click(); flyout.addEventListener("aftershow", function afterShow() { flyout.removeEventListener("aftershow", afterShow, false); flyout.dispose() flyout.element.parentElement.removeChild(flyout.element); complete(); }, false); } testOverflowBehaviorOfSeparatorCommand() { var data = new WinJS.Binding.List([ new Command(null, { type: _Constants.typeButton, label: "2", extraClass: "c2", disabled: true }), new Command(null, { type: _Constants.typeSeparator }), ]); this._element.style.width = "10px"; var commandingSurface = new _CommandingSurface(this._element, { data: data }); LiveUnit.Assert.areEqual(0, Helper._CommandingSurface.getVisibleCommandsInElement(commandingSurface._dom.actionArea).length, "Invalid number of commands in the actionarea"); var menuCommand = commandingSurface._dom.overflowArea.querySelectorAll(_Constants.commandSelector)[1]["winControl"]; LiveUnit.Assert.areEqual(_Constants.typeSeparator, menuCommand.type, "Invalid menuCommand type"); } testOverflowBehaviorDefaultPriority() { var data = new WinJS.Binding.List([ new Command(null, { type: _Constants.typeButton, label: "1" }), new Command(null, { type: _Constants.typeSeparator, label: "2" }), new Command(null, { type: _Constants.typeButton, label: "3" }), new Command(null, { type: _Constants.typeButton, label: "4" }), new Command(null, { type: _Constants.typeSeparator, label: "5" }), new Command(null, { type: _Constants.typeButton, label: "6" }), ]); var commandingSurface = new _CommandingSurface(this._element, { data: data, closedDisplayMode: _CommandingSurface.ClosedDisplayMode.compact, }); // Make sure everything fits, nothing should overflow var args: Helper._CommandingSurface.ISizeForCommandsArgs = { closedDisplayMode: commandingSurface.closedDisplayMode, numStandardCommandsShownInActionArea: 4, numSeparatorsShownInActionArea: 2, widthOfContentCommandsShownInActionArea: 0, isACommandVisbleInTheOverflowArea: false, additionalFreeSpace: 0, }; Helper._CommandingSurface.sizeForCommands(this._element, args); commandingSurface.forceLayout(); LiveUnit.Assert.areEqual(6, Helper._CommandingSurface.getVisibleCommandsInElement(commandingSurface._dom.actionArea).length, "Invalid number of commands in the actionarea"); // Decrease size to overflow 1 command args = { closedDisplayMode: commandingSurface.closedDisplayMode, numStandardCommandsShownInActionArea: 3, numSeparatorsShownInActionArea: 2, widthOfContentCommandsShownInActionArea: 0, isACommandVisbleInTheOverflowArea: true, additionalFreeSpace: 0, }; Helper._CommandingSurface.sizeForCommands(this._element, args); commandingSurface.forceLayout(); LiveUnit.Assert.areEqual(5 - 1 /* trailing separator is hidden */, Helper._CommandingSurface.getVisibleCommandsInElement(commandingSurface._dom.actionArea).length, "Invalid number of commands in the actionarea"); LiveUnit.Assert.areEqual(1, Helper._CommandingSurface.getVisibleCommandsInElement(commandingSurface._dom.overflowArea).length, "Menu commands list has an invalid length"); // Increase size to put command back into the actionarea args = { closedDisplayMode: commandingSurface.closedDisplayMode, numStandardCommandsShownInActionArea: 4, numSeparatorsShownInActionArea: 2, widthOfContentCommandsShownInActionArea: 0, isACommandVisbleInTheOverflowArea: false, additionalFreeSpace: 0, }; Helper._CommandingSurface.sizeForCommands(this._element, args); commandingSurface.forceLayout(); LiveUnit.Assert.areEqual(6, Helper._CommandingSurface.getVisibleCommandsInElement(commandingSurface._dom.actionArea).length, "Invalid number of commands in the actionarea"); LiveUnit.Assert.areEqual(0, Helper._CommandingSurface.getVisibleCommandsInElement(commandingSurface._dom.overflowArea).length, "Menu commands list has an invalid length"); // Decrease size to overflow 2 commands args = { closedDisplayMode: commandingSurface.closedDisplayMode, numStandardCommandsShownInActionArea: 3, numSeparatorsShownInActionArea: 1, widthOfContentCommandsShownInActionArea: 0, isACommandVisbleInTheOverflowArea: true, additionalFreeSpace: 0, }; Helper._CommandingSurface.sizeForCommands(this._element, args); commandingSurface.forceLayout(); LiveUnit.Assert.areEqual(4, Helper._CommandingSurface.getVisibleCommandsInElement(commandingSurface._dom.actionArea).length, "Invalid number of commands in the actionarea"); LiveUnit.Assert.areEqual(2 - 1 /* leading separator is hidden */, Helper._CommandingSurface.getVisibleCommandsInElement(commandingSurface._dom.overflowArea).length, "Menu commands list has an invalid length"); // Decrease size to overflow 3 commands args = { closedDisplayMode: commandingSurface.closedDisplayMode, numStandardCommandsShownInActionArea: 2, numSeparatorsShownInActionArea: 1, widthOfContentCommandsShownInActionArea: 0, isACommandVisbleInTheOverflowArea: true, additionalFreeSpace: 0, }; Helper._CommandingSurface.sizeForCommands(this._element, args); commandingSurface.forceLayout(); LiveUnit.Assert.areEqual(3, Helper._CommandingSurface.getVisibleCommandsInElement(commandingSurface._dom.actionArea).length, "Invalid number of commands in the actionarea"); LiveUnit.Assert.areEqual(3, Helper._CommandingSurface.getVisibleCommandsInElement(commandingSurface._dom.overflowArea).length, "Menu commands list has an invalid length"); // Decrease size to overflow 4 commands args = { closedDisplayMode: commandingSurface.closedDisplayMode, numStandardCommandsShownInActionArea: 1, numSeparatorsShownInActionArea: 1, widthOfContentCommandsShownInActionArea: 0, isACommandVisbleInTheOverflowArea: true, additionalFreeSpace: 0, }; Helper._CommandingSurface.sizeForCommands(this._element, args); commandingSurface.forceLayout(); LiveUnit.Assert.areEqual(2 - 1 /* trailing separator is hidden */, Helper._CommandingSurface.getVisibleCommandsInElement(commandingSurface._dom.actionArea).length, "Invalid number of commands in the actionarea"); LiveUnit.Assert.areEqual(4, Helper._CommandingSurface.getVisibleCommandsInElement(commandingSurface._dom.overflowArea).length, "Menu commands list has an invalid length"); // Decrease size to overflow 5 commands args = { closedDisplayMode: commandingSurface.closedDisplayMode, numStandardCommandsShownInActionArea: 1, numSeparatorsShownInActionArea: 0, widthOfContentCommandsShownInActionArea: 0, isACommandVisbleInTheOverflowArea: true, additionalFreeSpace: 0, }; Helper._CommandingSurface.sizeForCommands(this._element, args); commandingSurface.forceLayout(); LiveUnit.Assert.areEqual(1, Helper._CommandingSurface.getVisibleCommandsInElement(commandingSurface._dom.actionArea).length, "Invalid number of commands in the actionarea"); LiveUnit.Assert.areEqual(5 - 1 /* leading separator is hidden */, Helper._CommandingSurface.getVisibleCommandsInElement(commandingSurface._dom.overflowArea).length, "Menu commands list has an invalid length"); // Decrease size to overflow 6 commands args = { closedDisplayMode: commandingSurface.closedDisplayMode, numStandardCommandsShownInActionArea: 0, numSeparatorsShownInActionArea: 0, widthOfContentCommandsShownInActionArea: 0, isACommandVisbleInTheOverflowArea: false, additionalFreeSpace: 0, }; Helper._CommandingSurface.sizeForCommands(this._element, args); commandingSurface.forceLayout(); LiveUnit.Assert.areEqual(0, Helper._CommandingSurface.getVisibleCommandsInElement(commandingSurface._dom.actionArea).length, "Invalid number of commands in the actionarea"); LiveUnit.Assert.areEqual(6, Helper._CommandingSurface.getVisibleCommandsInElement(commandingSurface._dom.overflowArea).length, "Menu commands list has an invalid length"); } testOverflowBehaviorDefaultPriorityWithCustomContent() { var customEl1 = document.createElement("div"); customEl1.style.width = "200px"; customEl1.style.height = "50px"; var customEl2 = document.createElement("div"); customEl2.style.width = "350px"; customEl2.style.height = "50px"; var data = new WinJS.Binding.List([ new Command(null, { type: _Constants.typeButton, label: "1" }), new Command(customEl1, { type: _Constants.typeContent, label: "2" }), new Command(customEl2, { type: _Constants.typeContent, label: "3" }), ]); var commandingSurface = new _CommandingSurface(this._element, { data: data, closedDisplayMode: _CommandingSurface.ClosedDisplayMode.compact, }); var customContent1Width = commandingSurface._getCommandWidth(data.getAt(1)); var customContent2Width = commandingSurface._getCommandWidth(data.getAt(2)); // Make sure everything fits, nothing should overflow var args: Helper._CommandingSurface.ISizeForCommandsArgs = { closedDisplayMode: commandingSurface.closedDisplayMode, numStandardCommandsShownInActionArea: 1, numSeparatorsShownInActionArea: 0, widthOfContentCommandsShownInActionArea: customContent1Width + customContent2Width, isACommandVisbleInTheOverflowArea: true, additionalFreeSpace: 0, }; Helper._CommandingSurface.sizeForCommands(this._element, args); commandingSurface.forceLayout(); LiveUnit.Assert.areEqual(3, Helper._CommandingSurface.getVisibleCommandsInElement(commandingSurface._dom.actionArea).length, "Invalid number of commands in the actionarea"); // Decrease size to overflow 1 command args = { closedDisplayMode: commandingSurface.closedDisplayMode, numStandardCommandsShownInActionArea: 1, numSeparatorsShownInActionArea: 0, widthOfContentCommandsShownInActionArea: customContent1Width, isACommandVisbleInTheOverflowArea: true, additionalFreeSpace: 0, }; Helper._CommandingSurface.sizeForCommands(this._element, args); commandingSurface.forceLayout(); LiveUnit.Assert.areEqual(2, Helper._CommandingSurface.getVisibleCommandsInElement(commandingSurface._dom.actionArea).length, "Invalid number of commands in the actionarea"); LiveUnit.Assert.areEqual(1, Helper._CommandingSurface.getVisibleCommandsInElement(commandingSurface._dom.overflowArea).length, "Menu commands list has an invalid length"); // Decrease size to overflow 2 commands args = { closedDisplayMode: commandingSurface.closedDisplayMode, numStandardCommandsShownInActionArea: 1, numSeparatorsShownInActionArea: 0, widthOfContentCommandsShownInActionArea: 0, isACommandVisbleInTheOverflowArea: true, additionalFreeSpace: customContent1Width - 1, }; Helper._CommandingSurface.sizeForCommands(this._element, args); commandingSurface.forceLayout(); LiveUnit.Assert.areEqual(1, Helper._CommandingSurface.getVisibleCommandsInElement(commandingSurface._dom.actionArea).length, "Invalid number of commands in the actionarea"); LiveUnit.Assert.areEqual(2, Helper._CommandingSurface.getVisibleCommandsInElement(commandingSurface._dom.overflowArea).length, "Menu commands list has an invalid length"); } testOverflowBehaviorCustomPriorityContentInFlyout(complete) { var createCustomElement = (text: string) => { var customEl = document.createElement("div"); var customContent = document.createElement("div"); customContent.style.width = "200px"; customContent.style.height = "50px"; customContent.innerHTML = text; customContent.style.backgroundColor = "red"; customEl.appendChild(customContent); return customEl; } var data = new WinJS.Binding.List([ new Command(createCustomElement("custom 1"), { type: _Constants.typeContent, label: "1", priority: 5, section: _Constants.secondaryCommandSection }), new Command(createCustomElement("custom 2"), { type: _Constants.typeContent, label: "2", priority: 5, section: _Constants.secondaryCommandSection }), ]); var commandingSurface = new _CommandingSurface(this._element, { data: data, opened: true, }); // Click on the first menu item var menuCommand = ( commandingSurface._dom.overflowArea.children[0]); menuCommand.click(); LiveUnit.Assert.areEqual("custom 1", commandingSurface._contentFlyoutInterior.textContent, "The custom content flyout has invalid content"); var testSecondCommandClick = () => { commandingSurface._contentFlyout.removeEventListener("afterhide", testSecondCommandClick); // Click on the second menu item menuCommand = ( commandingSurface._dom.overflowArea.children[1]); menuCommand.click(); LiveUnit.Assert.areEqual("custom 2", commandingSurface._contentFlyoutInterior.textContent, "The custom content flyout has invalid content"); complete(); }; commandingSurface._contentFlyout.addEventListener("afterhide", testSecondCommandClick); commandingSurface._contentFlyout.hide(); } testOverflowBehaviorCustomPriority() { var customEl = document.createElement("div"); var customContent = document.createElement("div"); customContent.style.width = "200px"; customContent.style.height = "50px"; customContent.innerHTML = "custom 2"; customContent.style.backgroundColor = "red"; customEl.appendChild(customContent); var data = new WinJS.Binding.List([ new Command(null, { type: _Constants.typeButton, label: "1", priority: 1 }), new Command(customEl, { type: _Constants.typeContent, label: "2", priority: 5 }), new Command(null, { type: _Constants.typeSeparator, priority: 2 }), new Command(null, { type: _Constants.typeButton, label: "3", priority: 3 }), new Command(null, { type: _Constants.typeButton, label: "4", priority: 2 }), new Command(null, { type: _Constants.typeButton, label: "5", priority: 4 }), new Command(null, { type: _Constants.typeSeparator, priority: 5 }), new Command(null, { type: _Constants.typeButton, label: "6", priority: 5 }), new Command(null, { type: _Constants.typeButton, label: "sec 1", section: _Constants.secondaryCommandSection }), new Command(null, { type: _Constants.typeButton, label: "sec 2", section: _Constants.secondaryCommandSection }), ]); var commandingSurface = new _CommandingSurface(this._element, { data: data, closedDisplayMode: _CommandingSurface.ClosedDisplayMode.compact, }); var customContentWidth = commandingSurface._getCommandWidth(data.getAt(1)); // Make sure everything fits, nothing should overflow var args: Helper._CommandingSurface.ISizeForCommandsArgs = { closedDisplayMode: commandingSurface.closedDisplayMode, numStandardCommandsShownInActionArea: 5, numSeparatorsShownInActionArea: 2, widthOfContentCommandsShownInActionArea: customContentWidth, isACommandVisbleInTheOverflowArea: true, additionalFreeSpace: 0, }; Helper._CommandingSurface.sizeForCommands(this._element, args); commandingSurface.forceLayout(); LiveUnit.Assert.areEqual(8, Helper._CommandingSurface.getVisibleCommandsInElement(commandingSurface._dom.actionArea).length, "Invalid number of commands in the actionarea"); LiveUnit.Assert.areEqual(2, Helper._CommandingSurface.getVisibleCommandsInElement(commandingSurface._dom.overflowArea).length, "Menu commands list has an invalid length"); // Decrease size to overflow priority 5 commands args = { closedDisplayMode: commandingSurface.closedDisplayMode, numStandardCommandsShownInActionArea: 5, numSeparatorsShownInActionArea: 2, widthOfContentCommandsShownInActionArea: 0, isACommandVisbleInTheOverflowArea: true, additionalFreeSpace: customContentWidth - 1, }; Helper._CommandingSurface.sizeForCommands(this._element, args); commandingSurface.forceLayout(); LiveUnit.Assert.areEqual(5, Helper._CommandingSurface.getVisibleCommandsInElement(commandingSurface._dom.actionArea).length, "Invalid number of commands in the actionarea"); var expectedMenuCommands = 6 /* 2 secondary commands + 1 separator + 2 primary commands with 1 separator */; var visibleMenuCommands = Helper._CommandingSurface.getVisibleCommandsInElement(commandingSurface._dom.overflowArea); LiveUnit.Assert.areEqual(expectedMenuCommands, visibleMenuCommands.length, "Menu commands list has an invalid length"); Helper._CommandingSurface.verifyOverflowMenuContent(visibleMenuCommands, ["2", _Constants.typeSeparator, "6", _Constants.typeSeparator, "sec 1", "sec 2"]); // Decrease size to overflow priority 4 commands args = { closedDisplayMode: commandingSurface.closedDisplayMode, numStandardCommandsShownInActionArea: 3, numSeparatorsShownInActionArea: 1, widthOfContentCommandsShownInActionArea: 0, isACommandVisbleInTheOverflowArea: true, additionalFreeSpace: 0, }; Helper._CommandingSurface.sizeForCommands(this._element, args); commandingSurface.forceLayout(); LiveUnit.Assert.areEqual(4, Helper._CommandingSurface.getVisibleCommandsInElement(commandingSurface._dom.actionArea).length, "Invalid number of commands in the actionarea"); var expectedMenuCommands = 7 /* 2 secondary commands + 1 separator + 3 primary commands with 1 separator */; var visibleMenuCommands = Helper._CommandingSurface.getVisibleCommandsInElement(commandingSurface._dom.overflowArea); LiveUnit.Assert.areEqual(expectedMenuCommands, visibleMenuCommands.length, "Menu commands list has an invalid length"); Helper._CommandingSurface.verifyOverflowMenuContent(visibleMenuCommands, ["2", "5", _Constants.typeSeparator, "6", _Constants.typeSeparator, "sec 1", "sec 2"]); // Decrease size to overflow priority 3 commands args = { closedDisplayMode: commandingSurface.closedDisplayMode, numStandardCommandsShownInActionArea: 2, numSeparatorsShownInActionArea: 1, widthOfContentCommandsShownInActionArea: 0, isACommandVisbleInTheOverflowArea: true, additionalFreeSpace: 0, }; Helper._CommandingSurface.sizeForCommands(this._element, args); commandingSurface.forceLayout(); LiveUnit.Assert.areEqual(3, Helper._CommandingSurface.getVisibleCommandsInElement(commandingSurface._dom.actionArea).length, "Invalid number of commands in the actionarea"); var expectedMenuCommands = 8 /* 2 secondary commands + 1 separator + 4 primary commands with 1 separator */; var visibleMenuCommands = Helper._CommandingSurface.getVisibleCommandsInElement(commandingSurface._dom.overflowArea); LiveUnit.Assert.areEqual(expectedMenuCommands, visibleMenuCommands.length, "Menu commands list has an invalid length"); Helper._CommandingSurface.verifyOverflowMenuContent(visibleMenuCommands, ["2", "3", "5", _Constants.typeSeparator, "6", _Constants.typeSeparator, "sec 1", "sec 2"]); // Decrease size to overflow priority 2 commands args = { closedDisplayMode: commandingSurface.closedDisplayMode, numStandardCommandsShownInActionArea: 1, numSeparatorsShownInActionArea: 0, widthOfContentCommandsShownInActionArea: 0, isACommandVisbleInTheOverflowArea: true, additionalFreeSpace: 0, }; Helper._CommandingSurface.sizeForCommands(this._element, args); commandingSurface.forceLayout(); LiveUnit.Assert.areEqual(1, Helper._CommandingSurface.getVisibleCommandsInElement(commandingSurface._dom.actionArea).length, "Invalid number of commands in the actionarea"); var expectedMenuCommands = 10 /* 2 secondary commands + 1 separator + 5 primary commands with 2 separators */; var visibleMenuCommands = Helper._CommandingSurface.getVisibleCommandsInElement(commandingSurface._dom.overflowArea); LiveUnit.Assert.areEqual(expectedMenuCommands, visibleMenuCommands.length, "Menu commands list has an invalid length"); Helper._CommandingSurface.verifyOverflowMenuContent(visibleMenuCommands, ["2", _Constants.typeSeparator, "3", "4", "5", _Constants.typeSeparator, "6", _Constants.typeSeparator, "sec 1", "sec 2"]); // Decrease size to overflow priority 1 commands args = { closedDisplayMode: commandingSurface.closedDisplayMode, numStandardCommandsShownInActionArea: 0, numSeparatorsShownInActionArea: 0, widthOfContentCommandsShownInActionArea: 0, isACommandVisbleInTheOverflowArea: true, additionalFreeSpace: 0, }; Helper._CommandingSurface.sizeForCommands(this._element, args); commandingSurface.forceLayout(); LiveUnit.Assert.areEqual(0, Helper._CommandingSurface.getVisibleCommandsInElement(commandingSurface._dom.actionArea).length, "Invalid number of commands in the actionarea"); var expectedMenuCommands = 11 /* 2 secondary commands + 1 separator + 6 primary commands with 2 separator */; var visibleMenuCommands = Helper._CommandingSurface.getVisibleCommandsInElement(commandingSurface._dom.overflowArea); LiveUnit.Assert.areEqual(expectedMenuCommands, visibleMenuCommands.length, "Menu commands list has an invalid length"); Helper._CommandingSurface.verifyOverflowMenuContent(visibleMenuCommands, ["1", "2", _Constants.typeSeparator, "3", "4", "5", _Constants.typeSeparator, "6", _Constants.typeSeparator, "sec 1", "sec 2"]); } testMinWidth() { this._element.style.width = "10px"; var commandingSurface = new _CommandingSurface(this._element); LiveUnit.Assert.areEqual(_Constants.controlMinWidth, parseInt(getComputedStyle(this._element).width, 10), "Invalid min width of commandingSurface element"); } testOverflowAreaContainerHeightWhenThereIsNoOverflow() { var data = new WinJS.Binding.List([ new Command(null, { type: _Constants.typeContent, label: "1" }), new Command(null, { type: _Constants.typeContent, label: "2" }), ]); var commandingSurface = new _CommandingSurface(this._element, { data: data }); LiveUnit.Assert.areEqual(0, WinJS.Utilities._getPreciseTotalHeight(commandingSurface._dom.overflowArea), "Invalid height for the overflowarea container when there are no commands that overflow"); } xtestOverflowAreaContainerSize() { var data = new WinJS.Binding.List([ new Command(null, { type: _Constants.typeButton, label: "1" }), new Command(null, { type: _Constants.typeButton, label: "2" }), new Command(null, { type: _Constants.typeButton, label: "3" }), new Command(null, { type: _Constants.typeButton, label: "4" }), new Command(null, { type: _Constants.typeButton, label: "5" }), new Command(null, { type: _Constants.typeButton, label: "6" }), new Command(null, { type: _Constants.typeButton, label: "1", section: _Constants.secondaryCommandSection }), new Command(null, { type: _Constants.typeButton, label: "this is a really long label this is a really long label this is a really long label this is a really long label this is a really long label this is a really long label this is a really long label this is a really long label this is a really long label this is a really long label this is a really long label this is a really long label this is a really long label this is a really long label this is a really long label this is a really long label ", section: _Constants.secondaryCommandSection }), ]); this._element.style.width = "10px"; var commandingSurface = new _CommandingSurface(this._element, { data: data, opened: true, closedDisplayMode: _CommandingSurface.ClosedDisplayMode.compact, }); // Make sure primary commands fit exactly var args: Helper._CommandingSurface.ISizeForCommandsArgs = { closedDisplayMode: commandingSurface.closedDisplayMode, numStandardCommandsShownInActionArea: 6, numSeparatorsShownInActionArea: 0, widthOfContentCommandsShownInActionArea: 0, isACommandVisbleInTheOverflowArea: true, additionalFreeSpace: 0, }; Helper._CommandingSurface.sizeForCommands(this._element, args); commandingSurface.forceLayout(); LiveUnit.Assert.areEqual(2, Helper._CommandingSurface.getVisibleCommandsInElement(commandingSurface._dom.overflowArea).length, "There should only be 2 commands in the overflowarea"); LiveUnit.Assert.areEqual(2 * _Constants.overflowCommandHeight, WinJS.Utilities._getPreciseTotalHeight(commandingSurface._dom.overflowArea), "Invalid height for the overflowarea container"); LiveUnit.Assert.areEqual(parseInt(this._element.style.width), WinJS.Utilities._getPreciseTotalWidth(commandingSurface._dom.overflowArea), "Invalid width for the overflowarea container"); LiveUnit.Assert.areEqual(commandingSurface.element, commandingSurface._dom.overflowArea.parentNode, "Invalid parent for the overflowarea container"); LiveUnit.Assert.areEqual(commandingSurface.element, commandingSurface._dom.actionArea.parentNode, "Invalid parent for the actionarea container"); } xtestOverflowMaxHeightForOnlySecondaryCommands() { var data = new WinJS.Binding.List([ new Command(null, { type: _Constants.typeButton, label: "1", section: _Constants.secondaryCommandSection }), new Command(null, { type: _Constants.typeButton, label: "2", section: _Constants.secondaryCommandSection }), new Command(null, { type: _Constants.typeButton, label: "3", section: _Constants.secondaryCommandSection }), new Command(null, { type: _Constants.typeButton, label: "4", section: _Constants.secondaryCommandSection }), new Command(null, { type: _Constants.typeButton, label: "5", section: _Constants.secondaryCommandSection }), new Command(null, { type: _Constants.typeButton, label: "6", section: _Constants.secondaryCommandSection }), new Command(null, { type: _Constants.typeButton, label: "7", section: _Constants.secondaryCommandSection }), new Command(null, { type: _Constants.typeButton, label: "8", section: _Constants.secondaryCommandSection }), new Command(null, { type: _Constants.typeButton, label: "9", section: _Constants.secondaryCommandSection }), ]); this._element.style.width = "1000px"; var commandingSurface = new _CommandingSurface(this._element, { data: data, opened: true, }); LiveUnit.Assert.areEqual(4.5 * _Constants.overflowCommandHeight, WinJS.Utilities._getPreciseTotalHeight(commandingSurface._dom.overflowArea), "Invalid height for the overflowarea container"); LiveUnit.Assert.areEqual(9, Helper._CommandingSurface.getVisibleCommandsInElement(commandingSurface._dom.overflowArea).length, "There should be 9 commands in the overflowarea"); } xtestOverflowMaxHeightForMixedCommands() { var data = new WinJS.Binding.List([ new Command(null, { type: _Constants.typeButton, label: "1" }), new Command(null, { type: _Constants.typeButton, label: "2" }), new Command(null, { type: _Constants.typeButton, label: "3" }), new Command(null, { type: _Constants.typeButton, label: "4" }), new Command(null, { type: _Constants.typeButton, label: "5" }), new Command(null, { type: _Constants.typeButton, label: "6" }), new Command(null, { type: _Constants.typeButton, label: "7" }), new Command(null, { type: _Constants.typeButton, label: "8" }), new Command(null, { type: _Constants.typeButton, label: "s1", section: _Constants.secondaryCommandSection }), new Command(null, { type: _Constants.typeButton, label: "s2", section: _Constants.secondaryCommandSection }), new Command(null, { type: _Constants.typeButton, label: "s3", section: _Constants.secondaryCommandSection }), new Command(null, { type: _Constants.typeButton, label: "s4", section: _Constants.secondaryCommandSection }), new Command(null, { type: _Constants.typeButton, label: "s5", section: _Constants.secondaryCommandSection }), new Command(null, { type: _Constants.typeButton, label: "s6", section: _Constants.secondaryCommandSection }), new Command(null, { type: _Constants.typeButton, label: "s7", section: _Constants.secondaryCommandSection }), ]); this._element.style.width = "320px"; var commandingSurface = new _CommandingSurface(this._element, { data: data, opened: true, }); LiveUnit.Assert.areEqual(4.5 * _Constants.overflowCommandHeight, WinJS.Utilities._getPreciseTotalHeight(commandingSurface._dom.overflowArea), "Invalid height for the overflowarea container"); } testKeyboarding_Opened(complete) { var Key = WinJS.Utilities.Key; var firstEL = document.createElement("button"); var data = new WinJS.Binding.List([ new Command(firstEL, { type: _Constants.typeButton, label: "1" }), new Command(null, { type: _Constants.typeButton, label: "2" }), new Command(null, { type: _Constants.typeButton, label: "3", hidden: true }), new Command(null, { type: _Constants.typeButton, label: "4" }), new Command(null, { type: _Constants.typeButton, label: "s1", section: _Constants.secondaryCommandSection }), new Command(null, { type: _Constants.typeButton, label: "s2", section: _Constants.secondaryCommandSection }), new Command(null, { type: _Constants.typeButton, label: "s3", section: _Constants.secondaryCommandSection }), new Command(null, { type: _Constants.typeButton, label: "s4", section: _Constants.secondaryCommandSection }), ]); this._element.style.width = "320px"; var commandingSurface = new _CommandingSurface(this._element, { data: data, opened: true, }); commandingSurface.element.focus(); setTimeout(function () { Helper.keydown(commandingSurface.element, Key.rightArrow); LiveUnit.Assert.areEqual(firstEL, document.activeElement); LiveUnit.Assert.areEqual("1", document.activeElement.textContent); Helper.keydown(commandingSurface.element, Key.end); LiveUnit.Assert.areEqual("s4", document.activeElement.textContent); Helper.keydown(commandingSurface.element, Key.home); LiveUnit.Assert.areEqual("1", document.activeElement.textContent); Helper.keydown(commandingSurface.element, Key.rightArrow); LiveUnit.Assert.areEqual("2", document.activeElement.textContent); Helper.keydown(commandingSurface.element, Key.downArrow); LiveUnit.Assert.areEqual("4", document.activeElement.textContent, "Down arrow should skip '3' because that command is hidden"); Helper.keydown(commandingSurface.element, Key.rightArrow); LiveUnit.Assert.areEqual(commandingSurface._dom.overflowButton, document.activeElement); Helper.keydown(commandingSurface.element, Key.rightArrow); LiveUnit.Assert.areEqual("s1", document.activeElement.textContent); Helper.keydown(commandingSurface.element, Key.downArrow); LiveUnit.Assert.areEqual("s2", document.activeElement.textContent); Helper.keydown(commandingSurface.element, Key.leftArrow); LiveUnit.Assert.areEqual("s1", document.activeElement.textContent); Helper.keydown(commandingSurface.element, Key.upArrow); LiveUnit.Assert.areEqual(commandingSurface._dom.overflowButton, document.activeElement); Helper.keydown(commandingSurface.element, Key.upArrow); LiveUnit.Assert.areEqual("4", document.activeElement.textContent); Helper.keydown(commandingSurface.element, Key.upArrow); LiveUnit.Assert.areEqual("2", document.activeElement.textContent, "Up arrow should skip '3' because that command is hidden"); complete(); }); } testKeyboarding_Closed(complete) { var Key = WinJS.Utilities.Key; var firstEL = document.createElement("button"); var data = new WinJS.Binding.List([ new Command(firstEL, { type: _Constants.typeButton, icon: "1", label: "1" }), new Command(null, { type: _Constants.typeButton, icon: "2", label: "2", disabled: true }), new Command(null, { type: _Constants.typeButton, icon: "3", label: "3" }), new Command(null, { type: _Constants.typeButton, icon: "4", label: "4" }), new Command(null, { type: _Constants.typeButton, label: "s1", section: _Constants.secondaryCommandSection }), new Command(null, { type: _Constants.typeButton, label: "s2", section: _Constants.secondaryCommandSection }), new Command(null, { type: _Constants.typeButton, label: "s3", section: _Constants.secondaryCommandSection }), new Command(null, { type: _Constants.typeButton, label: "s4", section: _Constants.secondaryCommandSection }) ]); this._element.style.width = "10px"; var commandingSurface = new _CommandingSurface(this._element, { data: data, closedDisplayMode: _CommandingSurface.ClosedDisplayMode.compact, }); var args: Helper._CommandingSurface.ISizeForCommandsArgs = { closedDisplayMode: commandingSurface.closedDisplayMode, numStandardCommandsShownInActionArea: 3, numSeparatorsShownInActionArea: 0, widthOfContentCommandsShownInActionArea: 0, isACommandVisbleInTheOverflowArea: true, additionalFreeSpace: 0, }; Helper._CommandingSurface.sizeForCommands(this._element, args); commandingSurface.forceLayout(); // The actionarea should only show | 1 | 2 (disabled) | 3 | ... | commandingSurface.element.focus(); setTimeout(function () { Helper.keydown(commandingSurface.element, Key.downArrow); LiveUnit.Assert.areEqual(firstEL, document.activeElement); LiveUnit.Assert.areEqual("1", document.activeElement.winControl.label); Helper.keydown(commandingSurface.element, Key.end); LiveUnit.Assert.areEqual(commandingSurface._dom.overflowButton, document.activeElement); Helper.keydown(commandingSurface.element, Key.home); LiveUnit.Assert.areEqual("1", document.activeElement.winControl.label); Helper.keydown(commandingSurface.element, Key.rightArrow); LiveUnit.Assert.areEqual("3", document.activeElement.winControl.label, "Right arrow, should skip '2' because that command is disabled"); Helper.keydown(commandingSurface.element, Key.downArrow); LiveUnit.Assert.areEqual(commandingSurface._dom.overflowButton, document.activeElement); Helper.keydown(commandingSurface.element, Key.rightArrow); LiveUnit.Assert.areEqual(commandingSurface._dom.overflowButton, document.activeElement); Helper.keydown(commandingSurface.element, Key.leftArrow); LiveUnit.Assert.areEqual("3", document.activeElement.winControl.label); Helper.keydown(commandingSurface.element, Key.upArrow); LiveUnit.Assert.areEqual("1", document.activeElement.winControl.label, "Up arrow, should skip '2' because that command is disabled"); complete(); }); } testKeyboardingWithCustomContent(complete) { var Key = WinJS.Utilities.Key; var firstCommand = document.createElement("button"); var customCommand = document.createElement("div"); var firstCheckBox = document.createElement("input"); firstCheckBox.type = "checkbox"; var secondCheckBox = document.createElement("input"); secondCheckBox.type = "checkbox"; customCommand.appendChild(firstCheckBox); customCommand.appendChild(secondCheckBox); var lastCommand = document.createElement("button"); var data = new WinJS.Binding.List([ new Command(firstCommand, { type: _Constants.typeButton, label: "1" }), new Command(customCommand, { type: _Constants.typeContent, label: "2", firstElementFocus: firstCheckBox, lastElementFocus: secondCheckBox }), new Command(lastCommand, { type: _Constants.typeButton, label: "3" }), ]); this._element.style.width = "10px"; var commandingSurface = new _CommandingSurface(this._element, { data: data, closedDisplayMode: _CommandingSurface.ClosedDisplayMode.compact, }); var overflowButton = commandingSurface._dom.overflowButton; // Size the width of the control to fit all 3 commands. var customContentWidth = commandingSurface._getCommandWidth(data.getAt(1)); var args: Helper._CommandingSurface.ISizeForCommandsArgs = { closedDisplayMode: commandingSurface.closedDisplayMode, numStandardCommandsShownInActionArea: 2, numSeparatorsShownInActionArea: 0, widthOfContentCommandsShownInActionArea: customContentWidth, isACommandVisbleInTheOverflowArea: true, additionalFreeSpace: 0, }; Helper._CommandingSurface.sizeForCommands(this._element, args); commandingSurface.forceLayout(); // The actionarea should show | 1 | 2 (custom) | 3 | ... | commandingSurface.element.focus(); setTimeout(function () { Helper.keydown(commandingSurface.element, Key.rightArrow); LiveUnit.Assert.areEqual(firstCommand, document.activeElement); Helper.keydown(commandingSurface.element, Key.end); LiveUnit.Assert.areEqual(overflowButton, document.activeElement); Helper.keydown(commandingSurface.element, Key.leftArrow); LiveUnit.Assert.areEqual(lastCommand, document.activeElement); Helper.keydown(commandingSurface.element, Key.leftArrow); LiveUnit.Assert.areEqual(secondCheckBox, document.activeElement); Helper.keydown(commandingSurface.element, Key.leftArrow); LiveUnit.Assert.areEqual(firstCommand, document.activeElement); Helper.keydown(commandingSurface.element, Key.rightArrow); LiveUnit.Assert.areEqual(firstCheckBox, document.activeElement); Helper.keydown(commandingSurface.element, Key.home); LiveUnit.Assert.areEqual(firstCommand, document.activeElement); complete(); }); } testDataEdits(complete) { var Key = WinJS.Utilities.Key; var firstEL = document.createElement("button"); var data = new WinJS.Binding.List([ new Command(firstEL, { type: _Constants.typeButton, label: "1" }), new Command(null, { type: _Constants.typeButton, label: "2" }), new Command(null, { type: _Constants.typeButton, label: "3" }), new Command(null, { type: _Constants.typeButton, label: "4" }), new Command(null, { type: _Constants.typeButton, label: "s1", section: _Constants.secondaryCommandSection }), new Command(null, { type: _Constants.typeButton, label: "s2", section: _Constants.secondaryCommandSection }), new Command(null, { type: _Constants.typeButton, label: "s3", section: _Constants.secondaryCommandSection }), new Command(null, { type: _Constants.typeContent, label: "content", section: _Constants.secondaryCommandSection }), ]); this._element.style.width = "10px"; var commandingSurface = new _CommandingSurface(this._element, { data: data, closedDisplayMode: _CommandingSurface.ClosedDisplayMode.compact, }); // Limit the width of the control to fit only 3 commands. var args: Helper._CommandingSurface.ISizeForCommandsArgs = { closedDisplayMode: commandingSurface.closedDisplayMode, numStandardCommandsShownInActionArea: 3, numSeparatorsShownInActionArea: 0, widthOfContentCommandsShownInActionArea: 0, isACommandVisbleInTheOverflowArea: true, additionalFreeSpace: 0, }; Helper._CommandingSurface.sizeForCommands(this._element, args); commandingSurface.forceLayout(); // The actionarea should now show | 1 | 2 | 3 | ... | LiveUnit.Assert.areEqual(3, Helper._CommandingSurface.getVisibleCommandsInElement(commandingSurface._dom.actionArea).length); // Delete item wth label 3 commandingSurface.data.splice(2, 1); WinJS.Utilities.Scheduler.schedule(() => { LiveUnit.Assert.areEqual("4", Helper._CommandingSurface.getVisibleCommandsInElement(commandingSurface._dom.actionArea)[2].textContent); // The actionarea should now show | 1 | 2 | 4 | ... | LiveUnit.Assert.areEqual(3, Helper._CommandingSurface.getVisibleCommandsInElement(commandingSurface._dom.actionArea).length); commandingSurface.data.splice(0, 0, new Command(null, { type: _Constants.typeButton, label: "new" })); WinJS.Utilities.Scheduler.schedule(() => { var visibleCommands = Helper._CommandingSurface.getVisibleCommandsInElement(commandingSurface._dom.actionArea); LiveUnit.Assert.areEqual("new", visibleCommands[0].textContent); LiveUnit.Assert.areEqual("1", visibleCommands[1].textContent); LiveUnit.Assert.areEqual("2", visibleCommands[2].textContent); // The actionarea should now show | new | 1 | 2 | ... | LiveUnit.Assert.areEqual(3, Helper._CommandingSurface.getVisibleCommandsInElement(commandingSurface._dom.actionArea).length); // Force all commands into the overflowarea this._element.style.width = "10px"; commandingSurface.forceLayout(); // Delete the the content command and verify CommandingSurface Dom updates. // Also verify that we dispose the deleted command's associated MenuCommand projection. var deletedCommand = commandingSurface.data.splice(data.length - 1, 1)[0]; // PRECONDITION: Sanity check that the command we got back is our content command. LiveUnit.Assert.areEqual(_Constants.typeContent, deletedCommand.type); var deletedMenuCommand = Helper._CommandingSurface.getProjectedCommandFromOriginalCommand(commandingSurface, deletedCommand); WinJS.Utilities.Scheduler.schedule(() => { LiveUnit.Assert.areEqual(0, Helper._CommandingSurface.getVisibleCommandsInElement(commandingSurface._dom.actionArea).length); LiveUnit.Assert.areEqual(8, Helper._CommandingSurface.getVisibleCommandsInElement(commandingSurface._dom.overflowArea).length); LiveUnit.Assert.isTrue(deletedMenuCommand._disposed, "Removing a command from the CommandingSurface's overflowarea should dispose the associated menucommand projection"); LiveUnit.Assert.isFalse(commandingSurface._contentFlyout._disposed, "Disposing a menucommand projection should not dispose the CommandingSurface._contentFlyout"); complete(); }); }, WinJS.Utilities.Scheduler.Priority.high); }, WinJS.Utilities.Scheduler.Priority.high); } testDataEditEmptyScenario(complete) { var Key = WinJS.Utilities.Key; var firstEL = document.createElement("button"); var data = new WinJS.Binding.List([ new Command(firstEL, { type: _Constants.typeButton, label: "1" }), new Command(null, { type: _Constants.typeButton, label: "2" }), new Command(null, { type: _Constants.typeButton, label: "3" }), new Command(null, { type: _Constants.typeButton, label: "4" }), new Command(null, { type: _Constants.typeButton, label: "s1", section: _Constants.secondaryCommandSection }), new Command(null, { type: _Constants.typeButton, label: "s2", section: _Constants.secondaryCommandSection }), new Command(null, { type: _Constants.typeButton, label: "s3", section: _Constants.secondaryCommandSection }), new Command(null, { type: _Constants.typeButton, label: "s4", section: _Constants.secondaryCommandSection }), ]); this._element.style.width = "10px"; var commandingSurface = new _CommandingSurface(this._element, { data: data, closedDisplayMode: _CommandingSurface.ClosedDisplayMode.compact, }); // Limit the width of the control to fit 3 commands. var args: Helper._CommandingSurface.ISizeForCommandsArgs = { closedDisplayMode: commandingSurface.closedDisplayMode, numStandardCommandsShownInActionArea: 3, numSeparatorsShownInActionArea: 0, widthOfContentCommandsShownInActionArea: 0, isACommandVisbleInTheOverflowArea: true, additionalFreeSpace: 0, }; Helper._CommandingSurface.sizeForCommands(this._element, args); commandingSurface.forceLayout(); // The actionarea should now show | 1 | 2 | 3 | ... | LiveUnit.Assert.areEqual(3, Helper._CommandingSurface.getVisibleCommandsInElement(commandingSurface._dom.actionArea).length); var menuCommandProjections = Helper._CommandingSurface.getVisibleCommandsInElement(commandingSurface._dom.overflowArea).map(function (element) { return element.winControl; }); // Delete all items commandingSurface.data = new WinJS.Binding.List([]); WinJS.Utilities.Scheduler.schedule(() => { LiveUnit.Assert.areEqual(0, Helper._CommandingSurface.getVisibleCommandsInElement(commandingSurface._dom.actionArea).length, "Action area should be empty"); LiveUnit.Assert.areEqual(0, Helper._CommandingSurface.getVisibleCommandsInElement(commandingSurface._dom.overflowArea).length, "Overflow area should be empty"); LiveUnit.Assert.isTrue(menuCommandProjections.every(function (menuCommand) { return menuCommand._disposed; }), "Setting new data should have disposed all previous overflowarea MenuCommand projections."); complete(); }, WinJS.Utilities.Scheduler.Priority.high); } testDataMutationsAreProjectedToOverflowCommands(complete) { // Verifies that mutations to an ICommand in the actionarea are reflected to that ICommand's MenuCommand projection // in the overflowarea, if such a projection exists. // var buttonCmd = new Command(null, { type: _Constants.typeButton, label: "button", section: 'primary', extraClass: "myClass", }); var toggleCmd = new Command(null, { type: _Constants.typeToggle, label: 'toggle', section: 'primary' }); var flyoutCmd = new Command(null, { type: _Constants.typeFlyout, label: "flyout", section: 'primary' }); var data = new WinJS.Binding.List([buttonCmd, toggleCmd, flyoutCmd]); this._element.style.width = "10px"; var commandingSurface = new _CommandingSurface(this._element, { data: data, opened: true }); Helper._CommandingSurface.useSynchronousAnimations(commandingSurface); var startingLength = 3; // PRECONDITION: Test assumes there are 3 overflowing primary commands in the CommandingSurface overflowarea. LiveUnit.Assert.areEqual(startingLength, Helper._CommandingSurface.getVisibleCommandsInElement(commandingSurface._dom.overflowArea).length, "TEST ERROR: Test expects 3 overflowing commands at the start"); // Commands in the overflowarea are all MenuCommand projections of the original ICommands in the actionarea. // These projections and the rest of the overflowarea are redrawn whenever the data in the binding list changes // or when certain properties of ICommands in the CommandingSurface are mutated. var projections = { get button() { return Helper._CommandingSurface.getProjectedCommandFromOriginalCommand(commandingSurface, buttonCmd); }, get toggle() { return Helper._CommandingSurface.getProjectedCommandFromOriginalCommand(commandingSurface, toggleCmd); }, get flyout() { return Helper._CommandingSurface.getProjectedCommandFromOriginalCommand(commandingSurface, flyoutCmd); } } var msg = " property of projected menucommand should have updated"; buttonCmd.label = "new label"; new WinJS.Promise((c) => { commandingSurface._layoutCompleteCallback = () => { LiveUnit.Assert.areEqual(buttonCmd.label, projections.button.label, "label" + msg); c(); }; }).then( () => { buttonCmd.disabled = true; return new WinJS.Promise((c) => { commandingSurface._layoutCompleteCallback = () => { LiveUnit.Assert.areEqual(buttonCmd.disabled, projections.button.disabled, "disabled" + msg); c(); }; }); } ).then( () => { buttonCmd.disabled = false; return new WinJS.Promise((c) => { commandingSurface._layoutCompleteCallback = () => { LiveUnit.Assert.areEqual(buttonCmd.disabled, projections.button.disabled, "disabled" + msg); c(); }; }); } ).then( () => { buttonCmd.extraClass = "new class"; return new WinJS.Promise((c) => { commandingSurface._layoutCompleteCallback = () => { LiveUnit.Assert.areEqual(buttonCmd.extraClass, projections.button.extraClass, "extraClass" + msg); c(); }; }); } ).then( () => { buttonCmd.onclick = () => { }; return new WinJS.Promise((c) => { commandingSurface._layoutCompleteCallback = () => { LiveUnit.Assert.areEqual(buttonCmd.onclick, projections.button.onclick, "onclick" + msg); c(); }; }); } ).then( () => { buttonCmd.hidden = true; return new WinJS.Promise((c) => { commandingSurface._layoutCompleteCallback = () => { LiveUnit.Assert.isNull(projections.button, "Setting hidden = true on an overflowing ICommand should remove its menucommand projection from the overflowarea"); LiveUnit.Assert.areEqual(startingLength - 1, Helper._CommandingSurface.getVisibleCommandsInElement(commandingSurface._dom.overflowArea).length, "Setting hidden = true on an overflowing ICommand should remove its menucommand projection from the overflowarea"); c(); }; }); } ).then( () => { buttonCmd.hidden = false; return new WinJS.Promise((c) => { commandingSurface._layoutCompleteCallback = () => { LiveUnit.Assert.isNotNull(projections.button, "Setting hidden = false on an overflowing ICommand should add a menucommand projection of it to the overflowarea"); LiveUnit.Assert.areEqual(startingLength, Helper._CommandingSurface.getVisibleCommandsInElement(commandingSurface._dom.overflowArea).length, "Setting hidden = false on an overflowing ICommand should add a menucommand projection of it to the overflowarea"); c(); }; }); } ).then( () => { toggleCmd.selected = true; return new WinJS.Promise((c) => { commandingSurface._layoutCompleteCallback = () => { LiveUnit.Assert.areEqual(toggleCmd.selected, projections.toggle.selected, "selected" + msg); c(); }; }); } ).then( () => { toggleCmd.selected = false; return new WinJS.Promise((c) => { commandingSurface._layoutCompleteCallback = () => { LiveUnit.Assert.areEqual(toggleCmd.selected, projections.toggle.selected, "selected" + msg); c(); }; }); } ).then( () => { var flyout = new WinJS.UI.Flyout(); flyoutCmd.flyout = flyout; return new WinJS.Promise((c) => { commandingSurface._layoutCompleteCallback = () => { LiveUnit.Assert.areEqual(flyoutCmd.flyout, projections.flyout.flyout, "flyout" + msg); flyout.dispose(); c(); }; }); } ).done(complete); } testSelectionAndGlobalSection() { // Values of "global" and "selection" are deprecated starting in WinJS 4.0. // Makes sure they are both just parsed as "primary" commands. this._element.style.width = "1000px"; var data = new WinJS.Binding.List([ new Command(null, { type: _Constants.typeButton, label: "opt 1", section: 'selection' }), new Command(null, { type: _Constants.typeButton, label: "opt 2", section: 'global' }), new Command(null, { type: _Constants.typeButton, label: "opt 3", section: 'primary' }), new Command(null, { type: _Constants.typeButton, label: "opt 4", section: _Constants.secondaryCommandSection }) ]); var commandingSurface = new _CommandingSurface(this._element, { data: data }); Helper._CommandingSurface.verifyActionAreaVisibleCommandsLabels(commandingSurface, ["opt 1", "opt 2", "opt 3"]); Helper._CommandingSurface.verifyOverflowAreaCommandsLabels(commandingSurface, ["opt 4"]); } testClosedDisplayModeConstructorOptions() { var commandingSurface = new _CommandingSurface(); LiveUnit.Assert.areEqual(_Constants.defaultClosedDisplayMode, commandingSurface.closedDisplayMode, "'closedDisplayMode' property has incorrect default value."); commandingSurface.dispose(); Object.keys(_CommandingSurface.ClosedDisplayMode).forEach(function (mode) { commandingSurface = new _CommandingSurface(null, { closedDisplayMode: mode }); LiveUnit.Assert.areEqual(mode, commandingSurface.closedDisplayMode, "closedDisplayMode does not match the value passed to the constructor."); commandingSurface.dispose(); }) } testClosedDisplayModes() { this._element.style.width = "1000px"; var contentElement = document.createElement("DIV"); contentElement.style.height = "100px"; contentElement.style.border = "none"; var data = new WinJS.Binding.List([ new Command(null, { type: _Constants.typeButton, icon: 'add', label: "button" }), new Command(null, { type: _Constants.typeSeparator }), new Command(contentElement, { type: _Constants.typeContent, label: "content" }), new Command(null, { type: _Constants.typeButton, section: 'secondary', label: "secondary" }), ]); var commandingSurface = new _CommandingSurface(this._element, { data: data, opened: false, }); var msg = "Changing the closedDisplayMode property should not trigger this event"; commandingSurface.onbeforeopen = failEventHandler(_Constants.EventNames.beforeOpen, msg); commandingSurface.onbeforeclose = failEventHandler(_Constants.EventNames.beforeClose, msg); commandingSurface.onafteropen = failEventHandler(_Constants.EventNames.afterOpen, msg); commandingSurface.onafterclose = failEventHandler(_Constants.EventNames.afterClose, msg); Object.keys(_CommandingSurface.ClosedDisplayMode).forEach(function (mode) { commandingSurface.closedDisplayMode = mode; LiveUnit.Assert.areEqual(mode, commandingSurface.closedDisplayMode, "closedDisplayMode property should be writeable."); Helper._CommandingSurface.verifyRenderedClosed(commandingSurface); }); } testOpen() { var data = new WinJS.Binding.List([ new Command(null, { type: _Constants.typeButton, icon: 'add', label: "button" }), new Command(null, { type: _Constants.typeSeparator }), new Command(null, { type: _Constants.typeButton, section: 'secondary', label: "secondary" }) ]); var commandingSurface = new _CommandingSurface(this._element, { opened: false }); Helper._CommandingSurface.useSynchronousAnimations(commandingSurface); // Test empty scenario. commandingSurface.open(); LiveUnit.Assert.isTrue(commandingSurface.opened); Helper._CommandingSurface.verifyRenderedOpened(commandingSurface); commandingSurface.close(); LiveUnit.Assert.isFalse(commandingSurface.opened); // Test scenario with data. commandingSurface.data = data; commandingSurface.open(); LiveUnit.Assert.isTrue(commandingSurface.opened); Helper._CommandingSurface.verifyRenderedOpened(commandingSurface); } testOpenIsIdempotent() { var data = new WinJS.Binding.List([ new Command(null, { type: _Constants.typeButton, icon: 'add', label: "button" }), new Command(null, { type: _Constants.typeSeparator }), new Command(null, { type: _Constants.typeButton, section: 'secondary', label: "secondary" }) ]); // Initialize opened. var commandingSurface = new _CommandingSurface(this._element, { data: data, opened: true }); Helper._CommandingSurface.useSynchronousAnimations(commandingSurface); var msg = "Opening an already opened AppBar should not fire events"; commandingSurface.onbeforeopen = failEventHandler(_Constants.EventNames.beforeOpen, msg); commandingSurface.onbeforeclose = failEventHandler(_Constants.EventNames.beforeClose, msg); commandingSurface.onafteropen = failEventHandler(_Constants.EventNames.afterOpen, msg); commandingSurface.onafterclose = failEventHandler(_Constants.EventNames.afterClose, msg); // Verify nothing changes when opening again. var originalOpenedRect = commandingSurface.element.getBoundingClientRect(); commandingSurface.open(); LiveUnit.Assert.isTrue(commandingSurface.opened) Helper._CommandingSurface.verifyRenderedOpened(commandingSurface); Helper.Assert.areBoundingClientRectsEqual(originalOpenedRect, commandingSurface.element.getBoundingClientRect(), "opening an opened CommandingSurface should not affect its bounding client rect", 0); } testClose() { var data = new WinJS.Binding.List([ new Command(null, { type: _Constants.typeButton, icon: 'add', label: "button" }), new Command(null, { type: _Constants.typeSeparator }), new Command(null, { type: _Constants.typeButton, section: 'secondary', label: "secondary" }) ]); var commandingSurface = new _CommandingSurface(this._element, { data: data, opened: true }); Helper._CommandingSurface.useSynchronousAnimations(commandingSurface); commandingSurface.close(); LiveUnit.Assert.isFalse(commandingSurface.opened) Helper._CommandingSurface.verifyRenderedClosed(commandingSurface); } testCloseIsIdempotent() { var data = new WinJS.Binding.List([ new Command(null, { type: _Constants.typeButton, icon: 'add', label: "button" }), new Command(null, { type: _Constants.typeSeparator }), new Command(null, { type: _Constants.typeButton, section: 'secondary', label: "secondary" }) ]); // Initialize closed. var commandingSurface = new _CommandingSurface(this._element, { data: data, opened: false }); Helper._CommandingSurface.useSynchronousAnimations(commandingSurface); var msg = "Closing an already closed AppBar should not fire events"; commandingSurface.onbeforeopen = failEventHandler(_Constants.EventNames.beforeOpen, msg); commandingSurface.onbeforeclose = failEventHandler(_Constants.EventNames.beforeClose, msg); commandingSurface.onafteropen = failEventHandler(_Constants.EventNames.afterOpen, msg); commandingSurface.onafterclose = failEventHandler(_Constants.EventNames.afterClose, msg); // Verify nothing changes when closing again. var originalClosedRect = commandingSurface.element.getBoundingClientRect(); commandingSurface.close(); LiveUnit.Assert.isFalse(commandingSurface.opened) Helper._CommandingSurface.verifyRenderedClosed(commandingSurface); Helper.Assert.areBoundingClientRectsEqual(originalClosedRect, commandingSurface.element.getBoundingClientRect(), "closing a closed CommandingSurface should not affect its bounding client rect", 0); } testOpenedPropertyConstructorOptions() { var commandingSurface = new _CommandingSurface(); LiveUnit.Assert.areEqual(_Constants.defaultOpened, commandingSurface.opened, "opened property has incorrect default value"); commandingSurface.dispose(); [true, false].forEach(function (initiallyOpen) { commandingSurface = new _CommandingSurface(null, { opened: initiallyOpen }); LiveUnit.Assert.areEqual(initiallyOpen, commandingSurface.opened, "opened property does not match the value passed to the constructor."); commandingSurface.dispose(); }) } testTogglingOpenedProperty() { var data = new WinJS.Binding.List([ new Command(null, { type: _Constants.typeButton, icon: 'add', label: "button" }), new Command(null, { type: _Constants.typeSeparator }), new Command(null, { type: _Constants.typeButton, section: 'secondary', label: "secondary" }) ]); var commandingSurface = new _CommandingSurface(this._element, { data: data, opened: false }); Helper._CommandingSurface.useSynchronousAnimations(commandingSurface); Helper._CommandingSurface.verifyRenderedClosed(commandingSurface); commandingSurface.opened = true; LiveUnit.Assert.isTrue(commandingSurface.opened, "opened property should be writeable."); Helper._CommandingSurface.verifyRenderedOpened(commandingSurface); commandingSurface.opened = false; LiveUnit.Assert.isFalse(commandingSurface.opened, "opened property should be writeable."); Helper._CommandingSurface.verifyRenderedClosed(commandingSurface); } testOverFlowButtonClick() { var data = new WinJS.Binding.List([ new Command(null, { type: _Constants.typeButton, icon: 'add', label: "button" }), new Command(null, { type: _Constants.typeSeparator }), new Command(null, { type: _Constants.typeButton, section: 'secondary', label: "secondary" }) ]); var commandingSurface = new _CommandingSurface(this._element, { data: data, opened: true }); Helper._CommandingSurface.useSynchronousAnimations(commandingSurface); commandingSurface._dom.overflowButton.click() LiveUnit.Assert.isFalse(commandingSurface.opened) Helper._CommandingSurface.verifyRenderedClosed(commandingSurface); commandingSurface._dom.overflowButton.click() LiveUnit.Assert.isTrue(commandingSurface.opened) Helper._CommandingSurface.verifyRenderedOpened(commandingSurface); } testTabIndicesWhileClosed() { // Commanding surface should not carousel tab key focus movement while closed. // Verify that both the elements we use to trap focus have tabIndex === -1. var innerHTML = '' + '' + '
' + '
' + '' + ' ' + '
' + ''; this._element.innerHTML = innerHTML; var commandingSurface = new _CommandingSurface(this._element, { opened: false }); Helper._CommandingSurface.useSynchronousAnimations(commandingSurface); var firstTabStopIndex = -1; var finalTabStopIndex = -1; verifyTabIndices(commandingSurface, firstTabStopIndex, finalTabStopIndex); } testTabIndiciesWhileOpened() { // Commanding surface should validate first and last tab stops while opened. // This is what allows tab key focus movement to carousel instead of leaving the control. var innerHTML = '' + '' + '
' + '
' + '' + ' ' + '
' + ''; this._element.innerHTML = innerHTML; var commandingSurface = new _CommandingSurface(this._element, { opened: false }); Helper._CommandingSurface.useSynchronousAnimations(commandingSurface); commandingSurface.open(); LiveUnit.LoggingCore.logComment("Verify that first and last tabStop have tabIndex === 0, " + "when the control is opened"); var firstTabStopIndex = 0; var finalTabStopIndex = 0; verifyTabIndices(commandingSurface, firstTabStopIndex, finalTabStopIndex); } testAriaFlowAttributes() { var commandingSurface = new _CommandingSurface(this._element, { opened: false }); Helper._CommandingSurface.useSynchronousAnimations(commandingSurface); LiveUnit.Assert.isFalse(commandingSurface._dom.firstTabStop.hasAttribute("x-ms-aria-flowfrom"), "aria-flowfrom should not be set, while closed"); LiveUnit.Assert.isFalse(commandingSurface._dom.finalTabStop.hasAttribute("aria-flowto"), "aria-flowto should not be set, while closed"); commandingSurface.opened = true; LiveUnit.Assert.areEqual(commandingSurface._dom.finalTabStop.id, commandingSurface._dom.firstTabStop.getAttribute("x-ms-aria-flowfrom"), "first tab stop should flow from final tab stop, while opened"); LiveUnit.Assert.areEqual(commandingSurface._dom.firstTabStop.id, commandingSurface._dom.finalTabStop.getAttribute("aria-flowto"), "final tab stop should flow to first tab stop, while opened"); } testDomLevel0_OpenCloseEvents() { testEvents(this._element, (commandingSurface: WinJS.UI.PrivateCommandingSurface, eventName: string, handler: Function) => { commandingSurface["on" + eventName] = handler; }); } testDomLevel2_OpenCloseEvents() { testEvents(this._element, (commandingSurface: WinJS.UI.PrivateCommandingSurface, eventName: string, handler: Function) => { commandingSurface.addEventListener(eventName, handler); }); } testBeforeOpenIsCancelable() { var commandingSurface = new _CommandingSurface(this._element, { opened: false }); Helper._CommandingSurface.useSynchronousAnimations(commandingSurface); commandingSurface.onbeforeopen = function (eventObject) { eventObject.preventDefault(); }; commandingSurface.onafteropen = function (eventObject) { LiveUnit.Assert.fail("afteropen shouldn't have fired due to beforeopen being canceled"); }; commandingSurface.open(); LiveUnit.Assert.isFalse(commandingSurface.opened, "CommandingSurface should still be closed"); commandingSurface.opened = true; LiveUnit.Assert.isFalse(commandingSurface.opened, "CommandingSurface should still be closed"); } testBeforeCloseIsCancelable() { var commandingSurface = new _CommandingSurface(this._element, { opened: true }); Helper._CommandingSurface.useSynchronousAnimations(commandingSurface); commandingSurface.onbeforeclose = function (eventObject) { eventObject.preventDefault(); }; commandingSurface.onafterclose = function (eventObject) { LiveUnit.Assert.fail("afterclose shouldn't have fired due to beforeclose being canceled"); }; commandingSurface.close(); LiveUnit.Assert.isTrue(commandingSurface.opened, "CommandingSurface should still be open"); commandingSurface.opened = false; LiveUnit.Assert.isTrue(commandingSurface.opened, "CommandingSurface should still be open"); } testOverflowDirectionConstructorOptions() { var commandingSurface = new _CommandingSurface(); LiveUnit.Assert.areEqual(_Constants.defaultOverflowDirection, commandingSurface.overflowDirection, "overflowDirection property has incorrect default value"); commandingSurface.dispose(); Object.keys(_CommandingSurface.OverflowDirection).forEach(function (direction) { commandingSurface = new _CommandingSurface(null, { overflowDirection: direction }); LiveUnit.Assert.areEqual(direction, commandingSurface.overflowDirection, "overflowDirection does not match the value passed to the constructor."); commandingSurface.dispose(); }); } testOverflowDirectionProperty() { var data = new WinJS.Binding.List([ new Command(null, { type: _Constants.typeButton, icon: 'add', label: "button" }), new Command(null, { type: _Constants.typeSeparator }), new Command(null, { type: _Constants.typeButton, section: 'secondary', label: "secondary" }) ]); var commandingSurface = new _CommandingSurface(this._element, { data: data, opened: false }); Helper._CommandingSurface.useSynchronousAnimations(commandingSurface); commandingSurface.element.style.top = "45%"; Object.keys(_CommandingSurface.OverflowDirection).forEach(function (overflowDirection) { commandingSurface.overflowDirection = overflowDirection; LiveUnit.Assert.areEqual(overflowDirection, commandingSurface.overflowDirection, "overflowDirection property should be writeable."); commandingSurface.open(); var actionAreaRect = commandingSurface._dom.actionArea.getBoundingClientRect(); var overflowAreaRect = commandingSurface._dom.overflowArea.getBoundingClientRect(); switch (overflowDirection) { case _CommandingSurface.OverflowDirection.top: // Bottom of the overflowArea is drawn at the top of the actionArea LiveUnit.Assert.areEqual(overflowAreaRect.bottom, actionAreaRect.top); break; case _CommandingSurface.OverflowDirection.bottom: // Top of the overflowArea is drawn at the bottom of the actionArea LiveUnit.Assert.areEqual(overflowAreaRect.top, actionAreaRect.bottom); break; default: LiveUnit.Assert.fail("TEST ERROR: Encountered unknown OverflowDirection enum value: " + overflowDirection); break; } commandingSurface.close(); }); } testOverflowAreaHorizontalAlignment() { ["LTR", "RTL"].forEach((direction: string) => { var edgeOfViewport, offsetCommandingSurfaceBy, left, right, Left, Right, prevLang = document.documentElement.lang; if (direction === "LTR") { document.documentElement.lang = "en-us"; edgeOfViewport = 0; offsetCommandingSurfaceBy = 10; right = "right"; left = "left"; Right = "Right"; Left = "Left"; } else { document.documentElement.lang = "ar-sa"; offsetCommandingSurfaceBy = -10; edgeOfViewport = window.innerWidth; right = "left"; left = "right"; Right = "Left"; Left = "Right"; } LiveUnit.LoggingCore.logComment( "When the " + direction + " CommandingSurface is opening, the overflowarea will typically align its " + right + " edge with the " + right + " edge of the CommandingSurface, " + "However, if while trying to align this way, part of the overflowarea would clip through the " + left + " edge of the viewport, then the " + "overflowarea should instead align its " + left + " edge to the " + left + " edge of the viewport." ); var data = new WinJS.Binding.List([ new Command(null, { type: _Constants.typeButton, section: _Constants.secondaryCommandSection, label: "opt 1" }), ]); var initialMargin = Math.abs(offsetCommandingSurfaceBy); var el = document.createElement("DIV"); el.style.width = "10px"; el.style["margin" + Left] = initialMargin + "px"; document.body.appendChild(el); var commandingSurface = new _CommandingSurface(el, { data: data, overflowDirection: _CommandingSurface.OverflowDirection.bottom }); Helper._CommandingSurface.useSynchronousAnimations(commandingSurface); // Measure commandingSurface.open(); var overflowArea = commandingSurface._dom.overflowArea, commandingSurfaceRect = el.getBoundingClientRect(), overflowAreaRect = overflowArea.getBoundingClientRect(); LiveUnit.LoggingCore.logComment( "Verify that we start from a sane place. " + "Test that there is " + initialMargin + " space between the " + left + " edge of the CommandingSurface and the " + left + " edge of the view. " + "Test that the overflowarea width with one command is greater than the " + left + " offset of the commandingsurface width with no commands." ); Helper.Assert.areFloatsEqual(edgeOfViewport + offsetCommandingSurfaceBy, commandingSurfaceRect[left], "TEST ERROR: " + direction + " Test expects the CommandingSurface to be " + initialMargin + " from the " + left + " edge of the view.", 1); LiveUnit.Assert.isTrue(commandingSurfaceRect.width + 10 < overflowAreaRect.width, "TEST ERROR: " + direction + " Test expects the overflowarea to be wider than the CommandingSurface + " + initialMargin + "."); LiveUnit.LoggingCore.logComment( "Because there is NOT enough room to display the " + right + " aligned overflowarea without clipping through the " + left + " edge of the viewport, " + "verify that overflowarea " + left + " edge is instead aligned to the " + left + " edge of the viewport." ); Helper.Assert.areFloatsEqual(edgeOfViewport, overflowAreaRect[left], "OverflowArea in " + direction + " should align its " + left + " edge with the " + left + " edge of the viewport to avoid clipping through it", 1); LiveUnit.LoggingCore.logComment( "Move the CommandingSurface further away from the " + left + " edge." ); commandingSurface.close(); commandingSurface.element.style["margin" + Left] = overflowAreaRect.width + "px"; // Re Measure commandingSurface.open(); commandingSurfaceRect = el.getBoundingClientRect(), overflowAreaRect = overflowArea.getBoundingClientRect(); LiveUnit.LoggingCore.logComment( "Because there IS now enough room to display the " + right + " aligned overflowarea without clipping through the " + left + " edge of the viewport, " + "verify that overflowarea " + right + " edge is aligned to the " + right + " edge of the CommandingSurface." ); LiveUnit.Assert.areEqual(commandingSurfaceRect[right], overflowAreaRect[right], direction + " OverflowArea should be " + right + " aligned with the CommandingSurface"); // Cleanup el.parentElement.removeChild(el); commandingSurface.dispose(); document.documentElement.lang = prevLang; }); } testGetCommandById() { var data = new WinJS.Binding.List([ new Command(null, { type: _Constants.typeButton, label: "A", id: "extraneous" }) ]); this._element.style.width = "10px"; var commandingSurface = new _CommandingSurface(this._element, { data: data }); LiveUnit.Assert.isNull(commandingSurface.getCommandById("someID")); var firstAddedCommand = new Command(null, { type: _Constants.typeButton, label: "B", id: "someID" }); data.push(firstAddedCommand); LiveUnit.Assert.areEqual(firstAddedCommand, commandingSurface.getCommandById("someID")); var secondAddedCommand = new Command(null, { type: _Constants.typeButton, label: "C", id: "someID" }); data.push(secondAddedCommand); LiveUnit.Assert.areEqual(firstAddedCommand, commandingSurface.getCommandById("someID")); } testShowOnlyCommands(complete) { var data = new WinJS.Binding.List([ new Command(null, { type: _Constants.typeButton, label: "A", id: "A" }), new Command(null, { type: _Constants.typeButton, label: "B", id: "B" }), new Command(null, { type: _Constants.typeButton, label: "C", id: "C", section: "secondary" }), new Command(null, { type: _Constants.typeButton, label: "D", id: "D" }), new Command(null, { type: _Constants.typeButton, label: "E", id: "E" }) ]); this._element.style.width = "1000px"; var commandingSurface = new _CommandingSurface(this._element, { data: data }); function checkCommandVisibility(expectedShown, expectedHidden) { return new WinJS.Promise(c => { commandingSurface._layoutCompleteCallback = function () { for (var i = 0, len = expectedShown.length; i < len; i++) { var shownCommand = commandingSurface.getCommandById(expectedShown[i]); LiveUnit.Assert.isFalse(shownCommand.hidden); if (shownCommand.section === "secondary") { LiveUnit.Assert.areEqual("none", getComputedStyle(shownCommand.element).display); var overflowAreaCommands = Helper._CommandingSurface.getVisibleCommandsInElement(commandingSurface._dom.overflowArea); LiveUnit.Assert.areEqual(shownCommand.label, overflowAreaCommands[0].winControl.label); } else { LiveUnit.Assert.areEqual("inline-block", getComputedStyle(shownCommand.element).display); } } for (var i = 0, len = expectedHidden.length; i < len; i++) { var hiddenCommand = commandingSurface.getCommandById(expectedHidden[i]); LiveUnit.Assert.isTrue(hiddenCommand.hidden); LiveUnit.Assert.areEqual("none", getComputedStyle(hiddenCommand.element).display); } c(); }; }); } commandingSurface.showOnlyCommands([]); checkCommandVisibility([], ["A", "B", "C", "D", "E"]).then( () => { commandingSurface.showOnlyCommands(["A", "B", "C", "D", "E"]); return checkCommandVisibility(["A", "B", "C", "D", "E"], []); }).then(() => { commandingSurface.showOnlyCommands(["A"]); return checkCommandVisibility(["A"], ["B", "C", "D", "E"]); }).then(() => { commandingSurface.showOnlyCommands([data.getAt(1)]); return checkCommandVisibility(["B"], ["A", "C", "D", "E"]); }).then(() => { commandingSurface.showOnlyCommands(["C", data.getAt(4)]); checkCommandVisibility(["C", "E"], ["A", "B", "D"]); }).done(complete); } testThatHiddenCommandsDoNotAppearVisible(complete) { // Regression test for https://github.com/winjs/winjs/issues/915 var p0 = new Command(null, { id: "p0", label: "p0", type: _Constants.typeButton, section: "primary", hidden: false }); var p1 = new Command(null, { id: "p1", label: "p1", type: _Constants.typeButton, section: "primary", hidden: false }); var p2 = new Command(null, { id: "p2", label: "p2", type: _Constants.typeButton, section: "primary", hidden: true }); var s0 = new Command(null, { id: "s0", label: "s0", type: _Constants.typeButton, section: "secondary", hidden: false }); var s1 = new Command(null, { id: "s1", label: "s1", type: _Constants.typeButton, section: "secondary", hidden: true }); this._element.style.width = "1000px"; var commandingSurface = new _CommandingSurface(this._element, { data: new WinJS.Binding.List([p0, p1, p2, s0, s1]) }); var actionAreaCommands = Helper._CommandingSurface.getVisibleCommandsInElement(commandingSurface._dom.actionArea); var overflowAreaCommands = Helper._CommandingSurface.getVisibleCommandsInElement(commandingSurface._dom.overflowArea); // The actionarea should only show | p0 | p1 | ... | LiveUnit.Assert.areEqual(2, actionAreaCommands.length, "actionarea should display 2 command"); LiveUnit.Assert.areEqual(p0.label, actionAreaCommands[0].winControl.label); LiveUnit.Assert.areEqual(p1.label, actionAreaCommands[1].winControl.label); // The overflowarea should only show | s0 | LiveUnit.Assert.areEqual(1, overflowAreaCommands.length, "overflowarea should display 1 command"); LiveUnit.Assert.areEqual(s0.label, overflowAreaCommands[0].winControl.label); new WinJS.Promise((c) => { commandingSurface._layoutCompleteCallback = () => { actionAreaCommands = Helper._CommandingSurface.getVisibleCommandsInElement(commandingSurface._dom.actionArea); overflowAreaCommands = Helper._CommandingSurface.getVisibleCommandsInElement(commandingSurface._dom.overflowArea); // The actionarea should not show any commands LiveUnit.Assert.areEqual(0, actionAreaCommands.length, "actionarea should display 0 command"); // The overflowarea should show | p0 | p1 | separator | s0 | LiveUnit.Assert.areEqual(4, overflowAreaCommands.length, "overflowarea should display 4 command"); LiveUnit.Assert.areEqual(p0.label, overflowAreaCommands[0].winControl.label); LiveUnit.Assert.areEqual(p1.label, overflowAreaCommands[1].winControl.label); LiveUnit.Assert.areEqual(_Constants.typeSeparator, overflowAreaCommands[2].winControl.type); LiveUnit.Assert.areEqual(s0.label, overflowAreaCommands[3].winControl.label); c(); }; // Overflow everything this._element.style.width = "10px"; commandingSurface.forceLayout(); }).done(complete); } } } LiveUnit.registerTestClass("CorsicaTests._CommandingSurfaceTests");