chromium/chrome/test/data/webui/chromeos/settings/internet_page/settings_traffic_counters_test.ts

// Copyright 2021 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://os-settings/lazy_load.js';

import {SettingsTrafficCountersElement} from 'chrome://os-settings/lazy_load.js';
import {MojoInterfaceProviderImpl} from 'chrome://resources/ash/common/network/mojo_interface_provider.js';
import {OncMojo} from 'chrome://resources/ash/common/network/onc_mojo.js';
import {TrafficCounter, TrafficCounterSource} from 'chrome://resources/mojo/chromeos/services/network_config/public/mojom/cros_network_config.mojom-webui.js';
import {ConnectionStateType, NetworkType} from 'chrome://resources/mojo/chromeos/services/network_config/public/mojom/network_types.mojom-webui.js';
import {Time} from 'chrome://resources/mojo/mojo/public/mojom/base/time.mojom-webui.js';
import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
import {assertEquals, assertTrue} from 'chrome://webui-test/chai_assert.js';
import {FakeNetworkConfig} from 'chrome://webui-test/chromeos/fake_network_config_mojom.js';
import {flushTasks} from 'chrome://webui-test/polymer_test_util.js';

suite('<settings-traffic-counters>', () => {
  /**
   * Fake last reset time. Corresponds to a time on September 10, 2021.
   */
  const FAKE_TIME_IN_MICROSECONDS: bigint = BigInt(13275778457938000);
  const FAKE_INITIAL_LAST_RESET_TIME: Time = {
    internalValue: FAKE_TIME_IN_MICROSECONDS,
  };
  const FAKE_INITIAL_FRIENDLY_DATE = 'September 10, 2021';
  const EXPECTED_INITIAL_DATA_USAGE_LABEL =
      'Data usage since September 10, 2021';
  const EXPECTED_INITIAL_DATA_USAGE_SUBLABEL = '1.80 KB';
  const EXPECTED_POST_RESET_FRIENDLY_DATE = 'September 12, 2021';
  const EXPECTED_POST_RESET_DATA_USAGE_LABEL =
      'Data usage since September 12, 2021';
  const EXPECTED_POST_RESET_DATA_USAGE_SUBLABEL = '0.00 B';

  let settingsTrafficCounters: SettingsTrafficCountersElement;
  let networkConfigRemote: FakeNetworkConfig;

  function generateTrafficCounters(
      rxBytes: bigint, txBytes: bigint): TrafficCounter[] {
    return [
      {
        source: TrafficCounterSource.kUnknown,
        rxBytes,
        txBytes,
      },
      {
        source: TrafficCounterSource.kChrome,
        rxBytes,
        txBytes,
      },
      {
        source: TrafficCounterSource.kUser,
        rxBytes,
        txBytes,
      },
      {
        source: TrafficCounterSource.kArc,
        rxBytes,
        txBytes,
      },
      {
        source: TrafficCounterSource.kCrosvm,
        rxBytes,
        txBytes,
      },
      {
        source: TrafficCounterSource.kPluginvm,
        rxBytes,
        txBytes,
      },
      {
        source: TrafficCounterSource.kUpdateEngine,
        rxBytes,
        txBytes,
      },
      {
        source: TrafficCounterSource.kVpn,
        rxBytes,
        txBytes,
      },
      {
        source: TrafficCounterSource.kSystem,
        rxBytes,
        txBytes,
      },
    ];
  }

  function getDataUsageLabel(): string {
    const dataUsageLabelDiv = settingsTrafficCounters.$.dataUsageLabel;
    return dataUsageLabelDiv.textContent!.trim();
  }

  function getDataUsageSubLabel(): string {
    const dataUsageSubLabelDiv = settingsTrafficCounters.$.dataUsageSubLabel;
    return dataUsageSubLabelDiv.textContent!.trim();
  }

  setup(() => {
    networkConfigRemote = new FakeNetworkConfig();
    MojoInterfaceProviderImpl.getInstance().setMojoServiceRemoteForTest(
        networkConfigRemote);

    settingsTrafficCounters =
        document.createElement('settings-traffic-counters');
    document.body.appendChild(settingsTrafficCounters);
    flush();

    // Remove default network.
    networkConfigRemote.setNetworkConnectionStateForTest(
        'eth0_guid', ConnectionStateType.kNotConnected);
    flush();
  });

  teardown(() => {
    settingsTrafficCounters.remove();
  });

  test('Missing friendly date info', async () => {
    // Set managed properties for a connected cellular network.
    const managedProperties = OncMojo.getDefaultManagedProperties(
        NetworkType.kCellular, 'cellular_guid', 'cellular');
    managedProperties.connectionState = ConnectionStateType.kConnected;
    managedProperties.connectable = true;

    const trafficCounterProps = OncMojo.createTrafficCounterProperties();
    trafficCounterProps.userSpecifiedResetDay = 31;
    managedProperties.trafficCounterProperties = trafficCounterProps;
    networkConfigRemote.setManagedPropertiesForTest(managedProperties);
    await flushTasks();

    // Set traffic counters.
    // A bigint primitive is created by appending n to the end of an integer
    // literal
    networkConfigRemote.setTrafficCountersForTest(
        'cellular_guid', generateTrafficCounters(100n, 100n));
    await flushTasks();

    settingsTrafficCounters.guid = 'cellular_guid';
    settingsTrafficCounters.load();
    await flushTasks();

    assertEquals(
        settingsTrafficCounters.i18n(
            'TrafficCountersDataUsageLastResetDateUnavailableLabel'),
        getDataUsageLabel());
    assertEquals(EXPECTED_INITIAL_DATA_USAGE_SUBLABEL, getDataUsageSubLabel());
  });

  test('Show traffic counter info', async () => {
    // Set managed properties for a connected cellular network.
    const managedProperties = OncMojo.getDefaultManagedProperties(
        NetworkType.kCellular, 'cellular_guid', 'cellular');
    managedProperties.connectionState = ConnectionStateType.kConnected;
    managedProperties.connectable = true;

    const trafficCounterProps = OncMojo.createTrafficCounterProperties();
    trafficCounterProps.lastResetTime = FAKE_INITIAL_LAST_RESET_TIME;
    trafficCounterProps.friendlyDate = FAKE_INITIAL_FRIENDLY_DATE;
    trafficCounterProps.userSpecifiedResetDay = 31;
    managedProperties.trafficCounterProperties = trafficCounterProps;
    networkConfigRemote.setManagedPropertiesForTest(managedProperties);
    await flushTasks();

    // Set traffic counters.
    // A bigint primitive is created by appending n to the end of an integer
    // literal
    networkConfigRemote.setTrafficCountersForTest(
        'cellular_guid', generateTrafficCounters(100n, 100n));
    await flushTasks();

    settingsTrafficCounters.guid = 'cellular_guid';
    settingsTrafficCounters.load();
    await flushTasks();

    assertEquals(EXPECTED_INITIAL_DATA_USAGE_LABEL, getDataUsageLabel());
    assertEquals(EXPECTED_INITIAL_DATA_USAGE_SUBLABEL, getDataUsageSubLabel());
    assertEquals(String(31), settingsTrafficCounters.$.resetDayList.value);

    // Simulate a reset by updating the last reset time for the cellular
    // network. The internal value represents two days after the initial
    // reset time.
    networkConfigRemote.setLastResetTimeForTest('cellular_guid', {
      internalValue: FAKE_INITIAL_LAST_RESET_TIME.internalValue +
          BigInt(2 * 24 * 60 * 60 * (1000 * 1000)),
    });
    networkConfigRemote.setFriendlyDateForTest(
        'cellular_guid', EXPECTED_POST_RESET_FRIENDLY_DATE);
    await flushTasks();

    // Reset the data usage.
    settingsTrafficCounters.$.resetDataUsageButton.click();
    await flushTasks();

    assertEquals(EXPECTED_POST_RESET_DATA_USAGE_LABEL, getDataUsageLabel());
    assertEquals(
        EXPECTED_POST_RESET_DATA_USAGE_SUBLABEL, getDataUsageSubLabel());
  });

  test('Reset date functionality', async () => {
    // Set managed properties for a connected cellular network.
    const managedProperties = OncMojo.getDefaultManagedProperties(
        NetworkType.kCellular, 'cellular_guid', 'cellular');
    managedProperties.connectionState = ConnectionStateType.kConnected;
    managedProperties.connectable = true;

    const trafficCounterProps = OncMojo.createTrafficCounterProperties();
    trafficCounterProps.userSpecifiedResetDay = 31;
    managedProperties.trafficCounterProperties = trafficCounterProps;
    networkConfigRemote.setManagedPropertiesForTest(managedProperties);
    await flushTasks();

    settingsTrafficCounters.guid = 'cellular_guid';
    await flushTasks();

    assertEquals('31', settingsTrafficCounters.$.resetDayList.value);

    // Simulate an auto reset day update.
    settingsTrafficCounters.$.resetDayList.value = '5';
    settingsTrafficCounters.$.resetDayList.dispatchEvent(
        new CustomEvent('change'));
    await flushTasks();

    await networkConfigRemote.whenCalled('setTrafficCountersResetDay');

    const properties = await networkConfigRemote.getManagedProperties(
        settingsTrafficCounters.guid);

    const trafficCounterPropsRet = properties.result.trafficCounterProperties;
    assertTrue(trafficCounterPropsRet !== undefined);
    assertEquals(5, trafficCounterPropsRet!.userSpecifiedResetDay);
  });
});