<!DOCTYPE HTML>
<html>
<head>
  <meta charset="utf-8">
  <title>Test InspectorUtils::replaceBlockRuleBodyTextInStylesheet</title>
  <script src="/tests/SimpleTest/SimpleTest.js"></script>
  <link rel="stylesheet" href="/tests/SimpleTest/test.css"/>
  <style>
#test-simple {
  color: #f0c;
}
#test-unicode,[data-unicode="๐Ÿฆ„๐Ÿ‘จโ€๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘ฆ"]::after {
  content: /* test comment */ "๐Ÿ‘จโ€๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘ฆ๐Ÿฆ„";
  outline: 2px solid salmon;
}
#test-empty {} /* ๐Ÿ› ๏ธโš’๏ธ๐Ÿ› ๏ธ */ #test-same-line { font-size: 3em; }
#test-nested-parent {
  color: tomato;
  #test-nested-child {
    background: gold;
  }
}#test-after-closing-bracket{--modified:false}
  </style>
  <script>SimpleTest.waitForExplicitFinish();</script>
  <script defer>
    const InspectorUtils = SpecialPowers.InspectorUtils;
    let stylesheet = document.styleSheets[1];
    let authoredStyleSheetText = document.querySelector("style").textContent;

    const existingRulesAuthoredText = [
`#test-simple {
  color: #f0c;
}`,
`#test-unicode,[data-unicode="๐Ÿฆ„๐Ÿ‘จโ€๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘ฆ"]::after {
  content: /* test comment */ "๐Ÿ‘จโ€๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘ฆ๐Ÿฆ„";
  outline: 2px solid salmon;
}`,
`#test-empty {}`,
`#test-same-line { font-size: 3em; }`,
`#test-nested-parent {
  color: tomato;
  #test-nested-child {
    background: gold;
  }
}`,
`#test-nested-child {
    background: gold;
  }`,
`#test-after-closing-bracket{--modified:false}`,
];

    const replaceBlockRuleBodyTextInStylesheet = (rule, newBodyText) => {
      return InspectorUtils.replaceBlockRuleBodyTextInStylesheet(
        authoredStyleSheetText,
        InspectorUtils.getRelativeRuleLine(rule),
        InspectorUtils.getRuleColumn(rule),
        newBodyText
      )};

    info("Check a simple case");
    let newBodyText = `border-color: cyan;`;
    is(
      replaceBlockRuleBodyTextInStylesheet(stylesheet.cssRules[0], newBodyText),
      authoredStyleSheetText.replace(
        existingRulesAuthoredText[0],
        `#test-simple {${newBodyText}}`,
      ),
      "Got the expected result for #test-simple"
    );

    info("Check that the rule body can be emptied");
    is(
      replaceBlockRuleBodyTextInStylesheet(stylesheet.cssRules[0], ""),
      authoredStyleSheetText.replace(
        existingRulesAuthoredText[0],
        `#test-simple {}`,
      ),
      "Successfuly removed rule content for #test-simple"
    );

    info("Check that it can handle unicode characters");
    newBodyText = `content: "o ๐ŸฆŠ o";`;
    is(
      replaceBlockRuleBodyTextInStylesheet(stylesheet.cssRules[1], newBodyText),
      authoredStyleSheetText.replace(existingRulesAuthoredText[1],
        `#test-unicode,[data-unicode="๐Ÿฆ„๐Ÿ‘จโ€๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘ฆ"]::after {${newBodyText}}`,
      ),
      "Got the expected result for #test-unicode"
    );

    info("Check that it can replace content of an empty rule");
    newBodyText = `font-family: "Zilla;"`;
    is(
      replaceBlockRuleBodyTextInStylesheet(stylesheet.cssRules[2], newBodyText),
      authoredStyleSheetText.replace(
        existingRulesAuthoredText[2],
        `#test-empty {${newBodyText}}`,
      ),
      "Got the expected result for #test-empty"
    );

    info("Check that it can handle a rule on a same line as another rule");
    newBodyText = `color: pink;`;
    is(
      replaceBlockRuleBodyTextInStylesheet(stylesheet.cssRules[3], newBodyText),
      authoredStyleSheetText.replace(
        existingRulesAuthoredText[3],
        `#test-same-line {${newBodyText}}`,
      ),
      "Got the expected result for #test-same-line"
    );

    info("Check that it can handle a rule with a child rule");
    newBodyText = `background: silver;
    & > span {
      color: white;
    }`;
    is(
      replaceBlockRuleBodyTextInStylesheet(stylesheet.cssRules[4], newBodyText),
      authoredStyleSheetText.replace(
        existingRulesAuthoredText[4],
        `#test-nested-parent {${newBodyText}}`,
      ),
      "Got the expected result for #test-nested-parent"
    );

    info("Check that it can handle a nested rule");
    newBodyText = `color: white;height: 100%;`;
    is(
      replaceBlockRuleBodyTextInStylesheet(stylesheet.cssRules[4].cssRules[0], newBodyText),
      authoredStyleSheetText.replace(
        existingRulesAuthoredText[5],
        `#test-nested-child {${newBodyText}}`,
      ),
      "Got the expected result for #test-nested-child"
    );

    // Covering fix for Bug 1890775
    info("Check that it can handle rules  whose declaration is directly after the } of the previous rule, without spaces");
    isnot(
      InspectorUtils.getRelativeRuleLine(stylesheet.cssRules[5]),
      1,
      "The rule should not be on the first line of the stylesheet to check the issue it covers"
    );
    newBodyText = `--modified:true`;
    is(
      replaceBlockRuleBodyTextInStylesheet(stylesheet.cssRules[5], newBodyText),
      authoredStyleSheetText.replace(
        existingRulesAuthoredText[6],
        `#test-after-closing-bracket{${newBodyText}}`,
      ),
      "Got the expected result for #test-after-closing-bracket"
    );

    info("Checking fix for files with crlf EOL sequence");
    let styleEl = document.createElement("style");
    let ruleText = `#test-after-closing-bracket-crlf{--modified-crlf:false}`
    authoredStyleSheetText = `\r\nhtml{}${ruleText}`;
    styleEl.append(document.createTextNode(authoredStyleSheetText));
    document.head.append(styleEl);
    stylesheet = document.styleSheets[2];
    isnot(
      InspectorUtils.getRelativeRuleLine(stylesheet.cssRules[1]),
      1,
      "The rule should not be on the first line of the stylesheet to check the issue it covers"
    );
    newBodyText = `--modified-crlf:true`;
    is(
      replaceBlockRuleBodyTextInStylesheet(stylesheet.cssRules[1], newBodyText),
      authoredStyleSheetText.replace(
        ruleText,
        `#test-after-closing-bracket-crlf{${newBodyText}}`,
      ),
      "Got the expected result for #test-after-closing-bracket-crlf"
    );

    info("Checking fix for files with cr EOL sequence");
    ruleText = `#test-after-closing-bracket-cr{--modified-cr:false}`
    authoredStyleSheetText = `\rhtml{}${ruleText}`;
    styleEl.innerText = "";
    styleEl.append(document.createTextNode(authoredStyleSheetText));
    isnot(
      InspectorUtils.getRelativeRuleLine(stylesheet.cssRules[1]),
      1,
      "The rule should not be on the first line of the stylesheet to check the issue it covers"
    );
    newBodyText = `--modified-cr:true`;
    is(
      replaceBlockRuleBodyTextInStylesheet(stylesheet.cssRules[1], newBodyText),
      authoredStyleSheetText.replace(
        ruleText,
        `#test-after-closing-bracket-cr{${newBodyText}}`,
      ),
      "Got the expected result for #test-after-closing-bracket-cr"
    );

    SimpleTest.finish();
  </script>
</head>
<body>
<h1>Test InspectorUtils::replaceBlockRuleBodyTextInStylesheet</h1>
<p id="display"></p>
<div id="content" style="display: none">

</div>
<pre id="test">
</pre>
</body>
</html>