зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1507870 - add Print to JSON functionality to the a11y inspector. r=pbro
MozReview-Commit-ID: HyqYgHCCp3T Differential Revision: https://phabricator.services.mozilla.com/D12504 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
80eec2f7ae
Коммит
e2f524a9d5
|
@ -16,12 +16,20 @@ const TreeRow = require("devtools/client/shared/components/tree/TreeRow");
|
|||
// Utils
|
||||
const {flashElementOn, flashElementOff} =
|
||||
require("devtools/client/inspector/markup/utils");
|
||||
const { openDocLink } = require("devtools/client/shared/link");
|
||||
const { VALUE_FLASHING_DURATION, VALUE_HIGHLIGHT_DURATION } = require("../constants");
|
||||
|
||||
// Actions
|
||||
const { updateDetails } = require("../actions/details");
|
||||
const { unhighlight } = require("../actions/accessibles");
|
||||
|
||||
const { L10N } = require("../utils/l10n");
|
||||
|
||||
loader.lazyRequireGetter(this, "Menu", "devtools/client/framework/menu");
|
||||
loader.lazyRequireGetter(this, "MenuItem", "devtools/client/framework/menu-item");
|
||||
|
||||
const JSON_URL_PREFIX = "data:application/json;charset=UTF-8,";
|
||||
|
||||
class HighlightableTreeRowClass extends TreeRow {
|
||||
shouldComponentUpdate(nextProps) {
|
||||
const props = ["name", "open", "value", "loading", "selected", "hasChildren"];
|
||||
|
@ -138,6 +146,44 @@ class AccessibilityRow extends Component {
|
|||
walker.unhighlight().catch(error => console.warn(error));
|
||||
}
|
||||
|
||||
async printToJSON() {
|
||||
const { member, supports } = this.props;
|
||||
if (!supports.snapshot) {
|
||||
// Debugger server does not support Accessible actor snapshots.
|
||||
return;
|
||||
}
|
||||
|
||||
const snapshot = await member.object.snapshot();
|
||||
openDocLink(`${JSON_URL_PREFIX}${encodeURIComponent(JSON.stringify(snapshot))}`);
|
||||
}
|
||||
|
||||
onContextMenu(e) {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
|
||||
if (!gToolbox) {
|
||||
return;
|
||||
}
|
||||
|
||||
const menu = new Menu({ id: "accessibility-row-contextmenu" });
|
||||
const { supports } = this.props;
|
||||
|
||||
if (supports.snapshot) {
|
||||
menu.append(new MenuItem({
|
||||
id: "menu-printtojson",
|
||||
label: L10N.getStr("accessibility.tree.menu.printToJSON"),
|
||||
click: () => this.printToJSON(),
|
||||
}));
|
||||
}
|
||||
|
||||
menu.popup(e.screenX, e.screenY, gToolbox);
|
||||
}
|
||||
|
||||
get hasContextMenu() {
|
||||
const { supports } = this.props;
|
||||
return supports.snapshot;
|
||||
}
|
||||
|
||||
/**
|
||||
* Render accessible row component.
|
||||
* @returns acecssible-row React component.
|
||||
|
@ -145,6 +191,7 @@ class AccessibilityRow extends Component {
|
|||
render() {
|
||||
const { object } = this.props.member;
|
||||
const props = Object.assign({}, this.props, {
|
||||
onContextMenu: this.hasContextMenu && (e => this.onContextMenu(e)),
|
||||
onMouseOver: () => this.highlight(object),
|
||||
onMouseOut: () => this.unhighlight(),
|
||||
});
|
||||
|
|
|
@ -5,3 +5,4 @@ support-files =
|
|||
[test_accessible_learnMoreLink.html]
|
||||
[test_accessible_openLink.html]
|
||||
[test_accessible_relations.html]
|
||||
[test_accessible_row_context_menu.html]
|
||||
|
|
|
@ -0,0 +1,164 @@
|
|||
<!-- This Source Code Form is subject to the terms of the Mozilla Public
|
||||
- License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
Test that openLink function is called if accessible object property is rendered as a link.
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>AccessibilityRow context menu test</title>
|
||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
|
||||
<link rel="stylesheet" href="chrome://devtools/skin/light-theme.css" type="text/css">
|
||||
</head>
|
||||
<body>
|
||||
<pre id="test">
|
||||
<script src="head.js" type="application/javascript"></script>
|
||||
<script type="application/javascript">
|
||||
|
||||
"use strict";
|
||||
|
||||
window.onload = async function() {
|
||||
try {
|
||||
const { gDevTools } = require("devtools/client/framework/devtools");
|
||||
const Services = browserRequire("Services");
|
||||
const ReactDOM = browserRequire("devtools/client/shared/vendor/react-dom");
|
||||
const { createFactory, createElement } =
|
||||
browserRequire("devtools/client/shared/vendor/react");
|
||||
const { Provider } = require("devtools/client/shared/vendor/react-redux");
|
||||
const createStore = require("devtools/client/shared/redux/create-store")();
|
||||
const { Simulate } =
|
||||
browserRequire("devtools/client/shared/vendor/react-dom-test-utils");
|
||||
const AccessibilityRow = createFactory(
|
||||
browserRequire("devtools/client/accessibility/components/AccessibilityRow"));
|
||||
|
||||
async function withMockEnv(func) {
|
||||
const { gToolbox: originalToolbox, gTelemetry: originalTelemetry } = window;
|
||||
window.gToolbox = { doc: document };
|
||||
window.gTelemetry = null;
|
||||
|
||||
await func();
|
||||
|
||||
window.gToolbox = originalToolbox;
|
||||
window.gTelemetry = originalTelemetry;
|
||||
}
|
||||
|
||||
function renderAccessibilityRow(newProps, newState) {
|
||||
let container = document.getElementById("container");
|
||||
if (container) {
|
||||
container.remove();
|
||||
}
|
||||
|
||||
const accRow = AccessibilityRow(newProps);
|
||||
const mockStore = createStore((state, action) =>
|
||||
action ? { ...state, ...action } : state, newState);
|
||||
const provider = createElement(Provider, { store: mockStore }, accRow);
|
||||
|
||||
container = document.createElement("div");
|
||||
container.id = "container";
|
||||
document.body.appendChild(container);
|
||||
return ReactDOM.render(provider, container);
|
||||
}
|
||||
|
||||
const checker = Symbol();
|
||||
let isCalled;
|
||||
|
||||
const ROW_ID = "test-row";
|
||||
const JSON_URL_PREFIX = "data:application/json;charset=UTF-8,";
|
||||
const SNAPSHOT = { "snapshot": true };
|
||||
const defaultProps = {
|
||||
id: ROW_ID,
|
||||
member: {
|
||||
object: {
|
||||
name: "test",
|
||||
value: "test",
|
||||
loading: false,
|
||||
selected: false,
|
||||
hasChildren: false,
|
||||
snapshot: async () => SNAPSHOT,
|
||||
},
|
||||
},
|
||||
columns: [
|
||||
{ "id": "default", "title": "role" },
|
||||
{ "id": "value", "title": "name" },
|
||||
],
|
||||
provider: {
|
||||
getValue: (object, id) => object[id],
|
||||
},
|
||||
};
|
||||
|
||||
const mockProps = {
|
||||
...defaultProps,
|
||||
onContextMenu: () => {
|
||||
isCalled = true;
|
||||
},
|
||||
};
|
||||
|
||||
const defaultState = { ui: { supports: { snapshot: true }}};
|
||||
const mockState = { ui: { supports: {}}};
|
||||
|
||||
info("Check contextmenu default behaviour.");
|
||||
renderAccessibilityRow(defaultProps, defaultState);
|
||||
let row = document.getElementById(ROW_ID);
|
||||
|
||||
await withMockEnv(async function() {
|
||||
Simulate.contextMenu(row);
|
||||
|
||||
const menu = document.getElementById("accessibility-row-contextmenu");
|
||||
const printtojsonMenuItem = document.getElementById("menu-printtojson");
|
||||
|
||||
ok(menu, "Accessibility row context menu is open");
|
||||
ok(printtojsonMenuItem, "Print to JSON menu item is visible");
|
||||
|
||||
const browserWindow = Services.wm.getMostRecentWindow(gDevTools.chromeWindowType);
|
||||
const defaultOpenWebLinkIn = browserWindow.openWebLinkIn;
|
||||
|
||||
let openWebLinkInCalled;
|
||||
const openWebLinkInPromise = new Promise(resolve => {
|
||||
openWebLinkInCalled = resolve;
|
||||
});
|
||||
|
||||
// Mock top chrome window's @openWebLinkIn method.
|
||||
browserWindow.openWebLinkIn = (...args) => {
|
||||
openWebLinkInCalled(args);
|
||||
};
|
||||
printtojsonMenuItem.click();
|
||||
|
||||
const [ url, where ] = await openWebLinkInPromise;
|
||||
is(url, `${JSON_URL_PREFIX}${encodeURIComponent(JSON.stringify(SNAPSHOT))}`,
|
||||
"Correct URL is opened");
|
||||
is(where, "tab", "URL was opened correctly");
|
||||
|
||||
// Reset @openWebLinkIn to default.
|
||||
browserWindow.openWebLinkIn = defaultOpenWebLinkIn;
|
||||
});
|
||||
|
||||
info("Check accessibility row when context menu is not supported.");
|
||||
renderAccessibilityRow(mockProps, mockState);
|
||||
row = document.getElementById(ROW_ID);
|
||||
|
||||
info("Check contextmenu listener is not called when context menu is not supported.");
|
||||
isCalled = checker;
|
||||
Simulate.contextMenu(row);
|
||||
ok(isCalled === checker, "contextmenu event handler was never called.");
|
||||
|
||||
info("Check accessibility row when context menu is supported.");
|
||||
renderAccessibilityRow(mockProps, defaultState);
|
||||
row = document.getElementById(ROW_ID);
|
||||
|
||||
info("Check contextmenu listener is called when context menu is supported.");
|
||||
isCalled = checker;
|
||||
Simulate.contextMenu(row);
|
||||
ok(isCalled, "contextmenu event handler was called correctly.");
|
||||
} catch (e) {
|
||||
ok(false, "Got an error: " + DevToolsUtils.safeErrorString(e));
|
||||
} finally {
|
||||
SimpleTest.finish();
|
||||
}
|
||||
};
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
|
@ -101,3 +101,8 @@ accessibility.description.general.p2=Accessibility features may affect the perfo
|
|||
# when accessibility service description is provided when a client is connected
|
||||
# to an older version of accessibility actor.
|
||||
accessibility.description.oldVersion=You are connected to a debugger server that is too old. To use Accessibility panel, please connect to the latest debugger server version.
|
||||
|
||||
# LOCALIZATION NOTE (accessibility.tree.menu.printToJSON): A title text used when a
|
||||
# context menu item for printing an accessible tree to JSON is rendered after triggering a
|
||||
# context menu for an accessible tree row.
|
||||
accessibility.tree.menu.printToJSON=Print to JSON
|
||||
|
|
Загрузка…
Ссылка в новой задаче