text: // Copyright 2017 The Chromium Authors. All rights reserved.
  // Use of this source code is governed by a BSD-style license that can be
  // found in the LICENSE file.
  
  (async function() {
    TestRunner.addResult(`Tests that InspectorCSSAgent API methods work as expected.\n`);
    await TestRunner.loadModule('elements_test_runner');
    await TestRunner.showPanel('elements');
    await TestRunner.loadHTML(`
  <head>
  <link rel="stylesheet" href="resources/styles-new-API.css">
  <style>
  
  /* An inline stylesheet */
  body.mainpage {
      text-decoration: none; /* at least one valid property is necessary for WebCore to match a rule */
      ;badproperty: 1badvalue1;
  }
  
  body.mainpage {
      prop1: val1;
      prop2: val2;
  }
  
  body:hover {
    color: #CDE;
  }
  </style>
  </head>
  <body id="mainBody" class="main1 main2 mainpage" style="font-weight: normal; width: 85%; background-image: url(bar.png)">
    <table width="50%" id="thetable">
    </table>
    <h1 id="toggle">H1</h1>
  </body>
      `);
  
    await (() => {
      // TODO(crbug.com/1046354): This is a workaround for loadHTML() resolving
      // before parsing is finished. In this case the link stylesheet is blocking
      // html parsing with BlockHTMLParsingOnStyleSheets enabled and mainBody is
      // not  found by selectNodeWithId below.
      let resolve;
      const promise = new Promise(r => resolve = r);
      TestRunner.waitForPageLoad(() => resolve());
      return promise;
    })();
  
    var bodyId;
    TestRunner.runTestSuite([
      function test_styles(next) {
        function callback(styles) {
          TestRunner.addResult('');
          TestRunner.addResult('=== Computed style property count for body ===');
          var propCount = styles.computedStyle.length;
          TestRunner.addResult(propCount > 200 ? 'OK' : 'FAIL (' + propCount + ')');
  
          TestRunner.addResult('');
          TestRunner.addResult('=== Matched rules for body ===');
          ElementsTestRunner.dumpRuleMatchesArray(styles.matchedCSSRules);
  
          TestRunner.addResult('');
          TestRunner.addResult('=== Pseudo rules for body ===');
          for (var i = 0; i < styles.pseudoElements.length; ++i) {
            TestRunner.addResult('PseudoType=' + styles.pseudoElements[i].pseudoType);
            ElementsTestRunner.dumpRuleMatchesArray(styles.pseudoElements[i].matches);
          }
  
          TestRunner.addResult('');
          TestRunner.addResult('=== Inherited styles for body ===');
          for (var i = 0; i < styles.inherited.length; ++i) {
            TestRunner.addResult('Level=' + (i + 1));
            ElementsTestRunner.dumpStyle(styles.inherited[i].inlineStyle);
            ElementsTestRunner.dumpRuleMatchesArray(styles.inherited[i].matchedCSSRules);
          }
  
          TestRunner.addResult('');
          TestRunner.addResult('=== Inline style for body ===');
          ElementsTestRunner.dumpStyle(styles.inlineStyle);
          next();
        }
  
        var resultStyles = {};
  
        function computedCallback(computedStyle) {
          if (!computedStyle) {
            TestRunner.addResult('Error');
            TestRunner.completeTest();
            return;
          }
          resultStyles.computedStyle = computedStyle;
        }
  
        function matchedCallback(response) {
          if (response[Protocol.Error]) {
            TestRunner.addResult('error: ' + response[Protocol.Error]);
            TestRunner.completeTest();
            return;
          }
  
          resultStyles.inlineStyle = response.inlineStyle;
          resultStyles.matchedCSSRules = response.matchedCSSRules;
          resultStyles.pseudoElements = response.pseudoElements;
          resultStyles.inherited = response.inherited;
        }
  
        function nodeCallback(node) {
          bodyId = node.id;
          var promises = [
            TestRunner.CSSAgent.getComputedStyleForNode(node.id).then(computedCallback),
            TestRunner.CSSAgent.invoke_getMatchedStylesForNode({nodeId: node.id}).then(matchedCallback)
          ];
          Promise.all(promises).then(callback.bind(null, resultStyles));
        }
        ElementsTestRunner.selectNodeWithId('mainBody', nodeCallback);
      },
  
      async function test_forcedState(next) {
        TestRunner.CSSAgent.forcePseudoState(bodyId, ['hover']);
        var response = await TestRunner.CSSAgent.invoke_getMatchedStylesForNode({nodeId: bodyId});
  
        TestRunner.addResult('=== BODY with forced :hover ===');
        ElementsTestRunner.dumpRuleMatchesArray(response.matchedCSSRules);
        TestRunner.CSSAgent.forcePseudoState(bodyId, ['hover']).then(next);
      },
  
      function test_textNodeComputedStyles(next) {
        ElementsTestRunner.nodeWithId('toggle', nodeCallback);
  
        async function nodeCallback(node) {
          var textNode = node.children()[0];
          if (textNode.nodeType() !== Node.TEXT_NODE) {
            TestRunner.addResult('Failed to retrieve TextNode.');
            TestRunner.completeTest();
            return;
          }
          var computedStyle = await TestRunner.CSSAgent.getComputedStyleForNode(textNode.id);
          if (!computedStyle) {
            TestRunner.addResult('Error');
            return;
          }
          TestRunner.addResult('');
          TestRunner.addResult('=== Computed style property count for TextNode ===');
          var propCount = computedStyle.length;
          TestRunner.addResult(propCount > 200 ? 'OK' : 'FAIL (' + propCount + ')');
          next();
        }
      },
  
      function test_tableStyles(next) {
        async function nodeCallback(node) {
          var response = await TestRunner.CSSAgent.invoke_getInlineStylesForNode({nodeId: node.id});
          if (response[Protocol.Error]) {
            TestRunner.addResult('error: ' + response[Protocol.Error]);
            next();
            return;
          }
          TestRunner.addResult('');
          TestRunner.addResult('=== Attributes style for table ===');
          ElementsTestRunner.dumpStyle(response.attributesStyle);
  
          var result = await TestRunner.CSSAgent.getStyleSheetText(response.inlineStyle.styleSheetId);
  
          TestRunner.addResult('');
          TestRunner.addResult('=== Stylesheet-for-inline-style text ===');
          TestRunner.addResult(result || '');
  
          await TestRunner.CSSAgent.setStyleSheetText(response.inlineStyle.styleSheetId, '');
  
          TestRunner.addResult('');
          TestRunner.addResult('=== Stylesheet-for-inline-style modification result ===');
          TestRunner.addResult(null);
          next();
        }
        ElementsTestRunner.nodeWithId('thetable', nodeCallback);
      },
  
      async function test_addRule(next) {
        var frameId = TestRunner.resourceTreeModel.mainFrame.id;
        var styleSheetId = await TestRunner.CSSAgent.createStyleSheet(frameId);
        if (!styleSheetId) {
          TestRunner.addResult('Error in CSS.createStyleSheet');
          next();
          return;
        }
  
        var range = {startLine: 0, startColumn: 0, endLine: 0, endColumn: 0};
  
        var rule = await TestRunner.CSSAgent.addRule(styleSheetId, 'body {}', range);
        if (!rule) {
          TestRunner.addResult('Error in CSS.addRule');
          next();
          return;
        }
  
        var style = await TestRunner.CSSAgent.setStyleTexts([{
          styleSheetId: rule.style.styleSheetId,
          range: {
            startLine: rule.style.range.startLine,
            startColumn: rule.style.range.startColumn,
            endLine: rule.style.range.startLine,
            endColumn: rule.style.range.startColumn
          },
          text: 'font-family: serif;'
        }]);
        if (!style) {
          TestRunner.addResult('Error in CSS.setStyleTexts');
          next();
          return;
        }
  
        var response = await TestRunner.CSSAgent.invoke_getMatchedStylesForNode({nodeId: bodyId});
        if (response[Protocol.Error]) {
          TestRunner.addResult('error: ' + response[Protocol.Error]);
          next();
          return;
        }
  
        TestRunner.addResult('');
        TestRunner.addResult('=== Matched rules after rule added ===');
        ElementsTestRunner.dumpRuleMatchesArray(response.matchedCSSRules);
        next();
      },
    ]);
  })();
  