mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-05 07:18:39 +09:00
import FIREFOX_52_6_0esr_RELEASE from mozilla-esr52 hg repo
This commit is contained in:
commit
dcd9973243
150858 changed files with 23884658 additions and 0 deletions
|
|
@ -0,0 +1,6 @@
|
|||
"use strict";
|
||||
|
||||
module.exports = {
|
||||
// Extend from the shared list of defined globals for mochitests.
|
||||
"extends": "../../../../.eslintrc.mochitests.js"
|
||||
};
|
||||
44
devtools/client/responsive.html/test/browser/browser.ini
Normal file
44
devtools/client/responsive.html/test/browser/browser.ini
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
[DEFAULT]
|
||||
tags = devtools
|
||||
subsuite = devtools
|
||||
# !e10s: RDM only works for remote tabs
|
||||
skip-if = !e10s
|
||||
support-files =
|
||||
devices.json
|
||||
doc_page_state.html
|
||||
geolocation.html
|
||||
head.js
|
||||
touch.html
|
||||
!/devtools/client/commandline/test/helpers.js
|
||||
!/devtools/client/framework/test/shared-head.js
|
||||
!/devtools/client/framework/test/shared-redux-head.js
|
||||
!/devtools/client/inspector/test/shared-head.js
|
||||
!/devtools/client/shared/test/test-actor.js
|
||||
!/devtools/client/shared/test/test-actor-registry.js
|
||||
|
||||
[browser_device_change.js]
|
||||
[browser_device_modal_error.js]
|
||||
[browser_device_modal_exit.js]
|
||||
[browser_device_modal_submit.js]
|
||||
[browser_device_width.js]
|
||||
[browser_dpr_change.js]
|
||||
[browser_exit_button.js]
|
||||
[browser_frame_script_active.js]
|
||||
[browser_menu_item_01.js]
|
||||
[browser_menu_item_02.js]
|
||||
[browser_mouse_resize.js]
|
||||
[browser_navigation.js]
|
||||
[browser_network_throttling.js]
|
||||
[browser_page_state.js]
|
||||
[browser_permission_doorhanger.js]
|
||||
[browser_resize_cmd.js]
|
||||
[browser_screenshot_button.js]
|
||||
[browser_tab_close.js]
|
||||
[browser_tab_remoteness_change.js]
|
||||
[browser_toolbox_computed_view.js]
|
||||
[browser_toolbox_rule_view.js]
|
||||
[browser_toolbox_swap_browsers.js]
|
||||
[browser_touch_device.js]
|
||||
[browser_touch_simulation.js]
|
||||
[browser_viewport_basics.js]
|
||||
[browser_window_close.js]
|
||||
|
|
@ -0,0 +1,95 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
// Tests changing viewport device
|
||||
const TEST_URL = "data:text/html;charset=utf-8,Device list test";
|
||||
|
||||
const DEFAULT_DPPX = window.devicePixelRatio;
|
||||
const DEFAULT_UA = Cc["@mozilla.org/network/protocol;1?name=http"]
|
||||
.getService(Ci.nsIHttpProtocolHandler)
|
||||
.userAgent;
|
||||
|
||||
const Types = require("devtools/client/responsive.html/types");
|
||||
|
||||
const testDevice = {
|
||||
"name": "Fake Phone RDM Test",
|
||||
"width": 320,
|
||||
"height": 570,
|
||||
"pixelRatio": 5.5,
|
||||
"userAgent": "Mozilla/5.0 (Mobile; rv:39.0) Gecko/39.0 Firefox/39.0",
|
||||
"touch": true,
|
||||
"firefoxOS": true,
|
||||
"os": "custom",
|
||||
"featured": true,
|
||||
};
|
||||
|
||||
// Add the new device to the list
|
||||
addDeviceForTest(testDevice);
|
||||
|
||||
addRDMTask(TEST_URL, function* ({ ui, manager }) {
|
||||
let { store } = ui.toolWindow;
|
||||
|
||||
// Wait until the viewport has been added and the device list has been loaded
|
||||
yield waitUntilState(store, state => state.viewports.length == 1
|
||||
&& state.devices.listState == Types.deviceListState.LOADED);
|
||||
|
||||
// Test defaults
|
||||
testViewportDimensions(ui, 320, 480);
|
||||
yield testUserAgent(ui, DEFAULT_UA);
|
||||
yield testDevicePixelRatio(ui, DEFAULT_DPPX);
|
||||
yield testTouchEventsOverride(ui, false);
|
||||
testViewportDeviceSelectLabel(ui, "no device selected");
|
||||
|
||||
// Test device with custom properties
|
||||
yield selectDevice(ui, "Fake Phone RDM Test");
|
||||
yield waitForViewportResizeTo(ui, testDevice.width, testDevice.height);
|
||||
yield testUserAgent(ui, testDevice.userAgent);
|
||||
yield testDevicePixelRatio(ui, testDevice.pixelRatio);
|
||||
yield testTouchEventsOverride(ui, true);
|
||||
|
||||
// Test resetting device when resizing viewport
|
||||
let deviceRemoved = once(ui, "device-removed");
|
||||
yield testViewportResize(ui, ".viewport-vertical-resize-handle",
|
||||
[-10, -10], [testDevice.width, testDevice.height - 10], [0, -10], ui);
|
||||
yield deviceRemoved;
|
||||
yield testUserAgent(ui, DEFAULT_UA);
|
||||
yield testDevicePixelRatio(ui, DEFAULT_DPPX);
|
||||
yield testTouchEventsOverride(ui, false);
|
||||
testViewportDeviceSelectLabel(ui, "no device selected");
|
||||
|
||||
// Test device with generic properties
|
||||
yield selectDevice(ui, "Laptop (1366 x 768)");
|
||||
yield waitForViewportResizeTo(ui, 1366, 768);
|
||||
yield testUserAgent(ui, DEFAULT_UA);
|
||||
yield testDevicePixelRatio(ui, 1);
|
||||
yield testTouchEventsOverride(ui, false);
|
||||
});
|
||||
|
||||
function testViewportDimensions(ui, w, h) {
|
||||
let viewport = ui.toolWindow.document.querySelector(".viewport-content");
|
||||
|
||||
is(ui.toolWindow.getComputedStyle(viewport).getPropertyValue("width"),
|
||||
`${w}px`, `Viewport should have width of ${w}px`);
|
||||
is(ui.toolWindow.getComputedStyle(viewport).getPropertyValue("height"),
|
||||
`${h}px`, `Viewport should have height of ${h}px`);
|
||||
}
|
||||
|
||||
function* testUserAgent(ui, expected) {
|
||||
let ua = yield ContentTask.spawn(ui.getViewportBrowser(), {}, function* () {
|
||||
return content.navigator.userAgent;
|
||||
});
|
||||
is(ua, expected, `UA should be set to ${expected}`);
|
||||
}
|
||||
|
||||
function* testDevicePixelRatio(ui, expected) {
|
||||
let dppx = yield getViewportDevicePixelRatio(ui);
|
||||
is(dppx, expected, `devicePixelRatio should be set to ${expected}`);
|
||||
}
|
||||
|
||||
function* getViewportDevicePixelRatio(ui) {
|
||||
return yield ContentTask.spawn(ui.getViewportBrowser(), {}, function* () {
|
||||
return content.devicePixelRatio;
|
||||
});
|
||||
}
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
// Test to check that RDM can handle properly an error in the device list
|
||||
|
||||
const TEST_URL = "data:text/html;charset=utf-8,";
|
||||
const Types = require("devtools/client/responsive.html/types");
|
||||
const { getStr } = require("devtools/client/responsive.html/utils/l10n");
|
||||
|
||||
// Set a wrong URL for the device list file
|
||||
add_task(function* () {
|
||||
yield SpecialPowers.pushPrefEnv({
|
||||
set: [["devtools.devices.url", TEST_URI_ROOT + "wrong_devices_file.json"]],
|
||||
});
|
||||
});
|
||||
|
||||
addRDMTask(TEST_URL, function* ({ ui }) {
|
||||
let { store, document } = ui.toolWindow;
|
||||
let select = document.querySelector(".viewport-device-selector");
|
||||
|
||||
// Wait until the viewport has been added and the device list state indicates
|
||||
// an error
|
||||
yield waitUntilState(store, state => state.viewports.length == 1
|
||||
&& state.devices.listState == Types.deviceListState.ERROR);
|
||||
|
||||
// The device selector placeholder should be set accordingly
|
||||
let placeholder = select.options[select.selectedIndex].innerHTML;
|
||||
ok(placeholder == getStr("responsive.deviceListError"),
|
||||
"Device selector indicates an error");
|
||||
|
||||
// The device selector should be disabled
|
||||
ok(select.disabled, "Device selector is disabled");
|
||||
});
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
// Test submitting display device changes on the device modal
|
||||
|
||||
const TEST_URL = "data:text/html;charset=utf-8,";
|
||||
const Types = require("devtools/client/responsive.html/types");
|
||||
|
||||
addRDMTask(TEST_URL, function* ({ ui }) {
|
||||
let { store, document } = ui.toolWindow;
|
||||
let modal = document.querySelector("#device-modal-wrapper");
|
||||
let closeButton = document.querySelector("#device-close-button");
|
||||
|
||||
// Wait until the viewport has been added and the device list has been loaded
|
||||
yield waitUntilState(store, state => state.viewports.length == 1
|
||||
&& state.devices.listState == Types.deviceListState.LOADED);
|
||||
|
||||
openDeviceModal(ui);
|
||||
|
||||
let preferredDevicesBefore = _loadPreferredDevices();
|
||||
|
||||
info("Check the first unchecked device and exit the modal.");
|
||||
let uncheckedCb = [...document.querySelectorAll(".device-input-checkbox")]
|
||||
.filter(cb => !cb.checked)[0];
|
||||
let value = uncheckedCb.value;
|
||||
uncheckedCb.click();
|
||||
closeButton.click();
|
||||
|
||||
ok(modal.classList.contains("closed") && !modal.classList.contains("opened"),
|
||||
"The device modal is closed on exit.");
|
||||
|
||||
info("Check that the device list remains unchanged after exitting.");
|
||||
let preferredDevicesAfter = _loadPreferredDevices();
|
||||
|
||||
is(preferredDevicesBefore.added.size, preferredDevicesAfter.added.size,
|
||||
"Got expected number of added devices.");
|
||||
|
||||
is(preferredDevicesBefore.removed.size, preferredDevicesAfter.removed.size,
|
||||
"Got expected number of removed devices.");
|
||||
|
||||
ok(!preferredDevicesAfter.removed.has(value),
|
||||
value + " was not added to removed device list.");
|
||||
});
|
||||
|
|
@ -0,0 +1,146 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
// Test submitting display device changes on the device modal
|
||||
const { getDevices } = require("devtools/client/shared/devices");
|
||||
|
||||
const addedDevice = {
|
||||
"name": "Fake Phone RDM Test",
|
||||
"width": 320,
|
||||
"height": 570,
|
||||
"pixelRatio": 1.5,
|
||||
"userAgent": "Mozilla/5.0 (Mobile; rv:39.0) Gecko/39.0 Firefox/39.0",
|
||||
"touch": true,
|
||||
"firefoxOS": false,
|
||||
"os": "custom",
|
||||
"featured": true,
|
||||
};
|
||||
|
||||
const TEST_URL = "data:text/html;charset=utf-8,";
|
||||
const Types = require("devtools/client/responsive.html/types");
|
||||
|
||||
addRDMTask(TEST_URL, function* ({ ui }) {
|
||||
let { store, document } = ui.toolWindow;
|
||||
let modal = document.querySelector("#device-modal-wrapper");
|
||||
let select = document.querySelector(".viewport-device-selector");
|
||||
let submitButton = document.querySelector("#device-submit-button");
|
||||
|
||||
// Wait until the viewport has been added and the device list has been loaded
|
||||
yield waitUntilState(store, state => state.viewports.length == 1
|
||||
&& state.devices.listState == Types.deviceListState.LOADED);
|
||||
|
||||
openDeviceModal(ui);
|
||||
|
||||
info("Checking displayed device checkboxes are checked in the device modal.");
|
||||
let checkedCbs = [...document.querySelectorAll(".device-input-checkbox")]
|
||||
.filter(cb => cb.checked);
|
||||
|
||||
let remoteList = yield getDevices();
|
||||
|
||||
let featuredCount = remoteList.TYPES.reduce((total, type) => {
|
||||
return total + remoteList[type].reduce((subtotal, device) => {
|
||||
return subtotal + ((device.os != "fxos" && device.featured) ? 1 : 0);
|
||||
}, 0);
|
||||
}, 0);
|
||||
|
||||
is(featuredCount, checkedCbs.length,
|
||||
"Got expected number of displayed devices.");
|
||||
|
||||
for (let cb of checkedCbs) {
|
||||
ok(Object.keys(remoteList).filter(type => remoteList[type][cb.value]),
|
||||
cb.value + " is correctly checked.");
|
||||
}
|
||||
|
||||
// Tests where the user adds a non-featured device
|
||||
info("Check the first unchecked device and submit new device list.");
|
||||
let uncheckedCb = [...document.querySelectorAll(".device-input-checkbox")]
|
||||
.filter(cb => !cb.checked)[0];
|
||||
let value = uncheckedCb.value;
|
||||
uncheckedCb.click();
|
||||
submitButton.click();
|
||||
|
||||
ok(modal.classList.contains("closed") && !modal.classList.contains("opened"),
|
||||
"The device modal is closed on submit.");
|
||||
|
||||
info("Checking that the new device is added to the user preference list.");
|
||||
let preferredDevices = _loadPreferredDevices();
|
||||
ok(preferredDevices.added.has(value), value + " in user added list.");
|
||||
|
||||
info("Checking new device is added to the device selector.");
|
||||
let options = [...select.options];
|
||||
is(options.length - 2, featuredCount + 1,
|
||||
"Got expected number of devices in device selector.");
|
||||
ok(options.filter(o => o.value === value)[0],
|
||||
value + " added to the device selector.");
|
||||
|
||||
info("Reopen device modal and check new device is correctly checked");
|
||||
openDeviceModal(ui);
|
||||
ok([...document.querySelectorAll(".device-input-checkbox")]
|
||||
.filter(cb => cb.checked && cb.value === value)[0],
|
||||
value + " is checked in the device modal.");
|
||||
|
||||
// Tests where the user removes a featured device
|
||||
info("Uncheck the first checked device different than the previous one");
|
||||
let checkedCb = [...document.querySelectorAll(".device-input-checkbox")]
|
||||
.filter(cb => cb.checked && cb.value != value)[0];
|
||||
let checkedVal = checkedCb.value;
|
||||
checkedCb.click();
|
||||
submitButton.click();
|
||||
|
||||
info("Checking that the device is removed from the user preference list.");
|
||||
preferredDevices = _loadPreferredDevices();
|
||||
ok(preferredDevices.removed.has(checkedVal), checkedVal + " in removed list");
|
||||
|
||||
info("Checking that the device is not in the device selector.");
|
||||
options = [...select.options];
|
||||
is(options.length - 2, featuredCount,
|
||||
"Got expected number of devices in device selector.");
|
||||
ok(!options.filter(o => o.value === checkedVal)[0],
|
||||
checkedVal + " removed from the device selector.");
|
||||
|
||||
info("Reopen device modal and check device is correctly unchecked");
|
||||
openDeviceModal(ui);
|
||||
ok([...document.querySelectorAll(".device-input-checkbox")]
|
||||
.filter(cb => !cb.checked && cb.value === checkedVal)[0],
|
||||
checkedVal + " is unchecked in the device modal.");
|
||||
|
||||
// Let's add a dummy device to simulate featured flag changes for next test
|
||||
addDeviceForTest(addedDevice);
|
||||
});
|
||||
|
||||
addRDMTask(TEST_URL, function* ({ ui }) {
|
||||
let { store, document } = ui.toolWindow;
|
||||
let select = document.querySelector(".viewport-device-selector");
|
||||
|
||||
// Wait until the viewport has been added and the device list has been loaded
|
||||
yield waitUntilState(store, state => state.viewports.length == 1
|
||||
&& state.devices.listState == Types.deviceListState.LOADED);
|
||||
|
||||
openDeviceModal(ui);
|
||||
|
||||
let remoteList = yield getDevices();
|
||||
let featuredCount = remoteList.TYPES.reduce((total, type) => {
|
||||
return total + remoteList[type].reduce((subtotal, device) => {
|
||||
return subtotal + ((device.os != "fxos" && device.featured) ? 1 : 0);
|
||||
}, 0);
|
||||
}, 0);
|
||||
let preferredDevices = _loadPreferredDevices();
|
||||
|
||||
// Tests to prove that reloading the RDM didn't break our device list
|
||||
info("Checking new featured device appears in the device selector.");
|
||||
let options = [...select.options];
|
||||
is(options.length - 2, featuredCount
|
||||
- preferredDevices.removed.size + preferredDevices.added.size,
|
||||
"Got expected number of devices in device selector.");
|
||||
|
||||
ok(options.filter(o => o.value === addedDevice.name)[0],
|
||||
"dummy device added to the device selector.");
|
||||
|
||||
ok(options.filter(o => preferredDevices.added.has(o.value))[0],
|
||||
"device added by user still in the device selector.");
|
||||
|
||||
ok(!options.filter(o => preferredDevices.removed.has(o.value))[0],
|
||||
"device removed by user not in the device selector.");
|
||||
});
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
const TEST_URL = "data:text/html;charset=utf-8,";
|
||||
|
||||
addRDMTask(TEST_URL, function* ({ ui, manager }) {
|
||||
ok(ui, "An instance of the RDM should be attached to the tab.");
|
||||
yield setViewportSize(ui, manager, 110, 500);
|
||||
|
||||
info("Checking initial width/height properties.");
|
||||
yield doInitialChecks(ui);
|
||||
|
||||
info("Changing the RDM size");
|
||||
yield setViewportSize(ui, manager, 90, 500);
|
||||
|
||||
info("Checking for screen props");
|
||||
yield checkScreenProps(ui);
|
||||
|
||||
info("Setting docShell.deviceSizeIsPageSize to false");
|
||||
yield ContentTask.spawn(ui.getViewportBrowser(), {}, function* () {
|
||||
let docShell = content.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIWebNavigation)
|
||||
.QueryInterface(Ci.nsIDocShell);
|
||||
docShell.deviceSizeIsPageSize = false;
|
||||
});
|
||||
|
||||
info("Checking for screen props once again.");
|
||||
yield checkScreenProps2(ui);
|
||||
});
|
||||
|
||||
function* doInitialChecks(ui) {
|
||||
let { innerWidth, matchesMedia } = yield grabContentInfo(ui);
|
||||
is(innerWidth, 110, "initial width should be 110px");
|
||||
ok(!matchesMedia, "media query shouldn't match.");
|
||||
}
|
||||
|
||||
function* checkScreenProps(ui) {
|
||||
let { matchesMedia, screen } = yield grabContentInfo(ui);
|
||||
ok(matchesMedia, "media query should match");
|
||||
isnot(window.screen.width, screen.width,
|
||||
"screen.width should not be the size of the screen.");
|
||||
is(screen.width, 90, "screen.width should be the page width");
|
||||
is(screen.height, 500, "screen.height should be the page height");
|
||||
}
|
||||
|
||||
function* checkScreenProps2(ui) {
|
||||
let { matchesMedia, screen } = yield grabContentInfo(ui);
|
||||
ok(!matchesMedia, "media query should be re-evaluated.");
|
||||
is(window.screen.width, screen.width,
|
||||
"screen.width should be the size of the screen.");
|
||||
}
|
||||
|
||||
function grabContentInfo(ui) {
|
||||
return ContentTask.spawn(ui.getViewportBrowser(), {}, function* () {
|
||||
return {
|
||||
screen: {
|
||||
width: content.screen.width,
|
||||
height: content.screen.height
|
||||
},
|
||||
innerWidth: content.innerWidth,
|
||||
matchesMedia: content.matchMedia("(max-device-width:100px)").matches
|
||||
};
|
||||
});
|
||||
}
|
||||
|
|
@ -0,0 +1,140 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
// Tests changing viewport DPR
|
||||
const TEST_URL = "data:text/html;charset=utf-8,DPR list test";
|
||||
const DEFAULT_DPPX = window.devicePixelRatio;
|
||||
const VIEWPORT_DPPX = DEFAULT_DPPX + 2;
|
||||
const Types = require("devtools/client/responsive.html/types");
|
||||
|
||||
const testDevice = {
|
||||
"name": "Fake Phone RDM Test",
|
||||
"width": 320,
|
||||
"height": 470,
|
||||
"pixelRatio": 5.5,
|
||||
"userAgent": "Mozilla/5.0 (Mobile; rv:39.0) Gecko/39.0 Firefox/39.0",
|
||||
"touch": true,
|
||||
"firefoxOS": true,
|
||||
"os": "custom",
|
||||
"featured": true,
|
||||
};
|
||||
|
||||
// Add the new device to the list
|
||||
addDeviceForTest(testDevice);
|
||||
|
||||
addRDMTask(TEST_URL, function* ({ ui, manager }) {
|
||||
yield waitStartup(ui);
|
||||
|
||||
yield testDefaults(ui);
|
||||
yield testChangingDevice(ui);
|
||||
yield testResetWhenResizingViewport(ui);
|
||||
yield testChangingDPR(ui);
|
||||
});
|
||||
|
||||
function* waitStartup(ui) {
|
||||
let { store } = ui.toolWindow;
|
||||
|
||||
// Wait until the viewport has been added and the device list has been loaded
|
||||
yield waitUntilState(store, state => state.viewports.length == 1
|
||||
&& state.devices.listState == Types.deviceListState.LOADED);
|
||||
}
|
||||
|
||||
function* testDefaults(ui) {
|
||||
info("Test Defaults");
|
||||
|
||||
yield testDevicePixelRatio(ui, window.devicePixelRatio);
|
||||
testViewportDPRSelect(ui, {value: window.devicePixelRatio, disabled: false});
|
||||
testViewportDeviceSelectLabel(ui, "no device selected");
|
||||
}
|
||||
|
||||
function* testChangingDevice(ui) {
|
||||
info("Test Changing Device");
|
||||
|
||||
let waitPixelRatioChange = onceDevicePixelRatioChange(ui);
|
||||
|
||||
yield selectDevice(ui, testDevice.name);
|
||||
yield waitForViewportResizeTo(ui, testDevice.width, testDevice.height);
|
||||
yield waitPixelRatioChange;
|
||||
yield testDevicePixelRatio(ui, testDevice.pixelRatio);
|
||||
testViewportDPRSelect(ui, {value: testDevice.pixelRatio, disabled: true});
|
||||
testViewportDeviceSelectLabel(ui, testDevice.name);
|
||||
}
|
||||
|
||||
function* testResetWhenResizingViewport(ui) {
|
||||
info("Test reset when resizing the viewport");
|
||||
|
||||
let waitPixelRatioChange = onceDevicePixelRatioChange(ui);
|
||||
|
||||
let deviceRemoved = once(ui, "device-removed");
|
||||
yield testViewportResize(ui, ".viewport-vertical-resize-handle",
|
||||
[-10, -10], [testDevice.width, testDevice.height - 10], [0, -10], ui);
|
||||
yield deviceRemoved;
|
||||
|
||||
yield waitPixelRatioChange;
|
||||
yield testDevicePixelRatio(ui, window.devicePixelRatio);
|
||||
|
||||
testViewportDPRSelect(ui, {value: window.devicePixelRatio, disabled: false});
|
||||
testViewportDeviceSelectLabel(ui, "no device selected");
|
||||
}
|
||||
|
||||
function* testChangingDPR(ui) {
|
||||
info("Test changing device pixel ratio");
|
||||
|
||||
let waitPixelRatioChange = onceDevicePixelRatioChange(ui);
|
||||
|
||||
yield selectDPR(ui, VIEWPORT_DPPX);
|
||||
yield waitPixelRatioChange;
|
||||
yield testDevicePixelRatio(ui, VIEWPORT_DPPX);
|
||||
testViewportDPRSelect(ui, {value: VIEWPORT_DPPX, disabled: false});
|
||||
testViewportDeviceSelectLabel(ui, "no device selected");
|
||||
}
|
||||
|
||||
function testViewportDPRSelect(ui, expected) {
|
||||
info("Test viewport's DPR Select");
|
||||
|
||||
let select = ui.toolWindow.document.querySelector("#global-dpr-selector > select");
|
||||
is(select.value, expected.value,
|
||||
`DPR Select value should be: ${expected.value}`);
|
||||
is(select.disabled, expected.disabled,
|
||||
`DPR Select should be ${expected.disabled ? "disabled" : "enabled"}.`);
|
||||
}
|
||||
|
||||
function* testDevicePixelRatio(ui, expected) {
|
||||
info("Test device pixel ratio");
|
||||
|
||||
let dppx = yield getViewportDevicePixelRatio(ui);
|
||||
is(dppx, expected, `devicePixelRatio should be: ${expected}`);
|
||||
}
|
||||
|
||||
function* getViewportDevicePixelRatio(ui) {
|
||||
return yield ContentTask.spawn(ui.getViewportBrowser(), {}, function* () {
|
||||
return content.devicePixelRatio;
|
||||
});
|
||||
}
|
||||
|
||||
function onceDevicePixelRatioChange(ui) {
|
||||
return ContentTask.spawn(ui.getViewportBrowser(), {}, function* () {
|
||||
info(`Listening for a pixel ratio change (current: ${content.devicePixelRatio}dppx)`);
|
||||
|
||||
let pixelRatio = content.devicePixelRatio;
|
||||
let mql = content.matchMedia(`(resolution: ${pixelRatio}dppx)`);
|
||||
|
||||
return new Promise(resolve => {
|
||||
const onWindowCreated = () => {
|
||||
if (pixelRatio !== content.devicePixelRatio) {
|
||||
resolve();
|
||||
}
|
||||
};
|
||||
|
||||
addEventListener("DOMWindowCreated", onWindowCreated, {once: true});
|
||||
|
||||
mql.addListener(function listener() {
|
||||
mql.removeListener(listener);
|
||||
removeEventListener("DOMWindowCreated", onWindowCreated, {once: true});
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
const TEST_URL = "data:text/html;charset=utf-8,";
|
||||
|
||||
// Test global exit button
|
||||
addRDMTask(TEST_URL, function* (...args) {
|
||||
yield testExitButton(...args);
|
||||
});
|
||||
|
||||
// Test global exit button on detached tab.
|
||||
// See Bug 1262806
|
||||
add_task(function* () {
|
||||
let tab = yield addTab(TEST_URL);
|
||||
let { ui, manager } = yield openRDM(tab);
|
||||
|
||||
yield waitBootstrap(ui);
|
||||
|
||||
let waitTabIsDetached = Promise.all([
|
||||
once(tab, "TabClose"),
|
||||
once(tab.linkedBrowser, "SwapDocShells")
|
||||
]);
|
||||
|
||||
// Detach the tab with RDM open.
|
||||
let newWindow = gBrowser.replaceTabWithWindow(tab);
|
||||
|
||||
// Waiting the tab is detached.
|
||||
yield waitTabIsDetached;
|
||||
|
||||
// Get the new tab instance.
|
||||
tab = newWindow.gBrowser.tabs[0];
|
||||
|
||||
// Detaching a tab closes RDM.
|
||||
ok(!manager.isActiveForTab(tab),
|
||||
"Responsive Design Mode is not active for the tab");
|
||||
|
||||
// Reopen the RDM and test the exit button again.
|
||||
yield testExitButton(yield openRDM(tab));
|
||||
yield BrowserTestUtils.closeWindow(newWindow);
|
||||
});
|
||||
|
||||
function* waitBootstrap(ui) {
|
||||
let { toolWindow, tab } = ui;
|
||||
let { store } = toolWindow;
|
||||
let url = String(tab.linkedBrowser.currentURI.spec);
|
||||
|
||||
// Wait until the viewport has been added.
|
||||
yield waitUntilState(store, state => state.viewports.length == 1);
|
||||
|
||||
// Wait until the document has been loaded.
|
||||
yield waitForFrameLoad(ui, url);
|
||||
}
|
||||
|
||||
function* testExitButton({ui, manager}) {
|
||||
yield waitBootstrap(ui);
|
||||
|
||||
let exitButton = ui.toolWindow.document.getElementById("global-exit-button");
|
||||
|
||||
ok(manager.isActiveForTab(ui.tab),
|
||||
"Responsive Design Mode active for the tab");
|
||||
|
||||
exitButton.click();
|
||||
|
||||
yield once(manager, "off");
|
||||
|
||||
ok(!manager.isActiveForTab(ui.tab),
|
||||
"Responsive Design Mode is not active for the tab");
|
||||
}
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
// Verify frame script is active when expected.
|
||||
|
||||
const e10s = require("devtools/client/responsive.html/utils/e10s");
|
||||
|
||||
const TEST_URL = "http://example.com/";
|
||||
add_task(function* () {
|
||||
let tab = yield addTab(TEST_URL);
|
||||
|
||||
let { ui } = yield openRDM(tab);
|
||||
|
||||
let mm = ui.getViewportBrowser().messageManager;
|
||||
let { active } = yield e10s.request(mm, "IsActive");
|
||||
is(active, true, "Frame script is active");
|
||||
|
||||
yield closeRDM(tab);
|
||||
|
||||
// Must re-get the messageManager on each run since it changes when RDM opens
|
||||
// or closes due to the design of swapFrameLoaders. Also, we only have access
|
||||
// to a valid `ui` instance while RDM is open.
|
||||
mm = tab.linkedBrowser.messageManager;
|
||||
({ active } = yield e10s.request(mm, "IsActive"));
|
||||
is(active, false, "Frame script is active");
|
||||
|
||||
// Try another round as well to be sure there is no state saved anywhere
|
||||
({ ui } = yield openRDM(tab));
|
||||
|
||||
mm = ui.getViewportBrowser().messageManager;
|
||||
({ active } = yield e10s.request(mm, "IsActive"));
|
||||
is(active, true, "Frame script is active");
|
||||
|
||||
yield closeRDM(tab);
|
||||
|
||||
// Must re-get the messageManager on each run since it changes when RDM opens
|
||||
// or closes due to the design of swapFrameLoaders. Also, we only have access
|
||||
// to a valid `ui` instance while RDM is open.
|
||||
mm = tab.linkedBrowser.messageManager;
|
||||
({ active } = yield e10s.request(mm, "IsActive"));
|
||||
is(active, false, "Frame script is active");
|
||||
|
||||
yield removeTab(tab);
|
||||
});
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
// Test RDM menu item is checked when expected, on multiple tabs.
|
||||
|
||||
const TEST_URL = "data:text/html;charset=utf-8,";
|
||||
|
||||
const tabUtils = require("sdk/tabs/utils");
|
||||
const { startup } = require("sdk/window/helpers");
|
||||
|
||||
const activateTab = (tab) => new Promise(resolve => {
|
||||
let { tabContainer } = tabUtils.getOwnerWindow(tab).gBrowser;
|
||||
|
||||
tabContainer.addEventListener("TabSelect", function listener({type}) {
|
||||
tabContainer.removeEventListener(type, listener);
|
||||
resolve();
|
||||
});
|
||||
|
||||
tabUtils.activateTab(tab);
|
||||
});
|
||||
|
||||
const isMenuChecked = () => {
|
||||
let menu = document.getElementById("menu_responsiveUI");
|
||||
return menu.getAttribute("checked") === "true";
|
||||
};
|
||||
|
||||
add_task(function* () {
|
||||
yield startup(window);
|
||||
|
||||
ok(!isMenuChecked(),
|
||||
"RDM menu item is unchecked by default");
|
||||
|
||||
const tab = yield addTab(TEST_URL);
|
||||
|
||||
ok(!isMenuChecked(),
|
||||
"RDM menu item is unchecked for new tab");
|
||||
|
||||
yield openRDM(tab);
|
||||
|
||||
ok(isMenuChecked(),
|
||||
"RDM menu item is checked with RDM open");
|
||||
|
||||
const tab2 = yield addTab(TEST_URL);
|
||||
|
||||
ok(!isMenuChecked(),
|
||||
"RDM menu item is unchecked for new tab");
|
||||
|
||||
yield activateTab(tab);
|
||||
|
||||
ok(isMenuChecked(),
|
||||
"RDM menu item is checked for the tab where RDM is open");
|
||||
|
||||
yield closeRDM(tab);
|
||||
|
||||
ok(!isMenuChecked(),
|
||||
"RDM menu item is unchecked after RDM is closed");
|
||||
|
||||
yield removeTab(tab);
|
||||
yield removeTab(tab2);
|
||||
});
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
// Test RDM menu item is checked when expected, on multiple windows.
|
||||
|
||||
const TEST_URL = "data:text/html;charset=utf-8,";
|
||||
|
||||
const { getMostRecentBrowserWindow } = require("sdk/window/utils");
|
||||
|
||||
const isMenuCheckedFor = ({document}) => {
|
||||
let menu = document.getElementById("menu_responsiveUI");
|
||||
return menu.getAttribute("checked") === "true";
|
||||
};
|
||||
|
||||
add_task(function* () {
|
||||
const window1 = yield BrowserTestUtils.openNewBrowserWindow();
|
||||
let { gBrowser } = window1;
|
||||
|
||||
yield BrowserTestUtils.withNewTab({ gBrowser, url: TEST_URL },
|
||||
function* (browser) {
|
||||
let tab = gBrowser.getTabForBrowser(browser);
|
||||
|
||||
is(window1, getMostRecentBrowserWindow(),
|
||||
"The new window is the active one");
|
||||
|
||||
ok(!isMenuCheckedFor(window1),
|
||||
"RDM menu item is unchecked by default");
|
||||
|
||||
yield openRDM(tab);
|
||||
|
||||
ok(isMenuCheckedFor(window1),
|
||||
"RDM menu item is checked with RDM open");
|
||||
|
||||
yield closeRDM(tab);
|
||||
|
||||
ok(!isMenuCheckedFor(window1),
|
||||
"RDM menu item is unchecked with RDM closed");
|
||||
});
|
||||
|
||||
yield BrowserTestUtils.closeWindow(window1);
|
||||
|
||||
is(window, getMostRecentBrowserWindow(),
|
||||
"The original window is the active one");
|
||||
|
||||
ok(!isMenuCheckedFor(window),
|
||||
"RDM menu item is unchecked");
|
||||
});
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
const TEST_URL = "data:text/html;charset=utf-8,";
|
||||
|
||||
addRDMTask(TEST_URL, function* ({ ui, manager }) {
|
||||
let store = ui.toolWindow.store;
|
||||
|
||||
// Wait until the viewport has been added
|
||||
yield waitUntilState(store, state => state.viewports.length == 1);
|
||||
|
||||
yield setViewportSize(ui, manager, 300, 300);
|
||||
|
||||
// Do horizontal + vertical resize
|
||||
yield testViewportResize(ui, ".viewport-resize-handle",
|
||||
[10, 10], [320, 310], [10, 10]);
|
||||
|
||||
// Do horizontal resize
|
||||
yield testViewportResize(ui, ".viewport-horizontal-resize-handle",
|
||||
[-10, 10], [300, 310], [-10, 0]);
|
||||
|
||||
// Do vertical resize
|
||||
yield testViewportResize(ui, ".viewport-vertical-resize-handle",
|
||||
[-10, -10], [300, 300], [0, -10], ui);
|
||||
});
|
||||
|
|
@ -0,0 +1,98 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
// Test the primary browser navigation UI to verify it's connected to the viewport.
|
||||
|
||||
const DUMMY_1_URL = "http://example.com/";
|
||||
const TEST_URL = `${URL_ROOT}doc_page_state.html`;
|
||||
const DUMMY_2_URL = "http://example.com/browser/";
|
||||
const DUMMY_3_URL = "http://example.com/browser/devtools/";
|
||||
|
||||
add_task(function* () {
|
||||
// Load up a sequence of pages:
|
||||
// 0. DUMMY_1_URL
|
||||
// 1. TEST_URL
|
||||
// 2. DUMMY_2_URL
|
||||
let tab = yield addTab(DUMMY_1_URL);
|
||||
let browser = tab.linkedBrowser;
|
||||
yield load(browser, TEST_URL);
|
||||
yield load(browser, DUMMY_2_URL);
|
||||
|
||||
// Check session history state
|
||||
let history = yield getSessionHistory(browser);
|
||||
is(history.index, 2, "At page 2 in history");
|
||||
is(history.entries.length, 3, "3 pages in history");
|
||||
is(history.entries[0].uri, DUMMY_1_URL, "Page 0 URL matches");
|
||||
is(history.entries[1].uri, TEST_URL, "Page 1 URL matches");
|
||||
is(history.entries[2].uri, DUMMY_2_URL, "Page 2 URL matches");
|
||||
|
||||
// Go back one so we're at the test page
|
||||
yield back(browser);
|
||||
|
||||
// Check session history state
|
||||
history = yield getSessionHistory(browser);
|
||||
is(history.index, 1, "At page 1 in history");
|
||||
is(history.entries.length, 3, "3 pages in history");
|
||||
is(history.entries[0].uri, DUMMY_1_URL, "Page 0 URL matches");
|
||||
is(history.entries[1].uri, TEST_URL, "Page 1 URL matches");
|
||||
is(history.entries[2].uri, DUMMY_2_URL, "Page 2 URL matches");
|
||||
|
||||
yield openRDM(tab);
|
||||
|
||||
ok(browser.webNavigation.canGoBack, "Going back is allowed");
|
||||
ok(browser.webNavigation.canGoForward, "Going forward is allowed");
|
||||
is(browser.documentURI.spec, TEST_URL, "documentURI matches page 1");
|
||||
is(browser.contentTitle, "Page State Test", "contentTitle matches page 1");
|
||||
|
||||
yield forward(browser);
|
||||
|
||||
ok(browser.webNavigation.canGoBack, "Going back is allowed");
|
||||
ok(!browser.webNavigation.canGoForward, "Going forward is not allowed");
|
||||
is(browser.documentURI.spec, DUMMY_2_URL, "documentURI matches page 2");
|
||||
is(browser.contentTitle, "mochitest index /browser/", "contentTitle matches page 2");
|
||||
|
||||
yield back(browser);
|
||||
yield back(browser);
|
||||
|
||||
ok(!browser.webNavigation.canGoBack, "Going back is not allowed");
|
||||
ok(browser.webNavigation.canGoForward, "Going forward is allowed");
|
||||
is(browser.documentURI.spec, DUMMY_1_URL, "documentURI matches page 0");
|
||||
is(browser.contentTitle, "mochitest index /", "contentTitle matches page 0");
|
||||
|
||||
let receivedStatusChanges = new Promise(resolve => {
|
||||
let statusChangesSeen = 0;
|
||||
let statusChangesExpected = 2;
|
||||
let progressListener = {
|
||||
onStatusChange(webProgress, request, status, message) {
|
||||
info(message);
|
||||
if (++statusChangesSeen == statusChangesExpected) {
|
||||
gBrowser.removeProgressListener(progressListener);
|
||||
ok(true, `${statusChangesExpected} status changes while loading`);
|
||||
resolve();
|
||||
}
|
||||
}
|
||||
};
|
||||
gBrowser.addProgressListener(progressListener);
|
||||
});
|
||||
yield load(browser, DUMMY_3_URL);
|
||||
yield receivedStatusChanges;
|
||||
|
||||
ok(browser.webNavigation.canGoBack, "Going back is allowed");
|
||||
ok(!browser.webNavigation.canGoForward, "Going forward is not allowed");
|
||||
is(browser.documentURI.spec, DUMMY_3_URL, "documentURI matches page 3");
|
||||
is(browser.contentTitle, "mochitest index /browser/devtools/",
|
||||
"contentTitle matches page 3");
|
||||
|
||||
yield closeRDM(tab);
|
||||
|
||||
// Check session history state
|
||||
history = yield getSessionHistory(browser);
|
||||
is(history.index, 1, "At page 1 in history");
|
||||
is(history.entries.length, 2, "2 pages in history");
|
||||
is(history.entries[0].uri, DUMMY_1_URL, "Page 0 URL matches");
|
||||
is(history.entries[1].uri, DUMMY_3_URL, "Page 1 URL matches");
|
||||
|
||||
yield removeTab(tab);
|
||||
});
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
const throttlingProfiles = require("devtools/client/shared/network-throttling-profiles");
|
||||
|
||||
// Tests changing network throttling
|
||||
const TEST_URL = "data:text/html;charset=utf-8,Network throttling test";
|
||||
|
||||
addRDMTask(TEST_URL, function* ({ ui, manager }) {
|
||||
let { store } = ui.toolWindow;
|
||||
|
||||
// Wait until the viewport has been added
|
||||
yield waitUntilState(store, state => state.viewports.length == 1);
|
||||
|
||||
// Test defaults
|
||||
testNetworkThrottlingSelectorLabel(ui, "No throttling");
|
||||
yield testNetworkThrottlingState(ui, null);
|
||||
|
||||
// Test a fast profile
|
||||
yield testThrottlingProfile(ui, "Wi-Fi");
|
||||
|
||||
// Test a slower profile
|
||||
yield testThrottlingProfile(ui, "Regular 3G");
|
||||
|
||||
// Test switching back to no throttling
|
||||
yield selectNetworkThrottling(ui, "No throttling");
|
||||
testNetworkThrottlingSelectorLabel(ui, "No throttling");
|
||||
yield testNetworkThrottlingState(ui, null);
|
||||
});
|
||||
|
||||
function testNetworkThrottlingSelectorLabel(ui, expected) {
|
||||
let selector = "#global-network-throttling-selector";
|
||||
let select = ui.toolWindow.document.querySelector(selector);
|
||||
is(select.selectedOptions[0].textContent, expected,
|
||||
`Select label should be changed to ${expected}`);
|
||||
}
|
||||
|
||||
var testNetworkThrottlingState = Task.async(function* (ui, expected) {
|
||||
let state = yield ui.emulationFront.getNetworkThrottling();
|
||||
Assert.deepEqual(state, expected, "Network throttling state should be " +
|
||||
JSON.stringify(expected, null, 2));
|
||||
});
|
||||
|
||||
var testThrottlingProfile = Task.async(function* (ui, profile) {
|
||||
yield selectNetworkThrottling(ui, profile);
|
||||
testNetworkThrottlingSelectorLabel(ui, profile);
|
||||
let data = throttlingProfiles.find(({ id }) => id == profile);
|
||||
let { download, upload, latency } = data;
|
||||
yield testNetworkThrottlingState(ui, {
|
||||
downloadThroughput: download,
|
||||
uploadThroughput: upload,
|
||||
latency,
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,76 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
// Test page state to ensure page is not reloaded and session history is not
|
||||
// modified.
|
||||
|
||||
const DUMMY_1_URL = "http://example.com/";
|
||||
const TEST_URL = `${URL_ROOT}doc_page_state.html`;
|
||||
const DUMMY_2_URL = "http://example.com/browser/";
|
||||
|
||||
add_task(function* () {
|
||||
// Load up a sequence of pages:
|
||||
// 0. DUMMY_1_URL
|
||||
// 1. TEST_URL
|
||||
// 2. DUMMY_2_URL
|
||||
let tab = yield addTab(DUMMY_1_URL);
|
||||
let browser = tab.linkedBrowser;
|
||||
yield load(browser, TEST_URL);
|
||||
yield load(browser, DUMMY_2_URL);
|
||||
|
||||
// Check session history state
|
||||
let history = yield getSessionHistory(browser);
|
||||
is(history.index, 2, "At page 2 in history");
|
||||
is(history.entries.length, 3, "3 pages in history");
|
||||
is(history.entries[0].uri, DUMMY_1_URL, "Page 0 URL matches");
|
||||
is(history.entries[1].uri, TEST_URL, "Page 1 URL matches");
|
||||
is(history.entries[2].uri, DUMMY_2_URL, "Page 2 URL matches");
|
||||
|
||||
// Go back one so we're at the test page
|
||||
yield back(browser);
|
||||
|
||||
// Check session history state
|
||||
history = yield getSessionHistory(browser);
|
||||
is(history.index, 1, "At page 1 in history");
|
||||
is(history.entries.length, 3, "3 pages in history");
|
||||
is(history.entries[0].uri, DUMMY_1_URL, "Page 0 URL matches");
|
||||
is(history.entries[1].uri, TEST_URL, "Page 1 URL matches");
|
||||
is(history.entries[2].uri, DUMMY_2_URL, "Page 2 URL matches");
|
||||
|
||||
// Click on content to set an altered state that would be lost on reload
|
||||
yield BrowserTestUtils.synthesizeMouseAtCenter("body", {}, browser);
|
||||
|
||||
let { ui } = yield openRDM(tab);
|
||||
|
||||
// Check color inside the viewport
|
||||
let color = yield spawnViewportTask(ui, {}, function* () {
|
||||
// eslint-disable-next-line mozilla/no-cpows-in-tests
|
||||
return content.getComputedStyle(content.document.body)
|
||||
.getPropertyValue("background-color");
|
||||
});
|
||||
is(color, "rgb(0, 128, 0)",
|
||||
"Content is still modified from click in viewport");
|
||||
|
||||
yield closeRDM(tab);
|
||||
|
||||
// Check color back in the browser tab
|
||||
color = yield ContentTask.spawn(browser, {}, function* () {
|
||||
// eslint-disable-next-line mozilla/no-cpows-in-tests
|
||||
return content.getComputedStyle(content.document.body)
|
||||
.getPropertyValue("background-color");
|
||||
});
|
||||
is(color, "rgb(0, 128, 0)",
|
||||
"Content is still modified from click in browser tab");
|
||||
|
||||
// Check session history state
|
||||
history = yield getSessionHistory(browser);
|
||||
is(history.index, 1, "At page 1 in history");
|
||||
is(history.entries.length, 3, "3 pages in history");
|
||||
is(history.entries[0].uri, DUMMY_1_URL, "Page 0 URL matches");
|
||||
is(history.entries[1].uri, TEST_URL, "Page 1 URL matches");
|
||||
is(history.entries[2].uri, DUMMY_2_URL, "Page 2 URL matches");
|
||||
|
||||
yield removeTab(tab);
|
||||
});
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
// Test that permission popups asking for user approval still appear in RDM
|
||||
const DUMMY_URL = "http://example.com/";
|
||||
const TEST_URL = `${URL_ROOT}geolocation.html`;
|
||||
|
||||
function waitForGeolocationPrompt(win, browser) {
|
||||
return new Promise(resolve => {
|
||||
win.PopupNotifications.panel.addEventListener("popupshown", function popupShown() {
|
||||
let notification = win.PopupNotifications.getNotification("geolocation", browser);
|
||||
if (notification) {
|
||||
win.PopupNotifications.panel.removeEventListener("popupshown", popupShown);
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
add_task(function* () {
|
||||
let tab = yield addTab(DUMMY_URL);
|
||||
let browser = tab.linkedBrowser;
|
||||
let win = browser.ownerGlobal;
|
||||
|
||||
let waitPromptPromise = waitForGeolocationPrompt(win, browser);
|
||||
|
||||
// Checks if a geolocation permission doorhanger appears when openning a page
|
||||
// requesting geolocation
|
||||
yield load(browser, TEST_URL);
|
||||
yield waitPromptPromise;
|
||||
|
||||
ok(true, "Permission doorhanger appeared without RDM enabled");
|
||||
|
||||
// Lets switch back to the dummy website and enable RDM
|
||||
yield load(browser, DUMMY_URL);
|
||||
let { ui } = yield openRDM(tab);
|
||||
let newBrowser = ui.getViewportBrowser();
|
||||
|
||||
waitPromptPromise = waitForGeolocationPrompt(win, newBrowser);
|
||||
|
||||
// Checks if the doorhanger appeared again when reloading the geolocation
|
||||
// page inside RDM
|
||||
yield load(browser, TEST_URL);
|
||||
yield waitPromptPromise;
|
||||
|
||||
ok(true, "Permission doorhanger appeared inside RDM");
|
||||
|
||||
yield closeRDM(tab);
|
||||
yield removeTab(tab);
|
||||
});
|
||||
|
|
@ -0,0 +1,148 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
/* global ResponsiveUIManager */
|
||||
/* eslint key-spacing: 0 */
|
||||
|
||||
add_task(function* () {
|
||||
let manager = ResponsiveUIManager;
|
||||
let done;
|
||||
|
||||
function isOpen() {
|
||||
return ResponsiveUIManager.isActiveForTab(gBrowser.selectedTab);
|
||||
}
|
||||
|
||||
const TEST_URL = "data:text/html;charset=utf-8,hi";
|
||||
yield helpers.addTabWithToolbar(TEST_URL, (options) => {
|
||||
return helpers.audit(options, [
|
||||
{
|
||||
setup() {
|
||||
done = once(manager, "on");
|
||||
return helpers.setInput(options, "resize toggle");
|
||||
},
|
||||
check: {
|
||||
input: "resize toggle",
|
||||
hints: "",
|
||||
markup: "VVVVVVVVVVVVV",
|
||||
status: "VALID"
|
||||
},
|
||||
exec: {
|
||||
output: ""
|
||||
},
|
||||
post: Task.async(function* () {
|
||||
yield done;
|
||||
ok(isOpen(), "responsive mode is open");
|
||||
}),
|
||||
},
|
||||
{
|
||||
setup() {
|
||||
done = once(manager, "off");
|
||||
return helpers.setInput(options, "resize toggle");
|
||||
},
|
||||
check: {
|
||||
input: "resize toggle",
|
||||
hints: "",
|
||||
markup: "VVVVVVVVVVVVV",
|
||||
status: "VALID"
|
||||
},
|
||||
exec: {
|
||||
output: ""
|
||||
},
|
||||
post: Task.async(function* () {
|
||||
yield done;
|
||||
ok(!isOpen(), "responsive mode is closed");
|
||||
}),
|
||||
},
|
||||
]);
|
||||
});
|
||||
yield helpers.addTabWithToolbar(TEST_URL, (options) => {
|
||||
return helpers.audit(options, [
|
||||
{
|
||||
setup() {
|
||||
done = once(manager, "on");
|
||||
return helpers.setInput(options, "resize on");
|
||||
},
|
||||
check: {
|
||||
input: "resize on",
|
||||
hints: "",
|
||||
markup: "VVVVVVVVV",
|
||||
status: "VALID"
|
||||
},
|
||||
exec: {
|
||||
output: ""
|
||||
},
|
||||
post: Task.async(function* () {
|
||||
yield done;
|
||||
ok(isOpen(), "responsive mode is open");
|
||||
}),
|
||||
},
|
||||
{
|
||||
setup() {
|
||||
done = once(manager, "off");
|
||||
return helpers.setInput(options, "resize off");
|
||||
},
|
||||
check: {
|
||||
input: "resize off",
|
||||
hints: "",
|
||||
markup: "VVVVVVVVVV",
|
||||
status: "VALID"
|
||||
},
|
||||
exec: {
|
||||
output: ""
|
||||
},
|
||||
post: Task.async(function* () {
|
||||
yield done;
|
||||
ok(!isOpen(), "responsive mode is closed");
|
||||
}),
|
||||
},
|
||||
]);
|
||||
});
|
||||
yield helpers.addTabWithToolbar(TEST_URL, (options) => {
|
||||
return helpers.audit(options, [
|
||||
{
|
||||
setup() {
|
||||
done = once(manager, "on");
|
||||
return helpers.setInput(options, "resize to 400 400");
|
||||
},
|
||||
check: {
|
||||
input: "resize to 400 400",
|
||||
hints: "",
|
||||
markup: "VVVVVVVVVVVVVVVVV",
|
||||
status: "VALID",
|
||||
args: {
|
||||
width: { value: 400 },
|
||||
height: { value: 400 },
|
||||
}
|
||||
},
|
||||
exec: {
|
||||
output: ""
|
||||
},
|
||||
post: Task.async(function* () {
|
||||
yield done;
|
||||
ok(isOpen(), "responsive mode is open");
|
||||
}),
|
||||
},
|
||||
{
|
||||
setup() {
|
||||
done = once(manager, "off");
|
||||
return helpers.setInput(options, "resize off");
|
||||
},
|
||||
check: {
|
||||
input: "resize off",
|
||||
hints: "",
|
||||
markup: "VVVVVVVVVV",
|
||||
status: "VALID"
|
||||
},
|
||||
exec: {
|
||||
output: ""
|
||||
},
|
||||
post: Task.async(function* () {
|
||||
yield done;
|
||||
ok(!isOpen(), "responsive mode is closed");
|
||||
}),
|
||||
},
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
// Test global exit button
|
||||
|
||||
const TEST_URL = "data:text/html;charset=utf-8,";
|
||||
|
||||
const { OS } = require("resource://gre/modules/osfile.jsm");
|
||||
|
||||
function* waitUntilScreenshot() {
|
||||
return new Promise(Task.async(function* (resolve) {
|
||||
let { Downloads } = require("resource://gre/modules/Downloads.jsm");
|
||||
let list = yield Downloads.getList(Downloads.ALL);
|
||||
|
||||
let view = {
|
||||
onDownloadAdded: download => {
|
||||
download.whenSucceeded().then(() => {
|
||||
resolve(download.target.path);
|
||||
list.removeView(view);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
yield list.addView(view);
|
||||
}));
|
||||
}
|
||||
|
||||
addRDMTask(TEST_URL, function* ({ ui: {toolWindow} }) {
|
||||
let { store, document } = toolWindow;
|
||||
|
||||
// Wait until the viewport has been added
|
||||
yield waitUntilState(store, state => state.viewports.length == 1);
|
||||
|
||||
info("Click the screenshot button");
|
||||
let screenshotButton = document.getElementById("global-screenshot-button");
|
||||
screenshotButton.click();
|
||||
|
||||
let whenScreenshotSucceeded = waitUntilScreenshot();
|
||||
|
||||
let filePath = yield whenScreenshotSucceeded;
|
||||
let image = new Image();
|
||||
image.src = OS.Path.toFileURI(filePath);
|
||||
|
||||
yield once(image, "load");
|
||||
|
||||
// We have only one viewport at the moment
|
||||
let viewport = store.getState().viewports[0];
|
||||
let ratio = window.devicePixelRatio;
|
||||
|
||||
is(image.width, viewport.width * ratio,
|
||||
"screenshot width has the expected width");
|
||||
|
||||
is(image.height, viewport.height * ratio,
|
||||
"screenshot width has the expected height");
|
||||
|
||||
yield OS.File.remove(filePath);
|
||||
});
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
// Verify RDM closes synchronously when tabs are closed.
|
||||
|
||||
const TEST_URL = "http://example.com/";
|
||||
|
||||
add_task(function* () {
|
||||
let tab = yield addTab(TEST_URL);
|
||||
|
||||
let { ui } = yield openRDM(tab);
|
||||
let clientClosed = waitForClientClose(ui);
|
||||
|
||||
closeRDM(tab, {
|
||||
reason: "TabClose",
|
||||
});
|
||||
|
||||
// This flag is set at the end of `ResponsiveUI.destroy`. If it is true
|
||||
// without yielding on `closeRDM` above, then we must have closed
|
||||
// synchronously.
|
||||
is(ui.destroyed, true, "RDM closed synchronously");
|
||||
|
||||
yield clientClosed;
|
||||
yield removeTab(tab);
|
||||
});
|
||||
|
||||
add_task(function* () {
|
||||
let tab = yield addTab(TEST_URL);
|
||||
|
||||
let { ui } = yield openRDM(tab);
|
||||
let clientClosed = waitForClientClose(ui);
|
||||
|
||||
yield removeTab(tab);
|
||||
|
||||
// This flag is set at the end of `ResponsiveUI.destroy`. If it is true without
|
||||
// yielding on `closeRDM` itself and only removing the tab, then we must have closed
|
||||
// synchronously in response to tab closing.
|
||||
is(ui.destroyed, true, "RDM closed synchronously");
|
||||
|
||||
yield clientClosed;
|
||||
});
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
// Verify RDM closes synchronously when tabs change remoteness.
|
||||
|
||||
const TEST_URL = "http://example.com/";
|
||||
|
||||
add_task(function* () {
|
||||
let tab = yield addTab(TEST_URL);
|
||||
|
||||
let { ui } = yield openRDM(tab);
|
||||
let clientClosed = waitForClientClose(ui);
|
||||
|
||||
closeRDM(tab, {
|
||||
reason: "BeforeTabRemotenessChange",
|
||||
});
|
||||
|
||||
// This flag is set at the end of `ResponsiveUI.destroy`. If it is true
|
||||
// without yielding on `closeRDM` above, then we must have closed
|
||||
// synchronously.
|
||||
is(ui.destroyed, true, "RDM closed synchronously");
|
||||
|
||||
yield clientClosed;
|
||||
yield removeTab(tab);
|
||||
});
|
||||
|
||||
add_task(function* () {
|
||||
let tab = yield addTab(TEST_URL);
|
||||
|
||||
let { ui } = yield openRDM(tab);
|
||||
let clientClosed = waitForClientClose(ui);
|
||||
|
||||
// Load URL that requires the main process, forcing a remoteness flip
|
||||
yield load(tab.linkedBrowser, "about:robots");
|
||||
|
||||
// This flag is set at the end of `ResponsiveUI.destroy`. If it is true without
|
||||
// yielding on `closeRDM` itself and only removing the tab, then we must have closed
|
||||
// synchronously in response to tab closing.
|
||||
is(ui.destroyed, true, "RDM closed synchronously");
|
||||
|
||||
yield clientClosed;
|
||||
yield removeTab(tab);
|
||||
});
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
// Check that when the viewport is resized, the computed-view refreshes.
|
||||
|
||||
const TEST_URI = "data:text/html;charset=utf-8,<html><style>" +
|
||||
"div {" +
|
||||
" width: 500px;" +
|
||||
" height: 10px;" +
|
||||
" background: purple;" +
|
||||
"} " +
|
||||
"@media screen and (max-width: 200px) {" +
|
||||
" div { " +
|
||||
" width: 100px;" +
|
||||
" }" +
|
||||
"};" +
|
||||
"</style><div></div></html>";
|
||||
|
||||
addRDMTask(TEST_URI, function* ({ ui, manager }) {
|
||||
info("Open the responsive design mode and set its size to 500x500 to start");
|
||||
yield setViewportSize(ui, manager, 500, 500);
|
||||
|
||||
info("Open the inspector, computed-view and select the test node");
|
||||
let { inspector, view } = yield openComputedView();
|
||||
yield selectNode("div", inspector);
|
||||
|
||||
info("Try shrinking the viewport and checking the applied styles");
|
||||
yield testShrink(view, inspector, ui, manager);
|
||||
|
||||
info("Try growing the viewport and checking the applied styles");
|
||||
yield testGrow(view, inspector, ui, manager);
|
||||
|
||||
yield closeToolbox();
|
||||
});
|
||||
|
||||
function* testShrink(computedView, inspector, ui, manager) {
|
||||
is(computedWidth(computedView), "500px", "Should show 500px initially.");
|
||||
|
||||
let onRefresh = inspector.once("computed-view-refreshed");
|
||||
yield setViewportSize(ui, manager, 100, 100);
|
||||
yield onRefresh;
|
||||
|
||||
is(computedWidth(computedView), "100px", "Should be 100px after shrinking.");
|
||||
}
|
||||
|
||||
function* testGrow(computedView, inspector, ui, manager) {
|
||||
let onRefresh = inspector.once("computed-view-refreshed");
|
||||
yield setViewportSize(ui, manager, 500, 500);
|
||||
yield onRefresh;
|
||||
|
||||
is(computedWidth(computedView), "500px", "Should be 500px after growing.");
|
||||
}
|
||||
|
||||
function computedWidth(computedView) {
|
||||
for (let prop of computedView.propertyViews) {
|
||||
if (prop.name === "width") {
|
||||
return prop.valueNode.textContent;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
|
@ -0,0 +1,78 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
// Check that when the viewport is resized, the rule-view refreshes.
|
||||
|
||||
const TEST_URI = "data:text/html;charset=utf-8,<html><style>" +
|
||||
"div {" +
|
||||
" width: 500px;" +
|
||||
" height: 10px;" +
|
||||
" background: purple;" +
|
||||
"} " +
|
||||
"@media screen and (max-width: 200px) {" +
|
||||
" div { " +
|
||||
" width: 100px;" +
|
||||
" }" +
|
||||
"};" +
|
||||
"</style><div></div></html>";
|
||||
|
||||
registerCleanupFunction(() => {
|
||||
Services.prefs.clearUserPref("devtools.toolbox.splitconsoleEnabled");
|
||||
});
|
||||
|
||||
addRDMTask(TEST_URI, function* ({ ui, manager }) {
|
||||
info("Open the responsive design mode and set its size to 500x500 to start");
|
||||
yield setViewportSize(ui, manager, 500, 500);
|
||||
|
||||
info("Open the inspector, rule-view and select the test node");
|
||||
let { inspector, view } = yield openRuleView();
|
||||
yield selectNode("div", inspector);
|
||||
|
||||
info("Try shrinking the viewport and checking the applied styles");
|
||||
yield testShrink(view, ui, manager);
|
||||
|
||||
info("Try growing the viewport and checking the applied styles");
|
||||
yield testGrow(view, ui, manager);
|
||||
|
||||
info("Check that ESC still opens the split console");
|
||||
yield testEscapeOpensSplitConsole(inspector);
|
||||
|
||||
yield closeToolbox();
|
||||
});
|
||||
|
||||
function* testShrink(ruleView, ui, manager) {
|
||||
is(numberOfRules(ruleView), 2, "Should have two rules initially.");
|
||||
|
||||
info("Resize to 100x100 and wait for the rule-view to update");
|
||||
let onRefresh = ruleView.once("ruleview-refreshed");
|
||||
yield setViewportSize(ui, manager, 100, 100);
|
||||
yield onRefresh;
|
||||
|
||||
is(numberOfRules(ruleView), 3, "Should have three rules after shrinking.");
|
||||
}
|
||||
|
||||
function* testGrow(ruleView, ui, manager) {
|
||||
info("Resize to 500x500 and wait for the rule-view to update");
|
||||
let onRefresh = ruleView.once("ruleview-refreshed");
|
||||
yield setViewportSize(ui, manager, 500, 500);
|
||||
yield onRefresh;
|
||||
|
||||
is(numberOfRules(ruleView), 2, "Should have two rules after growing.");
|
||||
}
|
||||
|
||||
function* testEscapeOpensSplitConsole(inspector) {
|
||||
ok(!inspector._toolbox._splitConsole, "Console is not split.");
|
||||
|
||||
info("Press escape");
|
||||
let onSplit = inspector._toolbox.once("split-console");
|
||||
EventUtils.synthesizeKey("VK_ESCAPE", {});
|
||||
yield onSplit;
|
||||
|
||||
ok(inspector._toolbox._splitConsole, "Console is split after pressing ESC.");
|
||||
}
|
||||
|
||||
function numberOfRules(ruleView) {
|
||||
return ruleView.element.querySelectorAll(".ruleview-code").length;
|
||||
}
|
||||
|
|
@ -0,0 +1,128 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
// Verify that toolbox remains open when opening and closing RDM.
|
||||
|
||||
const TEST_URL = "http://example.com/";
|
||||
|
||||
function getServerConnections(browser) {
|
||||
ok(browser.isRemoteBrowser, "Content browser is remote");
|
||||
return ContentTask.spawn(browser, {}, function* () {
|
||||
const Cu = Components.utils;
|
||||
const { require } = Cu.import("resource://devtools/shared/Loader.jsm", {});
|
||||
const { DebuggerServer } = require("devtools/server/main");
|
||||
if (!DebuggerServer._connections) {
|
||||
return 0;
|
||||
}
|
||||
return Object.getOwnPropertyNames(DebuggerServer._connections);
|
||||
});
|
||||
}
|
||||
|
||||
let checkServerConnectionCount = Task.async(function* (browser, expected, msg) {
|
||||
let conns = yield getServerConnections(browser);
|
||||
is(conns.length || 0, expected, "Server connection count: " + msg);
|
||||
});
|
||||
|
||||
let checkToolbox = Task.async(function* (tab, location) {
|
||||
let target = TargetFactory.forTab(tab);
|
||||
ok(!!gDevTools.getToolbox(target), `Toolbox exists ${location}`);
|
||||
});
|
||||
|
||||
add_task(function* setup() {
|
||||
yield SpecialPowers.pushPrefEnv({
|
||||
set: [["dom.ipc.processCount", 1]]
|
||||
});
|
||||
});
|
||||
|
||||
add_task(function* () {
|
||||
let tab = yield addTab(TEST_URL);
|
||||
|
||||
let tabsInDifferentProcesses = E10S_MULTI_ENABLED &&
|
||||
(gBrowser.tabs[0].linkedBrowser.frameLoader.childID !=
|
||||
gBrowser.tabs[1].linkedBrowser.frameLoader.childID);
|
||||
|
||||
info("Open toolbox outside RDM");
|
||||
{
|
||||
// 0: No DevTools connections yet
|
||||
yield checkServerConnectionCount(tab.linkedBrowser, 0,
|
||||
"0: No DevTools connections yet");
|
||||
let { toolbox } = yield openInspector();
|
||||
if (tabsInDifferentProcesses) {
|
||||
// 1: Two tabs open, but only one per content process
|
||||
yield checkServerConnectionCount(tab.linkedBrowser, 1,
|
||||
"1: Two tabs open, but only one per content process");
|
||||
} else {
|
||||
// 2: One for each tab (starting tab plus the one we opened)
|
||||
yield checkServerConnectionCount(tab.linkedBrowser, 2,
|
||||
"2: One for each tab (starting tab plus the one we opened)");
|
||||
}
|
||||
yield checkToolbox(tab, "outside RDM");
|
||||
let { ui } = yield openRDM(tab);
|
||||
if (tabsInDifferentProcesses) {
|
||||
// 2: RDM UI adds an extra connection, 1 + 1 = 2
|
||||
yield checkServerConnectionCount(ui.getViewportBrowser(), 2,
|
||||
"2: RDM UI uses an extra connection");
|
||||
} else {
|
||||
// 3: RDM UI adds an extra connection, 2 + 1 = 3
|
||||
yield checkServerConnectionCount(ui.getViewportBrowser(), 3,
|
||||
"3: RDM UI uses an extra connection");
|
||||
}
|
||||
yield checkToolbox(tab, "after opening RDM");
|
||||
yield closeRDM(tab);
|
||||
if (tabsInDifferentProcesses) {
|
||||
// 1: RDM UI closed, return to previous connection count
|
||||
yield checkServerConnectionCount(tab.linkedBrowser, 1,
|
||||
"1: RDM UI closed, return to previous connection count");
|
||||
} else {
|
||||
// 2: RDM UI closed, return to previous connection count
|
||||
yield checkServerConnectionCount(tab.linkedBrowser, 2,
|
||||
"2: RDM UI closed, return to previous connection count");
|
||||
}
|
||||
yield checkToolbox(tab, tab.linkedBrowser, "after closing RDM");
|
||||
yield toolbox.destroy();
|
||||
// 0: All DevTools usage closed
|
||||
yield checkServerConnectionCount(tab.linkedBrowser, 0,
|
||||
"0: All DevTools usage closed");
|
||||
}
|
||||
|
||||
info("Open toolbox inside RDM");
|
||||
{
|
||||
// 0: No DevTools connections yet
|
||||
yield checkServerConnectionCount(tab.linkedBrowser, 0,
|
||||
"0: No DevTools connections yet");
|
||||
let { ui } = yield openRDM(tab);
|
||||
// 1: RDM UI uses an extra connection
|
||||
yield checkServerConnectionCount(ui.getViewportBrowser(), 1,
|
||||
"1: RDM UI uses an extra connection");
|
||||
let { toolbox } = yield openInspector();
|
||||
if (tabsInDifferentProcesses) {
|
||||
// 2: Two tabs open, but only one per content process
|
||||
yield checkServerConnectionCount(ui.getViewportBrowser(), 2,
|
||||
"2: Two tabs open, but only one per content process");
|
||||
} else {
|
||||
// 3: One for each tab (starting tab plus the one we opened)
|
||||
yield checkServerConnectionCount(ui.getViewportBrowser(), 3,
|
||||
"3: One for each tab (starting tab plus the one we opened)");
|
||||
}
|
||||
yield checkToolbox(tab, ui.getViewportBrowser(), "inside RDM");
|
||||
yield closeRDM(tab);
|
||||
if (tabsInDifferentProcesses) {
|
||||
// 1: RDM UI closed, one less connection
|
||||
yield checkServerConnectionCount(tab.linkedBrowser, 1,
|
||||
"1: RDM UI closed, one less connection");
|
||||
} else {
|
||||
// 2: RDM UI closed, one less connection
|
||||
yield checkServerConnectionCount(tab.linkedBrowser, 2,
|
||||
"2: RDM UI closed, one less connection");
|
||||
}
|
||||
yield checkToolbox(tab, tab.linkedBrowser, "after closing RDM");
|
||||
yield toolbox.destroy();
|
||||
// 0: All DevTools usage closed
|
||||
yield checkServerConnectionCount(tab.linkedBrowser, 0,
|
||||
"0: All DevTools usage closed");
|
||||
}
|
||||
|
||||
yield removeTab(tab);
|
||||
});
|
||||
|
|
@ -0,0 +1,77 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
// Tests changing viewport touch simulation
|
||||
const TEST_URL = "data:text/html;charset=utf-8,touch simulation test";
|
||||
const Types = require("devtools/client/responsive.html/types");
|
||||
|
||||
const testDevice = {
|
||||
"name": "Fake Phone RDM Test",
|
||||
"width": 320,
|
||||
"height": 470,
|
||||
"pixelRatio": 5.5,
|
||||
"userAgent": "Mozilla/5.0 (Mobile; rv:39.0) Gecko/39.0 Firefox/39.0",
|
||||
"touch": true,
|
||||
"firefoxOS": true,
|
||||
"os": "custom",
|
||||
"featured": true,
|
||||
};
|
||||
|
||||
// Add the new device to the list
|
||||
addDeviceForTest(testDevice);
|
||||
|
||||
addRDMTask(TEST_URL, function* ({ ui, manager }) {
|
||||
yield waitStartup(ui);
|
||||
|
||||
yield testDefaults(ui);
|
||||
yield testChangingDevice(ui);
|
||||
yield testResizingViewport(ui, true, false);
|
||||
yield testEnableTouchSimulation(ui);
|
||||
yield testResizingViewport(ui, false, true);
|
||||
});
|
||||
|
||||
function* waitStartup(ui) {
|
||||
let { store } = ui.toolWindow;
|
||||
|
||||
// Wait until the viewport has been added and the device list has been loaded
|
||||
yield waitUntilState(store, state => state.viewports.length == 1
|
||||
&& state.devices.listState == Types.deviceListState.LOADED);
|
||||
}
|
||||
|
||||
function* testDefaults(ui) {
|
||||
info("Test Defaults");
|
||||
|
||||
yield testTouchEventsOverride(ui, false);
|
||||
testViewportDeviceSelectLabel(ui, "no device selected");
|
||||
}
|
||||
|
||||
function* testChangingDevice(ui) {
|
||||
info("Test Changing Device");
|
||||
|
||||
yield selectDevice(ui, testDevice.name);
|
||||
yield waitForViewportResizeTo(ui, testDevice.width, testDevice.height);
|
||||
yield testTouchEventsOverride(ui, true);
|
||||
testViewportDeviceSelectLabel(ui, testDevice.name);
|
||||
}
|
||||
|
||||
function* testResizingViewport(ui, device, expected) {
|
||||
info(`Test resizing the viewport, device ${device}, expected ${expected}`);
|
||||
|
||||
let deviceRemoved = once(ui, "device-removed");
|
||||
yield testViewportResize(ui, ".viewport-vertical-resize-handle",
|
||||
[-10, -10], [testDevice.width, testDevice.height - 10], [0, -10], ui);
|
||||
if (device) {
|
||||
yield deviceRemoved;
|
||||
}
|
||||
yield testTouchEventsOverride(ui, expected);
|
||||
testViewportDeviceSelectLabel(ui, "no device selected");
|
||||
}
|
||||
|
||||
function* testEnableTouchSimulation(ui) {
|
||||
info("Test enabling touch simulation via button");
|
||||
|
||||
yield enableTouchSimulation(ui);
|
||||
yield testTouchEventsOverride(ui, true);
|
||||
}
|
||||
|
|
@ -0,0 +1,228 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
// Test global touch simulation button
|
||||
|
||||
const TEST_URL = `${URL_ROOT}touch.html`;
|
||||
const PREF_DOM_META_VIEWPORT_ENABLED = "dom.meta-viewport.enabled";
|
||||
|
||||
addRDMTask(TEST_URL, function* ({ ui }) {
|
||||
yield waitBootstrap(ui);
|
||||
yield testWithNoTouch(ui);
|
||||
yield enableTouchSimulation(ui);
|
||||
yield testWithTouch(ui);
|
||||
yield testWithMetaViewportEnabled(ui);
|
||||
yield testWithMetaViewportDisabled(ui);
|
||||
testTouchButton(ui);
|
||||
});
|
||||
|
||||
function* testWithNoTouch(ui) {
|
||||
yield injectEventUtils(ui);
|
||||
yield ContentTask.spawn(ui.getViewportBrowser(), {}, function* () {
|
||||
let { EventUtils } = content;
|
||||
|
||||
let div = content.document.querySelector("div");
|
||||
let x = 0, y = 0;
|
||||
|
||||
info("testWithNoTouch: Initial test parameter and mouse mouse outside div");
|
||||
x = -1; y = -1;
|
||||
yield EventUtils.synthesizeMouse(div, x, y,
|
||||
{ type: "mousemove", isSynthesized: false }, content);
|
||||
div.style.transform = "none";
|
||||
div.style.backgroundColor = "";
|
||||
|
||||
info("testWithNoTouch: Move mouse into the div element");
|
||||
yield EventUtils.synthesizeMouseAtCenter(div,
|
||||
{ type: "mousemove", isSynthesized: false }, content);
|
||||
is(div.style.backgroundColor, "red", "mouseenter or mouseover should work");
|
||||
|
||||
info("testWithNoTouch: Drag the div element");
|
||||
yield EventUtils.synthesizeMouseAtCenter(div,
|
||||
{ type: "mousedown", isSynthesized: false }, content);
|
||||
x = 100; y = 100;
|
||||
yield EventUtils.synthesizeMouse(div, x, y,
|
||||
{ type: "mousemove", isSynthesized: false }, content);
|
||||
is(div.style.transform, "none", "touchmove shouldn't work");
|
||||
yield EventUtils.synthesizeMouse(div, x, y,
|
||||
{ type: "mouseup", isSynthesized: false }, content);
|
||||
|
||||
info("testWithNoTouch: Move mouse out of the div element");
|
||||
x = -1; y = -1;
|
||||
yield EventUtils.synthesizeMouse(div, x, y,
|
||||
{ type: "mousemove", isSynthesized: false }, content);
|
||||
is(div.style.backgroundColor, "blue", "mouseout or mouseleave should work");
|
||||
|
||||
info("testWithNoTouch: Click the div element");
|
||||
yield EventUtils.synthesizeClick(div);
|
||||
is(div.dataset.isDelay, "false",
|
||||
"300ms delay between touch events and mouse events should not work");
|
||||
});
|
||||
}
|
||||
|
||||
function* testWithTouch(ui) {
|
||||
yield injectEventUtils(ui);
|
||||
|
||||
yield ContentTask.spawn(ui.getViewportBrowser(), {}, function* () {
|
||||
let { EventUtils } = content;
|
||||
|
||||
let div = content.document.querySelector("div");
|
||||
let x = 0, y = 0;
|
||||
|
||||
info("testWithTouch: Initial test parameter and mouse mouse outside div");
|
||||
x = -1; y = -1;
|
||||
yield EventUtils.synthesizeMouse(div, x, y,
|
||||
{ type: "mousemove", isSynthesized: false }, content);
|
||||
div.style.transform = "none";
|
||||
div.style.backgroundColor = "";
|
||||
|
||||
info("testWithTouch: Move mouse into the div element");
|
||||
yield EventUtils.synthesizeMouseAtCenter(div,
|
||||
{ type: "mousemove", isSynthesized: false }, content);
|
||||
isnot(div.style.backgroundColor, "red",
|
||||
"mouseenter or mouseover should not work");
|
||||
|
||||
info("testWithTouch: Drag the div element");
|
||||
yield EventUtils.synthesizeMouseAtCenter(div,
|
||||
{ type: "mousedown", isSynthesized: false }, content);
|
||||
x = 100; y = 100;
|
||||
yield EventUtils.synthesizeMouse(div, x, y,
|
||||
{ type: "mousemove", isSynthesized: false }, content);
|
||||
isnot(div.style.transform, "none", "touchmove should work");
|
||||
yield EventUtils.synthesizeMouse(div, x, y,
|
||||
{ type: "mouseup", isSynthesized: false }, content);
|
||||
|
||||
info("testWithTouch: Move mouse out of the div element");
|
||||
x = -1; y = -1;
|
||||
yield EventUtils.synthesizeMouse(div, x, y,
|
||||
{ type: "mousemove", isSynthesized: false }, content);
|
||||
isnot(div.style.backgroundColor, "blue",
|
||||
"mouseout or mouseleave should not work");
|
||||
});
|
||||
}
|
||||
|
||||
function* testWithMetaViewportEnabled(ui) {
|
||||
yield SpecialPowers.pushPrefEnv({set: [[PREF_DOM_META_VIEWPORT_ENABLED, true]]});
|
||||
|
||||
yield injectEventUtils(ui);
|
||||
|
||||
yield ContentTask.spawn(ui.getViewportBrowser(), {}, function* () {
|
||||
let { synthesizeClick } = content.EventUtils;
|
||||
|
||||
let meta = content.document.querySelector("meta[name=viewport]");
|
||||
let div = content.document.querySelector("div");
|
||||
div.dataset.isDelay = "false";
|
||||
|
||||
info("testWithMetaViewportEnabled: " +
|
||||
"click the div element with <meta name='viewport'>");
|
||||
meta.content = "";
|
||||
yield synthesizeClick(div);
|
||||
is(div.dataset.isDelay, "true",
|
||||
"300ms delay between touch events and mouse events should work");
|
||||
|
||||
info("testWithMetaViewportEnabled: " +
|
||||
"click the div element with " +
|
||||
"<meta name='viewport' content='user-scalable=no'>");
|
||||
meta.content = "user-scalable=no";
|
||||
yield synthesizeClick(div);
|
||||
is(div.dataset.isDelay, "false",
|
||||
"300ms delay between touch events and mouse events should not work");
|
||||
|
||||
info("testWithMetaViewportEnabled: " +
|
||||
"click the div element with " +
|
||||
"<meta name='viewport' content='minimum-scale=maximum-scale'>");
|
||||
meta.content = "minimum-scale=maximum-scale";
|
||||
yield synthesizeClick(div);
|
||||
is(div.dataset.isDelay, "false",
|
||||
"300ms delay between touch events and mouse events should not work");
|
||||
|
||||
info("testWithMetaViewportEnabled: " +
|
||||
"click the div element with " +
|
||||
"<meta name='viewport' content='width=device-width'>");
|
||||
meta.content = "width=device-width";
|
||||
yield synthesizeClick(div);
|
||||
is(div.dataset.isDelay, "false",
|
||||
"300ms delay between touch events and mouse events should not work");
|
||||
});
|
||||
}
|
||||
|
||||
function* testWithMetaViewportDisabled(ui) {
|
||||
yield SpecialPowers.pushPrefEnv({set: [[PREF_DOM_META_VIEWPORT_ENABLED, false]]});
|
||||
|
||||
yield injectEventUtils(ui);
|
||||
|
||||
yield ContentTask.spawn(ui.getViewportBrowser(), {}, function* () {
|
||||
let { synthesizeClick } = content.EventUtils;
|
||||
|
||||
let meta = content.document.querySelector("meta[name=viewport]");
|
||||
let div = content.document.querySelector("div");
|
||||
div.dataset.isDelay = "false";
|
||||
|
||||
info("testWithMetaViewportDisabled: click the div with <meta name='viewport'>");
|
||||
meta.content = "";
|
||||
yield synthesizeClick(div);
|
||||
is(div.dataset.isDelay, "true",
|
||||
"300ms delay between touch events and mouse events should work");
|
||||
});
|
||||
}
|
||||
|
||||
function testTouchButton(ui) {
|
||||
let { document } = ui.toolWindow;
|
||||
let touchButton = document.querySelector("#global-touch-simulation-button");
|
||||
|
||||
ok(touchButton.classList.contains("active"),
|
||||
"Touch simulation is active at end of test.");
|
||||
|
||||
touchButton.click();
|
||||
|
||||
ok(!touchButton.classList.contains("active"),
|
||||
"Touch simulation is stopped on click.");
|
||||
|
||||
touchButton.click();
|
||||
|
||||
ok(touchButton.classList.contains("active"),
|
||||
"Touch simulation is started on click.");
|
||||
}
|
||||
|
||||
function* waitBootstrap(ui) {
|
||||
let { store } = ui.toolWindow;
|
||||
|
||||
yield waitUntilState(store, state => state.viewports.length == 1);
|
||||
yield waitForFrameLoad(ui, TEST_URL);
|
||||
}
|
||||
|
||||
function* injectEventUtils(ui) {
|
||||
yield ContentTask.spawn(ui.getViewportBrowser(), {}, function* () {
|
||||
if ("EventUtils" in content) {
|
||||
return;
|
||||
}
|
||||
|
||||
let EventUtils = content.EventUtils = {};
|
||||
|
||||
EventUtils.window = {};
|
||||
EventUtils.parent = EventUtils.window;
|
||||
/* eslint-disable camelcase */
|
||||
EventUtils._EU_Ci = Components.interfaces;
|
||||
EventUtils._EU_Cc = Components.classes;
|
||||
/* eslint-enable camelcase */
|
||||
// EventUtils' `sendChar` function relies on the navigator to synthetize events.
|
||||
EventUtils.navigator = content.navigator;
|
||||
EventUtils.KeyboardEvent = content.KeyboardEvent;
|
||||
|
||||
EventUtils.synthesizeClick = element => new Promise(resolve => {
|
||||
element.addEventListener("click", function onClick() {
|
||||
element.removeEventListener("click", onClick);
|
||||
resolve();
|
||||
});
|
||||
|
||||
EventUtils.synthesizeMouseAtCenter(element,
|
||||
{ type: "mousedown", isSynthesized: false }, content);
|
||||
EventUtils.synthesizeMouseAtCenter(element,
|
||||
{ type: "mouseup", isSynthesized: false }, content);
|
||||
});
|
||||
|
||||
Services.scriptloader.loadSubScript(
|
||||
"chrome://mochikit/content/tests/SimpleTest/EventUtils.js", EventUtils);
|
||||
});
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
// Test viewports basics after opening, like size and location
|
||||
|
||||
const TEST_URL = "http://example.org/";
|
||||
|
||||
addRDMTask(TEST_URL, function* ({ ui }) {
|
||||
let store = ui.toolWindow.store;
|
||||
|
||||
// Wait until the viewport has been added
|
||||
yield waitUntilState(store, state => state.viewports.length == 1);
|
||||
|
||||
// A single viewport of default size appeared
|
||||
let viewport = ui.toolWindow.document.querySelector(".viewport-content");
|
||||
|
||||
is(ui.toolWindow.getComputedStyle(viewport).getPropertyValue("width"),
|
||||
"320px", "Viewport has default width");
|
||||
is(ui.toolWindow.getComputedStyle(viewport).getPropertyValue("height"),
|
||||
"480px", "Viewport has default height");
|
||||
|
||||
// Browser's location should match original tab
|
||||
yield waitForFrameLoad(ui, TEST_URL);
|
||||
let location = yield spawnViewportTask(ui, {}, function* () {
|
||||
return content.location.href; // eslint-disable-line
|
||||
});
|
||||
is(location, TEST_URL, "Viewport location matches");
|
||||
});
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
add_task(function* () {
|
||||
let newWindowPromise = BrowserTestUtils.waitForNewWindow();
|
||||
window.open("data:text/html;charset=utf-8,", "_blank");
|
||||
let newWindow = yield newWindowPromise;
|
||||
|
||||
newWindow.focus();
|
||||
yield once(newWindow.gBrowser, "load", true);
|
||||
|
||||
let tab = newWindow.gBrowser.selectedTab;
|
||||
yield openRDM(tab);
|
||||
|
||||
// Close the window on a tab with an active responsive design UI and
|
||||
// wait for the UI to gracefully shutdown. This has leaked the window
|
||||
// in the past.
|
||||
ok(ResponsiveUIManager.isActiveForTab(tab),
|
||||
"ResponsiveUI should be active for tab when the window is closed");
|
||||
let offPromise = once(ResponsiveUIManager, "off");
|
||||
yield BrowserTestUtils.closeWindow(newWindow);
|
||||
yield offPromise;
|
||||
});
|
||||
651
devtools/client/responsive.html/test/browser/devices.json
Normal file
651
devtools/client/responsive.html/test/browser/devices.json
Normal file
|
|
@ -0,0 +1,651 @@
|
|||
{
|
||||
"TYPES": [ "phones", "tablets", "laptops", "televisions", "consoles", "watches" ],
|
||||
"phones": [
|
||||
{
|
||||
"name": "Firefox OS Flame",
|
||||
"width": 320,
|
||||
"height": 570,
|
||||
"pixelRatio": 1.5,
|
||||
"userAgent": "Mozilla/5.0 (Mobile; rv:39.0) Gecko/39.0 Firefox/39.0",
|
||||
"touch": true,
|
||||
"firefoxOS": true,
|
||||
"os": "fxos"
|
||||
},
|
||||
{
|
||||
"name": "Alcatel One Touch Fire",
|
||||
"width": 320,
|
||||
"height": 480,
|
||||
"pixelRatio": 1,
|
||||
"userAgent": "Mozilla/5.0 (Mobile; ALCATELOneTouch4012X; rv:28.0) Gecko/28.0 Firefox/28.0",
|
||||
"touch": true,
|
||||
"firefoxOS": true,
|
||||
"os": "fxos"
|
||||
},
|
||||
{
|
||||
"name": "Alcatel One Touch Fire C",
|
||||
"width": 320,
|
||||
"height": 480,
|
||||
"pixelRatio": 1,
|
||||
"userAgent": "Mozilla/5.0 (Mobile; ALCATELOneTouch4019X; rv:28.0) Gecko/28.0 Firefox/28.0",
|
||||
"touch": true,
|
||||
"firefoxOS": true,
|
||||
"os": "fxos"
|
||||
},
|
||||
{
|
||||
"name": "Alcatel One Touch Fire E",
|
||||
"width": 320,
|
||||
"height": 480,
|
||||
"pixelRatio": 2,
|
||||
"userAgent": "Mozilla/5.0 (Mobile; ALCATELOneTouch6015X; rv:32.0) Gecko/32.0 Firefox/32.0",
|
||||
"touch": true,
|
||||
"firefoxOS": true,
|
||||
"os": "fxos"
|
||||
},
|
||||
{
|
||||
"name": "Apple iPhone 4",
|
||||
"width": 320,
|
||||
"height": 480,
|
||||
"pixelRatio": 2,
|
||||
"userAgent": "Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_2_1 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8C148 Safari/6533.18.5",
|
||||
"touch": true,
|
||||
"firefoxOS": false,
|
||||
"os": "ios"
|
||||
},
|
||||
{
|
||||
"name": "Apple iPhone 5",
|
||||
"width": 320,
|
||||
"height": 568,
|
||||
"pixelRatio": 2,
|
||||
"userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 7_0 like Mac OS X; en-us) AppleWebKit/537.51.1 (KHTML, like Gecko) Version/7.0 Mobile/11A465 Safari/9537.53",
|
||||
"touch": true,
|
||||
"firefoxOS": false,
|
||||
"os": "ios"
|
||||
},
|
||||
{
|
||||
"name": "Apple iPhone 5s",
|
||||
"width": 320,
|
||||
"height": 568,
|
||||
"pixelRatio": 2,
|
||||
"userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 9_2_1 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Version/9.0 Mobile/13D15 Safari/601.1",
|
||||
"touch": true,
|
||||
"firefoxOS": false,
|
||||
"os": "ios",
|
||||
"featured": true
|
||||
},
|
||||
{
|
||||
"name": "Apple iPhone 6",
|
||||
"width": 375,
|
||||
"height": 667,
|
||||
"pixelRatio": 2,
|
||||
"userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 8_0 like Mac OS X) AppleWebKit/600.1.3 (KHTML, like Gecko) Version/8.0 Mobile/12A4345d Safari/600.1.4",
|
||||
"touch": true,
|
||||
"firefoxOS": false,
|
||||
"os": "ios"
|
||||
},
|
||||
{
|
||||
"name": "Apple iPhone 6 Plus",
|
||||
"width": 414,
|
||||
"height": 736,
|
||||
"pixelRatio": 3,
|
||||
"userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 8_0 like Mac OS X) AppleWebKit/600.1.3 (KHTML, like Gecko) Version/8.0 Mobile/12A4345d Safari/600.1.4",
|
||||
"touch": true,
|
||||
"firefoxOS": false,
|
||||
"os": "ios",
|
||||
"featured": true
|
||||
},
|
||||
{
|
||||
"name": "Apple iPhone 6s",
|
||||
"width": 375,
|
||||
"height": 667,
|
||||
"pixelRatio": 2,
|
||||
"userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 8_0 like Mac OS X) AppleWebKit/600.1.3 (KHTML, like Gecko) Version/8.0 Mobile/12A4345d Safari/600.1.4",
|
||||
"touch": true,
|
||||
"firefoxOS": false,
|
||||
"os": "ios",
|
||||
"featured": true
|
||||
},
|
||||
{
|
||||
"name": "Apple iPhone 6s Plus",
|
||||
"width": 414,
|
||||
"height": 736,
|
||||
"pixelRatio": 3,
|
||||
"userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 8_0 like Mac OS X) AppleWebKit/600.1.3 (KHTML, like Gecko) Version/8.0 Mobile/12A4345d Safari/600.1.4",
|
||||
"touch": true,
|
||||
"firefoxOS": false,
|
||||
"os": "ios"
|
||||
},
|
||||
{
|
||||
"name": "BlackBerry Z30",
|
||||
"width": 360,
|
||||
"height": 640,
|
||||
"pixelRatio": 2,
|
||||
"userAgent": "Mozilla/5.0 (BB10; Touch) AppleWebKit/537.10+ (KHTML, like Gecko) Version/10.0.9.2372 Mobile Safari/537.10+",
|
||||
"touch": true,
|
||||
"firefoxOS": false,
|
||||
"os": "blackberryos"
|
||||
},
|
||||
{
|
||||
"name": "Geeksphone Keon",
|
||||
"width": 320,
|
||||
"height": 480,
|
||||
"pixelRatio": 1,
|
||||
"userAgent": "Mozilla/5.0 (Mobile; rv:39.0) Gecko/39.0 Firefox/39.0",
|
||||
"touch": true,
|
||||
"firefoxOS": true,
|
||||
"os": "android"
|
||||
},
|
||||
{
|
||||
"name": "Geeksphone Peak, Revolution",
|
||||
"width": 360,
|
||||
"height": 640,
|
||||
"pixelRatio": 1.5,
|
||||
"userAgent": "Mozilla/5.0 (Mobile; rv:39.0) Gecko/39.0 Firefox/39.0",
|
||||
"touch": true,
|
||||
"firefoxOS": true,
|
||||
"os": "android"
|
||||
},
|
||||
{
|
||||
"name": "Google Nexus S",
|
||||
"width": 320,
|
||||
"height": 533,
|
||||
"pixelRatio": 1.5,
|
||||
"userAgent": "Mozilla/5.0 (Linux; U; Android 2.3.4; en-us; Nexus S Build/GRJ22) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1",
|
||||
"touch": true,
|
||||
"firefoxOS": true,
|
||||
"os": "android"
|
||||
},
|
||||
{
|
||||
"name": "Google Nexus 4",
|
||||
"width": 384,
|
||||
"height": 640,
|
||||
"pixelRatio": 2,
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 4.4.4; en-us; Nexus 4 Build/JOP40D) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2307.2 Mobile Safari/537.36",
|
||||
"touch": true,
|
||||
"firefoxOS": true,
|
||||
"os": "android",
|
||||
"featured": true
|
||||
},
|
||||
{
|
||||
"name": "Google Nexus 5",
|
||||
"width": 360,
|
||||
"height": 640,
|
||||
"pixelRatio": 3,
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 4.4.4; en-us; Nexus 5 Build/JOP40D) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2307.2 Mobile Safari/537.36",
|
||||
"touch": true,
|
||||
"firefoxOS": true,
|
||||
"os": "android",
|
||||
"featured": true
|
||||
},
|
||||
{
|
||||
"name": "Google Nexus 6",
|
||||
"width": 412,
|
||||
"height": 732,
|
||||
"pixelRatio": 3.5,
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 5.1.1; Nexus 6 Build/LYZ28E) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/48.0.2564.23 Mobile Safari/537.36",
|
||||
"touch": true,
|
||||
"firefoxOS": true,
|
||||
"os": "android",
|
||||
"featured": true
|
||||
},
|
||||
{
|
||||
"name": "Intex Cloud Fx",
|
||||
"width": 320,
|
||||
"height": 480,
|
||||
"pixelRatio": 1,
|
||||
"userAgent": "Mozilla/5.0 (Mobile; rv:32.0) Gecko/32.0 Firefox/32.0",
|
||||
"touch": true,
|
||||
"firefoxOS": true,
|
||||
"os": "fxos"
|
||||
},
|
||||
{
|
||||
"name": "KDDI Fx0",
|
||||
"width": 360,
|
||||
"height": 640,
|
||||
"pixelRatio": 2,
|
||||
"userAgent": "Mozilla/5.0 (Mobile; LGL25; rv:32.0) Gecko/32.0 Firefox/32.0",
|
||||
"touch": true,
|
||||
"firefoxOS": true,
|
||||
"os": "fxos"
|
||||
},
|
||||
{
|
||||
"name": "LG Fireweb",
|
||||
"width": 320,
|
||||
"height": 480,
|
||||
"pixelRatio": 1,
|
||||
"userAgent": "Mozilla/5.0 (Mobile; LG-D300; rv:18.1) Gecko/18.1 Firefox/18.1",
|
||||
"touch": true,
|
||||
"firefoxOS": true,
|
||||
"os": "fxos"
|
||||
},
|
||||
{
|
||||
"name": "LG Optimus L70",
|
||||
"width": 384,
|
||||
"height": 640,
|
||||
"pixelRatio": 1.25,
|
||||
"userAgent": "Mozilla/5.0 (Linux; U; Android 4.4.2; en-us; LGMS323 Build/KOT49I.MS32310c) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/30.0.1599.103 Mobile Safari/537.36",
|
||||
"touch": true,
|
||||
"firefoxOS": false,
|
||||
"os": "android"
|
||||
},
|
||||
{
|
||||
"name": "Nokia Lumia 520",
|
||||
"width": 320,
|
||||
"height": 533,
|
||||
"pixelRatio": 1.4,
|
||||
"userAgent": "Mozilla/5.0 (compatible; MSIE 10.0; Windows Phone 8.0; Trident/6.0; IEMobile/10.0; ARM; Touch; NOKIA; Lumia 520)",
|
||||
"touch": true,
|
||||
"firefoxOS": false,
|
||||
"os": "android",
|
||||
"featured": true
|
||||
},
|
||||
{
|
||||
"name": "Nokia N9",
|
||||
"width": 360,
|
||||
"height": 640,
|
||||
"pixelRatio": 1,
|
||||
"userAgent": "Mozilla/5.0 (MeeGo; NokiaN9) AppleWebKit/534.13 (KHTML, like Gecko) NokiaBrowser/8.5.0 Mobile Safari/534.13",
|
||||
"touch": true,
|
||||
"firefoxOS": false,
|
||||
"os": "android"
|
||||
},
|
||||
{
|
||||
"name": "OnePlus One",
|
||||
"width": 360,
|
||||
"height": 640,
|
||||
"pixelRatio": 3,
|
||||
"userAgent": "Mozilla/5.0 (Android 5.1.1; Mobile; rv:43.0) Gecko/43.0 Firefox/43.0",
|
||||
"touch": true,
|
||||
"firefoxOS": false,
|
||||
"os": "android"
|
||||
},
|
||||
{
|
||||
"name": "Samsung Galaxy S3",
|
||||
"width": 360,
|
||||
"height": 640,
|
||||
"pixelRatio": 2,
|
||||
"userAgent": "Mozilla/5.0 (Linux; U; Android 4.0; en-us; GT-I9300 Build/IMM76D) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30",
|
||||
"touch": true,
|
||||
"firefoxOS": false,
|
||||
"os": "android"
|
||||
},
|
||||
{
|
||||
"name": "Samsung Galaxy S4",
|
||||
"width": 360,
|
||||
"height": 640,
|
||||
"pixelRatio": 3,
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 4.4.2; GT-I9505 Build/JDQ39) AppleWebKit/537.36 (KHTML, like Gecko) Version/1.5 Chrome/28.0.1500.94 Mobile Safari/537.36",
|
||||
"touch": true,
|
||||
"firefoxOS": false,
|
||||
"os": "android"
|
||||
},
|
||||
{
|
||||
"name": "Samsung Galaxy S5",
|
||||
"width": 360,
|
||||
"height": 640,
|
||||
"pixelRatio": 3,
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 4.4.2; GT-I9505 Build/JDQ39) AppleWebKit/537.36 (KHTML, like Gecko) Version/1.5 Chrome/28.0.1500.94 Mobile Safari/537.36",
|
||||
"touch": true,
|
||||
"firefoxOS": false,
|
||||
"os": "android",
|
||||
"featured": true
|
||||
},
|
||||
{
|
||||
"name": "Samsung Galaxy S6",
|
||||
"width": 360,
|
||||
"height": 640,
|
||||
"pixelRatio": 4,
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 4.4.2; GT-I9505 Build/JDQ39) AppleWebKit/537.36 (KHTML, like Gecko) Version/1.5 Chrome/28.0.1500.94 Mobile Safari/537.36",
|
||||
"touch": true,
|
||||
"firefoxOS": false,
|
||||
"os": "android",
|
||||
"featured": true
|
||||
},
|
||||
{
|
||||
"name": "Sony Xperia Z3",
|
||||
"width": 360,
|
||||
"height": 640,
|
||||
"pixelRatio": 3,
|
||||
"userAgent": "Mozilla/5.0 (Mobile; rv:39.0) Gecko/39.0 Firefox/39.0",
|
||||
"touch": true,
|
||||
"firefoxOS": true,
|
||||
"os": "android"
|
||||
},
|
||||
{
|
||||
"name": "Spice Fire One Mi-FX1",
|
||||
"width": 320,
|
||||
"height": 480,
|
||||
"pixelRatio": 1,
|
||||
"userAgent": "Mozilla/5.0 (Mobile; rv:28.0) Gecko/28.0 Firefox/28.0",
|
||||
"touch": true,
|
||||
"firefoxOS": true,
|
||||
"os": "fxos"
|
||||
},
|
||||
{
|
||||
"name": "Symphony GoFox F15",
|
||||
"width": 320,
|
||||
"height": 480,
|
||||
"pixelRatio": 1,
|
||||
"userAgent": "Mozilla/5.0 (Mobile; rv:30.0) Gecko/30.0 Firefox/30.0",
|
||||
"touch": true,
|
||||
"firefoxOS": true,
|
||||
"os": "fxos"
|
||||
},
|
||||
{
|
||||
"name": "ZTE Open",
|
||||
"width": 320,
|
||||
"height": 480,
|
||||
"pixelRatio": 1,
|
||||
"userAgent": "Mozilla/5.0 (Mobile; ZTEOPEN; rv:18.1) Gecko/18.0 Firefox/18.1",
|
||||
"touch": true,
|
||||
"firefoxOS": true,
|
||||
"os": "fxos"
|
||||
},
|
||||
{
|
||||
"name": "ZTE Open II",
|
||||
"width": 320,
|
||||
"height": 480,
|
||||
"pixelRatio": 1,
|
||||
"userAgent": "Mozilla/5.0 (Mobile; OPEN2; rv:28.0) Gecko/28.0 Firefox/28.0",
|
||||
"touch": true,
|
||||
"firefoxOS": true,
|
||||
"os": "fxos"
|
||||
},
|
||||
{
|
||||
"name": "ZTE Open C",
|
||||
"width": 320,
|
||||
"height": 450,
|
||||
"pixelRatio": 1.5,
|
||||
"userAgent": "Mozilla/5.0 (Mobile; OPENC; rv:32.0) Gecko/32.0 Firefox/32.0",
|
||||
"touch": true,
|
||||
"firefoxOS": true,
|
||||
"os": "fxos"
|
||||
},
|
||||
{
|
||||
"name": "Zen Fire 105",
|
||||
"width": 320,
|
||||
"height": 480,
|
||||
"pixelRatio": 1,
|
||||
"userAgent": "Mozilla/5.0 (Mobile; rv:28.0) Gecko/28.0 Firefox/28.0",
|
||||
"touch": true,
|
||||
"firefoxOS": true,
|
||||
"os": "fxos"
|
||||
}
|
||||
],
|
||||
"tablets": [
|
||||
{
|
||||
"name": "Amazon Kindle Fire HDX 8.9",
|
||||
"width": 1280,
|
||||
"height": 800,
|
||||
"pixelRatio": 2,
|
||||
"userAgent": "Mozilla/5.0 (Linux; U; en-us; KFAPWI Build/JDQ39) AppleWebKit/535.19 (KHTML, like Gecko) Silk/3.13 Safari/535.19 Silk-Accelerated=true",
|
||||
"touch": true,
|
||||
"firefoxOS": false,
|
||||
"os": "fireos",
|
||||
"featured": true
|
||||
},
|
||||
{
|
||||
"name": "Apple iPad",
|
||||
"width": 1024,
|
||||
"height": 768,
|
||||
"pixelRatio": 2,
|
||||
"userAgent": "Mozilla/5.0 (iPad; CPU OS 7_0 like Mac OS X) AppleWebKit/537.51.1 (KHTML, like Gecko) Version/7.0 Mobile/11A465 Safari/9537.53",
|
||||
"touch": true,
|
||||
"firefoxOS": false,
|
||||
"os": "ios"
|
||||
},
|
||||
{
|
||||
"name": "Apple iPad Air 2",
|
||||
"width": 1024,
|
||||
"height": 768,
|
||||
"pixelRatio": 2,
|
||||
"userAgent": "Mozilla/5.0 (iPad; CPU OS 4_3_5 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8L1 Safari/6533.18.5",
|
||||
"touch": true,
|
||||
"firefoxOS": false,
|
||||
"os": "ios",
|
||||
"featured": true
|
||||
},
|
||||
{
|
||||
"name": "Apple iPad Mini",
|
||||
"width": 1024,
|
||||
"height": 768,
|
||||
"pixelRatio": 1,
|
||||
"userAgent": "Mozilla/5.0 (iPad; CPU OS 4_3_5 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8L1 Safari/6533.18.5",
|
||||
"touch": true,
|
||||
"firefoxOS": false,
|
||||
"os": "ios"
|
||||
},
|
||||
{
|
||||
"name": "Apple iPad Mini 2",
|
||||
"width": 1024,
|
||||
"height": 768,
|
||||
"pixelRatio": 2,
|
||||
"userAgent": "Mozilla/5.0 (iPad; CPU OS 4_3_5 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8L1 Safari/6533.18.5",
|
||||
"touch": true,
|
||||
"firefoxOS": false,
|
||||
"os": "ios",
|
||||
"featured": true
|
||||
},
|
||||
{
|
||||
"name": "BlackBerry PlayBook",
|
||||
"width": 1024,
|
||||
"height": 600,
|
||||
"pixelRatio": 1,
|
||||
"userAgent": "Mozilla/5.0 (PlayBook; U; RIM Tablet OS 2.1.0; en-US) AppleWebKit/536.2+ (KHTML like Gecko) Version/7.2.1.0 Safari/536.2+",
|
||||
"touch": true,
|
||||
"firefoxOS": false,
|
||||
"os": "blackberryos"
|
||||
},
|
||||
{
|
||||
"name": "Foxconn InFocus",
|
||||
"width": 1280,
|
||||
"height": 800,
|
||||
"pixelRatio": 1,
|
||||
"userAgent": "Mozilla/5.0 (Tablet; rv:32.0) Gecko/32.0 Firefox/32.0",
|
||||
"touch": true,
|
||||
"firefoxOS": true,
|
||||
"os": "android"
|
||||
},
|
||||
{
|
||||
"name": "Google Nexus 7",
|
||||
"width": 960,
|
||||
"height": 600,
|
||||
"pixelRatio": 2,
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 4.3; Nexus 7 Build/JSS15Q) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2307.2 Mobile Safari/537.36",
|
||||
"touch": true,
|
||||
"firefoxOS": false,
|
||||
"os": "android",
|
||||
"featured": true
|
||||
},
|
||||
{
|
||||
"name": "Google Nexus 10",
|
||||
"width": 1280,
|
||||
"height": 800,
|
||||
"pixelRatio": 2,
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 4.3; Nexus 10 Build/JSS15Q) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2307.2 Mobile Safari/537.36",
|
||||
"touch": true,
|
||||
"firefoxOS": false,
|
||||
"os": "android"
|
||||
},
|
||||
{
|
||||
"name": "Samsung Galaxy Note 2",
|
||||
"width": 360,
|
||||
"height": 640,
|
||||
"pixelRatio": 2,
|
||||
"userAgent": "Mozilla/5.0 (Linux; U; Android 4.1; en-us; GT-N7100 Build/JRO03C) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30",
|
||||
"touch": true,
|
||||
"firefoxOS": false,
|
||||
"os": "android"
|
||||
},
|
||||
{
|
||||
"name": "Samsung Galaxy Note 3",
|
||||
"width": 360,
|
||||
"height": 640,
|
||||
"pixelRatio": 3,
|
||||
"userAgent": "Mozilla/5.0 (Linux; U; Android 4.3; en-us; SM-N900T Build/JSS15J) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30",
|
||||
"touch": true,
|
||||
"firefoxOS": false,
|
||||
"os": "android",
|
||||
"featured": true
|
||||
},
|
||||
{
|
||||
"name": "Tesla Model S",
|
||||
"width": 1200,
|
||||
"height": 1920,
|
||||
"pixelRatio": 1,
|
||||
"userAgent": "Mozilla/5.0 (X11; Linux) AppleWebKit/534.34 (KHTML, like Gecko) QtCarBrowser Safari/534.34",
|
||||
"touch": true,
|
||||
"firefoxOS": false,
|
||||
"os": "linux"
|
||||
},
|
||||
{
|
||||
"name": "VIA Vixen",
|
||||
"width": 1024,
|
||||
"height": 600,
|
||||
"pixelRatio": 1,
|
||||
"userAgent": "Mozilla/5.0 (Tablet; rv:32.0) Gecko/32.0 Firefox/32.0",
|
||||
"touch": true,
|
||||
"firefoxOS": true,
|
||||
"os": "fxos"
|
||||
}
|
||||
],
|
||||
"laptops": [
|
||||
{
|
||||
"name": "Laptop (1366 x 768)",
|
||||
"width": 1366,
|
||||
"height": 768,
|
||||
"pixelRatio": 1,
|
||||
"userAgent": "",
|
||||
"touch": false,
|
||||
"firefoxOS": false,
|
||||
"os": "windows",
|
||||
"featured": true
|
||||
},
|
||||
{
|
||||
"name": "Laptop (1920 x 1080)",
|
||||
"width": 1280,
|
||||
"height": 720,
|
||||
"pixelRatio": 1.5,
|
||||
"userAgent": "",
|
||||
"touch": false,
|
||||
"firefoxOS": false,
|
||||
"os": "windows",
|
||||
"featured": true
|
||||
},
|
||||
{
|
||||
"name": "Laptop (1920 x 1080) with touch",
|
||||
"width": 1280,
|
||||
"height": 720,
|
||||
"pixelRatio": 1.5,
|
||||
"userAgent": "",
|
||||
"touch": true,
|
||||
"firefoxOS": false,
|
||||
"os": "windows"
|
||||
}
|
||||
],
|
||||
"televisions": [
|
||||
{
|
||||
"name": "720p HD Television",
|
||||
"width": 1280,
|
||||
"height": 720,
|
||||
"pixelRatio": 1,
|
||||
"userAgent": "",
|
||||
"touch": false,
|
||||
"firefoxOS": true,
|
||||
"os": "custom"
|
||||
},
|
||||
{
|
||||
"name": "1080p Full HD Television",
|
||||
"width": 1920,
|
||||
"height": 1080,
|
||||
"pixelRatio": 1,
|
||||
"userAgent": "",
|
||||
"touch": false,
|
||||
"firefoxOS": true,
|
||||
"os": "custom"
|
||||
},
|
||||
{
|
||||
"name": "4K Ultra HD Television",
|
||||
"width": 3840,
|
||||
"height": 2160,
|
||||
"pixelRatio": 1,
|
||||
"userAgent": "",
|
||||
"touch": false,
|
||||
"firefoxOS": true,
|
||||
"os": "custom"
|
||||
}
|
||||
],
|
||||
"consoles": [
|
||||
{
|
||||
"name": "Nintendo 3DS",
|
||||
"width": 320,
|
||||
"height": 240,
|
||||
"pixelRatio": 1,
|
||||
"userAgent": "Mozilla/5.0 (Nintendo 3DS; U; ; en) Version/1.7585.EU",
|
||||
"touch": true,
|
||||
"firefoxOS": false,
|
||||
"os": "nintendo"
|
||||
},
|
||||
{
|
||||
"name": "Nintendo Wii U Gamepad",
|
||||
"width": 854,
|
||||
"height": 480,
|
||||
"pixelRatio": 0.87,
|
||||
"userAgent": "Mozilla/5.0 (Nintendo WiiU) AppleWebKit/536.28 (KHTML, like Gecko) NX/3.0.3.12.15 NintendoBrowser/4.1.1.9601.EU",
|
||||
"touch": true,
|
||||
"firefoxOS": false,
|
||||
"os": "nintendo"
|
||||
},
|
||||
{
|
||||
"name": "Sony PlayStation Vita",
|
||||
"width": 960,
|
||||
"height": 544,
|
||||
"pixelRatio": 1,
|
||||
"userAgent": "Mozilla/5.0 (Playstation Vita 1.61) AppleWebKit/531.22.8 (KHTML, like Gecko) Silk/3.2",
|
||||
"touch": true,
|
||||
"firefoxOS": false,
|
||||
"os": "playstation"
|
||||
}
|
||||
],
|
||||
"watches": [
|
||||
{
|
||||
"name": "LG G Watch",
|
||||
"width": 280,
|
||||
"height": 280,
|
||||
"pixelRatio": 1,
|
||||
"userAgent": "",
|
||||
"touch": true,
|
||||
"firefoxOS": true,
|
||||
"os": "android"
|
||||
},
|
||||
{
|
||||
"name": "LG G Watch R",
|
||||
"width": 320,
|
||||
"height": 320,
|
||||
"pixelRatio": 1,
|
||||
"userAgent": "",
|
||||
"touch": true,
|
||||
"firefoxOS": true,
|
||||
"os": "android"
|
||||
},
|
||||
{
|
||||
"name": "Motorola Moto 360",
|
||||
"width": 320,
|
||||
"height": 290,
|
||||
"pixelRatio": 1,
|
||||
"userAgent": "Mozilla/5.0 (Linux; Android 5.0.1; Moto 360 Build/LWX48T) AppleWebkit/537.36 (KHTML, like Gecko) Chrome/19.77.34.5 Mobile Safari/537.36",
|
||||
"touch": true,
|
||||
"firefoxOS": true,
|
||||
"os": "android"
|
||||
},
|
||||
{
|
||||
"name": "Samsung Gear Live",
|
||||
"width": 320,
|
||||
"height": 320,
|
||||
"pixelRatio": 1,
|
||||
"userAgent": "",
|
||||
"touch": true,
|
||||
"firefoxOS": true,
|
||||
"os": "android"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Page State Test</title>
|
||||
<style>
|
||||
body {
|
||||
height: 100vh;
|
||||
background: red;
|
||||
}
|
||||
body.modified {
|
||||
background: green;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body onclick="this.classList.add('modified')"/>
|
||||
</html>
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Geolocation permission test</title>
|
||||
</head>
|
||||
<body>
|
||||
<script type="text/javascript">
|
||||
"use strict";
|
||||
navigator.geolocation.getCurrentPosition(function (pos) {});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
401
devtools/client/responsive.html/test/browser/head.js
Normal file
401
devtools/client/responsive.html/test/browser/head.js
Normal file
|
|
@ -0,0 +1,401 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
/* eslint no-unused-vars: [2, {"vars": "local"}] */
|
||||
/* import-globals-from ../../../framework/test/shared-head.js */
|
||||
/* import-globals-from ../../../framework/test/shared-redux-head.js */
|
||||
/* import-globals-from ../../../commandline/test/helpers.js */
|
||||
/* import-globals-from ../../../inspector/test/shared-head.js */
|
||||
|
||||
Services.scriptloader.loadSubScript(
|
||||
"chrome://mochitests/content/browser/devtools/client/framework/test/shared-head.js",
|
||||
this);
|
||||
Services.scriptloader.loadSubScript(
|
||||
"chrome://mochitests/content/browser/devtools/client/framework/test/shared-redux-head.js",
|
||||
this);
|
||||
|
||||
// Import the GCLI test helper
|
||||
Services.scriptloader.loadSubScript(
|
||||
"chrome://mochitests/content/browser/devtools/client/commandline/test/helpers.js",
|
||||
this);
|
||||
|
||||
// Import helpers registering the test-actor in remote targets
|
||||
Services.scriptloader.loadSubScript(
|
||||
"chrome://mochitests/content/browser/devtools/client/shared/test/test-actor-registry.js",
|
||||
this);
|
||||
|
||||
// Import helpers for the inspector that are also shared with others
|
||||
Services.scriptloader.loadSubScript(
|
||||
"chrome://mochitests/content/browser/devtools/client/inspector/test/shared-head.js",
|
||||
this);
|
||||
|
||||
const E10S_MULTI_ENABLED = Services.prefs.getIntPref("dom.ipc.processCount") > 1;
|
||||
const TEST_URI_ROOT = "http://example.com/browser/devtools/client/responsive.html/test/browser/";
|
||||
const OPEN_DEVICE_MODAL_VALUE = "OPEN_DEVICE_MODAL";
|
||||
|
||||
const { _loadPreferredDevices } = require("devtools/client/responsive.html/actions/devices");
|
||||
const { getOwnerWindow } = require("sdk/tabs/utils");
|
||||
const asyncStorage = require("devtools/shared/async-storage");
|
||||
const { addDevice, removeDevice } = require("devtools/client/shared/devices");
|
||||
|
||||
SimpleTest.requestCompleteLog();
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
// Toggling the RDM UI involves several docShell swap operations, which are somewhat slow
|
||||
// on debug builds. Usually we are just barely over the limit, so a blanket factor of 2
|
||||
// should be enough.
|
||||
requestLongerTimeout(2);
|
||||
|
||||
flags.testing = true;
|
||||
Services.prefs.clearUserPref("devtools.responsive.html.displayedDeviceList");
|
||||
Services.prefs.setCharPref("devtools.devices.url",
|
||||
TEST_URI_ROOT + "devices.json");
|
||||
Services.prefs.setBoolPref("devtools.responsive.html.enabled", true);
|
||||
|
||||
registerCleanupFunction(() => {
|
||||
flags.testing = false;
|
||||
Services.prefs.clearUserPref("devtools.devices.url");
|
||||
Services.prefs.clearUserPref("devtools.responsive.html.enabled");
|
||||
Services.prefs.clearUserPref("devtools.responsive.html.displayedDeviceList");
|
||||
asyncStorage.removeItem("devtools.devices.url_cache");
|
||||
});
|
||||
|
||||
// This depends on the "devtools.responsive.html.enabled" pref
|
||||
const { ResponsiveUIManager } = require("resource://devtools/client/responsivedesign/responsivedesign.jsm");
|
||||
|
||||
/**
|
||||
* Open responsive design mode for the given tab.
|
||||
*/
|
||||
var openRDM = Task.async(function* (tab) {
|
||||
info("Opening responsive design mode");
|
||||
let manager = ResponsiveUIManager;
|
||||
let ui = yield manager.openIfNeeded(getOwnerWindow(tab), tab);
|
||||
info("Responsive design mode opened");
|
||||
return { ui, manager };
|
||||
});
|
||||
|
||||
/**
|
||||
* Close responsive design mode for the given tab.
|
||||
*/
|
||||
var closeRDM = Task.async(function* (tab, options) {
|
||||
info("Closing responsive design mode");
|
||||
let manager = ResponsiveUIManager;
|
||||
yield manager.closeIfNeeded(getOwnerWindow(tab), tab, options);
|
||||
info("Responsive design mode closed");
|
||||
});
|
||||
|
||||
/**
|
||||
* Adds a new test task that adds a tab with the given URL, opens responsive
|
||||
* design mode, runs the given generator, closes responsive design mode, and
|
||||
* removes the tab.
|
||||
*
|
||||
* Example usage:
|
||||
*
|
||||
* addRDMTask(TEST_URL, function*({ ui, manager }) {
|
||||
* // Your tests go here...
|
||||
* });
|
||||
*/
|
||||
function addRDMTask(url, generator) {
|
||||
add_task(function* () {
|
||||
const tab = yield addTab(url);
|
||||
const results = yield openRDM(tab);
|
||||
|
||||
try {
|
||||
yield* generator(results);
|
||||
} catch (err) {
|
||||
ok(false, "Got an error: " + DevToolsUtils.safeErrorString(err));
|
||||
}
|
||||
|
||||
yield closeRDM(tab);
|
||||
yield removeTab(tab);
|
||||
});
|
||||
}
|
||||
|
||||
function spawnViewportTask(ui, args, task) {
|
||||
return ContentTask.spawn(ui.getViewportBrowser(), args, task);
|
||||
}
|
||||
|
||||
function waitForFrameLoad(ui, targetURL) {
|
||||
return spawnViewportTask(ui, { targetURL }, function* (args) {
|
||||
if ((content.document.readyState == "complete" ||
|
||||
content.document.readyState == "interactive") &&
|
||||
content.location.href == args.targetURL) {
|
||||
return;
|
||||
}
|
||||
yield ContentTaskUtils.waitForEvent(this, "DOMContentLoaded");
|
||||
});
|
||||
}
|
||||
|
||||
function waitForViewportResizeTo(ui, width, height) {
|
||||
return new Promise(Task.async(function* (resolve) {
|
||||
let isSizeMatching = (data) => data.width == width && data.height == height;
|
||||
|
||||
// If the viewport has already the expected size, we resolve the promise immediately.
|
||||
let size = yield getContentSize(ui);
|
||||
if (isSizeMatching(size)) {
|
||||
resolve();
|
||||
return;
|
||||
}
|
||||
|
||||
// Otherwise, we'll listen to both content's resize event and browser's load end;
|
||||
// since a racing condition can happen, where the content's listener is added after
|
||||
// the resize, because the content's document was reloaded; therefore the test would
|
||||
// hang forever. See bug 1302879.
|
||||
let browser = ui.getViewportBrowser();
|
||||
|
||||
let onResize = (_, data) => {
|
||||
if (!isSizeMatching(data)) {
|
||||
return;
|
||||
}
|
||||
ui.off("content-resize", onResize);
|
||||
browser.removeEventListener("mozbrowserloadend", onBrowserLoadEnd);
|
||||
info(`Got content-resize to ${width} x ${height}`);
|
||||
resolve();
|
||||
};
|
||||
|
||||
let onBrowserLoadEnd = Task.async(function* () {
|
||||
let data = yield getContentSize(ui);
|
||||
onResize(undefined, data);
|
||||
});
|
||||
|
||||
info(`Waiting for content-resize to ${width} x ${height}`);
|
||||
ui.on("content-resize", onResize);
|
||||
browser.addEventListener("mozbrowserloadend",
|
||||
onBrowserLoadEnd, { once: true });
|
||||
}));
|
||||
}
|
||||
|
||||
var setViewportSize = Task.async(function* (ui, manager, width, height) {
|
||||
let size = ui.getViewportSize();
|
||||
info(`Current size: ${size.width} x ${size.height}, ` +
|
||||
`set to: ${width} x ${height}`);
|
||||
if (size.width != width || size.height != height) {
|
||||
let resized = waitForViewportResizeTo(ui, width, height);
|
||||
ui.setViewportSize({ width, height });
|
||||
yield resized;
|
||||
}
|
||||
});
|
||||
|
||||
function getElRect(selector, win) {
|
||||
let el = win.document.querySelector(selector);
|
||||
return el.getBoundingClientRect();
|
||||
}
|
||||
|
||||
/**
|
||||
* Drag an element identified by 'selector' by [x,y] amount. Returns
|
||||
* the rect of the dragged element as it was before drag.
|
||||
*/
|
||||
function dragElementBy(selector, x, y, win) {
|
||||
let React = win.require("devtools/client/shared/vendor/react");
|
||||
let { Simulate } = React.addons.TestUtils;
|
||||
let rect = getElRect(selector, win);
|
||||
let startPoint = {
|
||||
clientX: rect.left + Math.floor(rect.width / 2),
|
||||
clientY: rect.top + Math.floor(rect.height / 2),
|
||||
};
|
||||
let endPoint = [ startPoint.clientX + x, startPoint.clientY + y ];
|
||||
|
||||
let elem = win.document.querySelector(selector);
|
||||
|
||||
// mousedown is a React listener, need to use its testing tools to avoid races
|
||||
Simulate.mouseDown(elem, startPoint);
|
||||
|
||||
// mousemove and mouseup are regular DOM listeners
|
||||
EventUtils.synthesizeMouseAtPoint(...endPoint, { type: "mousemove" }, win);
|
||||
EventUtils.synthesizeMouseAtPoint(...endPoint, { type: "mouseup" }, win);
|
||||
|
||||
return rect;
|
||||
}
|
||||
|
||||
function* testViewportResize(ui, selector, moveBy,
|
||||
expectedViewportSize, expectedHandleMove) {
|
||||
let win = ui.toolWindow;
|
||||
let resized = waitForViewportResizeTo(ui, ...expectedViewportSize);
|
||||
let startRect = dragElementBy(selector, ...moveBy, win);
|
||||
yield resized;
|
||||
|
||||
let endRect = getElRect(selector, win);
|
||||
is(endRect.left - startRect.left, expectedHandleMove[0],
|
||||
`The x move of ${selector} is as expected`);
|
||||
is(endRect.top - startRect.top, expectedHandleMove[1],
|
||||
`The y move of ${selector} is as expected`);
|
||||
}
|
||||
|
||||
function openDeviceModal({ toolWindow }) {
|
||||
let { document } = toolWindow;
|
||||
let React = toolWindow.require("devtools/client/shared/vendor/react");
|
||||
let { Simulate } = React.addons.TestUtils;
|
||||
let select = document.querySelector(".viewport-device-selector");
|
||||
let modal = document.querySelector("#device-modal-wrapper");
|
||||
|
||||
info("Checking initial device modal state");
|
||||
ok(modal.classList.contains("closed") && !modal.classList.contains("opened"),
|
||||
"The device modal is closed by default.");
|
||||
|
||||
info("Opening device modal through device selector.");
|
||||
select.value = OPEN_DEVICE_MODAL_VALUE;
|
||||
Simulate.change(select);
|
||||
ok(modal.classList.contains("opened") && !modal.classList.contains("closed"),
|
||||
"The device modal is displayed.");
|
||||
}
|
||||
|
||||
function changeSelectValue({ toolWindow }, selector, value) {
|
||||
info(`Selecting ${value} in ${selector}.`);
|
||||
|
||||
return new Promise(resolve => {
|
||||
let select = toolWindow.document.querySelector(selector);
|
||||
isnot(select, null, `selector "${selector}" should match an existing element.`);
|
||||
|
||||
let option = [...select.options].find(o => o.value === String(value));
|
||||
isnot(option, undefined, `value "${value}" should match an existing option.`);
|
||||
|
||||
let event = new toolWindow.UIEvent("change", {
|
||||
view: toolWindow,
|
||||
bubbles: true,
|
||||
cancelable: true
|
||||
});
|
||||
|
||||
select.addEventListener("change", () => {
|
||||
is(select.value, value,
|
||||
`Select's option with value "${value}" should be selected.`);
|
||||
resolve();
|
||||
}, { once: true });
|
||||
|
||||
select.value = value;
|
||||
select.dispatchEvent(event);
|
||||
});
|
||||
}
|
||||
|
||||
const selectDevice = (ui, value) => Promise.all([
|
||||
once(ui, "device-changed"),
|
||||
changeSelectValue(ui, ".viewport-device-selector", value)
|
||||
]);
|
||||
|
||||
const selectDPR = (ui, value) =>
|
||||
changeSelectValue(ui, "#global-dpr-selector > select", value);
|
||||
|
||||
const selectNetworkThrottling = (ui, value) => Promise.all([
|
||||
once(ui, "network-throttling-changed"),
|
||||
changeSelectValue(ui, "#global-network-throttling-selector", value)
|
||||
]);
|
||||
|
||||
function getSessionHistory(browser) {
|
||||
return ContentTask.spawn(browser, {}, function* () {
|
||||
/* eslint-disable no-undef */
|
||||
let { interfaces: Ci } = Components;
|
||||
let webNav = docShell.QueryInterface(Ci.nsIWebNavigation);
|
||||
let sessionHistory = webNav.sessionHistory;
|
||||
let result = {
|
||||
index: sessionHistory.index,
|
||||
entries: []
|
||||
};
|
||||
|
||||
for (let i = 0; i < sessionHistory.count; i++) {
|
||||
let entry = sessionHistory.getEntryAtIndex(i, false);
|
||||
result.entries.push({
|
||||
uri: entry.URI.spec,
|
||||
title: entry.title
|
||||
});
|
||||
}
|
||||
|
||||
return result;
|
||||
/* eslint-enable no-undef */
|
||||
});
|
||||
}
|
||||
|
||||
function getContentSize(ui) {
|
||||
return spawnViewportTask(ui, {}, () => ({
|
||||
width: content.screen.width,
|
||||
height: content.screen.height
|
||||
}));
|
||||
}
|
||||
|
||||
function waitForPageShow(browser) {
|
||||
let mm = browser.messageManager;
|
||||
return new Promise(resolve => {
|
||||
let onShow = message => {
|
||||
if (message.target != browser) {
|
||||
return;
|
||||
}
|
||||
mm.removeMessageListener("PageVisibility:Show", onShow);
|
||||
resolve();
|
||||
};
|
||||
mm.addMessageListener("PageVisibility:Show", onShow);
|
||||
});
|
||||
}
|
||||
|
||||
function waitForViewportLoad(ui) {
|
||||
return new Promise(resolve => {
|
||||
let browser = ui.getViewportBrowser();
|
||||
browser.addEventListener("mozbrowserloadend", () => {
|
||||
resolve();
|
||||
}, { once: true });
|
||||
});
|
||||
}
|
||||
|
||||
function load(browser, url) {
|
||||
let loaded = BrowserTestUtils.browserLoaded(browser, false, url);
|
||||
browser.loadURI(url, null, null);
|
||||
return loaded;
|
||||
}
|
||||
|
||||
function back(browser) {
|
||||
let shown = waitForPageShow(browser);
|
||||
browser.goBack();
|
||||
return shown;
|
||||
}
|
||||
|
||||
function forward(browser) {
|
||||
let shown = waitForPageShow(browser);
|
||||
browser.goForward();
|
||||
return shown;
|
||||
}
|
||||
|
||||
function addDeviceForTest(device) {
|
||||
info(`Adding Test Device "${device.name}" to the list.`);
|
||||
addDevice(device);
|
||||
|
||||
registerCleanupFunction(() => {
|
||||
// Note that assertions in cleanup functions are not displayed unless they failed.
|
||||
ok(removeDevice(device), `Removed Test Device "${device.name}" from the list.`);
|
||||
});
|
||||
}
|
||||
|
||||
function waitForClientClose(ui) {
|
||||
return new Promise(resolve => {
|
||||
info("Waiting for RDM debugger client to close");
|
||||
ui.client.addOneTimeListener("closed", () => {
|
||||
info("RDM's debugger client is now closed");
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function* testTouchEventsOverride(ui, expected) {
|
||||
let { document } = ui.toolWindow;
|
||||
let touchButton = document.querySelector("#global-touch-simulation-button");
|
||||
|
||||
let flag = yield ui.emulationFront.getTouchEventsOverride();
|
||||
is(flag === Ci.nsIDocShell.TOUCHEVENTS_OVERRIDE_ENABLED, expected,
|
||||
`Touch events override should be ${expected ? "enabled" : "disabled"}`);
|
||||
is(touchButton.classList.contains("active"), expected,
|
||||
`Touch simulation button should be ${expected ? "" : "in"}active.`);
|
||||
}
|
||||
|
||||
function testViewportDeviceSelectLabel(ui, expected) {
|
||||
info("Test viewport's device select label");
|
||||
|
||||
let select = ui.toolWindow.document.querySelector(".viewport-device-selector");
|
||||
is(select.selectedOptions[0].textContent, expected,
|
||||
`Device Select value should be: ${expected}`);
|
||||
}
|
||||
|
||||
function* enableTouchSimulation(ui) {
|
||||
let { document } = ui.toolWindow;
|
||||
let touchButton = document.querySelector("#global-touch-simulation-button");
|
||||
let loaded = waitForViewportLoad(ui);
|
||||
touchButton.click();
|
||||
yield loaded;
|
||||
}
|
||||
86
devtools/client/responsive.html/test/browser/touch.html
Normal file
86
devtools/client/responsive.html/test/browser/touch.html
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
<!DOCTYPE html>
|
||||
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" />
|
||||
<title>test</title>
|
||||
|
||||
|
||||
<style>
|
||||
div {
|
||||
border :1px solid red;
|
||||
width: 100px; height: 100px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div data-is-delay="false"></div>
|
||||
|
||||
<script type="text/javascript;version=1.8">
|
||||
"use strict";
|
||||
let div = document.querySelector("div");
|
||||
let initX, initY;
|
||||
let previousEvent = "", touchendTime = 0;
|
||||
let updatePreviousEvent = function (e) {
|
||||
previousEvent = e.type;
|
||||
};
|
||||
|
||||
div.style.transform = "none";
|
||||
div.style.backgroundColor = "";
|
||||
|
||||
div.addEventListener("touchstart", function (evt) {
|
||||
let touch = evt.changedTouches[0];
|
||||
initX = touch.pageX;
|
||||
initY = touch.pageY;
|
||||
updatePreviousEvent(evt);
|
||||
}, true);
|
||||
|
||||
div.addEventListener("touchmove", function (evt) {
|
||||
let touch = evt.changedTouches[0];
|
||||
let deltaX = touch.pageX - initX;
|
||||
let deltaY = touch.pageY - initY;
|
||||
div.style.transform = "translate(" + deltaX + "px, " + deltaY + "px)";
|
||||
updatePreviousEvent(evt);
|
||||
}, true);
|
||||
|
||||
div.addEventListener("touchend", function (evt) {
|
||||
if (!evt.touches.length) {
|
||||
div.style.transform = "none";
|
||||
}
|
||||
touchendTime = performance.now();
|
||||
updatePreviousEvent(evt);
|
||||
}, true);
|
||||
|
||||
div.addEventListener("mouseenter", function (evt) {
|
||||
div.style.backgroundColor = "red";
|
||||
updatePreviousEvent(evt);
|
||||
}, true);
|
||||
div.addEventListener("mouseover", function(evt) {
|
||||
div.style.backgroundColor = "red";
|
||||
updatePreviousEvent(evt);
|
||||
}, true);
|
||||
|
||||
div.addEventListener("mouseout", function (evt) {
|
||||
div.style.backgroundColor = "blue";
|
||||
updatePreviousEvent(evt);
|
||||
}, true);
|
||||
|
||||
div.addEventListener("mouseleave", function (evt) {
|
||||
div.style.backgroundColor = "blue";
|
||||
updatePreviousEvent(evt);
|
||||
}, true);
|
||||
|
||||
div.addEventListener("mousedown", function (evt) {
|
||||
if (previousEvent === "touchend" && touchendTime !== 0) {
|
||||
let now = performance.now();
|
||||
div.dataset.isDelay = ((now - touchendTime) >= 300);
|
||||
} else {
|
||||
div.dataset.isDelay = false;
|
||||
}
|
||||
updatePreviousEvent(evt);
|
||||
}, true);
|
||||
|
||||
div.addEventListener("mousemove", updatePreviousEvent, true);
|
||||
|
||||
div.addEventListener("mouseup", updatePreviousEvent, true);
|
||||
|
||||
div.addEventListener("click", updatePreviousEvent, true);
|
||||
</script>
|
||||
Loading…
Add table
Add a link
Reference in a new issue