forked from mirrors/gecko-dev
		
	 3dfa3a3d4c
			
		
	
	
		3dfa3a3d4c
		
	
	
	
	
		
			
			On X11 `mozInnerScreenX/Y` are ignored for the first test that runs in a new popup. For Wayland positions during resize tests are ignored, and `browser_popup_linux_move.js` is just a todo checking whether we can move a window at all. Also allows to run the tests with `resizeTo` and `moveTo` when size and position property setters are disabled. Differential Revision: https://phabricator.services.mozilla.com/D169963
		
			
				
	
	
		
			573 lines
		
	
	
	
		
			17 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			573 lines
		
	
	
	
		
			17 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| /* Any copyright is dedicated to the Public Domain.
 | |
|    http://creativecommons.org/publicdomain/zero/1.0/ */
 | |
| 
 | |
| "use strict";
 | |
| 
 | |
| const gfxInfo = Cc["@mozilla.org/gfx/info;1"].getService(
 | |
|   SpecialPowers.Ci.nsIGfxInfo
 | |
| );
 | |
| 
 | |
| async function waitForBlockedPopups(numberOfPopups, { doc }) {
 | |
|   let toolbarDoc = doc || document;
 | |
|   let menupopup = toolbarDoc.getElementById("blockedPopupOptions");
 | |
|   await BrowserTestUtils.waitForCondition(() => {
 | |
|     let popups = menupopup.querySelectorAll("[popupReportIndex]");
 | |
|     return popups.length == numberOfPopups;
 | |
|   }, `Waiting for ${numberOfPopups} popups`);
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * Tests that a sequence of size changes ultimately results in the latest
 | |
|  * requested size. The test also fails when an unexpected window size is
 | |
|  * observed in a resize event.
 | |
|  *
 | |
|  * aPropertyDeltas    List of objects where keys describe the name of a window
 | |
|  *                    property and the values the difference to its initial
 | |
|  *                    value.
 | |
|  *
 | |
|  * aInstant           Issue changes without additional waiting in between.
 | |
|  *
 | |
|  * A brief example of the resutling code that is effectively run for the
 | |
|  * following list of deltas:
 | |
|  * [{outerWidth: 5, outerHeight: 10}, {outerWidth: 10}]
 | |
|  *
 | |
|  * let initialWidth = win.outerWidth;
 | |
|  * let initialHeight = win.outerHeight;
 | |
|  *
 | |
|  * if (aInstant) {
 | |
|  *   win.outerWidth = initialWidth + 5;
 | |
|  *   win.outerHeight = initialHeight + 10;
 | |
|  *
 | |
|  *   win.outerWidth = initialWidth + 10;
 | |
|  * } else {
 | |
|  *   win.requestAnimationFrame(() => {
 | |
|  *     win.outerWidth = initialWidth + 5;
 | |
|  *     win.outerHeight = initialHeight + 10;
 | |
|  *
 | |
|  *     win.requestAnimationFrame(() => {
 | |
|  *        win.outerWidth = initialWidth + 10;
 | |
|  *     });
 | |
|  *   });
 | |
|  * }
 | |
|  */
 | |
| async function testPropertyDeltas(
 | |
|   aPropertyDeltas,
 | |
|   aInstant,
 | |
|   aPropInfo,
 | |
|   aMsg,
 | |
|   aWaitForCompletion
 | |
| ) {
 | |
|   let msg = `[${aMsg}]`;
 | |
| 
 | |
|   let win = this.content.popup || this.content.wrappedJSObject;
 | |
| 
 | |
|   // Property names and mapping from ResizeMoveTest
 | |
|   let {
 | |
|     sizeProps,
 | |
|     positionProps /* can be empty/incomplete as workaround on Linux */,
 | |
|     readonlyProps,
 | |
|     crossBoundsMapping,
 | |
|   } = aPropInfo;
 | |
| 
 | |
|   let stringifyState = state => {
 | |
|     let stateMsg = sizeProps
 | |
|       .concat(positionProps)
 | |
|       .filter(prop => state[prop] !== undefined)
 | |
|       .map(prop => `${prop}: ${state[prop]}`)
 | |
|       .join(", ");
 | |
|     return `{ ${stateMsg} }`;
 | |
|   };
 | |
| 
 | |
|   let initialState = {};
 | |
|   let finalState = {};
 | |
| 
 | |
|   info("Initializing all values to current state.");
 | |
|   for (let prop of sizeProps.concat(positionProps)) {
 | |
|     let value = win[prop];
 | |
|     initialState[prop] = value;
 | |
|     finalState[prop] = value;
 | |
|   }
 | |
| 
 | |
|   // List of potential states during resize events. The current state is also
 | |
|   // considered valid, as the resize event might still be outstanding.
 | |
|   let validResizeStates = [initialState];
 | |
| 
 | |
|   let updateFinalState = (aProp, aDelta) => {
 | |
|     if (
 | |
|       readonlyProps.includes(aProp) ||
 | |
|       !sizeProps.concat(positionProps).includes(aProp)
 | |
|     ) {
 | |
|       throw new Error(`Unexpected property "${aProp}".`);
 | |
|     }
 | |
| 
 | |
|     // Update both properties of the same axis.
 | |
|     let otherProp = crossBoundsMapping[aProp];
 | |
|     finalState[aProp] = initialState[aProp] + aDelta;
 | |
|     finalState[otherProp] = initialState[otherProp] + aDelta;
 | |
| 
 | |
|     // Mark size as valid in resize event.
 | |
|     if (sizeProps.includes(aProp)) {
 | |
|       let state = {};
 | |
|       sizeProps.forEach(p => (state[p] = finalState[p]));
 | |
|       validResizeStates.push(state);
 | |
|     }
 | |
|   };
 | |
| 
 | |
|   info("Adding resize event listener.");
 | |
|   let resizeCount = 0;
 | |
|   let resizeListener = evt => {
 | |
|     resizeCount++;
 | |
| 
 | |
|     let currentSizeState = {};
 | |
|     sizeProps.forEach(p => (currentSizeState[p] = win[p]));
 | |
| 
 | |
|     info(
 | |
|       `${msg} ${resizeCount}. resize event: ${stringifyState(currentSizeState)}`
 | |
|     );
 | |
|     let matchingIndex = validResizeStates.findIndex(state =>
 | |
|       sizeProps.every(p => state[p] == currentSizeState[p])
 | |
|     );
 | |
|     if (matchingIndex < 0) {
 | |
|       info(`${msg} Size state should have been one of:`);
 | |
|       for (let state of validResizeStates) {
 | |
|         info(stringifyState(state));
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     if (win.gBrowser && evt.target != win) {
 | |
|       // Without e10s we receive content resize events in chrome windows.
 | |
|       todo(false, `${msg} Resize event target is our window.`);
 | |
|       return;
 | |
|     }
 | |
| 
 | |
|     ok(
 | |
|       matchingIndex >= 0,
 | |
|       `${msg} Valid intermediate state. Current: ` +
 | |
|         stringifyState(currentSizeState)
 | |
|     );
 | |
| 
 | |
|     // No longer allow current and preceding states.
 | |
|     validResizeStates.splice(0, matchingIndex + 1);
 | |
|   };
 | |
|   win.addEventListener("resize", resizeListener);
 | |
| 
 | |
|   const useProperties = !Services.prefs.getBoolPref(
 | |
|     "dom.window_position_size_properties_replaceable.enabled",
 | |
|     true
 | |
|   );
 | |
| 
 | |
|   info("Starting property changes.");
 | |
|   await new Promise(resolve => {
 | |
|     let index = 0;
 | |
|     let next = async () => {
 | |
|       let pre = `${msg} [${index + 1}/${aPropertyDeltas.length}]`;
 | |
| 
 | |
|       let deltaObj = aPropertyDeltas[index];
 | |
|       for (let prop in deltaObj) {
 | |
|         updateFinalState(prop, deltaObj[prop]);
 | |
| 
 | |
|         let targetValue = initialState[prop] + deltaObj[prop];
 | |
|         info(`${pre} Setting ${prop} to ${targetValue}.`);
 | |
|         if (useProperties) {
 | |
|           win[prop] = targetValue;
 | |
|         } else if (sizeProps.includes(prop)) {
 | |
|           win.resizeTo(finalState.outerWidth, finalState.outerHeight);
 | |
|         } else {
 | |
|           win.moveTo(finalState.screenX, finalState.screenY);
 | |
|         }
 | |
|         if (aWaitForCompletion) {
 | |
|           await ContentTaskUtils.waitForCondition(
 | |
|             () => win[prop] == targetValue,
 | |
|             `${msg} Waiting for ${prop} to be ${targetValue}.`
 | |
|           );
 | |
|         }
 | |
|       }
 | |
| 
 | |
|       index++;
 | |
|       if (index < aPropertyDeltas.length) {
 | |
|         scheduleNext();
 | |
|       } else {
 | |
|         resolve();
 | |
|       }
 | |
|     };
 | |
| 
 | |
|     let scheduleNext = () => {
 | |
|       if (aInstant) {
 | |
|         next();
 | |
|       } else {
 | |
|         info(`${msg} Requesting animation frame.`);
 | |
|         win.requestAnimationFrame(next);
 | |
|       }
 | |
|     };
 | |
|     scheduleNext();
 | |
|   });
 | |
| 
 | |
|   try {
 | |
|     info(`${msg} Waiting for window to match the final state.`);
 | |
|     await ContentTaskUtils.waitForCondition(
 | |
|       () => sizeProps.concat(positionProps).every(p => win[p] == finalState[p]),
 | |
|       "Waiting for final state."
 | |
|     );
 | |
|   } catch (e) {}
 | |
| 
 | |
|   info(`${msg} Checking final state.`);
 | |
|   info(`${msg} Exepected: ${stringifyState(finalState)}`);
 | |
|   info(`${msg} Actual:    ${stringifyState(win)}`);
 | |
|   for (let prop of sizeProps.concat(positionProps)) {
 | |
|     is(win[prop], finalState[prop], `${msg} Expected final value for ${prop}`);
 | |
|   }
 | |
| 
 | |
|   win.removeEventListener("resize", resizeListener);
 | |
| }
 | |
| 
 | |
| function roundedCenter(aDimension, aOrigin) {
 | |
|   let center = aOrigin + Math.floor(aDimension / 2);
 | |
|   return center - (center % 100);
 | |
| }
 | |
| 
 | |
| class ResizeMoveTest {
 | |
|   static WindowWidth = 200;
 | |
|   static WindowHeight = 200;
 | |
|   static WindowLeft = roundedCenter(screen.availWidth - 200, screen.left);
 | |
|   static WindowTop = roundedCenter(screen.availHeight - 200, screen.top);
 | |
| 
 | |
|   static PropInfo = {
 | |
|     sizeProps: ["outerWidth", "outerHeight", "innerWidth", "innerHeight"],
 | |
|     positionProps: [
 | |
|       "screenX",
 | |
|       "screenY",
 | |
|       /* readonly */ "mozInnerScreenX",
 | |
|       /* readonly */ "mozInnerScreenY",
 | |
|     ],
 | |
|     readonlyProps: ["mozInnerScreenX", "mozInnerScreenY"],
 | |
|     crossAxisMapping: {
 | |
|       outerWidth: "outerHeight",
 | |
|       outerHeight: "outerWidth",
 | |
|       innerWidth: "innerHeight",
 | |
|       innerHeight: "innerWidth",
 | |
|       screenX: "screenY",
 | |
|       screenY: "screenX",
 | |
|       mozInnerScreenX: "mozInnerScreenY",
 | |
|       mozInnerScreenY: "mozInnerScreenX",
 | |
|     },
 | |
|     crossBoundsMapping: {
 | |
|       outerWidth: "innerWidth",
 | |
|       outerHeight: "innerHeight",
 | |
|       innerWidth: "outerWidth",
 | |
|       innerHeight: "outerHeight",
 | |
|       screenX: "mozInnerScreenX",
 | |
|       screenY: "mozInnerScreenY",
 | |
|       mozInnerScreenX: "screenX",
 | |
|       mozInnerScreenY: "screenY",
 | |
|     },
 | |
|   };
 | |
| 
 | |
|   constructor(
 | |
|     aPropertyDeltas,
 | |
|     aInstant = false,
 | |
|     aMsg = "ResizeMoveTest",
 | |
|     aWaitForCompletion = false
 | |
|   ) {
 | |
|     this.propertyDeltas = aPropertyDeltas;
 | |
|     this.instant = aInstant;
 | |
|     this.msg = aMsg;
 | |
|     this.waitForCompletion = aWaitForCompletion;
 | |
| 
 | |
|     // Allows to ignore positions while testing.
 | |
|     this.ignorePositions = false;
 | |
|     // Allows to ignore only mozInnerScreenX/Y properties while testing.
 | |
|     this.ignoreMozInnerScreen = false;
 | |
|     // Allows to skip checking the restored position after testing.
 | |
|     this.ignoreRestoredPosition = false;
 | |
| 
 | |
|     if (AppConstants.platform == "linux" && !SpecialPowers.isHeadless) {
 | |
|       // We can occasionally start the test while nsWindow reports a wrong
 | |
|       // client offset (gdk origin and root_origin are out of sync). This
 | |
|       // results in false expectations for the final mozInnerScreenX/Y values.
 | |
|       this.ignoreMozInnerScreen = !ResizeMoveTest.hasCleanUpTask;
 | |
| 
 | |
|       let { positionProps } = ResizeMoveTest.PropInfo;
 | |
|       let resizeOnlyTest = aPropertyDeltas.every(deltaObj =>
 | |
|         positionProps.every(prop => deltaObj[prop] === undefined)
 | |
|       );
 | |
| 
 | |
|       let isWayland = gfxInfo.windowProtocol == "wayland";
 | |
|       if (resizeOnlyTest && isWayland) {
 | |
|         // On Wayland we can't move the window in general. The window also
 | |
|         // doesn't necessarily open our specified position.
 | |
|         this.ignoreRestoredPosition = true;
 | |
|         // We can catch bad screenX/Y at the start of the first test in a
 | |
|         // window.
 | |
|         this.ignorePositions = !ResizeMoveTest.hasCleanUpTask;
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     if (!ResizeMoveTest.hasCleanUpTask) {
 | |
|       ResizeMoveTest.hasCleanUpTask = true;
 | |
|       registerCleanupFunction(ResizeMoveTest.Cleanup);
 | |
|     }
 | |
| 
 | |
|     add_task(async () => {
 | |
|       let tab = await ResizeMoveTest.GetOrCreateTab();
 | |
|       let browsingContext = await ResizeMoveTest.GetOrCreatePopupBrowsingContext();
 | |
|       if (!browsingContext) {
 | |
|         return;
 | |
|       }
 | |
| 
 | |
|       info("=== Running in content. ===");
 | |
|       await this.run(browsingContext, `${this.msg} (content)`);
 | |
|       await this.restorePopupState(browsingContext);
 | |
| 
 | |
|       info("=== Running in chrome. ===");
 | |
|       let popupChrome = browsingContext.topChromeWindow;
 | |
|       await this.run(popupChrome.browsingContext, `${this.msg} (chrome)`);
 | |
|       await this.restorePopupState(browsingContext);
 | |
| 
 | |
|       info("=== Running in opener. ===");
 | |
|       await this.run(tab.linkedBrowser, `${this.msg} (opener)`);
 | |
|       await this.restorePopupState(browsingContext);
 | |
|     });
 | |
|   }
 | |
| 
 | |
|   async run(aBrowsingContext, aMsg) {
 | |
|     let testType = this.instant ? "instant" : "fanned out";
 | |
|     let msg = `${aMsg} (${testType})`;
 | |
| 
 | |
|     let propInfo = {};
 | |
|     for (let k in ResizeMoveTest.PropInfo) {
 | |
|       propInfo[k] = ResizeMoveTest.PropInfo[k];
 | |
|     }
 | |
|     if (this.ignoreMozInnerScreen) {
 | |
|       todo(false, `[${aMsg}] Shouldn't ignore mozInnerScreenX/Y.`);
 | |
|       propInfo.positionProps = propInfo.positionProps.filter(
 | |
|         prop => !["mozInnerScreenX", "mozInnerScreenY"].includes(prop)
 | |
|       );
 | |
|     }
 | |
|     if (this.ignorePositions) {
 | |
|       todo(false, `[${aMsg}] Shouldn't ignore position.`);
 | |
|       propInfo.positionProps = [];
 | |
|     }
 | |
| 
 | |
|     info(`${msg}: ` + JSON.stringify(this.propertyDeltas));
 | |
|     await SpecialPowers.spawn(
 | |
|       aBrowsingContext,
 | |
|       [
 | |
|         this.propertyDeltas,
 | |
|         this.instant,
 | |
|         propInfo,
 | |
|         msg,
 | |
|         this.waitForCompletion,
 | |
|       ],
 | |
|       testPropertyDeltas
 | |
|     );
 | |
|   }
 | |
| 
 | |
|   async restorePopupState(aBrowsingContext) {
 | |
|     info("Restore popup state.");
 | |
| 
 | |
|     let { deltaWidth, deltaHeight } = await SpecialPowers.spawn(
 | |
|       aBrowsingContext,
 | |
|       [],
 | |
|       () => {
 | |
|         return {
 | |
|           deltaWidth: this.content.outerWidth - this.content.innerWidth,
 | |
|           deltaHeight: this.content.outerHeight - this.content.innerHeight,
 | |
|         };
 | |
|       }
 | |
|     );
 | |
| 
 | |
|     let chromeWindow = aBrowsingContext.topChromeWindow;
 | |
|     let {
 | |
|       WindowLeft: left,
 | |
|       WindowTop: top,
 | |
|       WindowWidth: width,
 | |
|       WindowHeight: height,
 | |
|     } = ResizeMoveTest;
 | |
| 
 | |
|     chromeWindow.resizeTo(width + deltaWidth, height + deltaHeight);
 | |
|     chromeWindow.moveTo(left, top);
 | |
| 
 | |
|     await SpecialPowers.spawn(
 | |
|       aBrowsingContext,
 | |
|       [left, top, width, height, this.ignoreRestoredPosition],
 | |
|       async (aLeft, aTop, aWidth, aHeight, aIgnorePosition) => {
 | |
|         let win = this.content.wrappedJSObject;
 | |
| 
 | |
|         info("Waiting for restored size.");
 | |
|         await ContentTaskUtils.waitForCondition(
 | |
|           () => win.innerWidth == aWidth && win.innerHeight === aHeight,
 | |
|           "Waiting for restored size."
 | |
|         );
 | |
|         is(win.innerWidth, aWidth, "Restored width.");
 | |
|         is(win.innerHeight, aHeight, "Restored height.");
 | |
| 
 | |
|         if (!aIgnorePosition) {
 | |
|           info("Waiting for restored position.");
 | |
|           await ContentTaskUtils.waitForCondition(
 | |
|             () => win.screenX == aLeft && win.screenY === aTop,
 | |
|             "Waiting for restored position."
 | |
|           );
 | |
|           is(win.screenX, aLeft, "Restored screenX.");
 | |
|           is(win.screenY, aTop, "Restored screenY.");
 | |
|         } else {
 | |
|           todo(false, "Shouldn't ignore restored position.");
 | |
|         }
 | |
|       }
 | |
|     );
 | |
|   }
 | |
| 
 | |
|   static async GetOrCreateTab() {
 | |
|     if (ResizeMoveTest.tab) {
 | |
|       return ResizeMoveTest.tab;
 | |
|     }
 | |
| 
 | |
|     info("Opening tab.");
 | |
|     ResizeMoveTest.tab = await BrowserTestUtils.openNewForegroundTab(
 | |
|       window.gBrowser,
 | |
|       "https://example.net/browser/browser/base/content/test/popups/popup_blocker_a.html"
 | |
|     );
 | |
|     return ResizeMoveTest.tab;
 | |
|   }
 | |
| 
 | |
|   static async GetOrCreatePopupBrowsingContext() {
 | |
|     if (ResizeMoveTest.popupBrowsingContext) {
 | |
|       if (!ResizeMoveTest.popupBrowsingContext.isActive) {
 | |
|         return undefined;
 | |
|       }
 | |
|       return ResizeMoveTest.popupBrowsingContext;
 | |
|     }
 | |
| 
 | |
|     let tab = await ResizeMoveTest.GetOrCreateTab();
 | |
|     info("Opening popup.");
 | |
|     ResizeMoveTest.popupBrowsingContext = await SpecialPowers.spawn(
 | |
|       tab.linkedBrowser,
 | |
|       [
 | |
|         ResizeMoveTest.WindowWidth,
 | |
|         ResizeMoveTest.WindowHeight,
 | |
|         ResizeMoveTest.WindowLeft,
 | |
|         ResizeMoveTest.WindowTop,
 | |
|       ],
 | |
|       async (aWidth, aHeight, aLeft, aTop) => {
 | |
|         let win = this.content.open(
 | |
|           this.content.document.location.href,
 | |
|           "_blank",
 | |
|           `left=${aLeft},top=${aTop},width=${aWidth},height=${aHeight}`
 | |
|         );
 | |
|         this.content.popup = win;
 | |
| 
 | |
|         await new Promise(r => (win.onload = r));
 | |
| 
 | |
|         return win.browsingContext;
 | |
|       }
 | |
|     );
 | |
| 
 | |
|     return ResizeMoveTest.popupBrowsingContext;
 | |
|   }
 | |
| 
 | |
|   static async Cleanup() {
 | |
|     let browsingContext = ResizeMoveTest.popupBrowsingContext;
 | |
|     if (browsingContext) {
 | |
|       await SpecialPowers.spawn(browsingContext, [], () => {
 | |
|         this.content.close();
 | |
|       });
 | |
|       delete ResizeMoveTest.popupBrowsingContext;
 | |
|     }
 | |
| 
 | |
|     let tab = ResizeMoveTest.tab;
 | |
|     if (tab) {
 | |
|       await BrowserTestUtils.removeTab(tab);
 | |
|       delete ResizeMoveTest.tab;
 | |
|     }
 | |
|     ResizeMoveTest.hasCleanUpTask = false;
 | |
|   }
 | |
| }
 | |
| 
 | |
| function chaosRequestLongerTimeout(aDoRequest) {
 | |
|   if (aDoRequest && parseInt(Services.env.get("MOZ_CHAOSMODE"), 16)) {
 | |
|     requestLongerTimeout(2);
 | |
|   }
 | |
| }
 | |
| 
 | |
| function createGenericResizeTests(aFirstValue, aSecondValue, aInstant, aMsg) {
 | |
|   // Runtime almost doubles in chaos mode on Mac.
 | |
|   chaosRequestLongerTimeout(AppConstants.platform == "macosx");
 | |
| 
 | |
|   let { crossBoundsMapping, crossAxisMapping } = ResizeMoveTest.PropInfo;
 | |
| 
 | |
|   for (let prop of ["innerWidth", "outerHeight"]) {
 | |
|     // Mixing inner and outer property.
 | |
|     for (let secondProp of [prop, crossBoundsMapping[prop]]) {
 | |
|       let first = {};
 | |
|       first[prop] = aFirstValue;
 | |
|       let second = {};
 | |
|       second[secondProp] = aSecondValue;
 | |
|       new ResizeMoveTest(
 | |
|         [first, second],
 | |
|         aInstant,
 | |
|         `${aMsg} ${prop},${secondProp}`
 | |
|       );
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   for (let prop of ["innerHeight", "outerWidth"]) {
 | |
|     let first = {};
 | |
|     first[prop] = aFirstValue;
 | |
|     let second = {};
 | |
|     second[prop] = aSecondValue;
 | |
| 
 | |
|     // Setting property of other axis before/between two changes.
 | |
|     let otherProps = [
 | |
|       crossAxisMapping[prop],
 | |
|       crossAxisMapping[crossBoundsMapping[prop]],
 | |
|     ];
 | |
|     for (let interferenceProp of otherProps) {
 | |
|       let interference = {};
 | |
|       interference[interferenceProp] = 20;
 | |
|       new ResizeMoveTest(
 | |
|         [first, interference, second],
 | |
|         aInstant,
 | |
|         `${aMsg} ${prop},${interferenceProp},${prop}`
 | |
|       );
 | |
|       new ResizeMoveTest(
 | |
|         [interference, first, second],
 | |
|         aInstant,
 | |
|         `${aMsg} ${interferenceProp},${prop},${prop}`
 | |
|       );
 | |
|     }
 | |
|   }
 | |
| }
 | |
| 
 | |
| function createGenericMoveTests(aInstant, aMsg) {
 | |
|   // Runtime almost doubles in chaos mode on Mac.
 | |
|   chaosRequestLongerTimeout(AppConstants.platform == "macosx");
 | |
| 
 | |
|   let { crossAxisMapping } = ResizeMoveTest.PropInfo;
 | |
| 
 | |
|   for (let prop of ["screenX", "screenY"]) {
 | |
|     for (let [v1, v2, msg] of [
 | |
|       [9, 10, `${aMsg}`],
 | |
|       [11, 11, `${aMsg} repeat`],
 | |
|       [12, 0, `${aMsg} revert`],
 | |
|     ]) {
 | |
|       let first = {};
 | |
|       first[prop] = v1;
 | |
|       let second = {};
 | |
|       second[prop] = v2;
 | |
|       new ResizeMoveTest([first, second], aInstant, `${msg} ${prop},${prop}`);
 | |
| 
 | |
|       let interferenceProp = crossAxisMapping[prop];
 | |
|       let interference = {};
 | |
|       interference[interferenceProp] = 20;
 | |
|       new ResizeMoveTest(
 | |
|         [first, interference, second],
 | |
|         aInstant,
 | |
|         `${aMsg} ${prop},${interferenceProp},${prop}`
 | |
|       );
 | |
|       new ResizeMoveTest(
 | |
|         [interference, first, second],
 | |
|         aInstant,
 | |
|         `${msg} ${interferenceProp},${prop},${prop}`
 | |
|       );
 | |
|     }
 | |
|   }
 | |
| }
 |