progress_indicator_animation_registry_unittest.cc 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. // Copyright 2022 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_animation_registry.h"
  5. #include <vector>
  6. #include "ash/constants/ash_features.h"
  7. #include "ash/system/progress_indicator/progress_icon_animation.h"
  8. #include "ash/system/progress_indicator/progress_indicator_animation.h"
  9. #include "ash/system/progress_indicator/progress_ring_animation.h"
  10. #include "base/containers/contains.h"
  11. #include "base/test/bind.h"
  12. #include "base/test/scoped_feature_list.h"
  13. #include "testing/gmock/include/gmock/gmock.h"
  14. #include "testing/gtest/include/gtest/gtest.h"
  15. namespace ash {
  16. namespace {
  17. // ProgressIndicatorAnimationRegistryTest --------------------------------------
  18. // Base class for tests of the `ProgressIndicatorAnimationRegistry`.
  19. class ProgressIndicatorAnimationRegistryTest : public testing::Test {
  20. public:
  21. // Returns the `registry_` under test.
  22. ProgressIndicatorAnimationRegistry* registry() { return &registry_; }
  23. private:
  24. ProgressIndicatorAnimationRegistry registry_;
  25. };
  26. } // namespace
  27. // Tests -----------------------------------------------------------------------
  28. TEST_F(ProgressIndicatorAnimationRegistryTest, EraseAllAnimations) {
  29. // Create `master_keys` for progress animations which may be referenced from
  30. // each test case.
  31. std::vector<size_t> master_keys = {1u, 2u, 3u, 4u, 5u, 6u, 7u, 8u, 9u};
  32. // A test case is defined by:
  33. // * keys for which to add progress animations,
  34. // * a callback to invoke to erase progress animations,
  35. // * keys for which to expect progress animations after erase invocation.
  36. struct TestCase {
  37. std::vector<size_t*> keys;
  38. base::OnceClosure erase_callback;
  39. std::vector<size_t*> keys_with_animations_after_erase_callback;
  40. };
  41. std::vector<TestCase> test_cases;
  42. // Test case: Invoke `EraseAllAnimations()`.
  43. test_cases.push_back(
  44. TestCase{.keys = {&master_keys[0], &master_keys[1], &master_keys[2]},
  45. .erase_callback = base::BindOnce(
  46. &ProgressIndicatorAnimationRegistry::EraseAllAnimations,
  47. base::Unretained(registry())),
  48. .keys_with_animations_after_erase_callback = {}});
  49. // Test case: Invoke `EraseAllAnimationsForKey()`.
  50. test_cases.push_back(TestCase{
  51. .keys = {&master_keys[3], &master_keys[4], &master_keys[5]},
  52. .erase_callback = base::BindOnce(
  53. &ProgressIndicatorAnimationRegistry::EraseAllAnimationsForKey,
  54. base::Unretained(registry()), base::Unretained(&master_keys[4])),
  55. .keys_with_animations_after_erase_callback = {&master_keys[3],
  56. &master_keys[5]}});
  57. // Test case: Invoke `EraseAllAnimationsForKeyIf()`.
  58. test_cases.push_back(TestCase{
  59. .keys = {&master_keys[6], &master_keys[7], &master_keys[8]},
  60. .erase_callback = base::BindOnce(
  61. &ProgressIndicatorAnimationRegistry::EraseAllAnimationsForKeyIf,
  62. base::Unretained(registry()),
  63. base::BindRepeating(
  64. [](const void* key, const void* candidate_key) {
  65. return candidate_key != key;
  66. },
  67. base::Unretained(&master_keys[7]))),
  68. .keys_with_animations_after_erase_callback = {&master_keys[7]}});
  69. // Iterate over `test_cases`.
  70. for (auto& test_case : test_cases) {
  71. const auto& keys = test_case.keys;
  72. // Track number of animation changed events.
  73. std::vector<base::CallbackListSubscription> subscriptions;
  74. size_t icon_callback_call_count = 0u;
  75. size_t ring_callback_call_count = 0u;
  76. // Iterate over `keys`.
  77. for (auto it = keys.begin(); it != keys.end(); ++it) {
  78. const auto* key = *it;
  79. const size_t index = std::distance(keys.begin(), it);
  80. // Verify no progress animations are set for `key`.
  81. EXPECT_FALSE(registry()->GetProgressIconAnimationForKey(key));
  82. EXPECT_FALSE(registry()->GetProgressRingAnimationForKey(key));
  83. // Count progress icon animation changed events for `key`.
  84. subscriptions.push_back(
  85. registry()->AddProgressIconAnimationChangedCallbackForKey(
  86. key, base::BindLambdaForTesting([&](ProgressIconAnimation*) {
  87. ++icon_callback_call_count;
  88. })));
  89. // Count progress ring animation changed events for `key`.
  90. subscriptions.push_back(
  91. registry()->AddProgressRingAnimationChangedCallbackForKey(
  92. key, base::BindLambdaForTesting([&](ProgressRingAnimation*) {
  93. ++ring_callback_call_count;
  94. })));
  95. // Create a progress icon animation for `key`.
  96. registry()->SetProgressIconAnimationForKey(
  97. key, std::make_unique<ProgressIconAnimation>());
  98. EXPECT_TRUE(registry()->GetProgressIconAnimationForKey(key));
  99. EXPECT_EQ(icon_callback_call_count, index + 1u);
  100. // Create a progress ring animation for `key`.
  101. registry()->SetProgressRingAnimationForKey(
  102. key, ProgressRingAnimation::CreateOfType(
  103. ProgressRingAnimation::Type::kPulse));
  104. EXPECT_TRUE(registry()->GetProgressRingAnimationForKey(key));
  105. EXPECT_EQ(ring_callback_call_count, index + 1u);
  106. }
  107. // Reset animation changed event counts.
  108. icon_callback_call_count = 0u;
  109. ring_callback_call_count = 0u;
  110. // Erase animations.
  111. std::move(test_case.erase_callback).Run();
  112. EXPECT_EQ(icon_callback_call_count,
  113. keys.size() -
  114. test_case.keys_with_animations_after_erase_callback.size());
  115. EXPECT_EQ(ring_callback_call_count,
  116. keys.size() -
  117. test_case.keys_with_animations_after_erase_callback.size());
  118. // Iterate over `keys`.
  119. for (const auto* key : keys) {
  120. const bool expected = base::Contains(
  121. test_case.keys_with_animations_after_erase_callback, key);
  122. // Verify progress animations are set for `key` only if `expected`.
  123. EXPECT_EQ(!!registry()->GetProgressIconAnimationForKey(key), expected);
  124. EXPECT_EQ(!!registry()->GetProgressRingAnimationForKey(key), expected);
  125. }
  126. }
  127. }
  128. TEST_F(ProgressIndicatorAnimationRegistryTest, SetProgressIconAnimationForKey) {
  129. // Create `key` and verify no progress icon animation is set.
  130. size_t key = 0u;
  131. EXPECT_FALSE(registry()->GetProgressIconAnimationForKey(&key));
  132. // Count progress icon animation changed events.
  133. size_t callback_call_count = 0u;
  134. auto subscription = registry()->AddProgressIconAnimationChangedCallbackForKey(
  135. &key, base::BindLambdaForTesting(
  136. [&](ProgressIconAnimation*) { ++callback_call_count; }));
  137. // Unset progress icon animation for `key`.
  138. EXPECT_FALSE(registry()->SetProgressIconAnimationForKey(&key, nullptr));
  139. EXPECT_FALSE(registry()->GetProgressIconAnimationForKey(&key));
  140. EXPECT_EQ(callback_call_count, 0u);
  141. // Create a progress icon `animation`.
  142. auto animation = std::make_unique<ProgressIconAnimation>();
  143. auto* animation_ptr = animation.get();
  144. // Set progress icon `animation` for `key`.
  145. EXPECT_EQ(
  146. registry()->SetProgressIconAnimationForKey(&key, std::move(animation)),
  147. animation_ptr);
  148. EXPECT_EQ(registry()->GetProgressIconAnimationForKey(&key), animation_ptr);
  149. EXPECT_EQ(callback_call_count, 1u);
  150. // Unset progress icon animation for `key`.
  151. EXPECT_FALSE(registry()->SetProgressIconAnimationForKey(&key, nullptr));
  152. EXPECT_FALSE(registry()->GetProgressIconAnimationForKey(&key));
  153. EXPECT_EQ(callback_call_count, 2u);
  154. }
  155. TEST_F(ProgressIndicatorAnimationRegistryTest, SetProgressRingAnimationForKey) {
  156. // Create `key` and verify no progress ring animation is set.
  157. size_t key = 0u;
  158. EXPECT_FALSE(registry()->GetProgressRingAnimationForKey(&key));
  159. // Count progress ring animation changed events.
  160. size_t callback_call_count = 0u;
  161. auto subscription = registry()->AddProgressRingAnimationChangedCallbackForKey(
  162. &key, base::BindLambdaForTesting(
  163. [&](ProgressRingAnimation*) { ++callback_call_count; }));
  164. // Unset progress ring animation for `key`.
  165. EXPECT_FALSE(registry()->SetProgressRingAnimationForKey(&key, nullptr));
  166. EXPECT_FALSE(registry()->GetProgressRingAnimationForKey(&key));
  167. EXPECT_EQ(callback_call_count, 0u);
  168. // Create a progress ring `animation`.
  169. auto animation =
  170. ProgressRingAnimation::CreateOfType(ProgressRingAnimation::Type::kPulse);
  171. auto* animation_ptr = animation.get();
  172. // Set progress ring `animation` for `key`.
  173. EXPECT_EQ(
  174. registry()->SetProgressRingAnimationForKey(&key, std::move(animation)),
  175. animation_ptr);
  176. EXPECT_EQ(registry()->GetProgressRingAnimationForKey(&key), animation_ptr);
  177. EXPECT_EQ(callback_call_count, 1u);
  178. // Unset progress ring animation for `key`.
  179. EXPECT_FALSE(registry()->SetProgressRingAnimationForKey(&key, nullptr));
  180. EXPECT_FALSE(registry()->GetProgressRingAnimationForKey(&key));
  181. EXPECT_EQ(callback_call_count, 2u);
  182. }
  183. } // namespace ash