chromium/chrome/test/data/webui/chromeos/set_time_dialog/set_time_dialog_test.js

// 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 'chrome://set-time/set_time.js';

import {webUIListenerCallback} from 'chrome://resources/js/cr.js';
import {loadTimeData} from 'chrome://resources/js/load_time_data.js';
import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
import {SetTimeBrowserProxyImpl} from 'chrome://set-time/set_time_browser_proxy.js';
import {assertEquals, assertGT, assertLE, assertNotEquals, assertTrue} from 'chrome://webui-test/chai_assert.js';

import {TestSetTimeBrowserProxy} from './test_set_time_browser_proxy.js';

suite('SetTimeDialog', function() {
  let setTimeElement = null;
  let testBrowserProxy = null;

  suiteSetup(function() {
    // Must use existing timezones in the test.
    loadTimeData.overrideValues({
      showTimezone: true,
      currentTimezoneId: 'America/Sao_Paulo',
      timezoneList: [
        [
          'America/Los_Angeles',
          '(GMT-7:00) Pacific Daylight Time (Los Angeles)',
        ],
        ['America/Sao_Paulo', '(GMT-3:00) Brasilis Standard Time (Sao Paulo)'],
        ['Asia/Seoul', '(GMT+9:00) Korean Standard Time (Seoul)'],
      ],
    });
  });

  setup(function() {
    testBrowserProxy = new TestSetTimeBrowserProxy();
    SetTimeBrowserProxyImpl.setInstance(testBrowserProxy);
    PolymerTest.clearBody();
    setTimeElement = document.createElement('set-time-dialog');
    document.body.appendChild(setTimeElement);
    flush();
  });

  teardown(function() {
    setTimeElement.remove();
  });

  test('PageReady', () => {
    // Verify the page sends the ready message.
    assertEquals(1, testBrowserProxy.getCallCount('sendPageReady'));
  });

  test('DateRangeContainsNow', () => {
    const dateInput = setTimeElement.shadowRoot.querySelector('#dateInput');

    // Input element attributes min and max are strings like '2019-03-01'.
    const minDate = new Date(dateInput.min);
    const maxDate = new Date(dateInput.max);
    const now = new Date();

    // Verify min <= now <= max.
    assertLE(minDate, now);
    assertLE(now, maxDate);
  });

  test('SetDate', async () => {
    const dateInput = setTimeElement.shadowRoot.querySelector('#dateInput');
    assertTrue(!!dateInput);

    // Simulate the user changing the date picker forward by a week.
    const today = dateInput.valueAsDate;
    const nextWeek = new Date(today.getTime() + 7 * 24 * 60 * 60 * 1000);
    dateInput.focus();
    dateInput.valueAsDate = nextWeek;
    setTimeElement.shadowRoot.querySelector('#doneButton').click();

    // The browser validates the change.
    await testBrowserProxy.whenCalled('doneClicked');
    webUIListenerCallback('validation-complete');

    // Verify the page sends a request to move time forward.
    const timeInSeconds = await testBrowserProxy.whenCalled('setTimeInSeconds');
    const todaySeconds = today.getTime() / 1000;
    // The exact value isn't important (it depends on the current time).
    assertGT(timeInSeconds, todaySeconds);
  });

  test('Revert invalid date on blur', () => {
    const dateInput = setTimeElement.shadowRoot.querySelector('#dateInput');
    dateInput.focus();
    dateInput.value = '9999-99-99';
    dateInput.blur();
    // The exact value isn't important (it depends on the current date, and
    // the date could change in the middle of the test).
    assertNotEquals('9999-99-99', dateInput.value);
  });

  test('SystemTimezoneChanged', () => {
    const timezoneSelect =
        setTimeElement.shadowRoot.querySelector('#timezoneSelect');
    assertTrue(!!timezoneSelect);
    assertEquals('America/Sao_Paulo', timezoneSelect.value);

    webUIListenerCallback('system-timezone-changed', 'America/Los_Angeles');
    assertEquals('America/Los_Angeles', timezoneSelect.value);

    webUIListenerCallback('system-timezone-changed', 'Asia/Seoul');
    assertEquals('Asia/Seoul', timezoneSelect.value);
  });

  // Disabled for flake. https://crbug.com/1043598
  test.skip('SetDateAndTimezone', async () => {
    const dateInput = setTimeElement.shadowRoot.querySelector('#dateInput');
    assertTrue(!!dateInput);

    const timeInput = setTimeElement.shadowRoot.querySelector('#timeInput');
    assertTrue(!!timeInput);

    const timezoneSelect =
        setTimeElement.shadowRoot.querySelector('#timezoneSelect');
    assertTrue(!!timezoneSelect);
    assertEquals('America/Sao_Paulo', timezoneSelect.value);

    // Simulate the user changing the time by forwarding it 15 minutes.
    const originalTime = dateInput.valueAsDate;
    originalTime.setMilliseconds(timeInput.valueAsNumber);
    const updatedTime = new Date(originalTime.getTime() + 15 * 60 * 1000);
    dateInput.focus();
    dateInput.valueAsDate = updatedTime;
    dateInput.blur();

    // Simulate the user changing the time zone.
    webUIListenerCallback('system-timezone-changed', 'America/Los_Angeles');
    assertEquals('America/Los_Angeles', timezoneSelect.value);

    // Make sure that time on input field was updated.
    const updatedTimeAndTimezone = dateInput.valueAsDate;
    updatedTimeAndTimezone.setMilliseconds(timeInput.valueAsNumber);
    // updatedTimeAndTimezone reflects the new timezone so it should be
    // smaller, because it is more to the west than the original
    // one, therefore even with the 15 minutes forwarded it should be smaller.
    assertGT(updatedTime.getTime(), updatedTimeAndTimezone.getTime());

    // Close the dialog.
    setTimeElement.shadowRoot.querySelector('#doneButton').click();

    // The browser validates the change.
    await testBrowserProxy.whenCalled('doneClicked');
    webUIListenerCallback('validation-complete');

    const timeInSeconds = await testBrowserProxy.whenCalled('setTimeInSeconds');
    const todaySeconds = originalTime.getTime() / 1000;
    // The exact value isn't important (it depends on the current time).
    // timeInSeconds should be bigger, because this timestamp is seconds
    // since epoch and it does not hold any information regarding the
    // current timezone.
    assertGT(timeInSeconds, todaySeconds);

    const newTimezone = await testBrowserProxy.whenCalled('setTimezone');
    assertEquals('America/Los_Angeles', newTimezone);
  });

  suite('HideTimezone', () => {
    suiteSetup(() => {
      loadTimeData.overrideValues({showTimezone: false});
    });

    test('SetDate', async () => {
      const dateInput = setTimeElement.shadowRoot.querySelector('#dateInput');
      assertTrue(!!dateInput);

      assertEquals(
          null, setTimeElement.shadowRoot.querySelector('#timezoneSelect'));

      // Simulates the user changing the date picker backward by two days. We
      // are changing the date to make the test simpler. Changing the time
      // would require timezone manipulation and handling corner cases over
      // midnight. valuesAsDate return the time in UTC, therefore the amount
      // of days here must be bigger than one to avoid situations where the
      // new time and old time are in the same day.
      const today = dateInput.valueAsDate;
      const twoDaysAgo = new Date(today.getTime() - 2 * 24 * 60 * 60 * 1000);
      dateInput.focus();
      dateInput.valueAsDate = twoDaysAgo;
      setTimeElement.shadowRoot.querySelector('#doneButton').click();

      // The browser validates the change.
      await testBrowserProxy.whenCalled('doneClicked');
      webUIListenerCallback('validation-complete');

      // Verify the page sends a request to move time backward.
      const newTimeSeconds =
          await testBrowserProxy.whenCalled('setTimeInSeconds');
      const todaySeconds = today.getTime() / 1000;
      // Check that the current time is bigger than the new time, which
      // is supposed to be two days ago. The exact value isn't
      // important, checking it is difficult because it depends on the
      // current time, which is constantly updated, therefore we only
      // assert that one is bigger than the other.
      assertGT(todaySeconds, newTimeSeconds);

      // Verify the page didn't try to change the timezone.
      assertEquals(0, testBrowserProxy.getCallCount('setTimezone'));
    });

    test('TimezoneUpdate', () => {
      assertEquals(
          null, setTimeElement.shadowRoot.querySelector('#timezoneSelect'));
      webUIListenerCallback('system-timezone-changed', 'America/Los_Angeles');
      // No crash.
    });
  });
});