UNPKG

gpii-windows

Version:

Components of the GPII personalization infrastructure for use on Microsoft's "Windows" ™

629 lines (580 loc) 18.7 kB
/* * Tests for Application Zoom * * Copyright 2015 Raising the Floor - International * * Licensed under the New BSD license. You may not use this file except in * compliance with this License. * * The research leading to these results has received funding from the European Union's * Seventh Framework Programme (FP7/2007-2013) * under grant agreement no. 289016. * * You may obtain a copy of the License at * https://github.com/GPII/universal/blob/master/LICENSE.txt */ "use strict"; var fluid = require("gpii-universal"); var jqUnit = fluid.require("node-jqunit"); var gpii = fluid.registerNamespace("gpii"); var ffi = require("ffi-napi"); require("../src/appZoom.js"); require("../../../../tests/TestWithMocks.js"); fluid.registerNamespace("gpii.tests.windows.appZoom"); var teardowns = []; jqUnit.module("gpii.tests.windows.appZoom", { setup: function () { }, teardown: function () { while (teardowns.length) { teardowns.pop()(); } } }); gpii.tests.windows.appZoom.user32 = ffi.Library("user32", { // https://msdn.microsoft.com/library/ms646301 "GetKeyState": [ "short", ["int"] ] }); gpii.tests.windows.appZoom.testConfigs = fluid.freezeRecursive([ { id: "mouse wheel", config: { wheel: {} } }, { id: "ctrl + mouse wheel", config: { wheel: {}, ctrl: true } }, { id: "keyboard", config: { key: { decrease: "-", increase: "=" } } }, { id: "ctrl + keyboard", config: { key: { decrease: "A", increase: "Z" }, ctrl: true } }, { id: "mouse wheel, getForegroundWindow", config: { wheel: {}, getForegroundWindow: true } } ]); gpii.windows.messages.messagePumpDelay = 100; jqUnit.asyncTest("Send zoom", function () { var testData = gpii.tests.windows.appZoom.testConfigs; var currentTest; var currentTestPromise; var testIndex = 0; var gotKeyDown = false; var appZoom; // Expand the tests to test increase and decrease. var allTests = []; fluid.each(testData, function (test) { allTests.push(Object.assign({direction: "increase"}, test)); allTests.push(Object.assign({direction: "decrease"}, test)); jqUnit.expect(6 * (test.config.key ? 2 : 1)); }); // Start the next test. var nextTest = function () { currentTest = allTests[testIndex++]; currentTestPromise = fluid.promise(); if (currentTest) { fluid.log("test: " + currentTest.id); gotKeyDown = false; appZoom.currentWindow = { hwnd: appZoom.getMessageWindow(), config: currentTest.config }; // Set control keys to a known state (depressed). gpii.windows.user32.keybd_event(gpii.windows.API_constants.virtualKeyCodes.VK_CONTROL, 0, 2, 0); gpii.windows.user32.keybd_event(gpii.windows.API_constants.virtualKeyCodes.VK_CONTROL, 0, 3, 0); // Send the zoom command. fluid.promise.sequence([ appZoom.sendZoom(currentTest.direction), currentTestPromise ]).then(nextTest); } else { appZoom.destroy(); jqUnit.start(); } }; appZoom = gpii.windows.appZoom({ listeners: { // The message window is the recipient of the zoom messages. "{gpii.windows.messages}.events.onMessage": function (hwnd, msg, wp) { var handled = false; switch (msg) { case gpii.windows.API_constants.WM_MOUSEWHEEL: jqUnit.assertTrue("WM_MOUSEWHEEL should only be received if testing the mouse wheel", !!currentTest.config.wheel); // Extract the scroll amount, and make it a signed short var amount = gpii.windows.hiWord(wp); if (amount & 0x8000) { amount -= 0x10000; } var dir = amount && (amount > 0 ? "increase" : "decrease"); jqUnit.assertEquals("WM_MOUSEWHEEL scroll direction should match the test direction.", currentTest.direction, dir); handled = true; break; case gpii.windows.API_constants.WM_KEYDOWN: jqUnit.assertTrue("WM_KEYDOWN should only be received if testing keys", !!currentTest.config.key); var expectedChar = currentTest.config.key[currentTest.direction]; var charCode = gpii.windows.user32.MapVirtualKeyW(wp, gpii.windows.API_constants.MAPVK_VK_TO_CHAR); var char = String.fromCharCode(charCode); jqUnit.assertEquals("WM_KEYDOWN should be the correct key for the direction", expectedChar, char); gotKeyDown = true; handled = true; break; case gpii.windows.API_constants.WM_KEYUP: jqUnit.assertTrue("WM_KEYUP should only be received if testing keys", !!currentTest.config.key); jqUnit.assertTrue("WM_KEYUP should be received after WM_KEYDOWN", gotKeyDown); handled = true; break; default: // Ignore anything else. break; } if (handled) { var ctrlDown = !!(gpii.tests.windows.appZoom.user32.GetKeyState( gpii.windows.API_constants.virtualKeyCodes.VK_CONTROL) & 0x8000); jqUnit.assertEquals("Control key should only be down if configured", !!currentTest.config.ctrl, ctrlDown); if (msg !== gpii.windows.API_constants.WM_KEYDOWN) { currentTestPromise.resolve(); } } } } }); nextTest(); }); jqUnit.test("Testing Invalid Zoom Direction", function () { var appZoom = gpii.windows.appZoom({}); appZoom.currentWindow = { hwnd: appZoom.getMessageWindow(), config: {} }; jqUnit.expectFrameworkDiagnostic("Should fail due to bad zoom direction", function () { appZoom.sendZoom("InvalidDirection"); }, "sendZoom: direction should be either 'decrease' or 'increase'"); }); jqUnit.test("Testing Send Zoom on Min Window", function () { var that = { currentWindow: { hwnd: "SimulatedWindow" } }; gpii.windows.tests.testWithMocks([{ "original": { obj: gpii, path: "windows.user32.IsIconic" }, "mock": function () { return true; } }], function () { var promise = gpii.windows.appZoom.sendZoom(that, "decrease"); jqUnit.assertEquals("Promise should resolve", "resolve", promise.disposition); }, function (e) { jqUnit.fail("Error sending zoom with the following exception: " + e); }); }); jqUnit.test("Testing Send Zoom with Child Window", function () { var that = { currentWindow: { hwnd: "SimulatedWindow", config: { childWindow: "InvalidChildWindow" } } }; var hwnd; gpii.windows.tests.testWithMocks([{ "original": { obj: gpii, path: "windows.user32.IsIconic" }, "mock": function () { return false; } }, { "original": { obj: gpii, path: "windows.appZoom.findChildWindow" }, "mock": function () { hwnd = 123; return hwnd; } }], function () { gpii.windows.appZoom.sendZoom(that, "decrease"); jqUnit.assertEquals("Window handle should equal mocked id", 123, hwnd); }, function (e) { jqUnit.fail("Error sending zoom with the following exception: " + e); }); }); jqUnit.test("Testing Child Window Not Found", function () { var currentWindow = { hwnd: "Parent", config: { childWindow: "InvalidChildWindow" } }; var hwnd = gpii.windows.appZoom.findChildWindow(currentWindow, currentWindow.config); jqUnit.assertNull("Child window should not be found", hwnd); }); jqUnit.test("Testing Child Window Not Found (no Config)", function () { var that = { currentWindow: { hwnd: "SimulatedWindow" } }; gpii.windows.tests.testWithMocks([{ "original": { obj: gpii, path: "windows.user32.IsIconic" }, "mock": function () { return false; } }], function () { var promise = gpii.windows.appZoom.sendZoom(that, "decrease"); jqUnit.assertEquals("Promise should resolve", "reject", promise.disposition); }, function (e) { jqUnit.fail("Error sending zoom with the following exception: " + e); }); }); jqUnit.test("Testing Active Window", function () { var that = { activeWindow: { hwnd: "SimulatedWindow" }, events: { onApplicationActivated: { fire: function (obj, currentWindow) { activeWindow = currentWindow.currentWindow; } } }, currentWindow: { hwnd: "SimulatedWindow" }, getConfig: function () { return { ignore: false, getForegroundWindow: true }; } }; var activeWindow; gpii.windows.tests.testWithMocks([{ "original": { obj: gpii, path: "windows.appZoom.getWindowInfo" }, "mock": function () { return { pid: -1, currentWindow: that.currentWindow }; } }], function () { gpii.windows.appZoom.windowActivated(that, "SimulatedWindow"); jqUnit.assertEquals("Active Window Properly Identified", "SimulatedWindow", activeWindow.hwnd); }, function (e) { jqUnit.fail("Error detecting active window with the following exception: " + e); }); }); jqUnit.test("Testing Send Wheel", function () { var currentWindow = { config: { wheel: { simulate: true } } }; var currentPosition; gpii.windows.tests.testWithMocks([{ "original": { obj: gpii, path: "windows.user32.SetCursorPos" }, "mock": function (x, y) { currentPosition = {x: x, y: y}; } }], function () { gpii.windows.appZoom.sendWheel("SimulatedWindow", -1, currentWindow); jqUnit.assertNotNull("Simulates wheel as expected", currentPosition); }, function (e) { jqUnit.fail("Error simulating wheel with the following exception: " + e); }); }); jqUnit.test("Testing Get Config", function () { var that = { getWindowInfo: function () { return {}; }, options: { configurations: { generic: { test: "data" } } } }; var config = gpii.windows.appZoom.getConfig(that, "SimulatedWindow"); jqUnit.assertDeepEq("Config as expected", config, {test: "data"}); }); jqUnit.test("Testing Get Window Info", function () { gpii.windows.tests.testWithMocks([{ "original": { obj: gpii, path: "windows.getWindowProcessId" }, "mock": function () { return 1; } }], function () { var windowInfo = gpii.windows.appZoom.getWindowInfo("SimulatedWindow"); jqUnit.assertDeepEq("Successfully got window info", windowInfo, {hwnd: "SimulatedWindow", pid: 1, exe: null}); }, function (e) { jqUnit.fail("Error getting window info with the following exception: " + e); }); }); jqUnit.test("Testing Set Control Key State (down)", function () { var keyState; gpii.windows.tests.testWithMocks([{ "original": { obj: gpii, path: "windows.user32.keybd_event" }, "mock": function () { keyState = arguments[2]; } }], function () { gpii.windows.appZoom.setControlKeyState(true); jqUnit.assertEquals("Keyboard flags zero on down", 0, keyState); }, function (e) { jqUnit.fail("Error setting keyState with the following exception: " + e); }); }); jqUnit.test("Testing Set Control Key State (up)", function () { var keyState; gpii.windows.tests.testWithMocks([{ "original": { obj: gpii, path: "windows.user32.keybd_event" }, "mock": function () { keyState = arguments[2]; } }], function () { gpii.windows.appZoom.setControlKeyState(false); jqUnit.assertEquals("Keyboard flags 3 on up", 3, keyState); }, function (e) { jqUnit.fail("Error setting keyState with the following exception: " + e); }); }); jqUnit.test("Testing Find Uncovered Point", function () { gpii.windows.tests.testWithMocks([{ "original": { obj: gpii, path: "windows.getWindowRect" }, "mock": function () { return { left: 20, right: 20, top: 20, bottom: 20 }; } }], function () { var rect = { left: 10, right: 100, top: 10, bottom: 100 }; var centre = { x: 100, y: 100 }; var points = gpii.windows.appZoom.getOverlappingPoints(rect, centre, "windowOver"); jqUnit.assertDeepEq("Points should be properly populated", points, [ {x: 19, y: 100}, {x: 100, y: 19}, {x: 20, y: 100}, {x: 100, y: 20} ]); }, function (e) { jqUnit.fail("Error populating points with the following exception: " + e); }); }); jqUnit.test("Testing Find Uncovered Point (single point)", function () { gpii.windows.tests.testWithMocks([{ "original": { obj: gpii, path: "windows.getWindowRect" }, "mock": function () { return { left: 20, right: 20, top: 20, bottom: 20 }; } }, { "original": { obj: gpii, path: "windows.appZoom.getOverlappingPoints" }, "mock": function () { return [{x: 19, y: 100}]; } }, { "original": { obj: gpii, path: "windows.getWindowProcessId" }, "mock": function () { return 1; } }], function () { var window = { pid: 15 }; var points = gpii.windows.appZoom.findUncoveredPoint("SimulatedWindow", window); jqUnit.assertDeepEq("Point should be properly populated", points, { x: 19, y: 100 }); }, function (e) { jqUnit.fail("Error populating points with the following exception: " + e); }); }); jqUnit.test("Testing Find Uncovered Point (single point)", function () { gpii.windows.tests.testWithMocks([{ "original": { obj: gpii, path: "windows.getWindowRect" }, "mock": function () { return { left: 20, right: 20, top: 20, bottom: 20 }; } }, { "original": { obj: gpii, path: "windows.appZoom.getOverlappingPoints" }, "mock": function () { return [ {x: 19, y: 100}, {x: 100, y: 19}, {x: 20, y: 100}, {x: 100, y: 20} ]; } }, { "original": { obj: gpii, path: "windows.getWindowProcessId" }, "mock": function () { return 1; } }], function () { var window = { pid: 15 }; var points = gpii.windows.appZoom.findUncoveredPoint("SimulatedWindow", window); jqUnit.assertDeepEq("Point should be properly populated", points, { x: 19, y: 100 }); }, function (e) { jqUnit.fail("Error populating points with the following exception: " + e); }); }); jqUnit.test("Testing Window Message", function () { gpii.windows.tests.testWithMocks([{ "original": { obj: process, path: "nextTick" }, "mock": function (callback, param) { callback(param); } }], function () { var debug; var msg = gpii.windows.API_constants.WM_SHELLHOOK; var lParam = { address: function () { return 456; } }; var that = { windowActivated: function () { debug = 123; } }; gpii.windows.appZoom.windowMessage(that, "SimulatedWindow", msg, 4, lParam); jqUnit.assertEquals("Debug var should be set by callback", 123, debug); }, function (e) { jqUnit.fail("Error sending window message with the following exception: " + e); }); }); jqUnit.test("Testing Window Message", function () { gpii.windows.tests.testWithMocks([{ "original": { obj: process, path: "nextTick" }, "mock": function (callback, param) { callback(param); } }], function () { var debug; var msg = gpii.windows.API_constants.WM_SHELLHOOK; var lParam = { address: function () { return 456; } }; var that = { windowActivated: function () { debug = 123; } }; gpii.windows.appZoom.windowMessage(that, "SimulatedWindow", msg, 0x8004, lParam); jqUnit.assertEquals("Debug var should be set by callback", 123, debug); }, function (e) { jqUnit.fail("Error sending window message with the following exception: " + e); }); });