chromium/chrome/test/data/webui/chromeos/personalization_app/ambient_preview_small_element_test.ts

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

import 'chrome://personalization/strings.m.js';

import {AmbientObserver, AmbientPreviewSmallElement, PersonalizationRouterElement, TopicSource} from 'chrome://personalization/js/personalization_app.js';
import {loadTimeData} from 'chrome://resources/js/load_time_data.js';
import {assertEquals, assertTrue} from 'chrome://webui-test/chai_assert.js';
import {waitAfterNextRender} from 'chrome://webui-test/polymer_test_util.js';
import {TestMock} from 'chrome://webui-test/test_mock.js';

import {baseSetup, initElement, teardownElement} from './personalization_app_test_utils.js';
import {TestAmbientProvider} from './test_ambient_interface_provider.js';
import {TestPersonalizationStore} from './test_personalization_store.js';


suite('AmbientPreviewSmallElementTest', function() {
  let ambientPreviewSmallElement: AmbientPreviewSmallElement|null;
  let ambientProvider: TestAmbientProvider;
  let personalizationStore: TestPersonalizationStore;
  const routerOriginal = PersonalizationRouterElement.instance;
  const routerMock = TestMock.fromClass(PersonalizationRouterElement);

  setup(() => {
    loadTimeData.overrideValues({isAmbientModeAllowed: true});
    const mocks = baseSetup();
    ambientProvider = mocks.ambientProvider;
    personalizationStore = mocks.personalizationStore;
    AmbientObserver.initAmbientObserverIfNeeded();
    PersonalizationRouterElement.instance = () => routerMock;
  });

  teardown(async () => {
    await teardownElement(ambientPreviewSmallElement);
    ambientPreviewSmallElement = null;
    AmbientObserver.shutdown();
    PersonalizationRouterElement.instance = routerOriginal;
  });

  test(
      'displays zero state message when ambient mode is disabled', async () => {
        personalizationStore.data.ambient.albums = ambientProvider.albums;
        personalizationStore.data.ambient.topicSource = TopicSource.kArtGallery;
        personalizationStore.data.ambient.ambientModeEnabled = false;
        personalizationStore.data.ambient.previews = ambientProvider.previews;
        ambientPreviewSmallElement = initElement(AmbientPreviewSmallElement);
        personalizationStore.notifyObservers();
        await waitAfterNextRender(ambientPreviewSmallElement);

        const zeroStateTextContainer =
            ambientPreviewSmallElement.shadowRoot!.getElementById(
                'zeroStateTextContainer');
        assertTrue(!!zeroStateTextContainer);
        const textSpan =
            zeroStateTextContainer.firstElementChild as HTMLSpanElement;
        assertTrue(!!textSpan);
        assertEquals('span', textSpan.tagName.toLowerCase());
        assertEquals(
            ambientPreviewSmallElement.i18n(
                'ambientModeMainPageZeroStateMessage'),
            textSpan.innerText.trim());
      });

  test('shows placeholders while loading', async () => {
    // Null indicates that this value has not yet loaded.
    personalizationStore.data.ambient.ambientModeEnabled = null;
    ambientPreviewSmallElement = initElement(AmbientPreviewSmallElement);
    personalizationStore.notifyObservers();
    await waitAfterNextRender(ambientPreviewSmallElement);

    const container = ambientPreviewSmallElement.$.container;
    assertEquals('imagePlaceholder', container.firstElementChild?.id);

    const textPlaceholder = container.querySelector('#textPlaceholder');
    assertTrue(!!textPlaceholder, 'textPlaceholder element exists');
    for (const child of textPlaceholder.children) {
      assertTrue(
          child.classList.contains('placeholder'),
          'every element has placeholder class');
    }

    assertEquals(null, container.querySelector('#imageContainer'));
  });

  test('shows placeholders while waiting for assets to load', async () => {
    // Only AmbientModeEnabled is set.
    personalizationStore.data.ambient.ambientModeEnabled = true;
    // Null indicates that albums have not yet loaded.
    personalizationStore.data.ambient.albums = null;
    ambientPreviewSmallElement = initElement(AmbientPreviewSmallElement);
    personalizationStore.notifyObservers();
    await waitAfterNextRender(ambientPreviewSmallElement);

    const container = ambientPreviewSmallElement.$.container;
    assertEquals('imagePlaceholder', container.firstElementChild?.id);

    const textPlaceholder = container.querySelector('#textPlaceholder');
    assertTrue(!!textPlaceholder, 'textPlaceholder element exists');
    for (const child of textPlaceholder.children) {
      assertTrue(
          child.classList.contains('placeholder'),
          'every element has placeholder class');
    }

    assertEquals(null, container.querySelector('#imageContainer'));
  });

  test('ends loading early if ambient mode is disabled', async () => {
    personalizationStore.data.ambient.ambientModeEnabled = false;
    ambientPreviewSmallElement = initElement(AmbientPreviewSmallElement);
    personalizationStore.notifyObservers();
    await waitAfterNextRender(ambientPreviewSmallElement);

    const zeroStateTextContainer =
        ambientPreviewSmallElement.shadowRoot!.getElementById(
            'zeroStateTextContainer');
    assertTrue(!!zeroStateTextContainer);
    const textSpan =
        zeroStateTextContainer.firstElementChild as HTMLSpanElement;
    assertTrue(!!textSpan);
    assertEquals('span', textSpan.tagName.toLowerCase());
    assertEquals(
        ambientPreviewSmallElement.i18n('ambientModeMainPageZeroStateMessage'),
        textSpan.innerText.trim());
  });

  test('shows image when loaded', async () => {
    personalizationStore.data.ambient.albums = ambientProvider.albums;
    personalizationStore.data.ambient.topicSource = TopicSource.kArtGallery;
    personalizationStore.data.ambient.ambientModeEnabled = true;
    personalizationStore.data.ambient.previews = ambientProvider.previews;
    ambientPreviewSmallElement = initElement(AmbientPreviewSmallElement);
    personalizationStore.notifyObservers();
    await waitAfterNextRender(ambientPreviewSmallElement);

    const imageContainer =
        ambientPreviewSmallElement.shadowRoot?.getElementById('imageContainer');
    assertTrue(!!imageContainer, 'imageContainer exists');
    assertEquals(
        1, imageContainer.getElementsByTagName('img').length,
        '1 img element displayed');
  });
});