зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1537598 - Test Column Breakpoints.
Differential Revision: https://phabricator.services.mozilla.com/D26827 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
e1d04ebd15
Коммит
ead0a1fa52
|
@ -51,6 +51,7 @@
|
|||
"waitForThreadEvents": false,
|
||||
"waitForState": false,
|
||||
"waitForElement": false,
|
||||
"waitForAllElements": false,
|
||||
"waitForElementWithSelector": false,
|
||||
"waitForPaused": false,
|
||||
"waitForSources": false,
|
||||
|
@ -59,7 +60,10 @@
|
|||
"waitForSelectedSource": false,
|
||||
"waitForBreakpoint": false,
|
||||
"waitForBreakpointCount": false,
|
||||
"waitForCondition": false,
|
||||
"waitForLog": false,
|
||||
"isPaused": false,
|
||||
"assertClass": false,
|
||||
"assertSourceCount": false,
|
||||
"assertEditorBreakpoint": false,
|
||||
"assertBreakpointSnippet": false,
|
||||
|
@ -92,7 +96,9 @@
|
|||
"clickDOMElement": false,
|
||||
"altClickElement": false,
|
||||
"rightClickElement": false,
|
||||
"rightClickEl": false,
|
||||
"clickGutter": false,
|
||||
"typeInPanel": false,
|
||||
"selectMenuItem": false,
|
||||
"selectContextMenuItem": false,
|
||||
"togglePauseOnExceptions": false,
|
||||
|
|
|
@ -1,111 +1,104 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
/* 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/>. */
|
||||
|
||||
function getColumnBreakpointElements(dbg) {
|
||||
return findAllElementsWithSelector(dbg, ".column-breakpoint");
|
||||
async function enableFirstBreakpoint(dbg) {
|
||||
getCM(dbg).setCursor({ line: 32, ch: 0 });
|
||||
await addBreakpoint(dbg, "long", 32);
|
||||
const bpMarkers = await waitForAllElements(dbg, "columnBreakpoints");
|
||||
|
||||
ok(bpMarkers.length === 2, "2 column breakpoints");
|
||||
assertClass(bpMarkers[0], "active");
|
||||
assertClass(bpMarkers[1], "active", false);
|
||||
}
|
||||
|
||||
async function assertConditionalBreakpointIsFocused(dbg) {
|
||||
const input = findElement(dbg, "conditionalPanelInput");
|
||||
await waitForElementFocus(dbg, input);
|
||||
}
|
||||
async function enableSecondBreakpoint(dbg) {
|
||||
let bpMarkers = await waitForAllElements(dbg, "columnBreakpoints");
|
||||
|
||||
function waitForElementFocus(dbg, el) {
|
||||
const doc = dbg.win.document;
|
||||
return waitFor(() => doc.activeElement == el && doc.hasFocus());
|
||||
}
|
||||
bpMarkers[1].click();
|
||||
await waitForBreakpointCount(dbg, 2);
|
||||
|
||||
function hasCondition(marker) {
|
||||
return marker.classList.contains("has-condition");
|
||||
bpMarkers = findAllElements(dbg, "columnBreakpoints");
|
||||
assertClass(bpMarkers[1], "active");
|
||||
await waitForAllElements(dbg, "breakpointItems", 2);
|
||||
}
|
||||
|
||||
async function setConditionalBreakpoint(dbg, index, condition) {
|
||||
const {
|
||||
addConditionalBreakpoint,
|
||||
editConditionalBreakpoint
|
||||
} = selectors.gutterContextMenu;
|
||||
// Make this work with either add or edit menu items
|
||||
const selector = `${addConditionalBreakpoint},${editConditionalBreakpoint}`;
|
||||
let bpMarkers = await waitForAllElements(dbg, "columnBreakpoints");
|
||||
rightClickEl(dbg, bpMarkers[index]);
|
||||
selectContextMenuItem(dbg, selectors.addConditionItem);
|
||||
await typeInPanel(dbg, condition);
|
||||
await waitForCondition(dbg, condition);
|
||||
|
||||
rightClickElement(dbg, "breakpointItem", index);
|
||||
selectContextMenuItem(dbg, selector);
|
||||
await waitForElement(dbg, "conditionalPanelInput");
|
||||
await assertConditionalBreakpointIsFocused(dbg);
|
||||
|
||||
// Position cursor reliably at the end of the text.
|
||||
pressKey(dbg, "End");
|
||||
type(dbg, condition);
|
||||
pressKey(dbg, "Enter");
|
||||
bpMarkers = await waitForAllElements(dbg, "columnBreakpoints");
|
||||
assertClass(bpMarkers[index], "has-condition");
|
||||
}
|
||||
|
||||
function removeBreakpointViaContext(dbg, index) {
|
||||
rightClickElement(dbg, "breakpointItem", index);
|
||||
selectContextMenuItem(dbg, "#node-menu-delete-self");
|
||||
async function setLogPoint(dbg, index, expression) {
|
||||
let bpMarkers = await waitForAllElements(dbg, "columnBreakpoints");
|
||||
rightClickEl(dbg, bpMarkers[index]);
|
||||
|
||||
selectContextMenuItem(dbg, selectors.addLogItem);
|
||||
await typeInPanel(dbg, expression);
|
||||
await waitForLog(dbg, expression);
|
||||
|
||||
bpMarkers = await waitForAllElements(dbg, "columnBreakpoints");
|
||||
assertClass(bpMarkers[index], "has-log");
|
||||
}
|
||||
|
||||
async function disableBreakpoint(dbg, index) {
|
||||
rightClickElement(dbg, "columnBreakpoints");
|
||||
selectContextMenuItem(dbg, selectors.disableItem);
|
||||
|
||||
await waitForState(dbg, state => {
|
||||
const bp = dbg.selectors.getBreakpointsList(state)[index];
|
||||
return bp.disabled;
|
||||
});
|
||||
|
||||
const bpMarkers = await waitForAllElements(dbg, "columnBreakpoints");
|
||||
assertClass(bpMarkers[0], "disabled");
|
||||
}
|
||||
|
||||
async function removeFirstBreakpoint(dbg) {
|
||||
let bpMarkers = await waitForAllElements(dbg, "columnBreakpoints");
|
||||
|
||||
bpMarkers[0].click();
|
||||
bpMarkers = await waitForAllElements(dbg, "columnBreakpoints");
|
||||
assertClass(bpMarkers[0], "active", false);
|
||||
}
|
||||
|
||||
async function removeAllBreakpoints(dbg, line, count) {
|
||||
clickGutter(dbg, 32);
|
||||
await waitForBreakpointCount(dbg, 0);
|
||||
|
||||
ok(findAllElements(dbg, "columnBreakpoints").length == 0);
|
||||
}
|
||||
|
||||
// Test enabling and disabling a breakpoint using the check boxes
|
||||
add_task(async function() {
|
||||
const dbg = await initDebugger("doc-scripts.html", "simple1");
|
||||
await pushPref("devtools.debugger.features.column-breakpoints", false);
|
||||
await selectSource(dbg, "long");
|
||||
|
||||
if(!Services.prefs.getBoolPref("devtools.debugger.features.column-breakpoints")) {
|
||||
ok(true, "This test only applies when column breakpoints are on");
|
||||
return;
|
||||
}
|
||||
info("1. Add a column breakpoint on line 32");
|
||||
await enableFirstBreakpoint(dbg);
|
||||
|
||||
await selectSource(dbg, "simple1");
|
||||
info("2. Click on the second breakpoint on line 32");
|
||||
await enableSecondBreakpoint(dbg);
|
||||
|
||||
// Scroll down to desired line so that column breakpoints render
|
||||
getCM(dbg).setCursor({ line: 15, ch: 0 });
|
||||
info("3. Add a condition to the first breakpoint");
|
||||
await setConditionalBreakpoint(dbg, 0, "foo");
|
||||
|
||||
// Create a breakpoint at 15:undefined
|
||||
await addBreakpoint(dbg, "simple1", 15);
|
||||
info("4. Add a log to the first breakpoint");
|
||||
await setLogPoint(dbg, 0, "bar");
|
||||
|
||||
// Wait for column breakpoint markers
|
||||
await waitForElementWithSelector(dbg, ".column-breakpoint");
|
||||
info("5. Disable the first breakpoint");
|
||||
await disableBreakpoint(dbg, 0);
|
||||
|
||||
let columnBreakpointMarkers = getColumnBreakpointElements(dbg);
|
||||
ok(
|
||||
columnBreakpointMarkers.length === 2,
|
||||
"2 column breakpoint markers display"
|
||||
);
|
||||
info("6. Remove the first breakpoint");
|
||||
await removeFirstBreakpoint(dbg);
|
||||
|
||||
// Create a breakpoint at 15:8
|
||||
columnBreakpointMarkers[0].click();
|
||||
info("7. Add a condition to the second breakpoint");
|
||||
await setConditionalBreakpoint(dbg, 1, "foo2");
|
||||
|
||||
// Create a breakpoint at 15:28
|
||||
columnBreakpointMarkers[1].click();
|
||||
|
||||
// Wait for breakpoints in right panel to render
|
||||
await waitForState(dbg, state => {
|
||||
return dbg.win.document.querySelectorAll(".breakpoints-list .breakpoint").length === 3;
|
||||
})
|
||||
|
||||
// Scroll down in secondary pane so element we want to right-click is showing
|
||||
dbg.win.document.querySelector(".secondary-panes").scrollTop = 100;
|
||||
|
||||
// Set a condition at 15:8
|
||||
await setConditionalBreakpoint(dbg, 4, "Eight");
|
||||
|
||||
// Ensure column breakpoint is yellow
|
||||
await waitForElementWithSelector(dbg, ".column-breakpoint.has-condition");
|
||||
|
||||
// Remove the breakpoint from 15:undefined via the secondary pane context menu
|
||||
removeBreakpointViaContext(dbg, 3);
|
||||
|
||||
// Ensure that there's still a marker on line 15
|
||||
await waitForState(dbg, state => dbg.selectors.getBreakpointCount(state) == 2);
|
||||
await waitForElementWithSelector(dbg, ".column-breakpoint.has-condition");
|
||||
columnBreakpointMarkers = getColumnBreakpointElements(dbg);
|
||||
ok(hasCondition(columnBreakpointMarkers[0]), "First column breakpoint has conditional style");
|
||||
|
||||
// Remove the breakpoint from 15:8
|
||||
removeBreakpointViaContext(dbg, 3);
|
||||
|
||||
// Ensure there's still a marker and it has no condition
|
||||
await waitForState(dbg, state => dbg.selectors.getBreakpointCount(state) == 1);
|
||||
await waitForElementWithSelector(dbg, ".column-breakpoint");
|
||||
|
||||
// Ensure the first column breakpoint has no conditional style
|
||||
await waitFor(() => !hasCondition(getColumnBreakpointElements(dbg)[0]));
|
||||
info("8. test removing the breakpoints by clicking in the gutter");
|
||||
await removeAllBreakpoints(dbg, 32, 0);
|
||||
});
|
||||
|
|
|
@ -31,27 +31,6 @@ function assertEditorBreakpoint(
|
|||
);
|
||||
}
|
||||
|
||||
function waitForElementFocus(dbg, el) {
|
||||
const doc = dbg.win.document;
|
||||
return waitFor(() => doc.activeElement == el && doc.hasFocus());
|
||||
}
|
||||
|
||||
function waitForBreakpointWithCondition(dbg, url, line, cond) {
|
||||
return waitForState(dbg, () => {
|
||||
const bp = findBreakpoint(dbg, url, line);
|
||||
return (
|
||||
bp && bp.options.condition && (!cond || bp.options.condition == cond)
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
function waitForBreakpointWithLog(dbg, url, line) {
|
||||
return waitForState(dbg, () => {
|
||||
const bp = findBreakpoint(dbg, url, line);
|
||||
return bp && bp.options.logValue;
|
||||
});
|
||||
}
|
||||
|
||||
function waitForBreakpointWithoutCondition(dbg, url, line) {
|
||||
return waitForState(dbg, () => {
|
||||
const bp = findBreakpoint(dbg, url, line);
|
||||
|
@ -60,37 +39,21 @@ function waitForBreakpointWithoutCondition(dbg, url, line) {
|
|||
}
|
||||
|
||||
async function setConditionalBreakpoint(dbg, index, condition) {
|
||||
const {
|
||||
addConditionalBreakpoint,
|
||||
editConditionalBreakpoint
|
||||
} = selectors.gutterContextMenu;
|
||||
// Make this work with either add or edit menu items
|
||||
const selector = `${addConditionalBreakpoint},${editConditionalBreakpoint}`;
|
||||
|
||||
const { addConditionItem, editConditionItem } = selectors;
|
||||
const selector = `${addConditionItem},${editConditionItem}`;
|
||||
rightClickElement(dbg, "gutter", index);
|
||||
selectContextMenuItem(dbg, selector);
|
||||
await waitForElement(dbg, "conditionalPanelInput");
|
||||
|
||||
// Position cursor reliably at the end of the text.
|
||||
pressKey(dbg, "End");
|
||||
type(dbg, condition);
|
||||
pressKey(dbg, "Enter");
|
||||
typeInPanel(dbg, condition);
|
||||
}
|
||||
|
||||
async function setLogPoint(dbg, index, value) {
|
||||
const { addLogPoint, editLogPoint } = selectors.gutterContextMenu;
|
||||
|
||||
// Make this work with either add or edit menu items
|
||||
const selector = `${addLogPoint},${editLogPoint}`;
|
||||
|
||||
rightClickElement(dbg, "gutter", index);
|
||||
selectContextMenuItem(dbg, selector);
|
||||
await waitForElement(dbg, "conditionalPanelInput");
|
||||
|
||||
// Position cursor reliably at the end of the text.
|
||||
pressKey(dbg, "End");
|
||||
type(dbg, value);
|
||||
pressKey(dbg, "Enter");
|
||||
selectContextMenuItem(
|
||||
dbg,
|
||||
`${selectors.addLogItem},${selectors.editLogItem}`
|
||||
);
|
||||
await typeInPanel(dbg, value);
|
||||
}
|
||||
|
||||
add_task(async function() {
|
||||
|
@ -101,9 +64,9 @@ add_task(async function() {
|
|||
await selectSource(dbg, "simple2");
|
||||
await waitForSelectedSource(dbg, "simple2");
|
||||
|
||||
info("Set condition `1`");
|
||||
await setConditionalBreakpoint(dbg, 5, "1");
|
||||
await waitForDispatch(dbg, "SET_BREAKPOINT");
|
||||
await waitForBreakpointWithCondition(dbg, "simple2", 5);
|
||||
await waitForCondition(dbg, 1);
|
||||
|
||||
let bp = findBreakpoint(dbg, "simple2", 5);
|
||||
is(bp.options.condition, "1", "breakpoint is created with the condition");
|
||||
|
@ -111,7 +74,7 @@ add_task(async function() {
|
|||
|
||||
info("Edit the conditional breakpoint set above");
|
||||
await setConditionalBreakpoint(dbg, 5, "2");
|
||||
await waitForBreakpointWithCondition(dbg, "simple2", 5, "12");
|
||||
await waitForCondition(dbg, 12);
|
||||
|
||||
bp = findBreakpoint(dbg, "simple2", 5);
|
||||
is(bp.options.condition, "12", "breakpoint is created with the condition");
|
||||
|
@ -127,7 +90,7 @@ add_task(async function() {
|
|||
clickElement(dbg, "gutter", 5);
|
||||
await waitForDispatch(dbg, "SET_BREAKPOINT");
|
||||
await setConditionalBreakpoint(dbg, 5, "1");
|
||||
await waitForBreakpointWithCondition(dbg, "simple2", 5);
|
||||
await waitForCondition(dbg, 1);
|
||||
|
||||
bp = findBreakpoint(dbg, "simple2", 5);
|
||||
is(bp.options.condition, "1", "breakpoint is created with the condition");
|
||||
|
@ -142,7 +105,7 @@ add_task(async function() {
|
|||
|
||||
info('Add "log point"');
|
||||
await setLogPoint(dbg, 5, "44");
|
||||
await waitForBreakpointWithLog(dbg, "simple2", 5);
|
||||
await waitForLog(dbg, 44);
|
||||
await assertEditorBreakpoint(dbg, 5, { hasLog: true });
|
||||
|
||||
bp = findBreakpoint(dbg, "simple2", 5);
|
||||
|
|
|
@ -204,11 +204,24 @@ async function waitForElement(dbg, name, ...args) {
|
|||
return findElement(dbg, name, ...args);
|
||||
}
|
||||
|
||||
async function waitForAllElements(dbg, name, count = 1) {
|
||||
await waitUntil(() => findAllElements(dbg, name).length >= count);
|
||||
return findAllElements(dbg, name);
|
||||
}
|
||||
|
||||
async function waitForElementWithSelector(dbg, selector) {
|
||||
await waitUntil(() => findElementWithSelector(dbg, selector));
|
||||
return findElementWithSelector(dbg, selector);
|
||||
}
|
||||
|
||||
function assertClass(el, className, exists = true) {
|
||||
if (exists) {
|
||||
ok(el.classList.contains(className), `${className} class exists`);
|
||||
} else {
|
||||
ok(!el.classList.contains(className), `${className} class does not exist`);
|
||||
}
|
||||
}
|
||||
|
||||
function waitForSelectedLocation(dbg, line) {
|
||||
return waitForState(dbg, state => {
|
||||
const location = dbg.selectors.getSelectedLocation(state);
|
||||
|
@ -487,6 +500,22 @@ async function waitForPaused(dbg, url) {
|
|||
await waitForSelectedSource(dbg, url);
|
||||
}
|
||||
|
||||
function waitForCondition(dbg, condition) {
|
||||
return waitForState(dbg, state =>
|
||||
dbg.selectors
|
||||
.getBreakpointsList(state)
|
||||
.find(bp => bp.options.condition == condition)
|
||||
);
|
||||
}
|
||||
|
||||
function waitForLog(dbg, logValue) {
|
||||
return waitForState(dbg, state =>
|
||||
dbg.selectors
|
||||
.getBreakpointsList(state)
|
||||
.find(bp => bp.options.logValue == logValue)
|
||||
);
|
||||
}
|
||||
|
||||
/*
|
||||
* useful for when you want to see what is happening
|
||||
* e.g await waitForever()
|
||||
|
@ -1190,6 +1219,7 @@ const selectors = {
|
|||
removeOthers: "#node-menu-delete-other",
|
||||
removeCondition: "#node-menu-remove-condition"
|
||||
},
|
||||
columnBreakpoints: ".column-breakpoint",
|
||||
scopes: ".scopes-list",
|
||||
scopeNode: i => `.scopes-list .tree-node:nth-child(${i}) .object-label`,
|
||||
scopeValue: i =>
|
||||
|
@ -1197,15 +1227,13 @@ const selectors = {
|
|||
frame: i => `.frames [role="list"] [role="listitem"]:nth-child(${i})`,
|
||||
frames: '.frames [role="list"] [role="listitem"]',
|
||||
gutter: i => `.CodeMirror-code *:nth-child(${i}) .CodeMirror-linenumber`,
|
||||
// These work for bobth the breakpoint listing and gutter marker
|
||||
gutterContextMenu: {
|
||||
addConditionalBreakpoint:
|
||||
"#node-menu-add-condition, #node-menu-add-conditional-breakpoint",
|
||||
editConditionalBreakpoint:
|
||||
"#node-menu-edit-condition, #node-menu-edit-conditional-breakpoint",
|
||||
addLogPoint: "#node-menu-add-log-point",
|
||||
editLogPoint: "#node-menu-edit-log-point"
|
||||
},
|
||||
addConditionItem:
|
||||
"#node-menu-add-condition, #node-menu-add-conditional-breakpoint",
|
||||
editConditionItem:
|
||||
"#node-menu-edit-condition, #node-menu-edit-conditional-breakpoint",
|
||||
addLogItem: "#node-menu-add-log-point",
|
||||
editLogItem: "#node-menu-edit-log-point",
|
||||
disableItem: "#node-menu-disable-breakpoint",
|
||||
menuitem: i => `menupopup menuitem:nth-child(${i})`,
|
||||
pauseOnExceptions: ".pause-exceptions",
|
||||
breakpoint: ".CodeMirror-code > .new-breakpoint",
|
||||
|
@ -1339,12 +1367,12 @@ function altClickElement(dbg, elementName, ...args) {
|
|||
function rightClickElement(dbg, elementName, ...args) {
|
||||
const selector = getSelector(elementName, ...args);
|
||||
const doc = dbg.win.document;
|
||||
return rightClickEl(dbg, doc.querySelector(selector));
|
||||
}
|
||||
|
||||
return EventUtils.synthesizeMouseAtCenter(
|
||||
doc.querySelector(selector),
|
||||
{ type: "contextmenu" },
|
||||
dbg.win
|
||||
);
|
||||
function rightClickEl(dbg, el) {
|
||||
const doc = dbg.win.document;
|
||||
EventUtils.synthesizeMouseAtCenter(el, { type: "contextmenu" }, dbg.win);
|
||||
}
|
||||
|
||||
async function clickGutter(dbg, line) {
|
||||
|
@ -1363,6 +1391,15 @@ function selectContextMenuItem(dbg, selector) {
|
|||
return EventUtils.synthesizeMouseAtCenter(item, {}, dbg.toolbox.win);
|
||||
}
|
||||
|
||||
async function typeInPanel(dbg, text) {
|
||||
await waitForElement(dbg, "conditionalPanelInput");
|
||||
|
||||
// Position cursor reliably at the end of the text.
|
||||
pressKey(dbg, "End");
|
||||
type(dbg, text);
|
||||
pressKey(dbg, "Enter");
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggles the debugger call stack accordian.
|
||||
*
|
||||
|
|
Загрузка…
Ссылка в новой задаче