layout/style/test/chrome/test_stylesheet_clone_import_rule.html
author Brad Werth <bwerth@mozilla.com>
Mon, 28 Aug 2017 17:02:06 -0700
changeset 654630 881304bcbe744b3dcef5167add84b20440a93759
parent 603494 30cb57034d1e7d92a3094e76ee08f2c62f08338c
child 656191 7fb3117e08044c73da2f8b9a345fd03b2a50e5e0
child 659288 881f05d360cc43700cfe3f4a3cc920ea6cd0c9bd
child 659396 afdb9c43e728ec46ade1ecf419321be267f88dbb
child 660414 469e63eff8941b9de5abdc9716d68a025c466dd5
permissions -rw-r--r--
Bug 1378577: Fix await race condition which causes intermittent timeouts in test_stylesheet_clone_import_rule.html. MozReview-Commit-ID: 2vWsCcnsmwF

<!DOCTYPE html>
<html lang="en-US">
<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"/>

<style>div { color: green; }</style>

<link id="theOnlyLink" rel="stylesheet" type="text/css" href="import_useless1.css">

<div id="theOnlyDiv">This text will change colors several times.</div>

<script>
  SimpleTest.waitForExplicitFinish();

  let DOMUtils = SpecialPowers.Cc["@mozilla.org/inspector/dom-utils;1"]
                 .getService(SpecialPowers.Ci.inIDOMUtils);
  const Cu = SpecialPowers.Components.utils;
  const { ContentTaskUtils } = Cu.import("resource://testing-common/ContentTaskUtils.jsm", {});

  document.styleSheetChangeEventsEnabled = true;

  let theOnlyDiv = document.getElementById("theOnlyDiv");
  let stylesheet = document.getElementById("theOnlyLink").sheet;

  runTest();

  function cssRulesToString(cssRules) {
    return Array.from(cssRules).map(rule => rule.cssText).join('');
  }

  async function runTest() {

    // Test that the div is initially red (from base.css)
    is(getComputedStyle(theOnlyDiv).color, "rgb(0, 128, 0)", "div begins as green.");

    // Create a Promise to watch for some number of events.
    let generateCountingListenerCallback = function(numberOfEventsToWaitFor) {
      let eventsReceived = 0;
      return function(event) {
        return (++eventsReceived >= numberOfEventsToWaitFor);
      }
    };
    let gotAllOurStyleRuleAddedEvents = ContentTaskUtils.waitForEvent(document,
      "StyleRuleAdded", true, generateCountingListenerCallback(2));

    stylesheet.insertRule('@import url("import_useless2.css")', 0);
    stylesheet.insertRule('@import url("import_useless2.css")', 1);

    // Wait for the StyleRuleAdded events to be fired. This function returns the last event,
    // but we don't care what it contains -- only that the correct number of events fired.
    await gotAllOurStyleRuleAddedEvents;

    // Get the imported sheets and confirm they are non-null and have rules.
    let importSheet1 = stylesheet.cssRules[0].styleSheet;
    let importSheet2 = stylesheet.cssRules[1].styleSheet;

    ok(importSheet1 && importSheet2, "Imported sheets exist.");
    if (!(importSheet1 && importSheet2)) {
      SimpleTest.finish();
      return;
    }

    ok(importSheet1.cssRules && importSheet2.cssRules, "Imported sheets have rules.");
    if (!(importSheet1.cssRules && importSheet2.cssRules)) {
      SimpleTest.finish();
      return;
    }

    // Confirm that these two sheets are meaningfully the same.
    is(cssRulesToString(importSheet1.cssRules), cssRulesToString(importSheet2.cssRules), "Cloned sheet rules are equivalent.");

    // Add a color-changing rule to the first stylesheet.
    importSheet1.insertRule('div { color: blue; }');
    // And make sure that it has an effect.
    is(getComputedStyle(theOnlyDiv).color, "rgb(0, 0, 255)", "div becomes blue.");

    // Make sure that the two sheets have different rules now.
    isnot(cssRulesToString(importSheet1.cssRules), cssRulesToString(importSheet2.cssRules), "Cloned sheet rules are no longer equivalent.");

    // Add a color-changing rule to the second stylesheet (that will mask the first).
    importSheet2.insertRule('div { color: red; }');
    // And make sure that it has an effect.
    is(getComputedStyle(theOnlyDiv).color, "rgb(255, 0, 0)", "div becomes red.");

    // Delete the second sheet by removing the import rule, and make sure the color changes back.
    stylesheet.deleteRule(1);
    is(getComputedStyle(theOnlyDiv).color, "rgb(0, 0, 255)", "div goes back to blue.");

    // Delete the first sheet by removing the import rule, and make sure the color changes back.
    stylesheet.deleteRule(0);
    is(getComputedStyle(theOnlyDiv).color, "rgb(0, 128, 0)", "div goes back to green.");

    SimpleTest.finish();
  }


</script>
</html>