chromium/ash/system/bluetooth/bluetooth_device_list_item_battery_view_unittest.cc

// 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.

#include "ash/system/bluetooth/bluetooth_device_list_item_battery_view.h"

#include "ash/resources/vector_icons/vector_icons.h"
#include "ash/strings/grit/ash_strings.h"
#include "ash/test/ash_test_base.h"
#include "base/strings/string_number_conversions.h"
#include "chromeos/ash/services/bluetooth_config/public/mojom/cros_bluetooth_config.mojom.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/gfx/image/image_skia.h"
#include "ui/gfx/image/image_unittest_util.h"
#include "ui/views/controls/image_view.h"
#include "ui/views/controls/label.h"
#include "ui/views/widget/widget.h"

namespace ash {

class BluetoothDeviceListItemBatteryViewTest : public AshTestBase {
 public:
  void SetUp() override {
    AshTestBase::SetUp();

    widget_ =
        CreateTestWidget(views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET);
    bluetooth_device_list_battery_item_ =
        std::make_unique<BluetoothDeviceListItemBatteryView>();
    // Add the item to widget hierarchy to make sure `ui::ColorProvider` will
    // not be nullptr while getting colors.
    widget_->GetContentsView()->AddChildView(
        bluetooth_device_list_battery_item_.get());
  }

  void TearDown() override {
    bluetooth_device_list_battery_item_.reset();

    AshTestBase::TearDown();
  }

  // Updates the view with |battery_percentage|, checks that the label is
  // correct, and returns whether the icon has been updated.
  bool UpdateBatteryPercentageAndCheckIfUpdated(uint8_t battery_percentage) {
    gfx::Image image;

    if (!bluetooth_device_list_battery_item_->children().empty())
      image = gfx::Image(GetIcon()->GetImage());

    bluetooth_device_list_battery_item_->UpdateBatteryInfo(
        battery_percentage,
        IDS_ASH_STATUS_TRAY_BLUETOOTH_DEVICE_BATTERY_PERCENTAGE_ONLY_LABEL);

    EXPECT_EQ(
        l10n_util::GetStringFUTF16(
            IDS_ASH_STATUS_TRAY_BLUETOOTH_DEVICE_BATTERY_PERCENTAGE_ONLY_LABEL,
            base::NumberToString16(battery_percentage)),
        GetLabel()->GetText());

    return !gfx::test::AreImagesEqual(image, gfx::Image(GetIcon()->GetImage()));
  }

  BluetoothDeviceListItemBatteryView* bluetooth_device_list_battery_item() {
    return bluetooth_device_list_battery_item_.get();
  }

 private:
  views::ImageView* GetIcon() {
    EXPECT_EQ(2u, bluetooth_device_list_battery_item()->children().size());
    return static_cast<views::ImageView*>(
        bluetooth_device_list_battery_item()->children().at(0));
  }

  views::Label* GetLabel() {
    EXPECT_EQ(2u, bluetooth_device_list_battery_item()->children().size());
    return static_cast<views::Label*>(
        bluetooth_device_list_battery_item()->children().at(1));
  }

  std::unique_ptr<views::Widget> widget_;
  std::unique_ptr<BluetoothDeviceListItemBatteryView>
      bluetooth_device_list_battery_item_;
};

TEST_F(BluetoothDeviceListItemBatteryViewTest, CorrectlyUpdatesIconAndLabel) {
  EXPECT_EQ(0u, bluetooth_device_list_battery_item()->children().size());

  uint8_t battery_percentage = 0;
  EXPECT_TRUE(UpdateBatteryPercentageAndCheckIfUpdated(battery_percentage));

  // The label should be updated regardless of the change, but the icon should
  // only update if the percentage is different enough.
  battery_percentage = 3;
  EXPECT_FALSE(UpdateBatteryPercentageAndCheckIfUpdated(battery_percentage));

  battery_percentage = 20;
  EXPECT_TRUE(UpdateBatteryPercentageAndCheckIfUpdated(battery_percentage));

  const uint8_t percent_change_threshold = 20;

  // The icon should be updated if there are enough small changes.
  for (int i = 0; i < percent_change_threshold; ++i) {
    battery_percentage++;

    if (UpdateBatteryPercentageAndCheckIfUpdated(battery_percentage))
      break;

    // Check that the loop isn't ending.
    EXPECT_NE(percent_change_threshold - 1, i);
  }

  // The icon should be updated when going to/from 25% since the color should be
  // updated to alert the user.
  battery_percentage = 24;
  UpdateBatteryPercentageAndCheckIfUpdated(battery_percentage);
  battery_percentage = 25;
  EXPECT_TRUE(UpdateBatteryPercentageAndCheckIfUpdated(battery_percentage));
  battery_percentage = 24;
  EXPECT_TRUE(UpdateBatteryPercentageAndCheckIfUpdated(battery_percentage));

  // The icon should be updated when going to/from 100% since the icon shown
  // will be distinct from any other percentage.
  battery_percentage = 99;
  UpdateBatteryPercentageAndCheckIfUpdated(battery_percentage);
  battery_percentage = 100;
  EXPECT_TRUE(UpdateBatteryPercentageAndCheckIfUpdated(battery_percentage));
  battery_percentage = 99;
  EXPECT_TRUE(UpdateBatteryPercentageAndCheckIfUpdated(battery_percentage));
}

}  // namespace ash