| // Copyright 2017 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/tray_action/tray_action.h" |
| |
| #include <memory> |
| #include <vector> |
| |
| #include "ash/shell.h" |
| #include "ash/test/ash_test_base.h" |
| #include "ash/tray_action/test_tray_action_client.h" |
| #include "ash/tray_action/tray_action_observer.h" |
| #include "base/memory/raw_ptr.h" |
| #include "base/run_loop.h" |
| |
| using ash::mojom::TrayActionState; |
| |
| namespace ash { |
| |
| namespace { |
| |
| class ScopedTestStateObserver : public TrayActionObserver { |
| public: |
| explicit ScopedTestStateObserver(TrayAction* tray_action) |
| : tray_action_(tray_action) { |
| tray_action_->AddObserver(this); |
| } |
| |
| ScopedTestStateObserver(const ScopedTestStateObserver&) = delete; |
| ScopedTestStateObserver& operator=(const ScopedTestStateObserver&) = delete; |
| |
| ~ScopedTestStateObserver() override { tray_action_->RemoveObserver(this); } |
| |
| // TrayActionObserver: |
| void OnLockScreenNoteStateChanged(TrayActionState state) override { |
| observed_states_.push_back(state); |
| } |
| |
| const std::vector<TrayActionState>& observed_states() const { |
| return observed_states_; |
| } |
| |
| void ClearObservedStates() { observed_states_.clear(); } |
| |
| private: |
| raw_ptr<TrayAction> tray_action_; |
| |
| std::vector<TrayActionState> observed_states_; |
| }; |
| |
| using TrayActionTest = AshTestBase; |
| |
| } // namespace |
| |
| TEST_F(TrayActionTest, NoTrayActionClient) { |
| TrayAction* tray_action = Shell::Get()->tray_action(); |
| ScopedTestStateObserver observer(tray_action); |
| |
| EXPECT_EQ(TrayActionState::kNotAvailable, |
| tray_action->GetLockScreenNoteState()); |
| |
| tray_action->UpdateLockScreenNoteState(TrayActionState::kAvailable); |
| |
| // The effective state should be |kNotAvailable| as long as an action handler |
| // is not set. |
| EXPECT_EQ(TrayActionState::kNotAvailable, |
| tray_action->GetLockScreenNoteState()); |
| EXPECT_EQ(0u, observer.observed_states().size()); |
| |
| std::unique_ptr<TestTrayActionClient> action_client = |
| std::make_unique<TestTrayActionClient>(); |
| tray_action->SetClient(action_client->CreateRemoteAndBind(), |
| TrayActionState::kLaunching); |
| |
| EXPECT_EQ(TrayActionState::kLaunching, tray_action->GetLockScreenNoteState()); |
| ASSERT_EQ(1u, observer.observed_states().size()); |
| EXPECT_EQ(TrayActionState::kLaunching, observer.observed_states()[0]); |
| observer.ClearObservedStates(); |
| |
| action_client.reset(); |
| tray_action->FlushMojoForTesting(); |
| |
| EXPECT_EQ(TrayActionState::kNotAvailable, |
| tray_action->GetLockScreenNoteState()); |
| EXPECT_EQ(1u, observer.observed_states().size()); |
| EXPECT_EQ(TrayActionState::kNotAvailable, observer.observed_states()[0]); |
| } |
| |
| TEST_F(TrayActionTest, SettingInitialState) { |
| TrayAction* tray_action = Shell::Get()->tray_action(); |
| |
| ScopedTestStateObserver observer(tray_action); |
| TestTrayActionClient action_client; |
| tray_action->SetClient(action_client.CreateRemoteAndBind(), |
| TrayActionState::kAvailable); |
| |
| EXPECT_EQ(TrayActionState::kAvailable, tray_action->GetLockScreenNoteState()); |
| ASSERT_EQ(1u, observer.observed_states().size()); |
| EXPECT_EQ(TrayActionState::kAvailable, observer.observed_states()[0]); |
| } |
| |
| TEST_F(TrayActionTest, StateChangeNotificationOnConnectionLoss) { |
| TrayAction* tray_action = Shell::Get()->tray_action(); |
| |
| ScopedTestStateObserver observer(tray_action); |
| std::unique_ptr<TestTrayActionClient> action_client( |
| new TestTrayActionClient()); |
| tray_action->SetClient(action_client->CreateRemoteAndBind(), |
| TrayActionState::kAvailable); |
| |
| EXPECT_EQ(TrayActionState::kAvailable, tray_action->GetLockScreenNoteState()); |
| ASSERT_EQ(1u, observer.observed_states().size()); |
| EXPECT_EQ(TrayActionState::kAvailable, observer.observed_states()[0]); |
| observer.ClearObservedStates(); |
| |
| action_client.reset(); |
| tray_action->FlushMojoForTesting(); |
| |
| EXPECT_EQ(TrayActionState::kNotAvailable, |
| tray_action->GetLockScreenNoteState()); |
| ASSERT_EQ(1u, observer.observed_states().size()); |
| EXPECT_EQ(TrayActionState::kNotAvailable, observer.observed_states()[0]); |
| } |
| |
| TEST_F(TrayActionTest, NormalStateProgression) { |
| TrayAction* tray_action = Shell::Get()->tray_action(); |
| |
| ScopedTestStateObserver observer(tray_action); |
| TestTrayActionClient action_client; |
| tray_action->SetClient(action_client.CreateRemoteAndBind(), |
| TrayActionState::kNotAvailable); |
| |
| tray_action->UpdateLockScreenNoteState(TrayActionState::kAvailable); |
| EXPECT_EQ(TrayActionState::kAvailable, tray_action->GetLockScreenNoteState()); |
| EXPECT_FALSE(tray_action->IsLockScreenNoteActive()); |
| ASSERT_EQ(1u, observer.observed_states().size()); |
| EXPECT_EQ(TrayActionState::kAvailable, observer.observed_states()[0]); |
| observer.ClearObservedStates(); |
| |
| tray_action->UpdateLockScreenNoteState(TrayActionState::kLaunching); |
| EXPECT_EQ(TrayActionState::kLaunching, tray_action->GetLockScreenNoteState()); |
| EXPECT_FALSE(tray_action->IsLockScreenNoteActive()); |
| ASSERT_EQ(1u, observer.observed_states().size()); |
| EXPECT_EQ(TrayActionState::kLaunching, observer.observed_states()[0]); |
| observer.ClearObservedStates(); |
| |
| tray_action->UpdateLockScreenNoteState(TrayActionState::kActive); |
| EXPECT_EQ(TrayActionState::kActive, tray_action->GetLockScreenNoteState()); |
| EXPECT_TRUE(tray_action->IsLockScreenNoteActive()); |
| ASSERT_EQ(1u, observer.observed_states().size()); |
| EXPECT_EQ(TrayActionState::kActive, observer.observed_states()[0]); |
| observer.ClearObservedStates(); |
| |
| tray_action->UpdateLockScreenNoteState(TrayActionState::kNotAvailable); |
| EXPECT_EQ(TrayActionState::kNotAvailable, |
| tray_action->GetLockScreenNoteState()); |
| EXPECT_FALSE(tray_action->IsLockScreenNoteActive()); |
| ASSERT_EQ(1u, observer.observed_states().size()); |
| EXPECT_EQ(TrayActionState::kNotAvailable, observer.observed_states()[0]); |
| } |
| |
| TEST_F(TrayActionTest, ObserversNotNotifiedOnDuplicateState) { |
| TrayAction* tray_action = Shell::Get()->tray_action(); |
| |
| ScopedTestStateObserver observer(tray_action); |
| TestTrayActionClient action_client; |
| tray_action->SetClient(action_client.CreateRemoteAndBind(), |
| TrayActionState::kNotAvailable); |
| |
| tray_action->UpdateLockScreenNoteState(TrayActionState::kAvailable); |
| EXPECT_EQ(TrayActionState::kAvailable, tray_action->GetLockScreenNoteState()); |
| ASSERT_EQ(1u, observer.observed_states().size()); |
| EXPECT_EQ(TrayActionState::kAvailable, observer.observed_states()[0]); |
| observer.ClearObservedStates(); |
| |
| tray_action->UpdateLockScreenNoteState(TrayActionState::kAvailable); |
| EXPECT_EQ(TrayActionState::kAvailable, tray_action->GetLockScreenNoteState()); |
| ASSERT_EQ(0u, observer.observed_states().size()); |
| } |
| |
| TEST_F(TrayActionTest, RequestAction) { |
| TrayAction* tray_action = Shell::Get()->tray_action(); |
| |
| TestTrayActionClient action_client; |
| tray_action->SetClient(action_client.CreateRemoteAndBind(), |
| TrayActionState::kNotAvailable); |
| |
| EXPECT_TRUE(action_client.note_origins().empty()); |
| tray_action->RequestNewLockScreenNote( |
| mojom::LockScreenNoteOrigin::kLockScreenButtonTap); |
| tray_action->FlushMojoForTesting(); |
| EXPECT_TRUE(action_client.note_origins().empty()); |
| |
| tray_action->UpdateLockScreenNoteState(TrayActionState::kAvailable); |
| tray_action->RequestNewLockScreenNote( |
| mojom::LockScreenNoteOrigin::kTrayAction); |
| tray_action->FlushMojoForTesting(); |
| EXPECT_EQ(std::vector<mojom::LockScreenNoteOrigin>( |
| {mojom::LockScreenNoteOrigin::kTrayAction}), |
| action_client.note_origins()); |
| } |
| |
| // Tests that there is no crash if handler is not set. |
| TEST_F(TrayActionTest, RequestActionWithNoHandler) { |
| TrayAction* tray_action = Shell::Get()->tray_action(); |
| tray_action->RequestNewLockScreenNote( |
| mojom::LockScreenNoteOrigin::kLockScreenButtonTap); |
| tray_action->FlushMojoForTesting(); |
| } |
| |
| TEST_F(TrayActionTest, CloseLockScreenNote) { |
| TrayAction* tray_action = Shell::Get()->tray_action(); |
| |
| TestTrayActionClient action_client; |
| tray_action->SetClient(action_client.CreateRemoteAndBind(), |
| TrayActionState::kNotAvailable); |
| |
| tray_action->UpdateLockScreenNoteState(TrayActionState::kActive); |
| EXPECT_TRUE(action_client.close_note_reasons().empty()); |
| tray_action->CloseLockScreenNote( |
| mojom::CloseLockScreenNoteReason::kUnlockButtonPressed); |
| tray_action->FlushMojoForTesting(); |
| EXPECT_EQ(std::vector<mojom::CloseLockScreenNoteReason>( |
| {mojom::CloseLockScreenNoteReason::kUnlockButtonPressed}), |
| action_client.close_note_reasons()); |
| } |
| |
| // Tests that there is no crash if handler is not set. |
| TEST_F(TrayActionTest, CloseLockScreenNoteWithNoHandler) { |
| TrayAction* tray_action = Shell::Get()->tray_action(); |
| tray_action->CloseLockScreenNote( |
| mojom::CloseLockScreenNoteReason::kUnlockButtonPressed); |
| tray_action->FlushMojoForTesting(); |
| } |
| |
| } // namespace ash |