tor-browser

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

browser_rules_copy_styles.js (11661B)


      1 /* Any copyright is dedicated to the Public Domain.
      2 http://creativecommons.org/publicdomain/zero/1.0/ */
      3 
      4 "use strict";
      5 
      6 /**
      7 * Tests the behaviour of the copy styles context menu items in the rule
      8 * view.
      9 */
     10 
     11 const osString = Services.appinfo.OS;
     12 
     13 const TEST_URI = URL_ROOT_SSL + "doc_copystyles.html";
     14 
     15 add_task(async function () {
     16  await addTab(TEST_URI);
     17  const { inspector, view } = await openRuleView();
     18  await selectNode("#testid", inspector);
     19 
     20  const ruleEditor = getRuleViewRuleEditor(view, 1);
     21 
     22  const data = [
     23    {
     24      desc: "Test Copy Property Name",
     25      node: ruleEditor.rule.textProps[0].editor.nameSpan,
     26      menuItemLabel: "styleinspector.contextmenu.copyPropertyName",
     27      expectedPattern: "color",
     28      visible: {
     29        copyLocation: false,
     30        copyDeclaration: true,
     31        copyPropertyName: true,
     32        copyPropertyValue: false,
     33        copySelector: false,
     34        copyRule: true,
     35      },
     36    },
     37    {
     38      desc: "Test Copy Property Value",
     39      node: ruleEditor.rule.textProps[2].editor.valueSpan,
     40      menuItemLabel: "styleinspector.contextmenu.copyPropertyValue",
     41      expectedPattern: "12px",
     42      visible: {
     43        copyLocation: false,
     44        copyDeclaration: true,
     45        copyPropertyName: false,
     46        copyPropertyValue: true,
     47        copySelector: false,
     48        copyRule: true,
     49      },
     50    },
     51    {
     52      desc: "Test Copy Property Value with Priority",
     53      node: ruleEditor.rule.textProps[3].editor.valueSpan,
     54      menuItemLabel: "styleinspector.contextmenu.copyPropertyValue",
     55      expectedPattern: "#00F !important",
     56      visible: {
     57        copyLocation: false,
     58        copyDeclaration: true,
     59        copyPropertyName: false,
     60        copyPropertyValue: true,
     61        copySelector: false,
     62        copyRule: true,
     63      },
     64    },
     65    {
     66      desc: "Test Copy Property Declaration",
     67      node: ruleEditor.rule.textProps[2].editor.nameSpan,
     68      menuItemLabel: "styleinspector.contextmenu.copyDeclaration",
     69      expectedPattern: "font-size: 12px;",
     70      visible: {
     71        copyLocation: false,
     72        copyDeclaration: true,
     73        copyPropertyName: true,
     74        copyPropertyValue: false,
     75        copySelector: false,
     76        copyRule: true,
     77      },
     78    },
     79    {
     80      desc: "Test Copy Property Declaration with Priority",
     81      node: ruleEditor.rule.textProps[3].editor.nameSpan,
     82      menuItemLabel: "styleinspector.contextmenu.copyDeclaration",
     83      expectedPattern: "border-color: #00F !important;",
     84      visible: {
     85        copyLocation: false,
     86        copyDeclaration: true,
     87        copyPropertyName: true,
     88        copyPropertyValue: false,
     89        copySelector: false,
     90        copyRule: true,
     91      },
     92    },
     93    {
     94      desc: "Test Copy Rule",
     95      node: ruleEditor.rule.textProps[2].editor.nameSpan,
     96      menuItemLabel: "styleinspector.contextmenu.copyRule",
     97      expectedPattern:
     98        "#testid {[\\r\\n]+" +
     99        "\tcolor: #F00;[\\r\\n]+" +
    100        "\tbackground-color: #00F;[\\r\\n]+" +
    101        "\tfont-size: 12px;[\\r\\n]+" +
    102        "\tborder-color: #00F !important;[\\r\\n]+" +
    103        '\t--var: "\\*/";[\\r\\n]+' +
    104        "}",
    105      visible: {
    106        copyLocation: false,
    107        copyDeclaration: true,
    108        copyPropertyName: true,
    109        copyPropertyValue: false,
    110        copySelector: false,
    111        copyRule: true,
    112      },
    113    },
    114    {
    115      desc: "Test Copy Rule with hidden unused variables",
    116      node: getRuleViewRuleEditor(view, 2).rule.textProps[0].editor.nameSpan,
    117      menuItemLabel: "styleinspector.contextmenu.copyRule",
    118      expectedPattern:
    119        ":where\\(#testid\\) {[\\r\\n]+" +
    120        "\tcolor: gold;[\\r\\n]+" +
    121        Array.from({ length: 13 }, (_, i) => {
    122          return `\t--unused-${i + 1}: ${i + 1};[\\r\\n]+`;
    123        }).join("") +
    124        "\tbackground-color: tomato;[\\r\\n]+" +
    125        "}",
    126      visible: {
    127        copyLocation: false,
    128        copyDeclaration: true,
    129        copyPropertyName: true,
    130        copyPropertyValue: false,
    131        copySelector: false,
    132        copyRule: true,
    133      },
    134    },
    135    {
    136      desc: "Test Copy Selector",
    137      node: ruleEditor.selectorText,
    138      menuItemLabel: "styleinspector.contextmenu.copySelector",
    139      expectedPattern: "html, body, #testid",
    140      visible: {
    141        copyLocation: false,
    142        copyDeclaration: false,
    143        copyPropertyName: false,
    144        copyPropertyValue: false,
    145        copySelector: true,
    146        copyRule: true,
    147      },
    148    },
    149    {
    150      desc: "Test Copy Location",
    151      node: ruleEditor.source,
    152      menuItemLabel: "styleinspector.contextmenu.copyLocation",
    153      expectedPattern:
    154        "https://example.com/browser/devtools/client/" +
    155        "inspector/rules/test/doc_copystyles.css",
    156      visible: {
    157        copyLocation: true,
    158        copyDeclaration: false,
    159        copyPropertyName: false,
    160        copyPropertyValue: false,
    161        copySelector: false,
    162        copyRule: true,
    163      },
    164    },
    165    {
    166      async setup() {
    167        await disableProperty(view, 0);
    168      },
    169      desc: "Test Copy Rule with Disabled Property",
    170      node: ruleEditor.rule.textProps[2].editor.nameSpan,
    171      menuItemLabel: "styleinspector.contextmenu.copyRule",
    172      expectedPattern:
    173        "#testid {[\\r\\n]+" +
    174        "\t/\\* color: #F00; \\*/[\\r\\n]+" +
    175        "\tbackground-color: #00F;[\\r\\n]+" +
    176        "\tfont-size: 12px;[\\r\\n]+" +
    177        "\tborder-color: #00F !important;[\\r\\n]+" +
    178        '\t--var: "\\*/";[\\r\\n]+' +
    179        "}",
    180      visible: {
    181        copyLocation: false,
    182        copyDeclaration: true,
    183        copyPropertyName: true,
    184        copyPropertyValue: false,
    185        copySelector: false,
    186        copyRule: true,
    187      },
    188    },
    189    {
    190      async setup() {
    191        await disableProperty(view, 4);
    192      },
    193      desc: "Test Copy Rule with Disabled Property with Comment",
    194      node: ruleEditor.rule.textProps[2].editor.nameSpan,
    195      menuItemLabel: "styleinspector.contextmenu.copyRule",
    196      expectedPattern:
    197        "#testid {[\\r\\n]+" +
    198        "\t/\\* color: #F00; \\*/[\\r\\n]+" +
    199        "\tbackground-color: #00F;[\\r\\n]+" +
    200        "\tfont-size: 12px;[\\r\\n]+" +
    201        "\tborder-color: #00F !important;[\\r\\n]+" +
    202        '\t/\\* --var: "\\*\\\\/"; \\*/[\\r\\n]+' +
    203        "}",
    204      visible: {
    205        copyLocation: false,
    206        copyDeclaration: true,
    207        copyPropertyName: true,
    208        copyPropertyValue: false,
    209        copySelector: false,
    210        copyRule: true,
    211      },
    212    },
    213    {
    214      desc: "Test Copy Property Declaration with Disabled Property",
    215      node: ruleEditor.rule.textProps[0].editor.nameSpan,
    216      menuItemLabel: "styleinspector.contextmenu.copyDeclaration",
    217      expectedPattern: "/\\* color: #F00; \\*/",
    218      visible: {
    219        copyLocation: false,
    220        copyDeclaration: true,
    221        copyPropertyName: true,
    222        copyPropertyValue: false,
    223        copySelector: false,
    224        copyRule: true,
    225      },
    226    },
    227    {
    228      desc: "Test Copy Rule not visible",
    229      // Click in the rule view, but not on a rule, to check that the "Copy Rule" entry
    230      // is not displayed in the menu
    231      node: ruleEditor.element.parentElement,
    232      visible: {
    233        copyLocation: false,
    234        copyDeclaration: false,
    235        copyPropertyName: false,
    236        copyPropertyValue: false,
    237        copySelector: false,
    238        copyRule: false,
    239      },
    240    },
    241  ];
    242 
    243  for (const {
    244    setup,
    245    desc,
    246    node,
    247    menuItemLabel,
    248    expectedPattern,
    249    visible,
    250  } of data) {
    251    if (setup) {
    252      await setup();
    253    }
    254 
    255    info(desc);
    256    await checkCopyStyle(view, node, menuItemLabel, expectedPattern, visible);
    257  }
    258 });
    259 
    260 async function checkCopyStyle(
    261  view,
    262  node,
    263  menuItemLabel,
    264  expectedPattern,
    265  visible
    266 ) {
    267  const allMenuItems = openStyleContextMenuAndGetAllItems(view, node);
    268 
    269  const menuitemCopy = allMenuItems.find(
    270    item =>
    271      item.label ===
    272      STYLE_INSPECTOR_L10N.getStr("styleinspector.contextmenu.copy")
    273  );
    274  const menuitemCopyLocation = allMenuItems.find(
    275    item =>
    276      item.label ===
    277      STYLE_INSPECTOR_L10N.getStr("styleinspector.contextmenu.copyLocation")
    278  );
    279  const menuitemCopyDeclaration = allMenuItems.find(
    280    item =>
    281      item.label ===
    282      STYLE_INSPECTOR_L10N.getStr("styleinspector.contextmenu.copyDeclaration")
    283  );
    284  const menuitemCopyPropertyName = allMenuItems.find(
    285    item =>
    286      item.label ===
    287      STYLE_INSPECTOR_L10N.getStr("styleinspector.contextmenu.copyPropertyName")
    288  );
    289  const menuitemCopyPropertyValue = allMenuItems.find(
    290    item =>
    291      item.label ===
    292      STYLE_INSPECTOR_L10N.getStr(
    293        "styleinspector.contextmenu.copyPropertyValue"
    294      )
    295  );
    296  const menuitemCopySelector = allMenuItems.find(
    297    item =>
    298      item.label ===
    299      STYLE_INSPECTOR_L10N.getStr("styleinspector.contextmenu.copySelector")
    300  );
    301  const menuitemCopyRule = allMenuItems.find(
    302    item =>
    303      item.label ===
    304      STYLE_INSPECTOR_L10N.getStr("styleinspector.contextmenu.copyRule")
    305  );
    306 
    307  ok(menuitemCopy.disabled, "Copy disabled is as expected: true");
    308  ok(menuitemCopy.visible, "Copy visible is as expected: true");
    309 
    310  is(
    311    menuitemCopyLocation.visible,
    312    visible.copyLocation,
    313    "Copy Location visible attribute is as expected: " + visible.copyLocation
    314  );
    315 
    316  is(
    317    menuitemCopyDeclaration.visible,
    318    visible.copyDeclaration,
    319    "Copy Property Declaration visible attribute is as expected: " +
    320      visible.copyDeclaration
    321  );
    322 
    323  is(
    324    menuitemCopyPropertyName.visible,
    325    visible.copyPropertyName,
    326    "Copy Property Name visible attribute is as expected: " +
    327      visible.copyPropertyName
    328  );
    329 
    330  is(
    331    menuitemCopyPropertyValue.visible,
    332    visible.copyPropertyValue,
    333    "Copy Property Value visible attribute is as expected: " +
    334      visible.copyPropertyValue
    335  );
    336 
    337  is(
    338    menuitemCopySelector.visible,
    339    visible.copySelector,
    340    "Copy Selector visible attribute is as expected: " + visible.copySelector
    341  );
    342 
    343  is(
    344    menuitemCopyRule.visible,
    345    visible.copyRule,
    346    "Copy Rule visible attribute is as expected: " + visible.copyRule
    347  );
    348 
    349  if (menuItemLabel) {
    350    const menuItem = allMenuItems.find(
    351      item => item.label === STYLE_INSPECTOR_L10N.getStr(menuItemLabel)
    352    );
    353    try {
    354      await waitForClipboardPromise(
    355        () => menuItem.click(),
    356        () => checkClipboardData(expectedPattern)
    357      );
    358    } catch (e) {
    359      failedClipboard(expectedPattern);
    360    }
    361  }
    362 }
    363 
    364 async function disableProperty(view, index) {
    365  const ruleEditor = getRuleViewRuleEditor(view, 1);
    366  const textProp = ruleEditor.rule.textProps[index];
    367  await togglePropStatus(view, textProp);
    368 }
    369 
    370 function checkClipboardData(expectedPattern) {
    371  const actual = SpecialPowers.getClipboardData("text/plain");
    372  const expectedRegExp = new RegExp(expectedPattern, "g");
    373  return expectedRegExp.test(actual);
    374 }
    375 
    376 function failedClipboard(expectedPattern) {
    377  // Format expected text for comparison
    378  const terminator = osString == "WINNT" ? "\r\n" : "\n";
    379  expectedPattern = expectedPattern.replace(/\[\\r\\n\][+*]/g, terminator);
    380  expectedPattern = expectedPattern.replace(/\\\(/g, "(");
    381  expectedPattern = expectedPattern.replace(/\\\)/g, ")");
    382 
    383  let actual = SpecialPowers.getClipboardData("text/plain");
    384 
    385  // Trim the right hand side of our strings. This is because expectedPattern
    386  // accounts for windows sometimes adding a newline to our copied data.
    387  expectedPattern = expectedPattern.trimRight();
    388  actual = actual.trimRight();
    389 
    390  ok(
    391    false,
    392    "Clipboard text does not match expected " +
    393      "results (escaped for accurate comparison):\n"
    394  );
    395  info("Actual: " + escape(actual));
    396  info("Expected: " + escape(expectedPattern));
    397 }