chromium/chrome/test/data/webui/chromeos/emoji_picker/emoji_picker_search_test.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 {EMOJI_TEXT_BUTTON_CLICK, EmojiPickerApp, EmojiSearch} from 'chrome://emoji-picker/emoji_picker.js';
import {assert} from 'chrome://resources/js/assert.js';
import {assertEquals, assertGT} from 'chrome://webui-test/chai_assert.js';

import {initialiseEmojiPickerForTest, waitForCondition, waitWithTimeout} from './emoji_picker_test_util.js';

suite('emoji-search', () => {
  let emojiPicker: EmojiPickerApp;
  let emojiSearch: EmojiSearch;
  let findInEmojiPicker: (...path: string[]) => HTMLElement | null;
  let expectEmojiButton: (text: string, getGroup?: () => HTMLElement | null) =>
      Promise<HTMLElement>;
  let expectEmojiButtons:
      (texts: string[], getGroup?: () => HTMLElement | null) =>
          Promise<HTMLElement[]>;
  let clickVariant: (text: string, button: HTMLElement) => Promise<void>;
  let findSearchGroup: (category: string) => HTMLElement | null;
  let reload: () => Promise<void>;

  const setSearchQuery = (value: string) => {
    const emojiSearch = findInEmojiPicker('emoji-search') as EmojiSearch;
    emojiSearch.setSearchQuery(value);
  };

  setup(async () => {
    const newPicker = initialiseEmojiPickerForTest();
    emojiPicker = newPicker.emojiPicker;
    findInEmojiPicker = newPicker.findInEmojiPicker;
    expectEmojiButton = newPicker.expectEmojiButton;
    expectEmojiButtons = newPicker.expectEmojiButtons;
    clickVariant = newPicker.clickVariant;
    findSearchGroup = newPicker.findSearchGroup;
    reload = newPicker.reload;
    await newPicker.readyPromise;
    emojiSearch = findInEmojiPicker('emoji-search') as EmojiSearch;
  });


  test('By default, there is no search result.', () => {
    const searchResults = findInEmojiPicker('emoji-search', '#results');
    assert(!searchResults);
  });

  test(
      'If matching, search should return both emoji and emoticon results.',
      async () => {
        emojiSearch.setSearchQuery('face');
        await waitForCondition(
            () => findInEmojiPicker(
                'emoji-search', 'emoji-group[category="emoji"]'),
            'wait for search results to enter');
        const emojiResults =
            findInEmojiPicker(
                'emoji-search',
                'emoji-group')!.shadowRoot!.querySelectorAll('.emoji-button');
        assertGT(emojiResults.length, 0);
        const emoticonResults =
            findInEmojiPicker(
                'emoji-search', 'emoji-group[category="emoticon"]')!.shadowRoot!
                .querySelectorAll('.emoji-button');
        assertGT(emoticonResults.length, 0);
      });

  test(
      'Search should display meaningful output when no result is found.',
      async () => {
        emojiSearch.setSearchQuery('zyxt');
        await waitForCondition(
            () => findInEmojiPicker('emoji-search', '.no-result'),
            'wait for no result to render');
        const message = findInEmojiPicker('emoji-search', '.no-result');
        assertEquals(message!.innerText, 'No result found');
      });

  test(
      'If there is only one emoji returned, pressing Enter triggers the ' +
          'clicking event.',
      async () => {
        emojiSearch.setSearchQuery('zombi');
        await waitForCondition(
            () => findInEmojiPicker('emoji-search', 'emoji-group'),
            'wait for search to render');
        const enterEvent = new KeyboardEvent(
            'keydown', {cancelable: true, key: 'Enter', keyCode: 13});
        const buttonClickPromise = new Promise<void>(
            (resolve) => emojiPicker.addEventListener(
                EMOJI_TEXT_BUTTON_CLICK, (event) => {
                  assertEquals('🧟', event.detail.text);
                  assertEquals('zombie', event.detail.name?.trim());
                  resolve();
                }));
        emojiSearch.onSearchKeyDown(enterEvent);
        await waitWithTimeout(
            buttonClickPromise, 1000,
            'Failed to receive emoji button click event.');
      });

  test(
      'If there is only emoticon returned, pressing Enter triggers the ' +
          'clicking event.',
      async () => {
        emojiSearch.setSearchQuery('cat');
        await waitForCondition(
            () => findInEmojiPicker('emoji-search', 'emoji-group'),
            'wait for search to be rendered');
        const enterEvent = new KeyboardEvent(
            'keydown', {cancelable: true, key: 'Enter', keyCode: 13});

        const buttonClickPromise = new Promise<void>(
            (resolve) => emojiPicker.addEventListener(
                EMOJI_TEXT_BUTTON_CLICK, (event) => {
                  assertEquals('=^.^=', event.detail.text);
                  resolve();
                }));

        emojiSearch.onSearchKeyDown(enterEvent);
        await waitWithTimeout(
            buttonClickPromise, 1000,
            'Failed to receive emoji button click event.');
      });

  test('Search only emoji groups are discoverable through search', async () => {
    emojiSearch.setSearchQuery('gamma');
    await waitForCondition(
        () => findInEmojiPicker('emoji-search', 'emoji-group'),
        'wait for search group to be rendered');
    const emojiResults =
        findInEmojiPicker('emoji-search', 'emoji-group[category="symbol"]')!
            .shadowRoot!.querySelectorAll('.emoji-button');
    assertEquals(
        emojiResults!.length,
        4,  // normal, italic, bold and san-serif bold
    );
  });

  test(
      'selecting a variant from search should update preferences', async () => {
        setSearchQuery('shrug');
        const searchEmoji =
            await expectEmojiButton('🤷', () => findSearchGroup('emoji'));
        await clickVariant('🤷🏿‍♀', searchEmoji);
        await reload();
        await expectEmojiButtons(['🤷🏿‍♀', '👍🏿', '🧞‍♀']);
      });

  test('preferences should be applied in emoji search', async () => {
    const thumbsUp = await expectEmojiButton('👍');
    await clickVariant('👍🏿', thumbsUp);
    await reload();
    setSearchQuery('shrug');
    await expectEmojiButton('🤷🏿', () => findSearchGroup('emoji'));
  });
});