chromium/chrome/test/data/webui/polymer_test_util.ts

// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import type {PolymerElement} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js';
import {afterNextRender, beforeNextRender, flush} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js';

/**
 * Converts beforeNextRender() API to promise-based.
 */
export function waitBeforeNextRender(element: HTMLElement): Promise<void> {
  return new Promise(resolve => {
    beforeNextRender(element, resolve);
  });
}

/**
 * Converts afterNextRender() API to promise-based.
 */
export function waitAfterNextRender(element: HTMLElement): Promise<void> {
  return new Promise(resolve => {
    afterNextRender(element, resolve);
  });
}

/*
 * Waits for queued up tasks to finish before proceeding. Inspired by:
 * https://github.com/Polymer/web-component-tester/blob/master/browser/environment/helpers.js#L97
 */
export function flushTasks(): Promise<void> {
  flush();
  // Promises have microtask timing, so we use setTimeout to explicitly force
  // a new task.
  return new Promise(function(resolve) {
    window.setTimeout(resolve, 1);
  });
}

/**
 * Data-binds two Polymer properties using the property-changed events and
 * set/notifyPath API. Useful for testing components which would normally be
 * used together.
 */
export function fakeDataBind(
    el1: PolymerElement, el2: PolymerElement, property: string) {
  type PropertyChangedEvent = CustomEvent<{path: string, value: any}>;

  const forwardChange = function(
      el: PolymerElement, event: PropertyChangedEvent) {
    if (event.detail.hasOwnProperty('path')) {
      el.notifyPath(event.detail.path, event.detail.value);
    } else {
      el.set(property, event.detail.value);
    }
  };
  // Add the listeners symmetrically. Polymer will prevent recursion.
  el1.addEventListener(
      property + '-changed',
      e => forwardChange(el2, e as PropertyChangedEvent));
  el2.addEventListener(
      property + '-changed',
      e => forwardChange(el1, e as PropertyChangedEvent));
}