1 // Copyright 2020 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "ash/system/phonehub/task_continuation_view.h"
6 
7 #include "ash/public/cpp/test/test_new_window_delegate.h"
8 #include "ash/system/phonehub/continue_browsing_chip.h"
9 #include "ash/test/ash_test_base.h"
10 #include "base/test/scoped_feature_list.h"
11 #include "chromeos/components/phonehub/fake_user_action_recorder.h"
12 #include "chromeos/components/phonehub/mutable_phone_model.h"
13 #include "chromeos/components/phonehub/phone_model_test_util.h"
14 #include "chromeos/constants/chromeos_features.h"
15 #include "testing/gmock/include/gmock/gmock.h"
16 #include "ui/views/test/button_test_api.h"
17 
18 namespace ash {
19 
20 using BrowserTabsModel = chromeos::phonehub::BrowserTabsModel;
21 
22 namespace {
23 
24 class MockNewWindowDelegate : public testing::NiceMock<TestNewWindowDelegate> {
25  public:
26   // TestNewWindowDelegate:
27   MOCK_METHOD(void,
28               NewTabWithUrl,
29               (const GURL& url, bool from_user_interaction),
30               (override));
31 };
32 
33 class DummyEvent : public ui::Event {
34  public:
DummyEvent()35   DummyEvent() : Event(ui::ET_UNKNOWN, base::TimeTicks(), 0) {}
36 };
37 
38 }  // namespace
39 
40 class TaskContinuationViewTest : public AshTestBase {
41  public:
42   TaskContinuationViewTest() = default;
43   ~TaskContinuationViewTest() override = default;
44 
45   // AshTestBase:
SetUp()46   void SetUp() override {
47     feature_list_.InitAndEnableFeature(chromeos::features::kPhoneHub);
48     AshTestBase::SetUp();
49 
50     task_continuation_view_ = std::make_unique<TaskContinuationView>(
51         &phone_model_, &fake_user_action_recorder_);
52   }
53 
TearDown()54   void TearDown() override {
55     task_continuation_view_.reset();
56     AshTestBase::TearDown();
57   }
58 
59  protected:
task_view()60   TaskContinuationView* task_view() { return task_continuation_view_.get(); }
phone_model()61   chromeos::phonehub::MutablePhoneModel* phone_model() { return &phone_model_; }
new_window_delegate()62   MockNewWindowDelegate& new_window_delegate() { return new_window_delegate_; }
63 
64  private:
65   std::unique_ptr<TaskContinuationView> task_continuation_view_;
66   chromeos::phonehub::FakeUserActionRecorder fake_user_action_recorder_;
67   chromeos::phonehub::MutablePhoneModel phone_model_;
68   base::test::ScopedFeatureList feature_list_;
69   MockNewWindowDelegate new_window_delegate_;
70 };
71 
TEST_F(TaskContinuationViewTest,TaskViewVisibility)72 TEST_F(TaskContinuationViewTest, TaskViewVisibility) {
73   phone_model()->SetBrowserTabsModel(
74       BrowserTabsModel(false /* is_tab_sync_enabled */));
75   // The view should not be shown when tab sync is not enabled.
76   EXPECT_FALSE(task_view()->GetVisible());
77 
78   phone_model()->SetBrowserTabsModel(
79       BrowserTabsModel(true /* is_tab_sync_enabled */));
80   // The view should not be shown when tab sync is enabled but no browser tabs
81   // open.
82   EXPECT_FALSE(task_view()->GetVisible());
83 
84   BrowserTabsModel::BrowserTabMetadata metadata =
85       chromeos::phonehub::CreateFakeBrowserTabMetadata();
86 
87   std::vector<BrowserTabsModel::BrowserTabMetadata> tabs = {metadata};
88 
89   phone_model()->SetBrowserTabsModel(BrowserTabsModel(true, tabs));
90   // The view should be shown when there is one browser tab.
91   EXPECT_TRUE(task_view()->GetVisible());
92 
93   tabs.push_back(metadata);
94   phone_model()->SetBrowserTabsModel(BrowserTabsModel(true, tabs));
95   // The view should be shown when there are two or more browser tabs.
96   EXPECT_TRUE(task_view()->GetVisible());
97 }
98 
TEST_F(TaskContinuationViewTest,TaskChipsView)99 TEST_F(TaskContinuationViewTest, TaskChipsView) {
100   BrowserTabsModel::BrowserTabMetadata metadata =
101       chromeos::phonehub::CreateFakeBrowserTabMetadata();
102 
103   std::vector<BrowserTabsModel::BrowserTabMetadata> tabs = {metadata};
104 
105   phone_model()->SetBrowserTabsModel(BrowserTabsModel(true, tabs));
106   // The chips view should contains 1 tab.
107   size_t expected_tabs = 1;
108   EXPECT_EQ(expected_tabs, task_view()->chips_view_->children().size());
109 
110   tabs.push_back(metadata);
111   phone_model()->SetBrowserTabsModel(BrowserTabsModel(true, tabs));
112   // The chips view should contains 2 tab.
113   expected_tabs = 2;
114   EXPECT_EQ(expected_tabs, task_view()->chips_view_->children().size());
115 
116   for (auto* child : task_view()->chips_view_->children()) {
117     ContinueBrowsingChip* chip = static_cast<ContinueBrowsingChip*>(child);
118     // NewTabWithUrl is expected to call after button pressed simulation.
119     EXPECT_CALL(new_window_delegate(), NewTabWithUrl)
120         .WillOnce([](const GURL& url, bool from_user_interaction) {
121           EXPECT_EQ(GURL("https://www.example.com/tab1"), url);
122           EXPECT_TRUE(from_user_interaction);
123         });
124     // Simulate clicking button using dummy event.
125     views::test::ButtonTestApi(chip).NotifyClick(DummyEvent());
126   }
127 }
128 
129 }  // namespace ash
130