// Copyright 2020 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.
import {assert} from 'chai';
import type * as puppeteer from 'puppeteer';
import {AsyncScope} from '../../shared/async-scope.js';

import {
  $,
  $$,
  click,
  getBrowserAndPages,
  getTextContent,
  goToResource,
  pressKey,
  step,
  summonSearchBox,
  timeout,
  typeText,
  waitFor,
  waitForAria,
  clickElement,
  waitForFunction,
} from '../../shared/helper.js';

const SELECTED_TREE_ELEMENT_SELECTOR = '.selected[role="treeitem"]';
const CSS_PROPERTY_NAME_SELECTOR = '.webkit-css-property';
const CSS_PROPERTY_VALUE_SELECTOR = '.value';
const CSS_DECLARATION_SELECTOR =
    `[role="treeitem"]:has(${CSS_PROPERTY_NAME_SELECTOR}):has(${CSS_PROPERTY_VALUE_SELECTOR})`;
const COLOR_SWATCH_SELECTOR = '.color-swatch-inner';
const CSS_STYLE_RULE_SELECTOR = '[aria-label*="css selector"]';
const COMPUTED_PROPERTY_SELECTOR = 'devtools-computed-style-property';
const COMPUTED_STYLES_PANEL_SELECTOR = '[aria-label="Computed panel"]';
const COMPUTED_STYLES_SHOW_ALL_SELECTOR = '[title="Show all"]';
const COMPUTED_STYLES_GROUP_SELECTOR = '[title="Group"]';
const ELEMENTS_PANEL_SELECTOR = '.panel[aria-label="elements"]';
const FONT_EDITOR_SELECTOR = '[aria-label="Font Editor"]';
const HIDDEN_FONT_EDITOR_SELECTOR = '.font-toolbar-hidden';
const SECTION_SUBTITLE_SELECTOR = '.styles-section-subtitle';
const CLS_PANE_SELECTOR = '.styles-sidebar-toolbar-pane';
const CLS_BUTTON_SELECTOR = '[aria-label="Element Classes"]';
const CLS_INPUT_SELECTOR = '[aria-placeholder="Add new class"]';
const LAYOUT_PANE_TAB_SELECTOR = '[aria-label="Layout"]';
const LAYOUT_PANE_TABPANEL_SELECTOR = '[aria-label="Layout panel"]';
const ADORNER_SELECTOR = 'devtools-adorner';
export const INACTIVE_GRID_ADORNER_SELECTOR = '[aria-label="Enable grid mode"]';
export const ACTIVE_GRID_ADORNER_SELECTOR = '[aria-label="Disable grid mode"]';
const ELEMENT_CHECKBOX_IN_LAYOUT_PANE_SELECTOR = '.elements input[type=checkbox]';
const ELEMENT_STYLE_SECTION_SELECTOR = '[aria-label="element.style, css selector"]';
const STYLE_QUERY_RULE_TEXT_SELECTOR = '.query-text';
const STYLE_PROPERTIES_SELECTOR = '.tree-outline-disclosure [role="treeitem"]';
const CSS_AUTHORING_HINTS_ICON_SELECTOR = '.hint';
export const SEARCH_BOX_SELECTOR = '.search-bar';
const SEARCH_RESULTS_MATCHES = '.search-results-matches';

export const openLayoutPane = async () => {
  await step('Open Layout pane', async () => {
    await waitFor(LAYOUT_PANE_TAB_SELECTOR);
    await click(LAYOUT_PANE_TAB_SELECTOR);

    const panel = await waitFor(LAYOUT_PANE_TABPANEL_SELECTOR);
    await waitFor('.elements', panel);
  });
};

export const waitForAdorners = async (expectedAdorners: {textContent: string, isActive: boolean}[]) => {
  await waitForFunction(async () => {
    const actualAdorners = await $$(ADORNER_SELECTOR);
    const actualAdornersStates = await Promise.all(actualAdorners.map(n => {
      return n.evaluate((node, activeSelector: string) => {
        // TODO for now only the grid adorner that can be active. When the flex (or other) adorner can be activated
        // too we should change the selector passed here crbug.com/1144090.
        return {textContent: node.textContent, isActive: node.matches(activeSelector)};
      }, ACTIVE_GRID_ADORNER_SELECTOR);
    }));

    if (actualAdornersStates.length !== expectedAdorners.length) {
      return false;
    }

    for (let i = 0; i < actualAdornersStates.length; i++) {
      const index = expectedAdorners.findIndex(expected => {
        const actual = actualAdornersStates[i];
        return expected.textContent === actual.textContent && expected.isActive === actual.isActive;
      });
      if (index !== -1) {
        expectedAdorners.splice(index, 1);
      }
    }

    return expectedAdorners.length === 0;
  });
};

export const waitForSelectedNodeToBeExpanded = async () => {
  await waitFor(`${SELECTED_TREE_ELEMENT_SELECTOR}[aria-expanded="true"]`);
};

export const waitForAdornerOnSelectedNode = async (expectedAdornerText: string) => {
  await waitForFunction(async () => {
    const selectedNode = await waitFor(SELECTED_TREE_ELEMENT_SELECTOR);
    const adorner = await waitFor(ADORNER_SELECTOR, selectedNode);
    return expectedAdornerText === await adorner.evaluate(node => node.textContent);
  });
};

export const toggleElementCheckboxInLayoutPane = async () => {
  await step('Click element checkbox in Layout pane', async () => {
    await waitFor(ELEMENT_CHECKBOX_IN_LAYOUT_PANE_SELECTOR);
    await click(ELEMENT_CHECKBOX_IN_LAYOUT_PANE_SELECTOR);
  });
};

export const getGridsInLayoutPane = async () => {
  const panel = await waitFor(LAYOUT_PANE_TABPANEL_SELECTOR);
  return await $$('.elements .element', panel);
};

export const waitForSomeGridsInLayoutPane = async (minimumGridCount: number) => {
  await waitForFunction(async () => {
    const grids = await getGridsInLayoutPane();
    return grids.length >= minimumGridCount;
  });
};

export const waitForContentOfSelectedElementsNode = async (expectedTextContent: string) => {
  await waitForFunction(async () => {
    const selectedTextContent = await getContentOfSelectedNode();
    return selectedTextContent === expectedTextContent;
  });
};

export const waitForPartialContentOfSelectedElementsNode = async (expectedPartialTextContent: string) => {
  await waitForFunction(async () => {
    const selectedTextContent = await getContentOfSelectedNode();
    return selectedTextContent.includes(expectedPartialTextContent);
  });
};

/**
 * Gets the text content of the currently selected element.
 */
export const getContentOfSelectedNode = async () => {
  const selectedNode = await waitFor(SELECTED_TREE_ELEMENT_SELECTOR);
  return await selectedNode.evaluate(node => node.textContent as string);
};

export const waitForSelectedNodeChange = async(initialValue: string, asyncScope = new AsyncScope()): Promise<void> => {
  await waitForFunction(async () => {
    const currentContent = await getContentOfSelectedNode();
    return currentContent !== initialValue;
  }, asyncScope);
};

export const assertSelectedElementsNodeTextIncludes = async (expectedTextContent: string) => {
  const selectedNode = await waitFor(SELECTED_TREE_ELEMENT_SELECTOR);
  const selectedTextContent = await selectedNode.evaluate(node => node.textContent as string);
  assert.include(selectedTextContent, expectedTextContent);
};

export const waitForSelectedTreeElementSelectorWithTextcontent = async (expectedTextContent: string) => {
  await waitForFunction(async () => {
    const selectedNode = await waitFor(SELECTED_TREE_ELEMENT_SELECTOR);
    const selectedTextContent = await selectedNode.evaluate(node => node.textContent);
    return selectedTextContent === expectedTextContent;
  });
};

export const waitForSelectedTreeElementSelectorWhichIncludesText = async (expectedTextContent: string) => {
  await waitForFunction(async () => {
    const selectedNode = await waitFor(SELECTED_TREE_ELEMENT_SELECTOR);
    const selectedTextContent = await selectedNode.evaluate(node => node.textContent);
    return selectedTextContent && selectedTextContent.includes(expectedTextContent);
  });
};

export const waitForChildrenOfSelectedElementNode = async () => {
  await waitFor(`${SELECTED_TREE_ELEMENT_SELECTOR} + ol > li`);
};

export const waitForAndClickTreeElementWithPartialText = async (text: string) =>
    waitForFunction(async () => clickTreeElementWithPartialText(text));

export const waitForElementWithPartialText = async (text: string) => {
  return waitForFunction(async () => elementWithPartialText(text));
};

const elementWithPartialText = async (text: string) => {
  const tree = await waitFor('Page DOM[role="tree"]', undefined, undefined, 'aria');
  const elements = await $$('[role="treeitem"]', tree, 'aria');
  for (const handle of elements) {
    const match = await handle.evaluate((element, text) => element.textContent?.includes(text), text);
    if (match) {
      return handle;
    }
  }
  return null;
};

export const clickTreeElementWithPartialText = async (text: string) => {
  const handle = await elementWithPartialText(text);
  if (handle) {
    await clickElement(handle);
    return true;
  }

  throw false;
};

export const clickNthChildOfSelectedElementNode = async (childIndex: number) => {
  assert(childIndex > 0, 'CSS :nth-child() selector indices are 1-based.');
  const element = await waitFor(`${SELECTED_TREE_ELEMENT_SELECTOR} + ol > li:nth-child(${childIndex})`);
  await element.click();
};

export const focusElementsTree = async () => {
  await click(SELECTED_TREE_ELEMENT_SELECTOR);
};

export const navigateToSidePane = async (paneName: string) => {
  await click(`[aria-label="${paneName}"]`);
  await waitFor(`[aria-label="${paneName} panel"]`);
};

export const waitForElementsStyleSection = async () => {
  // Wait for the file to be loaded and selectors to be shown
  await waitFor('.styles-selector');
};

export const waitForElementsComputedSection = async () => {
  await waitFor(COMPUTED_PROPERTY_SELECTOR);
};

export const getContentOfComputedPane = async () => {
  const pane = await waitFor('Computed panel', undefined, undefined, 'aria');
  const tree = await waitFor('[role="tree"]', pane, undefined, 'aria');
  return await tree.evaluate(node => node.textContent as string);
};

export const waitForComputedPaneChange = async (initialValue: string) => {
  await waitForFunction(async () => {
    const value = await getContentOfComputedPane();
    return value !== initialValue;
  });
};

export const getAllPropertiesFromComputedPane = async () => {
  const properties = await $$(COMPUTED_PROPERTY_SELECTOR);
  return (await Promise.all(properties.map(elem => elem.evaluate(async node => {
           const nameSlot = node.shadowRoot?.querySelector<HTMLSlotElement>('.property-name slot');
           const valueSlot = node.shadowRoot?.querySelector<HTMLSlotElement>('.property-value slot');
           const name = nameSlot?.assignedElements().at(0);
           const value = valueSlot?.assignedElements().at(0);

           return (!name || !value) ? null : {
             name: name.textContent ? name.textContent.trim().replace(/:$/, '') : '',
             value: value.textContent ? value.textContent.trim().replace(/;$/, '') : '',
           };
         }))))
      .filter(prop => Boolean(prop));
};

export const getPropertyFromComputedPane = async (name: string) => {
  const properties = await $$(COMPUTED_PROPERTY_SELECTOR);
  for (const property of properties) {
    const matchingProperty = await property.evaluate((node, name) => {
      const nameSlot = node.shadowRoot?.querySelector<HTMLSlotElement>('.property-name slot');
      const nameEl = nameSlot?.assignedElements().at(0);
      return nameEl?.textContent?.trim().replace(/:$/, '') === name;
    }, name);
    // Note that evaluateHandle always returns a handle, even if it points to an undefined remote object, so we need to
    // check it's defined here or continue iterating.
    if (matchingProperty) {
      return property;
    }
  }
  return undefined;
};

export const waitForPropertyValueInComputedPane = async (name: string, value: string) => {
  await waitForFunction(async () => {
    const properties = await getAllPropertiesFromComputedPane();
    for (const property of properties) {
      if (property && property.name === name && property.value === value) {
        return true;
      }
    }
    return false;
  });
};

export const expandSelectedNodeRecursively = async () => {
  const EXPAND_RECURSIVELY = '[aria-label="Expand recursively"]';

  // Find the selected node, right click.
  await click(SELECTED_TREE_ELEMENT_SELECTOR, {clickOptions: {button: 'right'}});

  // Wait for the 'expand recursively' option, and click it.
  await waitFor(EXPAND_RECURSIVELY);
  await click(EXPAND_RECURSIVELY);
};

export const forcePseudoState = async (pseudoState: string) => {
  // Open element state pane and wait for it to be loaded asynchronously
  await click('[aria-label="Toggle Element State"]');
  await waitFor(`[aria-label="${pseudoState}"]`);
  // FIXME(crbug/1112692): Refactor test to remove the timeout.
  await timeout(100);
  await click(`[aria-label="${pseudoState}"]`);
};

export const removePseudoState = async (pseudoState: string) => {
  await click(`[aria-label="${pseudoState}"]`);
};

export const getComputedStylesForDomNode =
    async (elementSelector: string, styleAttribute: keyof CSSStyleDeclaration) => {
  const {target} = getBrowserAndPages();

  return target.evaluate((elementSelector, styleAttribute) => {
    const element = document.querySelector(elementSelector);
    if (!element) {
      throw new Error(`${elementSelector} could not be found`);
    }
    return getComputedStyle(element)[styleAttribute];
  }, elementSelector, styleAttribute);
};

export const waitForNumberOfComputedProperties = async (numberToWaitFor: number) => {
  const computedPane = await getComputedPanel();
  return waitForFunction(
      async () => numberToWaitFor ===
          await computedPane.$$eval('pierce/' + COMPUTED_PROPERTY_SELECTOR, properties => properties.length));
};

export const getComputedPanel = async () => waitFor(COMPUTED_STYLES_PANEL_SELECTOR);

export const filterComputedProperties = async (filterString: string) => {
  const initialContent = await getContentOfComputedPane();

  const computedPanel = await waitFor(COMPUTED_STYLES_PANEL_SELECTOR);
  await click('[aria-label="Filter Computed Styles"]', {
    root: computedPanel,
  });
  await typeText(filterString);
  await waitForComputedPaneChange(initialContent);
};

export const toggleShowAllComputedProperties = async () => {
  const initialContent = await getContentOfComputedPane();

  const computedPanel = await waitFor(COMPUTED_STYLES_PANEL_SELECTOR);
  await click(COMPUTED_STYLES_SHOW_ALL_SELECTOR, {root: computedPanel});
  await waitForComputedPaneChange(initialContent);
};

export const toggleGroupComputedProperties = async () => {
  const computedPanel = await waitFor(COMPUTED_STYLES_PANEL_SELECTOR);
  const groupCheckbox = await waitFor(COMPUTED_STYLES_GROUP_SELECTOR, computedPanel);

  const wasChecked = await groupCheckbox.evaluate(checkbox => (checkbox as HTMLInputElement).checked);

  await click(COMPUTED_STYLES_GROUP_SELECTOR, {
    root: computedPanel,
  });

  if (wasChecked) {
    await waitFor('[role="tree"].alphabetical-list', computedPanel);
  } else {
    await waitFor('[role="tree"].grouped-list', computedPanel);
  }
};

export const waitForDomNodeToBeVisible = async (elementSelector: string) => {
  const {target} = getBrowserAndPages();

  // DevTools will force Blink to make the hover shown, so we have
  // to wait for the element to be DOM-visible (e.g. no `display: none;`)
  await target.waitForSelector(elementSelector, {visible: true});
};

export const waitForDomNodeToBeHidden = async (elementSelector: string) => {
  const {target} = getBrowserAndPages();
  await target.waitForSelector(elementSelector, {hidden: true});
};

export const assertGutterDecorationForDomNodeExists = async () => {
  await waitFor('.elements-gutter-decoration');
};

export const getStyleRuleSelector = (selector: string) => `[aria-label="${selector}, css selector"]`;

export const waitForStyleRule = async (expectedSelector: string) => {
  await waitForFunction(async () => {
    const rules = await getDisplayedStyleRules();
    return rules.map(rule => rule.selectorText).includes(expectedSelector);
  });
};

export const getComputedStyleProperties = async () => {
  const computedPanel = await getComputedPanel();
  const allProperties = await computedPanel.$$('pierce/[role="treeitem"][aria-level="1"]');
  const properties = [];
  for (const prop of allProperties) {
    const name = await prop.$eval('pierce/' + CSS_PROPERTY_NAME_SELECTOR, element => element.textContent);
    const value = await prop.$eval('pierce/' + CSS_PROPERTY_VALUE_SELECTOR, element => element.textContent);
    const traceElements = await prop.$$('pierce/devtools-computed-style-trace');
    const trace = await Promise.all(traceElements.map(async element => {
      const value = await element.$eval('pierce/.value', element => element.textContent);
      const selector = await element.$eval('pierce/.trace-selector', element => element.textContent);
      const link = await element.$eval('pierce/.trace-link', element => element.textContent);
      return {value, selector, link};
    }));
    properties.push({name, value, trace});
  }
  return properties;
};

export const getDisplayedCSSDeclarations = async () => {
  const cssDeclarations = await $$(CSS_DECLARATION_SELECTOR);
  return Promise.all(cssDeclarations.map(async node => await node.evaluate(n => n.textContent?.trim())));
};

export const getDisplayedStyleRulesCompact = async () => {
  const compactRules = [];
  for (const rule of await getDisplayedStyleRules()) {
    compactRules.push(
        {selectorText: rule.selectorText, propertyNames: rule.propertyData.map(data => data.propertyName)});
  }
  return compactRules;
};

export const getDisplayedStyleRules = async () => {
  const allRuleSelectors = await $$(CSS_STYLE_RULE_SELECTOR);
  const rules = [];
  for (const ruleSelector of allRuleSelectors) {
    const propertyData = await getDisplayedCSSPropertyData(ruleSelector);
    const selectorText = await ruleSelector.evaluate(node => {
      const attribute = node.getAttribute('aria-label') || '';
      return attribute.substring(0, attribute.lastIndexOf(', css selector'));
    });
    rules.push({selectorText, propertyData});
  }

  return rules;
};

/**
 * @param propertiesSection - The element containing this properties section.
 * @returns an array with an entry for each property in the section. Each entry has:
 * - propertyName: The name of this property.
 * - isOverloaded: True if this is an inherited properties section, and this property is overloaded by a child node.
 *                 The property will be shown as crossed out in the style pane.
 * - isInherited: True if this is an inherited properties section, and this property is a non-inherited CSS property.
 *                The property will be shown as grayed-out in the style pane.
 */
export const getDisplayedCSSPropertyData = async (propertiesSection: puppeteer.ElementHandle<Element>) => {
  const cssPropertyNames = await $$(CSS_PROPERTY_NAME_SELECTOR, propertiesSection);
  const propertyNamesData =
      (await Promise.all(cssPropertyNames.map(
           async node => {
             return {
               propertyName: await node.evaluate(n => n.textContent),
               isOverLoaded: await node.evaluate(n => n.parentElement && n.parentElement.matches('.overloaded')),
               isInherited: await node.evaluate(n => n.parentElement && n.parentElement.matches('.inherited')),
             };
           },
           )))
          .filter(c => Boolean(c.propertyName));
  return propertyNamesData;
};

export const getDisplayedCSSPropertyNames = async (propertiesSection: puppeteer.ElementHandle<Element>) => {
  const cssPropertyNames = await $$(CSS_PROPERTY_NAME_SELECTOR, propertiesSection);
  const propertyNamesText = (await Promise.all(cssPropertyNames.map(
                                 node => node.evaluate(n => n.textContent),
                                 )))
                                .filter(c => Boolean(c));
  return propertyNamesText;
};

export const getStyleRule = (selector: string) => {
  return waitFor(getStyleRuleSelector(selector));
};

export const getStyleRuleWithSourcePosition = (styleSelector: string, sourcePosition?: string) => {
  if (!sourcePosition) {
    return getStyleRule(styleSelector);
  }
  const selector = getStyleRuleSelector(styleSelector);
  return waitForFunction(async () => {
    const candidate = await waitFor(selector);
    if (candidate) {
      const sourcePositionElement = await candidate.$('.styles-section-subtitle .devtools-link');
      const text = await sourcePositionElement?.evaluate(node => node.textContent);
      if (text === sourcePosition) {
        return candidate;
      }
    }
    return undefined;
  });
};

export const getColorSwatch = async (parent: puppeteer.ElementHandle<Element>|undefined, index: number) => {
  const swatches = await $$(COLOR_SWATCH_SELECTOR, parent);
  return swatches[index];
};

export const getColorSwatchColor = async (parent: puppeteer.ElementHandle<Element>, index: number) => {
  const swatch = await getColorSwatch(parent, index);
  return await swatch.evaluate(node => (node as HTMLElement).style.backgroundColor);
};

export const shiftClickColorSwatch = async (ruleSection: puppeteer.ElementHandle<Element>, index: number) => {
  const swatch = await getColorSwatch(ruleSection, index);
  const {frontend} = getBrowserAndPages();
  await frontend.keyboard.down('Shift');
  await clickElement(swatch);
  await frontend.keyboard.up('Shift');
};

export const getElementStyleFontEditorButton = async () => {
  const section = await waitFor(ELEMENT_STYLE_SECTION_SELECTOR);
  return await $(FONT_EDITOR_SELECTOR, section);
};

export const getFontEditorButtons = async () => {
  const buttons = await $$(FONT_EDITOR_SELECTOR);
  return buttons;
};

export const getHiddenFontEditorButtons = async () => {
  const buttons = await $$(HIDDEN_FONT_EDITOR_SELECTOR);
  return buttons;
};

export const getStyleSectionSubtitles = async () => {
  const subtitles = await $$(SECTION_SUBTITLE_SELECTOR);
  return Promise.all(subtitles.map(node => node.evaluate(n => n.textContent)));
};

export const getCSSPropertyInRule =
    async (ruleSection: puppeteer.ElementHandle<Element>|string, name: string, sourcePosition?: string) => {
  if (typeof ruleSection === 'string') {
    ruleSection = await getStyleRuleWithSourcePosition(ruleSection, sourcePosition);
  }

  const propertyNames = await $$(CSS_PROPERTY_NAME_SELECTOR, ruleSection);
  for (const node of propertyNames) {
    const parent =
        (await node.evaluateHandle((node, name) => (name === node.textContent) ? node.parentNode : undefined, name))
            .asElement();
    if (parent) {
      return parent as puppeteer.ElementHandle<HTMLElement>;
    }
  }
  return undefined;
};

export const focusCSSPropertyValue = async (selector: string, propertyName: string) => {
  await waitForStyleRule(selector);
  let property = await getCSSPropertyInRule(selector, propertyName);
  // Clicking on the semicolon element to make sure we don't hit the swatch or other
  // non-editable elements.
  await click(CSS_PROPERTY_VALUE_SELECTOR + ' + .styles-semicolon', {root: property});
  await waitForFunction(async () => {
    property = await getCSSPropertyInRule(selector, propertyName);
    const value = await $(CSS_PROPERTY_VALUE_SELECTOR, property);
    if (!value) {
      assert.fail(`Could not find property ${propertyName} in rule ${selector}`);
    }
    return await value.evaluate(node => {
      return node.classList.contains('text-prompt') && node.hasAttribute('contenteditable');
    });
  });
};

/**
 * Edit a CSS property value in a given rule
 * @param selector The selector of the rule to be updated. Note that because of the way the Styles populates, it is
 * important to provide a rule selector that is unique here, to avoid editing a property in the wrong rule.
 * @param propertyName The name of the property to be found and edited. If several properties have the same names, the
 * first one is edited.
 * @param newValue The new value to be used.
 */
export async function editCSSProperty(selector: string, propertyName: string, newValue: string) {
  await focusCSSPropertyValue(selector, propertyName);

  const {frontend} = getBrowserAndPages();
  await frontend.keyboard.type(newValue, {delay: 100});
  await frontend.keyboard.press('Enter');

  await waitForFunction(async () => {
    // Wait until the value element is not a text-prompt anymore.
    const property = await getCSSPropertyInRule(selector, propertyName);
    const value = await $(CSS_PROPERTY_VALUE_SELECTOR, property);
    if (!value) {
      assert.fail(`Could not find property ${propertyName} in rule ${selector}`);
    }
    return await value.evaluate(node => {
      return !node.classList.contains('text-prompt') && !node.hasAttribute('contenteditable');
    });
  });
}

// Edit a media or container query rule text for the given styles section
export async function editQueryRuleText(queryStylesSections: puppeteer.ElementHandle<Element>, newQueryText: string) {
  await click(STYLE_QUERY_RULE_TEXT_SELECTOR, {root: queryStylesSections});
  await waitForFunction(async () => {
    // Wait until the value element has been marked as a text-prompt.
    const queryText = await $(STYLE_QUERY_RULE_TEXT_SELECTOR, queryStylesSections);
    if (!queryText) {
      assert.fail('Could not find any query in the given styles section');
    }
    const check = await queryText.evaluate(node => {
      return node.classList.contains('being-edited') && node.hasAttribute('contenteditable');
    });
    return check;
  });
  await typeText(newQueryText);
  await pressKey('Enter');

  await waitForFunction(async () => {
    // Wait until the value element is not a text-prompt anymore.
    const queryText = await $(STYLE_QUERY_RULE_TEXT_SELECTOR, queryStylesSections);
    if (!queryText) {
      assert.fail('Could not find any query in the given styles section');
    }
    const check = await queryText.evaluate(node => {
      return !node.classList.contains('being-edited') && !node.hasAttribute('contenteditable');
    });
    return check;
  });
}

export async function waitForCSSPropertyValue(selector: string, name: string, value: string, sourcePosition?: string) {
  return await waitForFunction(async () => {
    const propertyHandle = await getCSSPropertyInRule(selector, name, sourcePosition);
    if (!propertyHandle) {
      return undefined;
    }

    const valueHandle = await $(CSS_PROPERTY_VALUE_SELECTOR, propertyHandle);
    if (!valueHandle) {
      return undefined;
    }

    const matches = await valueHandle.evaluate((node, value) => node.textContent === value, value);
    if (matches) {
      return valueHandle;
    }
    return undefined;
  });
}

export async function waitForPropertyToHighlight(ruleSelector: string, propertyName: string) {
  await waitForFunction(async () => {
    const property = await getCSSPropertyInRule(ruleSelector, propertyName);
    if (!property) {
      assert.fail(`Could not find property ${propertyName} in rule ${ruleSelector}`);
    }
    // StylePropertyHighlighter temporarily highlights the property using the Web Animations API, so the only way to
    // know it's happening is by listing all animations.
    const animationCount = await property.evaluate(node => (node as HTMLElement).getAnimations().length);
    return animationCount > 0;
  });
}

export const getBreadcrumbsTextContent = async ({expectedNodeCount}: {expectedNodeCount: number}) => {
  const crumbsSelector = 'li.crumb > a > devtools-node-text';
  await waitForFunction(async () => {
    const crumbs = await $$(crumbsSelector);
    return crumbs.length === expectedNodeCount;
  });

  const crumbs = await $$(crumbsSelector);
  const crumbsAsText: string[] = await Promise.all(crumbs.map(node => node.evaluate((node: Element) => {
    if (!node.shadowRoot) {
      assert.fail('Found breadcrumbs node that unexpectedly has no shadowRoot.');
    }
    return Array.from(node.shadowRoot.querySelectorAll('span') || []).map(span => span.textContent).join('');
  })));
  return crumbsAsText;
};

export const getSelectedBreadcrumbTextContent = async () => {
  const selectedCrumb = await waitFor('li.crumb.selected > a > devtools-node-text');
  const text = selectedCrumb.evaluate((node: Element) => {
    if (!node.shadowRoot) {
      assert.fail('Found breadcrumbs node that unexpectedly has no shadowRoot.');
    }
    return Array.from(node.shadowRoot.querySelectorAll('span') || []).map(span => span.textContent).join('');
  });
  return text;
};

export const navigateToElementsTab = async () => {
  // Open Elements panel
  await click('#tab-elements');
  await waitFor(ELEMENTS_PANEL_SELECTOR);
};

export const clickOnFirstLinkInStylesPanel = async () => {
  const stylesPane = await waitFor('div.styles-pane');
  await click('div.styles-section-subtitle span.devtools-link', {root: stylesPane});
};

export const toggleClassesPane = async () => {
  await click(CLS_BUTTON_SELECTOR);
};

export const typeInClassesPaneInput =
    async (text: string, commitWith: puppeteer.KeyInput = 'Enter', waitForNodeChange: Boolean = true) => {
  await step(`Typing in new class names ${text}`, async () => {
    const clsInput = await waitFor(CLS_INPUT_SELECTOR);
    await clsInput.type(text, {delay: 50});
  });

  if (commitWith) {
    await step(`Committing the changes with ${commitWith}`, async () => {
      const {frontend} = getBrowserAndPages();
      await frontend.keyboard.press(commitWith);
    });
  }

  if (waitForNodeChange) {
    // Make sure the classes provided in text can be found in the selected element's content. This is important as the
    // cls pane applies classes as you type, so it is not enough to wait for the selected node to change just once.
    await step('Waiting for the selected node to change', async () => {
      await waitForFunction(async () => {
        const nodeContent = await getContentOfSelectedNode();
        return text.split(' ').every(cls => nodeContent.includes(cls));
      });
    });
  }
};

export const toggleClassesPaneCheckbox = async (checkboxLabel: string) => {
  const initialValue = await getContentOfSelectedNode();

  const classesPane = await waitFor(CLS_PANE_SELECTOR);
  await click(`[title="${checkboxLabel}"]`, {root: classesPane});

  await waitForSelectedNodeChange(initialValue);
};

export const uncheckStylesPaneCheckbox = async (checkboxLabel: string) => {
  const initialValue = await getContentOfSelectedNode();
  await click(`.enabled-button[aria-label="${checkboxLabel}"]`);
  await waitForSelectedNodeChange(initialValue);
};

export const assertSelectedNodeClasses = async (expectedClasses: string[]) => {
  const nodeText = await getContentOfSelectedNode();
  const match = nodeText.match(/class=\u200B"([^"]*)/);
  const classText = match ? match[1] : '';
  const classes = classText.split(/[\s]/).map(className => className.trim()).filter(className => className.length);

  assert.strictEqual(
      classes.length, expectedClasses.length, 'Did not find the expected number of classes on the element');

  for (const expectedClass of expectedClasses) {
    assert.include(classes, expectedClass, `Could not find class ${expectedClass} on the element`);
  }
};

export const toggleAccessibilityPane = async () => {
  let a11yPane = await $('Accessibility', undefined, 'aria');
  if (!a11yPane) {
    const elementsPanel = await waitForAria('Elements panel');
    const moreTabs = await waitForAria('More tabs', elementsPanel);
    await clickElement(moreTabs);
    a11yPane = await waitForAria('Accessibility');
  }
  await clickElement(a11yPane);
};

export const toggleAccessibilityTree = async () => {
  await click('aria/Switch to Accessibility Tree view');
};

export const getPropertiesWithHints = async () => {
  const allRuleSelectors = await $$(CSS_STYLE_RULE_SELECTOR);

  const propertiesWithHints = [];
  for (const propertiesSection of allRuleSelectors) {
    const cssRuleNodes = await $$('li ', propertiesSection);

    for (const cssRuleNode of cssRuleNodes) {
      const propertyNode = await $(CSS_PROPERTY_NAME_SELECTOR, cssRuleNode);
      const propertyName = propertyNode !== null ? await propertyNode.evaluate(n => n.textContent) : null;
      if (propertyName === null) {
        continue;
      }

      const authoringHintsIcon = await $(CSS_AUTHORING_HINTS_ICON_SELECTOR, cssRuleNode);
      if (authoringHintsIcon) {
        propertiesWithHints.push(propertyName);
      }
    }
  }

  return propertiesWithHints;
};

export const summonAndWaitForSearchBox = async () => {
  await summonSearchBox();
  await waitFor(SEARCH_BOX_SELECTOR);
};

export const assertSearchResultMatchesText = async (text: string) => {
  await waitForFunction(async () => {
    return await getTextContent(SEARCH_RESULTS_MATCHES) === text;
  });
};

export const goToResourceAndWaitForStyleSection = async (path: string) => {
  await goToResource(path);
  await waitForElementsStyleSection();

  // Check to make sure we have the correct node selected after opening a file.
  await waitForPartialContentOfSelectedElementsNode('<body>\u200B');
};

export const checkStyleAttributes = async (expectedStyles: string[]) => {
  const result = await $$(STYLE_PROPERTIES_SELECTOR, undefined, 'pierce');
  const actual = await Promise.all(result.map(e => e.evaluate(e => e.textContent?.trim())));
  return actual.sort().join(' ') === expectedStyles.sort().join(' ');
};
