tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

browser_dbg-blackbox.js (23633B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this
      3 * file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
      4 
      5 // This test covers all the blackboxing functionality relating to a selected
      6 // source open in the debugger editor.
      7 
      8 "use strict";
      9 
     10 requestLongerTimeout(5);
     11 
     12 const contextMenuItems = {
     13  ignoreSource: { selector: "#node-menu-blackbox", label: "Ignore source" },
     14  unignoreSource: { selector: "#node-menu-blackbox", label: "Unignore source" },
     15  ignoreLines: { selector: "#node-menu-blackbox-lines", label: "Ignore lines" },
     16  unignoreLines: {
     17    selector: "#node-menu-blackbox-lines",
     18    label: "Unignore lines",
     19  },
     20  ignoreLine: { selector: "#node-menu-blackbox-line", label: "Ignore line" },
     21  unignoreLine: {
     22    selector: "#node-menu-blackbox-line",
     23    label: "Unignore line",
     24  },
     25 };
     26 
     27 const SOURCE_IS_FULLY_IGNORED = "source";
     28 const SOURCE_LINES_ARE_IGNORED = "line";
     29 const SOURCE_IS_NOT_IGNORED = "none";
     30 
     31 // Tests basic functionality for blackbox source and blackbox single and multiple lines
     32 add_task(async function testAllBlackBox() {
     33  // using the doc-command-click.html as it has a simple js file we can use
     34  // testing.
     35  const file = "simple4.js";
     36  const dbg = await initDebugger("doc-command-click.html", file);
     37 
     38  const source = findSource(dbg, file);
     39 
     40  await selectSource(dbg, source);
     41 
     42  await addBreakpoint(dbg, file, 8);
     43 
     44  await testBlackBoxSource(dbg, source);
     45  await testBlackBoxMultipleLines(dbg, source);
     46  await testBlackBoxSingleLine(dbg, source);
     47 });
     48 
     49 // Test that the blackboxed lines are persisted accross reloads and still work accordingly.
     50 add_task(async function testBlackBoxOnReload() {
     51  const file = "simple4.js";
     52  const dbg = await initDebugger("doc-command-click.html", file);
     53 
     54  const source = findSource(dbg, file);
     55 
     56  await selectSource(dbg, source);
     57 
     58  // Adding 2 breakpoints in funcB() and funcC() which
     59  // would be hit in order.
     60  await addBreakpoint(dbg, file, 8);
     61  await addBreakpoint(dbg, file, 12);
     62 
     63  info("Reload without any blackboxing to make all necesary postions are hit");
     64  const onReloaded = reload(dbg, file);
     65 
     66  await waitForPaused(dbg);
     67  await assertPausedAtSourceAndLine(dbg, source.id, 2);
     68  await resume(dbg);
     69 
     70  await waitForPaused(dbg);
     71  await assertPausedAtSourceAndLine(dbg, source.id, 8);
     72  await resume(dbg);
     73 
     74  await waitForPaused(dbg);
     75  await assertPausedAtSourceAndLine(dbg, source.id, 12);
     76  await resume(dbg);
     77 
     78  info("Wait for reload to complete after resume");
     79  await onReloaded;
     80 
     81  assertNotPaused(dbg);
     82 
     83  info("Ignoring line 2 using the gutter context menu");
     84  await openContextMenuInDebugger(dbg, "gutterElement", 2);
     85  await selectBlackBoxContextMenuItem(dbg, "blackbox-line");
     86 
     87  info("Ignoring line 7 to 9 using the editor context menu");
     88  await selectEditorLinesAndOpenContextMenu(dbg, { startLine: 7, endLine: 9 });
     89  await selectBlackBoxContextMenuItem(dbg, "blackbox-lines");
     90 
     91  const onReloaded2 = reload(dbg, file);
     92 
     93  await waitForPaused(dbg);
     94  await assertPausedAtSourceAndLine(dbg, source.id, 12);
     95  await resume(dbg);
     96  info("Wait for reload to complete after resume");
     97  await onReloaded2;
     98 
     99  assertNotPaused(dbg);
    100 
    101  info(
    102    "Check that the expected blackbox context menu state is correct across reload"
    103  );
    104 
    105  await assertEditorBlackBoxBoxContextMenuItems(dbg, {
    106    blackboxedLine: 2,
    107    nonBlackBoxedLine: 4,
    108    blackBoxedLines: [7, 9],
    109    nonBlackBoxedLines: [3, 4],
    110    blackboxedSourceState: SOURCE_LINES_ARE_IGNORED,
    111  });
    112 
    113  await assertGutterBlackBoxBoxContextMenuItems(dbg, {
    114    blackboxedLine: 2,
    115    nonBlackBoxedLine: 4,
    116    blackboxedSourceState: SOURCE_LINES_ARE_IGNORED,
    117  });
    118 
    119  await assertSourceTreeBlackBoxBoxContextMenuItems(dbg, {
    120    blackBoxedSourceTreeNode: findSourceNodeWithText(dbg, "simple4.js"),
    121    nonBlackBoxedSourceTreeNode: findSourceNodeWithText(dbg, "simple2.js"),
    122  });
    123 });
    124 
    125 add_task(async function testBlackBoxOnToolboxRestart() {
    126  const dbg = await initDebugger("doc-command-click.html", "simple4.js");
    127  const source = findSource(dbg, "simple4.js");
    128 
    129  await selectSource(dbg, source);
    130 
    131  const onReloaded = reload(dbg, "simple4.js");
    132  await waitForPaused(dbg);
    133 
    134  info("Assert it paused at the debugger statement");
    135  await assertPausedAtSourceAndLine(dbg, source.id, 2);
    136  await resume(dbg);
    137  await onReloaded;
    138 
    139  info("Ignoring line 2 using the gutter context menu");
    140  await openContextMenuInDebugger(dbg, "gutterElement", 2);
    141  await selectBlackBoxContextMenuItem(dbg, "blackbox-line");
    142 
    143  await reloadBrowser();
    144  // Wait a little bit incase of a pause
    145  await wait(1000);
    146 
    147  info("Assert that the debugger no longer pauses on the debugger statement");
    148  assertNotPaused(dbg);
    149 
    150  info("Close the toolbox");
    151  await dbg.toolbox.closeToolbox();
    152 
    153  info("Reopen the toolbox on the debugger");
    154  const toolbox = await openToolboxForTab(gBrowser.selectedTab, "jsdebugger");
    155  const dbg2 = createDebuggerContext(toolbox);
    156  await waitForSelectedSource(dbg2, findSource(dbg2, "simple4.js"));
    157 
    158  // Reloading will automatically re-apply blackboxing which triggers a RDP request.
    159  // Wait for blackbox action and requests to settle to avoid unhandled promise
    160  // rejections due to pending promises.
    161  const onBlackboxDone = waitForDispatch(dbg2.store, "BLACKBOX_SOURCE_RANGES");
    162  await reloadBrowser();
    163 
    164  info("Wait for the blackbox action to complete");
    165  await onBlackboxDone;
    166  await waitForRequestsToSettle(dbg);
    167 
    168  // Wait a little incase of a pause
    169  await wait(1000);
    170 
    171  info("Assert that debbuger still does not pause on the debugger statement");
    172  assertNotPaused(dbg2);
    173 });
    174 
    175 async function testBlackBoxSource(dbg, source) {
    176  info("Start testing blackboxing the whole source");
    177 
    178  info("Assert the blackbox context menu items before any blackboxing is done");
    179  // When the source is not blackboxed there are no blackboxed lines
    180  await assertEditorBlackBoxBoxContextMenuItems(dbg, {
    181    blackboxedLine: null,
    182    nonBlackBoxedLine: 4,
    183    blackBoxedLines: null,
    184    nonBlackBoxedLines: [3, 4],
    185    blackboxedSourceState: SOURCE_IS_NOT_IGNORED,
    186  });
    187 
    188  await assertGutterBlackBoxBoxContextMenuItems(dbg, {
    189    blackboxedLine: null,
    190    nonBlackBoxedLine: 4,
    191    blackboxedSourceState: SOURCE_IS_NOT_IGNORED,
    192  });
    193 
    194  await assertSourceTreeBlackBoxBoxContextMenuItems(dbg, {
    195    blackBoxedSourceTreeNode: null,
    196    nonBlackBoxedSourceTreeNode: findSourceNodeWithText(dbg, "simple4.js"),
    197  });
    198 
    199  info(
    200    "Blackbox the whole simple4.js source file using the editor context menu"
    201  );
    202  await openContextMenuInDebugger(dbg, "CodeMirrorLines");
    203  await selectBlackBoxContextMenuItem(dbg, "blackbox");
    204 
    205  info("Assert that all lines in the source are styled correctly");
    206  await assertIgnoredStyleInSourceLines(dbg, { hasBlackboxedLinesClass: true });
    207 
    208  info("Assert that the source tree for simple4.js has the ignored style");
    209  const node = findSourceNodeWithText(dbg, "simple4.js");
    210  ok(
    211    node.querySelector(".blackboxed"),
    212    "simple4.js node does not have the ignored style"
    213  );
    214 
    215  invokeInTab("funcA");
    216 
    217  info(
    218    "The debugger statement on line 2 and the breakpoint on line 8 should not be hit"
    219  );
    220  assertNotPaused(dbg);
    221 
    222  info("Assert the blackbox context menu items after blackboxing is done");
    223  // When the whole source is blackboxed there are no nonBlackboxed lines
    224  await assertEditorBlackBoxBoxContextMenuItems(dbg, {
    225    blackboxedLine: 2,
    226    nonBlackBoxedLine: null,
    227    blackBoxedLines: [3, 5],
    228    nonBlackBoxedLines: null,
    229    blackboxedSourceState: SOURCE_IS_FULLY_IGNORED,
    230  });
    231 
    232  await assertGutterBlackBoxBoxContextMenuItems(dbg, {
    233    blackboxedLine: 2,
    234    nonBlackBoxedLine: null,
    235    blackboxedSourceState: SOURCE_IS_FULLY_IGNORED,
    236  });
    237 
    238  await assertSourceTreeBlackBoxBoxContextMenuItems(dbg, {
    239    blackBoxedSourceTreeNode: findSourceNodeWithText(dbg, "simple4.js"),
    240    nonBlackBoxedSourceTreeNode: findSourceNodeWithText(dbg, "simple2.js"),
    241  });
    242 
    243  info("Unblackbox the whole source using the sourcetree context menu");
    244  rightClickEl(dbg, findSourceNodeWithText(dbg, "simple4.js"));
    245  await waitForContextMenu(dbg);
    246  await selectBlackBoxContextMenuItem(dbg, "blackbox");
    247 
    248  info("Assert that all lines in the source are un-styled correctly");
    249  await assertIgnoredStyleInSourceLines(dbg, {
    250    hasBlackboxedLinesClass: false,
    251  });
    252 
    253  info(
    254    "Assert that the source tree for simple4.js does not have the ignored style"
    255  );
    256  const nodeAfterBlackbox = findSourceNodeWithText(dbg, "simple4.js");
    257  ok(
    258    !nodeAfterBlackbox.querySelector(".blackboxed"),
    259    "simple4.js node still has the ignored style"
    260  );
    261 
    262  invokeInTab("funcA");
    263 
    264  info("assert the pause at the debugger statement on line 2");
    265  await waitForPaused(dbg);
    266  await assertPausedAtSourceAndLine(dbg, source.id, 2);
    267  await resume(dbg);
    268 
    269  info("assert the pause at the breakpoint set on line 8");
    270  await waitForPaused(dbg);
    271  await assertPausedAtSourceAndLine(dbg, source.id, 8);
    272  await resume(dbg);
    273 
    274  assertNotPaused(dbg);
    275 
    276  // When the source is not blackboxed there are no blackboxed lines
    277  await assertEditorBlackBoxBoxContextMenuItems(dbg, {
    278    blackboxedLine: null,
    279    nonBlackBoxedLine: 4,
    280    blackBoxedLines: null,
    281    nonBlackBoxedLines: [3, 4],
    282    blackboxedSourceState: SOURCE_IS_NOT_IGNORED,
    283  });
    284 
    285  await assertGutterBlackBoxBoxContextMenuItems(dbg, {
    286    blackboxedLine: null,
    287    nonBlackBoxedLine: 4,
    288    blackboxedSourceState: SOURCE_IS_NOT_IGNORED,
    289  });
    290 
    291  await assertSourceTreeBlackBoxBoxContextMenuItems(dbg, {
    292    blackBoxedSourceTreeNode: null,
    293    nonBlackBoxedSourceTreeNode: findSourceNodeWithText(dbg, "simple2.js"),
    294  });
    295 }
    296 
    297 async function testBlackBoxMultipleLines(dbg, source) {
    298  info("Blackbox lines 7 to 13 using the  editor content menu items");
    299  await selectEditorLinesAndOpenContextMenu(dbg, { startLine: 7, endLine: 13 });
    300  await selectBlackBoxContextMenuItem(dbg, "blackbox-lines");
    301 
    302  await assertEditorBlackBoxBoxContextMenuItems(dbg, {
    303    blackboxedLine: null,
    304    nonBlackBoxedLine: 3,
    305    blackBoxedLines: [7, 9],
    306    nonBlackBoxedLines: [3, 4],
    307    blackboxedSourceState: SOURCE_LINES_ARE_IGNORED,
    308  });
    309 
    310  await assertGutterBlackBoxBoxContextMenuItems(dbg, {
    311    blackboxedLine: null,
    312    nonBlackBoxedLine: 3,
    313    blackboxedSourceState: SOURCE_LINES_ARE_IGNORED,
    314  });
    315 
    316  await assertSourceTreeBlackBoxBoxContextMenuItems(dbg, {
    317    blackBoxedSourceTreeNode: findSourceNodeWithText(dbg, "simple4.js"),
    318    nonBlackBoxedSourceTreeNode: findSourceNodeWithText(dbg, "simple2.js"),
    319  });
    320 
    321  info("Assert that the ignored lines are styled correctly");
    322  await assertIgnoredStyleInSourceLines(dbg, {
    323    lines: [7, 13],
    324    hasBlackboxedLinesClass: true,
    325  });
    326 
    327  info("Assert that the source tree for simple4.js has the ignored style");
    328  const node = findSourceNodeWithText(dbg, "simple4.js");
    329 
    330  ok(
    331    node.querySelector(".blackboxed"),
    332    "simple4.js node does not have the ignored style"
    333  );
    334 
    335  invokeInTab("funcA");
    336 
    337  info("assert the pause at the debugger statement on line 2");
    338  await waitForPaused(dbg);
    339  await assertPausedAtSourceAndLine(dbg, source.id, 2);
    340  await resume(dbg);
    341 
    342  info(
    343    "The breakpoint set on line 8 should not get hit as its within the blackboxed range"
    344  );
    345  assertNotPaused(dbg);
    346 
    347  info("Unblackbox lines 7 to 13");
    348  await selectEditorLinesAndOpenContextMenu(dbg, { startLine: 7, endLine: 13 });
    349  await selectBlackBoxContextMenuItem(dbg, "blackbox-lines");
    350 
    351  await assertEditorBlackBoxBoxContextMenuItems(dbg, {
    352    blackboxedLine: null,
    353    nonBlackBoxedLine: 4,
    354    blackBoxedLines: null,
    355    nonBlackBoxedLines: [3, 4],
    356    blackboxedSourceState: SOURCE_IS_NOT_IGNORED,
    357  });
    358 
    359  await assertGutterBlackBoxBoxContextMenuItems(dbg, {
    360    blackboxedLine: null,
    361    nonBlackBoxedLine: 4,
    362    blackboxedSourceState: SOURCE_IS_NOT_IGNORED,
    363  });
    364 
    365  await assertSourceTreeBlackBoxBoxContextMenuItems(dbg, {
    366    blackBoxedSourceTreeNode: null,
    367    nonBlackBoxedSourceTreeNode: findSourceNodeWithText(dbg, "simple2.js"),
    368  });
    369 
    370  info("Assert that the un-ignored lines are no longer have the style");
    371  await assertIgnoredStyleInSourceLines(dbg, {
    372    lines: [7, 13],
    373    hasBlackboxedLinesClass: false,
    374  });
    375 
    376  info(
    377    "Assert that the source tree for simple4.js does not have the ignored style"
    378  );
    379  const nodeAfterBlackbox = findSourceNodeWithText(dbg, "simple4.js");
    380  ok(
    381    !nodeAfterBlackbox.querySelector(".blackboxed"),
    382    "simple4.js still has the ignored style"
    383  );
    384 
    385  invokeInTab("funcA");
    386 
    387  // assert the pause at the debugger statement on line 2
    388  await waitForPaused(dbg);
    389  await assertPausedAtSourceAndLine(dbg, source.id, 2);
    390  await resume(dbg);
    391 
    392  // assert the pause at the breakpoint set on line 8
    393  await waitForPaused(dbg);
    394  await assertPausedAtSourceAndLine(dbg, source.id, 8);
    395  await resume(dbg);
    396 
    397  assertNotPaused(dbg);
    398 }
    399 
    400 async function testBlackBoxSingleLine(dbg, source) {
    401  info("Black box line 2 of funcA() with the debugger statement");
    402  await openContextMenuInDebugger(dbg, "gutterElement", 2);
    403  await selectBlackBoxContextMenuItem(dbg, "blackbox-line");
    404 
    405  await assertEditorBlackBoxBoxContextMenuItems(dbg, {
    406    blackboxedLine: 2,
    407    nonBlackBoxedLine: 4,
    408    blackBoxedLines: null,
    409    nonBlackBoxedLines: [3, 4],
    410    blackboxedSourceState: SOURCE_LINES_ARE_IGNORED,
    411  });
    412 
    413  await assertGutterBlackBoxBoxContextMenuItems(dbg, {
    414    blackboxedLine: null,
    415    nonBlackBoxedLine: 4,
    416    blackboxedSourceState: SOURCE_LINES_ARE_IGNORED,
    417  });
    418 
    419  await assertSourceTreeBlackBoxBoxContextMenuItems(dbg, {
    420    blackBoxedSourceTreeNode: findSourceNodeWithText(dbg, "simple4.js"),
    421    nonBlackBoxedSourceTreeNode: findSourceNodeWithText(dbg, "simple2.js"),
    422  });
    423 
    424  info("Assert that the ignored line 2 is styled correctly");
    425  await assertIgnoredStyleInSourceLines(dbg, {
    426    lines: [2],
    427    hasBlackboxedLinesClass: true,
    428  });
    429 
    430  info("Black box line 4 of funcC() with the debugger statement");
    431  await openContextMenuInDebugger(dbg, "gutterElement", 4);
    432  await selectBlackBoxContextMenuItem(dbg, "blackbox-line");
    433 
    434  info("Assert that the ignored line 4 is styled correctly");
    435  await assertIgnoredStyleInSourceLines(dbg, {
    436    lines: [4],
    437    hasBlackboxedLinesClass: true,
    438  });
    439 
    440  invokeInTab("funcA");
    441 
    442  // assert the pause at the breakpoint set on line 8
    443  await waitForPaused(dbg);
    444  await assertPausedAtSourceAndLine(dbg, source.id, 8);
    445  await resume(dbg);
    446 
    447  assertNotPaused(dbg);
    448 
    449  info("Un-blackbox line 2 of funcA()");
    450  await selectEditorLinesAndOpenContextMenu(
    451    dbg,
    452    { startLine: 2, endLine: 2 },
    453    "CodeMirrorLines"
    454  );
    455  await selectBlackBoxContextMenuItem(dbg, "blackbox-line");
    456 
    457  await assertEditorBlackBoxBoxContextMenuItems(dbg, {
    458    blackboxedLine: 4,
    459    nonBlackBoxedLine: 3,
    460    blackBoxedLines: null,
    461    nonBlackBoxedLines: [11, 12],
    462    blackboxedSourceState: SOURCE_LINES_ARE_IGNORED,
    463  });
    464 
    465  await assertGutterBlackBoxBoxContextMenuItems(dbg, {
    466    blackboxedLine: 4,
    467    nonBlackBoxedLine: 3,
    468    blackboxedSourceState: SOURCE_LINES_ARE_IGNORED,
    469  });
    470 
    471  await assertSourceTreeBlackBoxBoxContextMenuItems(dbg, {
    472    blackBoxedSourceTreeNode: null,
    473    nonBlackBoxedSourceTreeNode: findSourceNodeWithText(dbg, "simple2.js"),
    474  });
    475 
    476  info("Assert that the un-ignored line 2 is styled correctly");
    477  await assertIgnoredStyleInSourceLines(dbg, {
    478    lines: [2],
    479    hasBlackboxedLinesClass: false,
    480  });
    481 
    482  invokeInTab("funcA");
    483 
    484  // assert the pause at the debugger statement on line 2
    485  await waitForPaused(dbg);
    486  await assertPausedAtSourceAndLine(dbg, source.id, 2);
    487  await resume(dbg);
    488 
    489  // assert the pause at the breakpoint set on line 8
    490  await waitForPaused(dbg);
    491  await assertPausedAtSourceAndLine(dbg, source.id, 8);
    492  await resume(dbg);
    493 
    494  assertNotPaused(dbg);
    495 }
    496 
    497 async function assertContextMenuDisabled(dbg, selector, shouldBeDisabled) {
    498  const item = await waitFor(() => findContextMenu(dbg, selector));
    499  is(
    500    item.disabled,
    501    shouldBeDisabled,
    502    `The the context menu item is ${
    503      shouldBeDisabled ? "disabled" : "not disabled"
    504    }`
    505  );
    506 }
    507 
    508 /**
    509 * Asserts that the gutter blackbox context menu items which are visible are correct
    510 *
    511 * @param {object} dbg
    512 * @param {Array} testFixtures
    513 *                 Details needed for the assertion. Any blackboxed/nonBlackboxed lines
    514 *                 and any blackboxed/nonBlackboxed sources
    515 */
    516 async function assertGutterBlackBoxBoxContextMenuItems(dbg, testFixtures) {
    517  const { blackboxedLine, nonBlackBoxedLine, blackboxedSourceState } =
    518    testFixtures;
    519  if (blackboxedLine) {
    520    info(
    521      "Asserts that the gutter context menu items when clicking on the gutter of a blackboxed line"
    522    );
    523    const popup = await openContextMenuInDebugger(
    524      dbg,
    525      "gutterElement",
    526      blackboxedLine
    527    );
    528    // When the whole source is blackboxed the the gutter visually shows `ignore line`
    529    // but it is disabled indicating that individual lines cannot be nonBlackboxed.
    530    const item =
    531      blackboxedSourceState == SOURCE_IS_FULLY_IGNORED
    532        ? contextMenuItems.ignoreLine
    533        : contextMenuItems.unignoreLine;
    534 
    535    await assertContextMenuLabel(dbg, item.selector, item.label);
    536    await assertContextMenuDisabled(
    537      dbg,
    538      item.selector,
    539      blackboxedSourceState == SOURCE_IS_FULLY_IGNORED
    540    );
    541    await closeContextMenu(dbg, popup);
    542  }
    543 
    544  if (nonBlackBoxedLine) {
    545    info(
    546      "Asserts that the gutter context menu items when clicking on the gutter of a nonBlackboxed line"
    547    );
    548 
    549    // Wait for CM6 to complete any updates so the popup
    550    // does not lose focus while asserting the context menu items due
    551    // late updates completion.
    552    await waitForDocumentLoadComplete(dbg);
    553 
    554    const popup = await openContextMenuInDebugger(
    555      dbg,
    556      "gutterElement",
    557      nonBlackBoxedLine
    558    );
    559    const item = contextMenuItems.ignoreLine;
    560    await assertContextMenuLabel(dbg, item.selector, item.label);
    561    await assertContextMenuDisabled(dbg, item.selector, false);
    562    await closeContextMenu(dbg, popup);
    563  }
    564 }
    565 
    566 /**
    567 * Asserts that the source tree blackbox context menu items which are visible are correct
    568 *
    569 * @param {object} dbg
    570 * @param {Array} testFixtures
    571 *                 Details needed for the assertion. Any blackboxed/nonBlackboxed sources
    572 */
    573 async function assertSourceTreeBlackBoxBoxContextMenuItems(dbg, testFixtures) {
    574  const { blackBoxedSourceTreeNode, nonBlackBoxedSourceTreeNode } =
    575    testFixtures;
    576  if (blackBoxedSourceTreeNode) {
    577    info(
    578      "Asserts that the source tree blackbox context menu items when clicking on a blackboxed source tree node"
    579    );
    580    rightClickEl(dbg, blackBoxedSourceTreeNode);
    581    const popup = await waitForContextMenu(dbg);
    582    const item = contextMenuItems.unignoreSource;
    583    await assertContextMenuLabel(dbg, item.selector, item.label);
    584    await closeContextMenu(dbg, popup);
    585  }
    586 
    587  if (nonBlackBoxedSourceTreeNode) {
    588    info(
    589      "Asserts that the source tree blackbox context menu items when clicking on an un-blackboxed sorce tree node"
    590    );
    591    rightClickEl(dbg, nonBlackBoxedSourceTreeNode);
    592    const popup = await waitForContextMenu(dbg);
    593    const _item = contextMenuItems.ignoreSource;
    594    await assertContextMenuLabel(dbg, _item.selector, _item.label);
    595    await closeContextMenu(dbg, popup);
    596  }
    597 }
    598 
    599 /**
    600 * Asserts that the editor blackbox context menu items which are visible are correct
    601 *
    602 * @param {object} dbg
    603 * @param {Array} testFixtures
    604 *                 Details needed for the assertion. Any blackboxed/nonBlackboxed lines
    605 *                 and any blackboxed/nonBlackboxed sources
    606 */
    607 async function assertEditorBlackBoxBoxContextMenuItems(dbg, testFixtures) {
    608  const {
    609    blackboxedLine,
    610    nonBlackBoxedLine,
    611    blackBoxedLines,
    612    nonBlackBoxedLines,
    613    blackboxedSourceState,
    614  } = testFixtures;
    615 
    616  if (blackboxedLine) {
    617    info(
    618      "Asserts the editor blackbox context menu items when right-clicking on a single blackboxed line"
    619    );
    620    const popup = await selectEditorLinesAndOpenContextMenu(dbg, {
    621      startLine: blackboxedLine,
    622    });
    623 
    624    const expectedContextMenuItems = [contextMenuItems.unignoreSource];
    625 
    626    if (blackboxedSourceState !== SOURCE_IS_FULLY_IGNORED) {
    627      expectedContextMenuItems.push(contextMenuItems.unignoreLine);
    628    }
    629 
    630    for (const expectedContextMenuItem of expectedContextMenuItems) {
    631      info(
    632        "Checking context menu item " +
    633          expectedContextMenuItem.selector +
    634          " with label " +
    635          expectedContextMenuItem.label
    636      );
    637      await assertContextMenuLabel(
    638        dbg,
    639        expectedContextMenuItem.selector,
    640        expectedContextMenuItem.label
    641      );
    642    }
    643    await closeContextMenu(dbg, popup);
    644  }
    645 
    646  if (nonBlackBoxedLine) {
    647    info(
    648      "Asserts the editor blackbox context menu items when right-clicking on a single non-blackboxed line"
    649    );
    650    const popup = await selectEditorLinesAndOpenContextMenu(dbg, {
    651      startLine: nonBlackBoxedLine,
    652    });
    653 
    654    const expectedContextMenuItems = [
    655      blackboxedSourceState == SOURCE_IS_NOT_IGNORED
    656        ? contextMenuItems.ignoreSource
    657        : contextMenuItems.unignoreSource,
    658      contextMenuItems.ignoreLine,
    659    ];
    660 
    661    for (const expectedContextMenuItem of expectedContextMenuItems) {
    662      info(
    663        "Checking context menu item " +
    664          expectedContextMenuItem.selector +
    665          " with label " +
    666          expectedContextMenuItem.label
    667      );
    668      await assertContextMenuLabel(
    669        dbg,
    670        expectedContextMenuItem.selector,
    671        expectedContextMenuItem.label
    672      );
    673    }
    674    await closeContextMenu(dbg, popup);
    675  }
    676 
    677  if (blackBoxedLines) {
    678    info(
    679      "Asserts the editor blackbox context menu items when right-clicking on multiple blackboxed lines"
    680    );
    681    const popup = await selectEditorLinesAndOpenContextMenu(dbg, {
    682      startLine: blackBoxedLines[0],
    683      endLine: blackBoxedLines[1],
    684    });
    685 
    686    const expectedContextMenuItems = [contextMenuItems.unignoreSource];
    687 
    688    if (blackboxedSourceState !== SOURCE_IS_FULLY_IGNORED) {
    689      expectedContextMenuItems.push(contextMenuItems.unignoreLines);
    690    }
    691 
    692    for (const expectedContextMenuItem of expectedContextMenuItems) {
    693      info(
    694        "Checking context menu item " +
    695          expectedContextMenuItem.selector +
    696          " with label " +
    697          expectedContextMenuItem.label
    698      );
    699      await assertContextMenuLabel(
    700        dbg,
    701        expectedContextMenuItem.selector,
    702        expectedContextMenuItem.label
    703      );
    704    }
    705    await closeContextMenu(dbg, popup);
    706  }
    707 
    708  if (nonBlackBoxedLines) {
    709    info(
    710      "Asserts the editor blackbox context menu items when right-clicking on multiple non-blackboxed lines"
    711    );
    712    const popup = await selectEditorLinesAndOpenContextMenu(dbg, {
    713      startLine: nonBlackBoxedLines[0],
    714      endLine: nonBlackBoxedLines[1],
    715    });
    716 
    717    const expectedContextMenuItems = [
    718      blackboxedSourceState == SOURCE_IS_NOT_IGNORED
    719        ? contextMenuItems.ignoreSource
    720        : contextMenuItems.unignoreSource,
    721    ];
    722 
    723    if (blackboxedSourceState !== SOURCE_IS_FULLY_IGNORED) {
    724      expectedContextMenuItems.push(contextMenuItems.ignoreLines);
    725    }
    726 
    727    for (const expectedContextMenuItem of expectedContextMenuItems) {
    728      info(
    729        "Checking context menu item " +
    730          expectedContextMenuItem.selector +
    731          " with label " +
    732          expectedContextMenuItem.label
    733      );
    734      await assertContextMenuLabel(
    735        dbg,
    736        expectedContextMenuItem.selector,
    737        expectedContextMenuItem.label
    738      );
    739    }
    740    await closeContextMenu(dbg, popup);
    741  }
    742 }