progress_indicator_unittest.cc 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. // Copyright 2021 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. #include "ash/system/progress_indicator/progress_indicator.h"
  5. #include "ash/system/progress_indicator/progress_indicator_animation_registry.h"
  6. #include "ash/test/ash_test_base.h"
  7. #include "base/test/bind.h"
  8. #include "base/test/repeating_test_future.h"
  9. namespace ash {
  10. namespace {
  11. // TestProgressIndicator -------------------------------------------------------
  12. class TestProgressIndicator : public ProgressIndicator {
  13. public:
  14. TestProgressIndicator()
  15. : ProgressIndicator(/*animation_registry=*/nullptr,
  16. /*animation_key=*/this) {}
  17. void SetProgress(const absl::optional<float>& progress) {
  18. progress_ = progress;
  19. static_cast<ui::LayerDelegate*>(this)->UpdateVisualState();
  20. }
  21. private:
  22. // ProgressIndicator:
  23. absl::optional<float> CalculateProgress() const override { return progress_; }
  24. absl::optional<float> progress_;
  25. };
  26. } // namespace
  27. // ProgressIndicatorTest -------------------------------------------------------
  28. using ProgressIndicatorTest = AshTestBase;
  29. // Verifies that `ProgressIndicator::CreateDefaultInstance()` works as intended.
  30. // It should delegate progress calculation to a constructor provided callback
  31. // and manage progress animations as needed.
  32. TEST_F(ProgressIndicatorTest, CreateDefaultInstance) {
  33. absl::optional<float> progress;
  34. // Create a default instance of `ProgressIndicator` that paints `progress`
  35. // whenever visual state is updated.
  36. auto progress_indicator = ProgressIndicator::CreateDefaultInstance(
  37. base::BindLambdaForTesting([&]() { return progress; }));
  38. // Cache `layer_delegate` associate with `progress_indicator` to manually
  39. // trigger update of visual state.
  40. auto* layer_delegate =
  41. static_cast<ui::LayerDelegate*>(progress_indicator.get());
  42. // Cache animation `key` and `registry` associated with `progress_indicator`.
  43. auto* key = progress_indicator.get();
  44. auto* registry = progress_indicator->animation_registry();
  45. // Verify initial progress and animation states.
  46. EXPECT_EQ(progress_indicator->progress(), progress);
  47. EXPECT_FALSE(registry->GetProgressIconAnimationForKey(key));
  48. EXPECT_FALSE(registry->GetProgressRingAnimationForKey(key));
  49. // Update `progress` to 0%. Verify progress and animation states.
  50. progress = 0.f;
  51. layer_delegate->UpdateVisualState();
  52. EXPECT_EQ(progress_indicator->progress(), progress);
  53. ASSERT_TRUE(registry->GetProgressIconAnimationForKey(key));
  54. EXPECT_TRUE(registry->GetProgressIconAnimationForKey(key)->HasAnimated());
  55. EXPECT_FALSE(registry->GetProgressRingAnimationForKey(key));
  56. // Update `progress` to 50%. Verify progress and animation states.
  57. progress = 0.5f;
  58. layer_delegate->UpdateVisualState();
  59. EXPECT_EQ(progress_indicator->progress(), progress);
  60. ASSERT_TRUE(registry->GetProgressIconAnimationForKey(key));
  61. EXPECT_TRUE(registry->GetProgressIconAnimationForKey(key)->HasAnimated());
  62. EXPECT_FALSE(registry->GetProgressRingAnimationForKey(key));
  63. // Update `progress` to indeterminate. Verify progress and animation states.
  64. progress = absl::nullopt;
  65. layer_delegate->UpdateVisualState();
  66. EXPECT_EQ(progress_indicator->progress(), progress);
  67. ASSERT_TRUE(registry->GetProgressIconAnimationForKey(key));
  68. EXPECT_TRUE(registry->GetProgressIconAnimationForKey(key)->HasAnimated());
  69. ASSERT_TRUE(registry->GetProgressRingAnimationForKey(key));
  70. EXPECT_EQ(registry->GetProgressRingAnimationForKey(key)->type(),
  71. ProgressRingAnimation::Type::kIndeterminate);
  72. // Update `progress` to 75%. Verify progress and animation states.
  73. progress = 0.75f;
  74. layer_delegate->UpdateVisualState();
  75. EXPECT_EQ(progress_indicator->progress(), progress);
  76. ASSERT_TRUE(registry->GetProgressIconAnimationForKey(key));
  77. EXPECT_TRUE(registry->GetProgressIconAnimationForKey(key)->HasAnimated());
  78. EXPECT_FALSE(registry->GetProgressRingAnimationForKey(key));
  79. // Update `progress` to 100%. Verify progress an animation states.
  80. progress = ProgressIndicator::kProgressComplete;
  81. layer_delegate->UpdateVisualState();
  82. EXPECT_EQ(progress_indicator->progress(), progress);
  83. EXPECT_FALSE(registry->GetProgressIconAnimationForKey(key));
  84. ASSERT_TRUE(registry->GetProgressRingAnimationForKey(key));
  85. EXPECT_EQ(registry->GetProgressRingAnimationForKey(key)->type(),
  86. ProgressRingAnimation::Type::kPulse);
  87. // The pulse animation that runs on progress completion should be removed
  88. // automatically on animation completion.
  89. base::test::RepeatingTestFuture<ProgressRingAnimation*> future;
  90. auto subscription = registry->AddProgressRingAnimationChangedCallbackForKey(
  91. key, future.GetCallback());
  92. EXPECT_EQ(future.Take(), nullptr);
  93. }
  94. // Verifies that `ProgressIndicator::AddProgressChangedCallback()` works as
  95. // intended.
  96. TEST_F(ProgressIndicatorTest, AddProgressChangedCallback) {
  97. // Create a test `progress_indicator`.
  98. TestProgressIndicator progress_indicator;
  99. progress_indicator.SetProgress(0.5f);
  100. // Add a callback to be notified of progress changed events. The callback
  101. // should be invoked on progress changes so long as the returned subscription
  102. // continues to exist.
  103. int callback_call_count = 0;
  104. auto subscription =
  105. std::make_unique<base::RepeatingClosureList::Subscription>(
  106. progress_indicator.AddProgressChangedCallback(
  107. base::BindLambdaForTesting([&]() { ++callback_call_count; })));
  108. // Change the underlying progress.
  109. progress_indicator.SetProgress(0.75f);
  110. EXPECT_EQ(callback_call_count, 1);
  111. // Attempt to change the underlying progress to the same value.
  112. progress_indicator.SetProgress(0.75f);
  113. EXPECT_EQ(callback_call_count, 1);
  114. // Reset the subscription and change the underlying progress.
  115. subscription.reset();
  116. progress_indicator.SetProgress(1.f);
  117. EXPECT_EQ(callback_call_count, 1);
  118. }
  119. } // namespace ash