chromium/chrome/test/data/webui/js/cr_test.ts

// Copyright 2019 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 {WebUiListener} from 'chrome://resources/js/cr.js';
import {addWebUiListener, removeWebUiListener, sendWithPromise, webUIListenerCallback, webUIResponse} from 'chrome://resources/js/cr.js';
import {PromiseResolver} from 'chrome://resources/js/promise_resolver.js';
import {assertEquals, assertFalse, assertNotReached, assertTrue} from 'chrome://webui-test/chai_assert.js';

/** Name of the chrome.send() message to be used in tests. */
const CHROME_SEND_NAME: string = 'echoMessage';

suite('CrSendWithPromiseTest', function() {
  const originalChromeSend = chrome.send;
  let rejectPromises = false;

  function whenChromeSendCalled(_name: string): Promise<any[]> {
    assertEquals(originalChromeSend, chrome.send);
    return new Promise(function(resolve) {
      chrome.send = (_msg: string, args?: any[]) => {
        resolve(args!);
      };
    });
  }

  setup(function() {
    // Simulate a WebUI handler that echoes back all parameters passed to it.
    // Rejects the promise depending on |rejectPromises|.
    whenChromeSendCalled(CHROME_SEND_NAME).then(function(args: any[]) {
      const callbackId = args[0];
      const response = args[1];
      webUIResponse(callbackId, !rejectPromises, response);
    });
  });

  teardown(function() {
    rejectPromises = false;

    // Restore original chrome.send(), as it is necessary for the testing
    // framework to signal test completion.
    chrome.send = originalChromeSend;
  });

  test('ResponseObject', function() {
    const expectedResponse = {'foo': 'bar'};
    return sendWithPromise(CHROME_SEND_NAME, expectedResponse)
        .then(function(response) {
          assertEquals(
              JSON.stringify(expectedResponse), JSON.stringify(response));
        });
  });

  test('ResponseArray', function() {
    const expectedResponse = ['foo', 'bar'];
    return sendWithPromise(CHROME_SEND_NAME, expectedResponse)
        .then(function(response) {
          assertEquals(
              JSON.stringify(expectedResponse), JSON.stringify(response));
        });
  });

  test('ResponsePrimitive', function() {
    const expectedResponse = 1234;
    return sendWithPromise(CHROME_SEND_NAME, expectedResponse)
        .then(function(response) {
          assertEquals(expectedResponse, response);
        });
  });

  test('ResponseVoid', function() {
    return sendWithPromise(CHROME_SEND_NAME).then(function(response) {
      assertEquals(undefined, response);
    });
  });

  test('Reject', function() {
    rejectPromises = true;
    const expectedResponse = 1234;
    return sendWithPromise(CHROME_SEND_NAME, expectedResponse)
        .then(
            function() {
              assertNotReached('should have rejected promise');
            },
            function(error) {
              assertEquals(expectedResponse, error);
            });
  });
});

suite('CrWebUiListenersTest', function() {
  let listener1: WebUiListener|null = null;
  let listener2: WebUiListener|null = null;

  const EVENT_NAME: string = 'my-foo-event';

  teardown(function() {
    if (listener1) {
      removeWebUiListener(listener1);
    }
    if (listener2) {
      removeWebUiListener(listener2);
    }
  });

  test('removeWebUiListener', function() {
    listener1 = addWebUiListener(EVENT_NAME, function() {});
    assertTrue(removeWebUiListener(listener1));
    assertFalse(removeWebUiListener(listener1));
    assertFalse(removeWebUiListener({
      eventName: 'non-existing-event',
      uid: 12345,
    }));
  });

  test('addWebUiListener_ResponseParams', function() {
    const expectedString = 'foo';
    const expectedNumber = 123;
    const expectedArray = [1, 2];
    const expectedObject = {};

    return new Promise<void>(function(resolve) {
      listener1 = addWebUiListener(
          EVENT_NAME, function(s: string, n: number, a: number[], o: object) {
            assertEquals(expectedString, s);
            assertEquals(expectedNumber, n);
            assertEquals(expectedArray, a);
            assertEquals(expectedObject, o);
            resolve();
          });
      webUIListenerCallback(
          EVENT_NAME, expectedString, expectedNumber, expectedArray,
          expectedObject);
    });
  });

  test('addWebUiListener_NoResponseParams', function() {
    return new Promise<void>(function(resolve) {
      listener1 = addWebUiListener(EVENT_NAME, function() {
        assertEquals(0, arguments.length);
        resolve();
      });
      webUIListenerCallback(EVENT_NAME);
    });
  });

  test('addWebUiListener_MulitpleListeners', function() {
    const resolver1 = new PromiseResolver();
    const resolver2 = new PromiseResolver();
    listener1 = addWebUiListener(EVENT_NAME, resolver1.resolve);
    listener2 = addWebUiListener(EVENT_NAME, resolver2.resolve);
    webUIListenerCallback(EVENT_NAME);
    // Check that both listeners registered are invoked.
    return Promise.all([resolver1.promise, resolver2.promise]);
  });
});