123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325 |
- // Copyright 2021 The Chromium Authors. All rights reserved.
- // 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_controller_impl.h"
- #include <memory>
- #include <string>
- #include <vector>
- #include "ash/constants/ash_features.h"
- #include "ash/strings/grit/ash_strings.h"
- #include "ash/system/bluetooth/bluetooth_detailed_view.h"
- #include "ash/system/bluetooth/bluetooth_device_list_item_view.h"
- #include "ash/system/bluetooth/fake_bluetooth_detailed_view.h"
- #include "ash/system/tray/tri_view.h"
- #include "ash/test/ash_test_base.h"
- #include "base/test/scoped_feature_list.h"
- #include "chromeos/services/bluetooth_config/public/mojom/cros_bluetooth_config.mojom.h"
- #include "ui/base/l10n/l10n_util.h"
- #include "ui/views/controls/label.h"
- #include "ui/views/controls/separator.h"
- namespace ash {
- namespace {
- using chromeos::bluetooth_config::mojom::BluetoothDeviceProperties;
- using chromeos::bluetooth_config::mojom::DeviceConnectionState;
- using chromeos::bluetooth_config::mojom::PairedBluetoothDeviceProperties;
- using chromeos::bluetooth_config::mojom::PairedBluetoothDevicePropertiesPtr;
- const char kDeviceId1[] = "/device/id/1";
- const char kDeviceId2[] = "/device/id/2";
- const char kDeviceNickname[] = "mau5";
- } // namespace
- class BluetoothDeviceListControllerTest : public AshTestBase {
- public:
- void SetUp() override {
- AshTestBase::SetUp();
- feature_list_.InitAndEnableFeature(features::kBluetoothRevamp);
- fake_bluetooth_detailed_view_ =
- std::make_unique<FakeBluetoothDetailedView>(/*delegate=*/nullptr);
- bluetooth_device_list_controller_impl_ =
- std::make_unique<BluetoothDeviceListControllerImpl>(
- fake_bluetooth_detailed_view_.get());
- }
- void TearDown() override { AshTestBase::TearDown(); }
- const TriView* FindConnectedSubHeader() {
- return FindSubHeaderWithText(l10n_util::GetStringUTF16(
- IDS_ASH_STATUS_TRAY_BLUETOOTH_CURRENTLY_CONNECTED_DEVICES));
- }
- const TriView* FindPreviouslyConnectedSubHeader() {
- return FindSubHeaderWithText(l10n_util::GetStringUTF16(
- IDS_ASH_STATUS_TRAY_BLUETOOTH_PREVIOUSLY_CONNECTED_DEVICES));
- }
- const TriView* FindNoDeviceConnectedSubHeader() {
- return FindSubHeaderWithText(l10n_util::GetStringUTF16(
- IDS_ASH_STATUS_TRAY_BLUETOOTH_NO_DEVICE_CONNECTED));
- }
- const views::Separator* FindSeparator() {
- for (const auto* view : device_list()->children()) {
- if (!std::strcmp("Separator", view->GetClassName()))
- return static_cast<const views::Separator*>(view);
- }
- return nullptr;
- }
- PairedBluetoothDevicePropertiesPtr BuildDeviceProperties(
- const std::string& id) {
- PairedBluetoothDevicePropertiesPtr device_properties =
- PairedBluetoothDeviceProperties::New();
- device_properties->device_properties = BluetoothDeviceProperties::New();
- device_properties->device_properties->id = id;
- return device_properties;
- }
- const std::u16string& GetSubHeaderText(const TriView* sub_header) {
- EXPECT_TRUE(sub_header);
- EXPECT_EQ(1u, sub_header->children().at(1)->children().size());
- return static_cast<views::Label*>(
- sub_header->children().at(1)->children().at(0))
- ->GetText();
- }
- const char* GetDeviceId(const BluetoothDeviceListItemView* device_item_view) {
- return device_item_view->device_properties()->device_properties->id.c_str();
- }
- const BluetoothDeviceListItemView* GetFirstDeviceView() {
- EXPECT_LT(1u, device_list()->children().size());
- return static_cast<BluetoothDeviceListItemView*>(
- device_list()->children().at(1));
- }
- void CheckDeviceListOrdering(size_t connected_device_count,
- size_t previously_connected_device_count) {
- if (connected_device_count && previously_connected_device_count) {
- const TriView* connected_sub_header = FindConnectedSubHeader();
- const TriView* previously_connected_sub_header =
- FindPreviouslyConnectedSubHeader();
- const views::Separator* device_list_separator = FindSeparator();
- EXPECT_TRUE(connected_sub_header);
- EXPECT_TRUE(previously_connected_sub_header);
- EXPECT_TRUE(device_list_separator);
- const size_t connected_index =
- device_list()->GetIndexOf(connected_sub_header).value();
- const size_t previously_connected_index =
- device_list()->GetIndexOf(previously_connected_sub_header).value();
- const size_t separator_index =
- device_list()->GetIndexOf(device_list_separator).value();
- EXPECT_EQ(0u, connected_index);
- EXPECT_EQ(connected_device_count + 1, separator_index);
- EXPECT_EQ(separator_index + 1, previously_connected_index);
- return;
- }
- if (connected_device_count) {
- const TriView* connected_sub_header = FindConnectedSubHeader();
- EXPECT_TRUE(connected_sub_header);
- EXPECT_EQ(0u, device_list()->GetIndexOf(connected_sub_header));
- EXPECT_EQ(connected_device_count + 1, device_list()->children().size());
- return;
- }
- if (previously_connected_device_count) {
- const TriView* previously_connected_sub_header =
- FindPreviouslyConnectedSubHeader();
- EXPECT_TRUE(previously_connected_sub_header);
- EXPECT_EQ(0u, device_list()->GetIndexOf(previously_connected_sub_header));
- EXPECT_EQ(previously_connected_device_count + 1,
- device_list()->children().size());
- return;
- }
- const TriView* no_device_connected_sub_header =
- FindNoDeviceConnectedSubHeader();
- EXPECT_TRUE(no_device_connected_sub_header);
- EXPECT_EQ(0u, device_list()->GetIndexOf(no_device_connected_sub_header));
- EXPECT_EQ(1u, device_list()->children().size());
- }
- void CheckNotifyDeviceListChangedCount(size_t call_count) {
- EXPECT_EQ(call_count, fake_bluetooth_detailed_view()
- ->notify_device_list_changed_call_count());
- }
- views::View* device_list() {
- return static_cast<BluetoothDetailedView*>(
- fake_bluetooth_detailed_view_.get())
- ->device_list();
- }
- BluetoothDeviceListController* bluetooth_device_list_controller() {
- return bluetooth_device_list_controller_impl_.get();
- }
- FakeBluetoothDetailedView* fake_bluetooth_detailed_view() {
- return fake_bluetooth_detailed_view_.get();
- }
- protected:
- const std::vector<PairedBluetoothDevicePropertiesPtr> empty_list_;
- private:
- const TriView* FindSubHeaderWithText(const std::u16string text) {
- for (const auto* view : device_list()->children()) {
- if (std::strcmp("TriView", view->GetClassName()))
- continue;
- const TriView* sub_header = static_cast<const TriView*>(view);
- if (GetSubHeaderText(sub_header) == text)
- return sub_header;
- }
- return nullptr;
- }
- base::test::ScopedFeatureList feature_list_;
- std::unique_ptr<FakeBluetoothDetailedView> fake_bluetooth_detailed_view_;
- std::unique_ptr<BluetoothDeviceListControllerImpl>
- bluetooth_device_list_controller_impl_;
- };
- TEST_F(BluetoothDeviceListControllerTest,
- HasCorrectSubHeaderWithNoPairedDevices) {
- CheckNotifyDeviceListChangedCount(/*call_count=*/0u);
- bluetooth_device_list_controller()->UpdateBluetoothEnabledState(true);
- bluetooth_device_list_controller()->UpdateDeviceList(
- /*connected=*/empty_list_,
- /*previously_connected=*/empty_list_);
- CheckNotifyDeviceListChangedCount(/*call_count=*/1u);
- EXPECT_EQ(1u, device_list()->children().size());
- const TriView* no_device_connected_sub_header =
- FindNoDeviceConnectedSubHeader();
- EXPECT_TRUE(no_device_connected_sub_header);
- }
- TEST_F(BluetoothDeviceListControllerTest,
- HasCorrectDeviceListOrderWithPairedDevices) {
- CheckNotifyDeviceListChangedCount(/*call_count=*/0u);
- bluetooth_device_list_controller()->UpdateBluetoothEnabledState(true);
- std::vector<PairedBluetoothDevicePropertiesPtr> connected_list;
- connected_list.push_back(BuildDeviceProperties(kDeviceId1));
- bluetooth_device_list_controller()->UpdateDeviceList(
- /*connected=*/connected_list,
- /*previously_connected=*/empty_list_);
- CheckNotifyDeviceListChangedCount(/*call_count=*/1u);
- const TriView* connected_devices_sub_header = FindConnectedSubHeader();
- EXPECT_EQ(2u, device_list()->children().size());
- EXPECT_STREQ(kDeviceId1, GetDeviceId(GetFirstDeviceView()));
- EXPECT_TRUE(connected_devices_sub_header);
- CheckDeviceListOrdering(
- /*connected_device_count=*/connected_list.size(),
- /*previously_connected_device_count=*/empty_list_.size());
- std::vector<PairedBluetoothDevicePropertiesPtr> previously_connected_list;
- previously_connected_list.push_back(BuildDeviceProperties(kDeviceId2));
- bluetooth_device_list_controller()->UpdateDeviceList(
- /*connected=*/empty_list_,
- /*previously_connected=*/previously_connected_list);
- CheckNotifyDeviceListChangedCount(/*call_count=*/2u);
- const TriView* previously_connected_devices_sub_header =
- FindPreviouslyConnectedSubHeader();
- EXPECT_EQ(2u, device_list()->children().size());
- EXPECT_STREQ(kDeviceId2, GetDeviceId(GetFirstDeviceView()));
- EXPECT_TRUE(previously_connected_devices_sub_header);
- CheckDeviceListOrdering(
- /*connected_device_count=*/0,
- /*previously_connected_device_count=*/previously_connected_list.size());
- // "Update" the device list multiple times to be sure that no children are
- // duplicated and every child is re-ordered correctly.
- for (int i = 0; i < 2; i++) {
- bluetooth_device_list_controller()->UpdateDeviceList(
- /*connected=*/connected_list,
- /*previously_connected=*/previously_connected_list);
- }
- CheckNotifyDeviceListChangedCount(/*call_count=*/4u);
- EXPECT_EQ(5u, device_list()->children().size());
- CheckDeviceListOrdering(
- /*connected_device_count=*/connected_list.size(),
- /*previously_connected_device_count=*/previously_connected_list.size());
- }
- TEST_F(BluetoothDeviceListControllerTest, ExistingDeviceViewsAreUpdated) {
- CheckNotifyDeviceListChangedCount(/*call_count=*/0u);
- bluetooth_device_list_controller()->UpdateBluetoothEnabledState(true);
- std::vector<PairedBluetoothDevicePropertiesPtr> connected_list;
- connected_list.push_back(BuildDeviceProperties(kDeviceId1));
- bluetooth_device_list_controller()->UpdateDeviceList(
- /*connected=*/connected_list,
- /*previously_connected=*/empty_list_);
- CheckNotifyDeviceListChangedCount(/*call_count=*/1u);
- EXPECT_EQ(2u, device_list()->children().size());
- const BluetoothDeviceListItemView* first_item = GetFirstDeviceView();
- EXPECT_FALSE(first_item->device_properties()->nickname.has_value());
- connected_list.at(0)->nickname = kDeviceNickname;
- bluetooth_device_list_controller()->UpdateDeviceList(
- /*connected=*/connected_list,
- /*previously_connected=*/empty_list_);
- CheckNotifyDeviceListChangedCount(/*call_count=*/2u);
- EXPECT_EQ(2u, device_list()->children().size());
- EXPECT_EQ(1u, device_list()->GetIndexOf(first_item));
- EXPECT_TRUE(first_item->device_properties()->nickname.has_value());
- EXPECT_STREQ(kDeviceNickname,
- first_item->device_properties()->nickname.value().c_str());
- }
- TEST_F(BluetoothDeviceListControllerTest,
- DeviceListIsClearedWhenBluetoothBecomesDisabled) {
- CheckNotifyDeviceListChangedCount(/*call_count=*/0u);
- bluetooth_device_list_controller()->UpdateBluetoothEnabledState(true);
- std::vector<PairedBluetoothDevicePropertiesPtr> connected_list;
- connected_list.push_back(BuildDeviceProperties(kDeviceId1));
- bluetooth_device_list_controller()->UpdateDeviceList(
- /*connected=*/connected_list,
- /*previously_connected=*/empty_list_);
- CheckNotifyDeviceListChangedCount(/*call_count=*/1u);
- EXPECT_EQ(2u, device_list()->children().size());
- bluetooth_device_list_controller()->UpdateBluetoothEnabledState(false);
- EXPECT_EQ(0u, device_list()->children().size());
- }
- } // namespace ash
|