unified_message_list_view_unittest.cc 46 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185
  1. // Copyright 2018 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/message_center/unified_message_list_view.h"
  5. #include "ash/bubble/bubble_constants.h"
  6. #include "ash/constants/ash_features.h"
  7. #include "ash/system/message_center/message_center_constants.h"
  8. #include "ash/system/tray/tray_constants.h"
  9. #include "ash/system/unified/unified_system_tray_model.h"
  10. #include "ash/test/ash_test_base.h"
  11. #include "base/memory/scoped_refptr.h"
  12. #include "base/run_loop.h"
  13. #include "base/strings/string_number_conversions.h"
  14. #include "base/strings/utf_string_conversions.h"
  15. #include "base/test/scoped_feature_list.h"
  16. #include "base/time/time.h"
  17. #include "build/build_config.h"
  18. #include "chromeos/constants/chromeos_features.h"
  19. #include "ui/compositor/layer.h"
  20. #include "ui/compositor/layer_animator.h"
  21. #include "ui/message_center/message_center.h"
  22. #include "ui/message_center/views/message_view.h"
  23. #include "ui/message_center/views/notification_view.h"
  24. using message_center::MessageCenter;
  25. using message_center::MessageView;
  26. using message_center::Notification;
  27. namespace ash {
  28. namespace {
  29. class TestNotificationView : public message_center::NotificationView {
  30. public:
  31. TestNotificationView(const message_center::Notification& notification)
  32. : NotificationView(notification) {
  33. layer()->GetAnimator()->set_preemption_strategy(
  34. ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
  35. }
  36. TestNotificationView(const TestNotificationView&) = delete;
  37. TestNotificationView& operator=(const TestNotificationView&) = delete;
  38. ~TestNotificationView() override = default;
  39. // message_center::NotificationView:
  40. void UpdateCornerRadius(int top_radius, int bottom_radius) override {
  41. top_radius_ = top_radius;
  42. bottom_radius_ = bottom_radius;
  43. message_center::NotificationViewBase::UpdateCornerRadius(top_radius,
  44. bottom_radius);
  45. }
  46. float GetSlideAmount() const override {
  47. return slide_amount_.value_or(
  48. message_center::NotificationViewBase::GetSlideAmount());
  49. }
  50. int top_radius() const { return top_radius_; }
  51. int bottom_radius() const { return bottom_radius_; }
  52. void set_slide_amount(float slide_amount) { slide_amount_ = slide_amount; }
  53. private:
  54. int top_radius_ = 0;
  55. int bottom_radius_ = 0;
  56. absl::optional<float> slide_amount_;
  57. };
  58. class TestUnifiedMessageListView : public UnifiedMessageListView {
  59. public:
  60. explicit TestUnifiedMessageListView(UnifiedSystemTrayModel* model)
  61. : UnifiedMessageListView(nullptr, model) {}
  62. TestUnifiedMessageListView(const TestUnifiedMessageListView&) = delete;
  63. TestUnifiedMessageListView& operator=(const TestUnifiedMessageListView&) =
  64. delete;
  65. ~TestUnifiedMessageListView() override = default;
  66. void set_stacked_notification_count(int stacked_notification_count) {
  67. stacked_notifications_.clear();
  68. notification_id_list_.clear();
  69. for (int i = 0; i < stacked_notification_count; i++) {
  70. std::string id = base::NumberToString(0);
  71. auto notification = std::make_unique<Notification>(
  72. message_center::NOTIFICATION_TYPE_SIMPLE, id, u"test title",
  73. u"test message", ui::ImageModel(),
  74. std::u16string() /* display_source */, GURL(),
  75. message_center::NotifierId(), message_center::RichNotificationData(),
  76. new message_center::NotificationDelegate());
  77. stacked_notifications_.push_back(notification.get());
  78. notification_id_list_.push_back(id);
  79. }
  80. }
  81. // UnifiedMessageListView:
  82. message_center::MessageView* CreateMessageView(
  83. const message_center::Notification& notification) override {
  84. auto* message_view = new TestNotificationView(notification);
  85. ConfigureMessageView(message_view);
  86. return message_view;
  87. }
  88. std::vector<message_center::Notification*> GetStackedNotifications()
  89. const override {
  90. return stacked_notifications_;
  91. }
  92. std::vector<std::string> GetNonVisibleNotificationIdsInViewHierarchy()
  93. const override {
  94. return notification_id_list_;
  95. }
  96. private:
  97. std::vector<message_center::Notification*> stacked_notifications_;
  98. std::vector<std::string> notification_id_list_;
  99. };
  100. } // namespace
  101. // The base test class, has no params so tests with no params can inherit from
  102. // this.
  103. class UnifiedMessageListViewTest : public AshTestBase,
  104. public views::ViewObserver {
  105. public:
  106. UnifiedMessageListViewTest() = default;
  107. UnifiedMessageListViewTest(const UnifiedMessageListViewTest&) = delete;
  108. UnifiedMessageListViewTest& operator=(const UnifiedMessageListViewTest&) =
  109. delete;
  110. ~UnifiedMessageListViewTest() override = default;
  111. void SetUp() override {
  112. AshTestBase::SetUp();
  113. model_ = base::MakeRefCounted<UnifiedSystemTrayModel>(nullptr);
  114. }
  115. void TearDown() override {
  116. message_list_view_.reset();
  117. model_.reset();
  118. AshTestBase::TearDown();
  119. }
  120. // views::ViewObserver:
  121. void OnViewPreferredSizeChanged(views::View* view) override {
  122. view->SetBoundsRect(gfx::Rect(view->GetPreferredSize()));
  123. view->Layout();
  124. ++size_changed_count_;
  125. }
  126. protected:
  127. std::string AddNotification(bool pinned = false, bool expandable = false) {
  128. std::string id = base::NumberToString(id_++);
  129. // Make the message long enough to be collapsible. Generated by SpaceIpsum.
  130. auto notification = std::make_unique<Notification>(
  131. message_center::NOTIFICATION_TYPE_SIMPLE, id,
  132. u"Message To Flight Control",
  133. expandable ? u"From this day forward, Flight Control will be known by "
  134. u"two words: "
  135. u"‘Tough’ and ‘Competent.’ Tough means we are forever "
  136. u"accountable for "
  137. u"what we do or what we fail to do. We will never again "
  138. u"compromise our "
  139. u"responsibilities. Every time we walk into Mission "
  140. u"Control we will "
  141. u"know what we stand for. Competent means we will never "
  142. u"take anything "
  143. u"for granted. We will never be found short in our "
  144. u"knowledge and in "
  145. u"our skills. Mission Control will be perfect."
  146. : u"Hey Flight Control, who brought donuts?",
  147. ui::ImageModel(), std::u16string() /* display_source */, GURL(),
  148. message_center::NotifierId(), message_center::RichNotificationData(),
  149. new message_center::NotificationDelegate());
  150. notification->set_pinned(pinned);
  151. MessageCenter::Get()->AddNotification(std::move(notification));
  152. return id;
  153. }
  154. void OffsetNotificationTimestamp(const std::string& id,
  155. const int milliseconds) {
  156. MessageCenter::Get()->FindVisibleNotificationById(id)->set_timestamp(
  157. base::Time::Now() - base::Milliseconds(milliseconds));
  158. }
  159. void CreateMessageListView() {
  160. message_list_view_ =
  161. std::make_unique<TestUnifiedMessageListView>(model_.get());
  162. message_list_view_->Init();
  163. message_list_view_->AddObserver(this);
  164. OnViewPreferredSizeChanged(message_list_view_.get());
  165. size_changed_count_ = 0;
  166. }
  167. void DestroyMessageListView() { message_list_view_.reset(); }
  168. TestNotificationView* GetMessageViewAt(size_t index) const {
  169. return static_cast<TestNotificationView*>(
  170. message_list_view()->children()[index]->children()[1]);
  171. }
  172. gfx::Rect GetMessageViewBounds(size_t index) const {
  173. return message_list_view()->children()[index]->bounds();
  174. }
  175. void FinishSlideOutAnimation() { base::RunLoop().RunUntilIdle(); }
  176. void AnimateToMiddle() {
  177. EXPECT_TRUE(IsAnimating());
  178. message_list_view()->animation_->SetCurrentValue(0.5);
  179. message_list_view()->AnimationProgressed(
  180. message_list_view()->animation_.get());
  181. }
  182. void AnimateToEnd() { message_list_view()->animation_->End(); }
  183. void AnimateUntilIdle() {
  184. while (message_list_view()->animation_->is_animating())
  185. message_list_view()->animation_->End();
  186. }
  187. bool IsAnimating() { return message_list_view()->animation_->is_animating(); }
  188. TestUnifiedMessageListView* message_list_view() const {
  189. return message_list_view_.get();
  190. }
  191. int size_changed_count() const { return size_changed_count_; }
  192. ui::LayerAnimator* LayerAnimatorAt(int i) {
  193. return GetMessageViewAt(i)->layer()->GetAnimator();
  194. }
  195. private:
  196. int id_ = 0;
  197. int size_changed_count_ = 0;
  198. scoped_refptr<UnifiedSystemTrayModel> model_;
  199. std::unique_ptr<TestUnifiedMessageListView> message_list_view_;
  200. };
  201. // Tests with NotificationsRefresh enabled and disabled.
  202. class ParameterizedUnifiedMessageListViewTest
  203. : public UnifiedMessageListViewTest,
  204. public testing::WithParamInterface<bool> {
  205. public:
  206. ParameterizedUnifiedMessageListViewTest() = default;
  207. ParameterizedUnifiedMessageListViewTest(
  208. const ParameterizedUnifiedMessageListViewTest&) = delete;
  209. ParameterizedUnifiedMessageListViewTest& operator=(
  210. const ParameterizedUnifiedMessageListViewTest&) = delete;
  211. ~ParameterizedUnifiedMessageListViewTest() override = default;
  212. // AshTestBase:
  213. void SetUp() override {
  214. scoped_feature_list_ = std::make_unique<base::test::ScopedFeatureList>();
  215. if (IsNotificationsRefreshEnabled()) {
  216. scoped_feature_list_->InitWithFeatures(
  217. /*enabled_features=*/{features::kNotificationsRefresh,
  218. chromeos::features::kDarkLightMode},
  219. /*disabled_features=*/{});
  220. } else {
  221. scoped_feature_list_->InitWithFeatures(
  222. /*enabled_features=*/{},
  223. /*disabled_features=*/{features::kNotificationsRefresh,
  224. chromeos::features::kDarkLightMode});
  225. }
  226. UnifiedMessageListViewTest::SetUp();
  227. }
  228. int GetMessageCenterNotificationCornerRadius() {
  229. return IsNotificationsRefreshEnabled()
  230. ? kMessageCenterNotificationCornerRadius
  231. : 0;
  232. }
  233. bool IsNotificationsRefreshEnabled() const { return GetParam(); }
  234. private:
  235. std::unique_ptr<base::test::ScopedFeatureList> scoped_feature_list_;
  236. };
  237. INSTANTIATE_TEST_SUITE_P(All,
  238. ParameterizedUnifiedMessageListViewTest,
  239. testing::Bool() /* IsNotificationsRefreshEnabled() */);
  240. TEST_P(ParameterizedUnifiedMessageListViewTest, Open) {
  241. auto id0 = AddNotification();
  242. auto id1 = AddNotification();
  243. auto id2 = AddNotification();
  244. CreateMessageListView();
  245. EXPECT_EQ(3u, message_list_view()->children().size());
  246. if (!features::IsNotificationsRefreshEnabled()) {
  247. EXPECT_EQ(id0, GetMessageViewAt(0)->notification_id());
  248. EXPECT_EQ(id1, GetMessageViewAt(1)->notification_id());
  249. EXPECT_EQ(id2, GetMessageViewAt(2)->notification_id());
  250. EXPECT_FALSE(GetMessageViewAt(0)->IsExpanded());
  251. EXPECT_FALSE(GetMessageViewAt(1)->IsExpanded());
  252. EXPECT_TRUE(GetMessageViewAt(2)->IsExpanded());
  253. } else {
  254. EXPECT_EQ(id0, GetMessageViewAt(2)->notification_id());
  255. EXPECT_EQ(id1, GetMessageViewAt(1)->notification_id());
  256. EXPECT_EQ(id2, GetMessageViewAt(0)->notification_id());
  257. EXPECT_FALSE(GetMessageViewAt(2)->IsExpanded());
  258. EXPECT_FALSE(GetMessageViewAt(1)->IsExpanded());
  259. EXPECT_TRUE(GetMessageViewAt(0)->IsExpanded());
  260. }
  261. // Check the position of notifications within the list. When the new feature
  262. // is enabled, we have extra spacing between notifications.
  263. if (IsNotificationsRefreshEnabled()) {
  264. EXPECT_EQ(
  265. GetMessageViewBounds(0).bottom() + kMessageListNotificationSpacing,
  266. GetMessageViewBounds(1).y());
  267. EXPECT_EQ(
  268. GetMessageViewBounds(1).bottom() + kMessageListNotificationSpacing,
  269. GetMessageViewBounds(2).y());
  270. } else {
  271. EXPECT_EQ(GetMessageViewBounds(0).bottom(), GetMessageViewBounds(1).y());
  272. EXPECT_EQ(GetMessageViewBounds(1).bottom(), GetMessageViewBounds(2).y());
  273. }
  274. int top_most_corner_radius = IsNotificationsRefreshEnabled()
  275. ? kBubbleCornerRadius
  276. : GetMessageCenterNotificationCornerRadius();
  277. EXPECT_EQ(top_most_corner_radius, GetMessageViewAt(0)->top_radius());
  278. EXPECT_EQ(GetMessageCenterNotificationCornerRadius(),
  279. GetMessageViewAt(1)->top_radius());
  280. EXPECT_EQ(GetMessageCenterNotificationCornerRadius(),
  281. GetMessageViewAt(2)->top_radius());
  282. EXPECT_EQ(GetMessageCenterNotificationCornerRadius(),
  283. GetMessageViewAt(0)->bottom_radius());
  284. EXPECT_EQ(GetMessageCenterNotificationCornerRadius(),
  285. GetMessageViewAt(1)->bottom_radius());
  286. EXPECT_EQ(kBubbleCornerRadius, GetMessageViewAt(2)->bottom_radius());
  287. EXPECT_LT(0, message_list_view()->GetPreferredSize().height());
  288. }
  289. TEST_P(ParameterizedUnifiedMessageListViewTest, AddNotifications) {
  290. CreateMessageListView();
  291. EXPECT_EQ(0, message_list_view()->GetPreferredSize().height());
  292. auto id0 = AddNotification();
  293. EXPECT_EQ(1, size_changed_count());
  294. EXPECT_EQ(1u, message_list_view()->children().size());
  295. EXPECT_EQ(id0, GetMessageViewAt(0)->notification_id());
  296. EXPECT_EQ(kBubbleCornerRadius, GetMessageViewAt(0)->top_radius());
  297. EXPECT_EQ(kBubbleCornerRadius, GetMessageViewAt(0)->bottom_radius());
  298. int previous_message_list_view_height =
  299. message_list_view()->GetPreferredSize().height();
  300. EXPECT_LT(0, previous_message_list_view_height);
  301. gfx::Rect previous_bounds = GetMessageViewBounds(0);
  302. auto id1 = AddNotification();
  303. EXPECT_EQ(2, size_changed_count());
  304. EXPECT_EQ(2u, message_list_view()->children().size());
  305. EXPECT_EQ(id1,
  306. GetMessageViewAt(features::IsNotificationsRefreshEnabled() ? 0 : 1)
  307. ->notification_id());
  308. EXPECT_LT(previous_message_list_view_height,
  309. message_list_view()->GetPreferredSize().height());
  310. if (!IsNotificationsRefreshEnabled()) {
  311. // 1dip larger because now it has separator border.
  312. previous_bounds.Inset(gfx::Insets::TLBR(0, 0, -1, 0));
  313. }
  314. EXPECT_EQ(previous_bounds, GetMessageViewBounds(0));
  315. // When the new feature is enabled, we have extra spacing between
  316. // notifications.
  317. if (IsNotificationsRefreshEnabled()) {
  318. EXPECT_EQ(
  319. GetMessageViewBounds(0).bottom() + kMessageListNotificationSpacing,
  320. GetMessageViewBounds(1).y());
  321. } else {
  322. EXPECT_EQ(GetMessageViewBounds(0).bottom(), GetMessageViewBounds(1).y());
  323. }
  324. int top_most_corner_radius = IsNotificationsRefreshEnabled()
  325. ? kBubbleCornerRadius
  326. : GetMessageCenterNotificationCornerRadius();
  327. EXPECT_EQ(top_most_corner_radius, GetMessageViewAt(0)->top_radius());
  328. EXPECT_EQ(GetMessageCenterNotificationCornerRadius(),
  329. GetMessageViewAt(1)->top_radius());
  330. EXPECT_EQ(kBubbleCornerRadius, GetMessageViewAt(1)->bottom_radius());
  331. }
  332. TEST_P(ParameterizedUnifiedMessageListViewTest, RemoveNotification) {
  333. auto id0 = AddNotification();
  334. auto id1 = AddNotification();
  335. CreateMessageListView();
  336. int previous_height = message_list_view()->GetPreferredSize().height();
  337. EXPECT_EQ(2u, message_list_view()->children().size());
  338. int top_most_corner_radius = IsNotificationsRefreshEnabled()
  339. ? kBubbleCornerRadius
  340. : GetMessageCenterNotificationCornerRadius();
  341. EXPECT_EQ(top_most_corner_radius, GetMessageViewAt(0)->top_radius());
  342. EXPECT_EQ(GetMessageCenterNotificationCornerRadius(),
  343. GetMessageViewAt(0)->bottom_radius());
  344. gfx::Rect previous_bounds = GetMessageViewBounds(0);
  345. MessageCenter::Get()->RemoveNotification(id0, true /* by_user */);
  346. FinishSlideOutAnimation();
  347. AnimateUntilIdle();
  348. EXPECT_EQ(1u, message_list_view()->children().size());
  349. EXPECT_EQ(previous_bounds.y(), GetMessageViewBounds(0).y());
  350. EXPECT_LT(0, message_list_view()->GetPreferredSize().height());
  351. EXPECT_GT(previous_height, message_list_view()->GetPreferredSize().height());
  352. EXPECT_EQ(kBubbleCornerRadius, GetMessageViewAt(0)->top_radius());
  353. EXPECT_EQ(kBubbleCornerRadius, GetMessageViewAt(0)->bottom_radius());
  354. MessageCenter::Get()->RemoveNotification(id1, true /* by_user */);
  355. FinishSlideOutAnimation();
  356. AnimateUntilIdle();
  357. EXPECT_EQ(0u, message_list_view()->children().size());
  358. EXPECT_EQ(0, message_list_view()->GetPreferredSize().height());
  359. }
  360. TEST_P(ParameterizedUnifiedMessageListViewTest, CollapseOlderNotifications) {
  361. AddNotification();
  362. CreateMessageListView();
  363. EXPECT_TRUE(GetMessageViewAt(0)->IsExpanded());
  364. AddNotification();
  365. if (!features::IsNotificationsRefreshEnabled()) {
  366. EXPECT_FALSE(GetMessageViewAt(0)->IsExpanded());
  367. EXPECT_TRUE(GetMessageViewAt(1)->IsExpanded());
  368. } else {
  369. EXPECT_FALSE(GetMessageViewAt(1)->IsExpanded());
  370. EXPECT_TRUE(GetMessageViewAt(0)->IsExpanded());
  371. }
  372. AddNotification();
  373. if (!features::IsNotificationsRefreshEnabled()) {
  374. EXPECT_FALSE(GetMessageViewAt(0)->IsExpanded());
  375. EXPECT_FALSE(GetMessageViewAt(1)->IsExpanded());
  376. EXPECT_TRUE(GetMessageViewAt(2)->IsExpanded());
  377. } else {
  378. EXPECT_FALSE(GetMessageViewAt(2)->IsExpanded());
  379. EXPECT_FALSE(GetMessageViewAt(1)->IsExpanded());
  380. EXPECT_TRUE(GetMessageViewAt(0)->IsExpanded());
  381. }
  382. GetMessageViewAt(1)->SetExpanded(true);
  383. GetMessageViewAt(1)->SetManuallyExpandedOrCollapsed(true);
  384. AddNotification();
  385. if (!features::IsNotificationsRefreshEnabled()) {
  386. EXPECT_FALSE(GetMessageViewAt(0)->IsExpanded());
  387. EXPECT_TRUE(GetMessageViewAt(1)->IsExpanded());
  388. EXPECT_FALSE(GetMessageViewAt(2)->IsExpanded());
  389. EXPECT_TRUE(GetMessageViewAt(3)->IsExpanded());
  390. } else {
  391. EXPECT_TRUE(GetMessageViewAt(0)->IsExpanded());
  392. EXPECT_FALSE(GetMessageViewAt(1)->IsExpanded());
  393. EXPECT_TRUE(GetMessageViewAt(2)->IsExpanded());
  394. EXPECT_FALSE(GetMessageViewAt(3)->IsExpanded());
  395. }
  396. }
  397. TEST_P(ParameterizedUnifiedMessageListViewTest, RemovingNotificationAnimation) {
  398. auto id0 = AddNotification(/*pinned=*/false);
  399. auto id1 = AddNotification();
  400. auto id2 = AddNotification();
  401. CreateMessageListView();
  402. int previous_height = message_list_view()->GetPreferredSize().height();
  403. gfx::Rect bounds0 = GetMessageViewBounds(0);
  404. gfx::Rect bounds1 = GetMessageViewBounds(1);
  405. MessageCenter::Get()->RemoveNotification(id1, true /* by_user */);
  406. FinishSlideOutAnimation();
  407. AnimateToEnd();
  408. EXPECT_GT(previous_height, message_list_view()->GetPreferredSize().height());
  409. previous_height = message_list_view()->GetPreferredSize().height();
  410. if (!IsNotificationsRefreshEnabled()) {
  411. // Now it lost separator border.
  412. bounds1.Inset(gfx::Insets::TLBR(0, 0, 1, 0));
  413. }
  414. EXPECT_EQ(bounds0, GetMessageViewBounds(0));
  415. EXPECT_EQ(bounds1, GetMessageViewBounds(1));
  416. MessageCenter::Get()->RemoveNotification(id2, true /* by_user */);
  417. FinishSlideOutAnimation();
  418. AnimateToEnd();
  419. EXPECT_GT(previous_height, message_list_view()->GetPreferredSize().height());
  420. previous_height = message_list_view()->GetPreferredSize().height();
  421. if (!IsNotificationsRefreshEnabled()) {
  422. // Now it lost separator border.
  423. bounds0.Inset(gfx::Insets::TLBR(0, 0, 1, 0));
  424. }
  425. EXPECT_EQ(bounds0, GetMessageViewBounds(0));
  426. MessageCenter::Get()->RemoveNotification(id0, true /* by_user */);
  427. FinishSlideOutAnimation();
  428. AnimateToEnd();
  429. EXPECT_GT(previous_height, message_list_view()->GetPreferredSize().height());
  430. previous_height = message_list_view()->GetPreferredSize().height();
  431. EXPECT_EQ(0, message_list_view()->GetPreferredSize().height());
  432. }
  433. // Flaky: https://crbug.com/1292774.
  434. TEST_P(ParameterizedUnifiedMessageListViewTest, DISABLED_ResetAnimation) {
  435. auto id0 = AddNotification();
  436. auto id1 = AddNotification();
  437. CreateMessageListView();
  438. MessageCenter::Get()->RemoveNotification(id0, true /* by_user */);
  439. FinishSlideOutAnimation();
  440. EXPECT_TRUE(IsAnimating());
  441. AnimateToMiddle();
  442. // New event resets the animation.
  443. auto id2 = AddNotification();
  444. EXPECT_FALSE(IsAnimating());
  445. EXPECT_EQ(2u, message_list_view()->children().size());
  446. EXPECT_EQ(id1, GetMessageViewAt(0)->notification_id());
  447. EXPECT_EQ(id2, GetMessageViewAt(1)->notification_id());
  448. }
  449. TEST_P(ParameterizedUnifiedMessageListViewTest, KeepManuallyExpanded) {
  450. AddNotification();
  451. AddNotification();
  452. CreateMessageListView();
  453. if (!features::IsNotificationsRefreshEnabled()) {
  454. EXPECT_FALSE(GetMessageViewAt(0)->IsExpanded());
  455. EXPECT_TRUE(GetMessageViewAt(1)->IsExpanded());
  456. } else {
  457. EXPECT_FALSE(GetMessageViewAt(1)->IsExpanded());
  458. EXPECT_TRUE(GetMessageViewAt(0)->IsExpanded());
  459. }
  460. EXPECT_FALSE(GetMessageViewAt(0)->IsManuallyExpandedOrCollapsed());
  461. EXPECT_FALSE(GetMessageViewAt(1)->IsManuallyExpandedOrCollapsed());
  462. // Manually expand the first notification & manually collapse the second one.
  463. GetMessageViewAt(0)->SetExpanded(true);
  464. GetMessageViewAt(0)->SetManuallyExpandedOrCollapsed(true);
  465. GetMessageViewAt(1)->SetExpanded(false);
  466. GetMessageViewAt(1)->SetManuallyExpandedOrCollapsed(true);
  467. DestroyMessageListView();
  468. // Reopen and confirm the expanded state & manually expanded flags are kept.
  469. CreateMessageListView();
  470. EXPECT_TRUE(GetMessageViewAt(0)->IsExpanded());
  471. EXPECT_FALSE(GetMessageViewAt(1)->IsExpanded());
  472. EXPECT_TRUE(GetMessageViewAt(0)->IsManuallyExpandedOrCollapsed());
  473. EXPECT_TRUE(GetMessageViewAt(1)->IsManuallyExpandedOrCollapsed());
  474. DestroyMessageListView();
  475. // Add a new notification.
  476. auto id = AddNotification();
  477. CreateMessageListView();
  478. // Confirm the new notification isn't affected & others are still kept.
  479. if (!features::IsNotificationsRefreshEnabled()) {
  480. EXPECT_TRUE(GetMessageViewAt(0)->IsExpanded());
  481. EXPECT_FALSE(GetMessageViewAt(1)->IsExpanded());
  482. EXPECT_TRUE(GetMessageViewAt(2)->IsExpanded());
  483. EXPECT_TRUE(GetMessageViewAt(0)->IsManuallyExpandedOrCollapsed());
  484. EXPECT_TRUE(GetMessageViewAt(1)->IsManuallyExpandedOrCollapsed());
  485. EXPECT_FALSE(GetMessageViewAt(2)->IsManuallyExpandedOrCollapsed());
  486. } else {
  487. EXPECT_FALSE(GetMessageViewAt(2)->IsExpanded());
  488. EXPECT_TRUE(GetMessageViewAt(1)->IsExpanded());
  489. EXPECT_TRUE(GetMessageViewAt(0)->IsExpanded());
  490. EXPECT_TRUE(GetMessageViewAt(2)->IsManuallyExpandedOrCollapsed());
  491. EXPECT_TRUE(GetMessageViewAt(1)->IsManuallyExpandedOrCollapsed());
  492. EXPECT_FALSE(GetMessageViewAt(0)->IsManuallyExpandedOrCollapsed());
  493. }
  494. }
  495. TEST_P(ParameterizedUnifiedMessageListViewTest,
  496. ClearAllWithOnlyVisibleNotifications) {
  497. AddNotification();
  498. AddNotification();
  499. CreateMessageListView();
  500. EXPECT_EQ(2u, message_list_view()->children().size());
  501. int previous_height = message_list_view()->GetPreferredSize().height();
  502. int removed_view_index = features::IsNotificationsRefreshEnabled() ? 1 : 0;
  503. gfx::Rect previous_bounds = GetMessageViewBounds(removed_view_index);
  504. message_list_view()->ClearAllWithAnimation();
  505. AnimateToMiddle();
  506. EXPECT_LT(previous_bounds.x(), GetMessageViewBounds(removed_view_index).x());
  507. EXPECT_EQ(previous_height, message_list_view()->GetPreferredSize().height());
  508. AnimateToEnd();
  509. EXPECT_EQ(1u, message_list_view()->children().size());
  510. EXPECT_EQ(previous_height, message_list_view()->GetPreferredSize().height());
  511. previous_bounds = GetMessageViewBounds(0);
  512. AnimateToMiddle();
  513. EXPECT_LT(previous_bounds.x(), GetMessageViewBounds(0).x());
  514. EXPECT_GT(previous_height, message_list_view()->GetPreferredSize().height());
  515. previous_height = message_list_view()->GetPreferredSize().height();
  516. AnimateToEnd();
  517. EXPECT_GT(previous_height, message_list_view()->GetPreferredSize().height());
  518. previous_height = message_list_view()->GetPreferredSize().height();
  519. EXPECT_EQ(0u, message_list_view()->children().size());
  520. AnimateToMiddle();
  521. EXPECT_GT(previous_height, message_list_view()->GetPreferredSize().height());
  522. previous_height = message_list_view()->GetPreferredSize().height();
  523. AnimateToEnd();
  524. EXPECT_GT(previous_height, message_list_view()->GetPreferredSize().height());
  525. EXPECT_EQ(0, message_list_view()->GetPreferredSize().height());
  526. EXPECT_TRUE(MessageCenter::Get()->GetVisibleNotifications().empty());
  527. EXPECT_FALSE(IsAnimating());
  528. }
  529. TEST_P(ParameterizedUnifiedMessageListViewTest,
  530. ClearAllWithStackingNotifications) {
  531. AddNotification();
  532. AddNotification();
  533. AddNotification();
  534. CreateMessageListView();
  535. message_list_view()->set_stacked_notification_count(2);
  536. EXPECT_EQ(3u, message_list_view()->children().size());
  537. message_list_view()->ClearAllWithAnimation();
  538. EXPECT_EQ(2u, message_list_view()->children().size());
  539. message_list_view()->set_stacked_notification_count(1);
  540. int previous_height = message_list_view()->GetPreferredSize().height();
  541. gfx::Rect previous_bounds = GetMessageViewBounds(1);
  542. AnimateToMiddle();
  543. EXPECT_EQ(previous_height, message_list_view()->GetPreferredSize().height());
  544. EXPECT_EQ(previous_bounds, GetMessageViewBounds(1));
  545. AnimateToEnd();
  546. EXPECT_EQ(1u, message_list_view()->children().size());
  547. message_list_view()->set_stacked_notification_count(0);
  548. previous_height = message_list_view()->GetPreferredSize().height();
  549. AnimateToMiddle();
  550. EXPECT_EQ(previous_height, message_list_view()->GetPreferredSize().height());
  551. AnimateToEnd();
  552. EXPECT_EQ(1u, message_list_view()->children().size());
  553. previous_bounds = GetMessageViewBounds(0);
  554. AnimateToMiddle();
  555. EXPECT_LT(previous_bounds.x(), GetMessageViewBounds(0).x());
  556. AnimateToEnd();
  557. EXPECT_EQ(0u, message_list_view()->children().size());
  558. previous_height = message_list_view()->GetPreferredSize().height();
  559. AnimateToMiddle();
  560. EXPECT_GT(previous_height, message_list_view()->GetPreferredSize().height());
  561. previous_height = message_list_view()->GetPreferredSize().height();
  562. AnimateToEnd();
  563. EXPECT_EQ(0u, message_list_view()->children().size());
  564. EXPECT_GT(previous_height, message_list_view()->GetPreferredSize().height());
  565. EXPECT_EQ(0, message_list_view()->GetPreferredSize().height());
  566. EXPECT_FALSE(IsAnimating());
  567. }
  568. TEST_P(ParameterizedUnifiedMessageListViewTest, ClearAllClosedInTheMiddle) {
  569. AddNotification();
  570. AddNotification();
  571. AddNotification();
  572. CreateMessageListView();
  573. message_list_view()->ClearAllWithAnimation();
  574. AnimateToMiddle();
  575. DestroyMessageListView();
  576. EXPECT_TRUE(MessageCenter::Get()->GetVisibleNotifications().empty());
  577. }
  578. TEST_P(ParameterizedUnifiedMessageListViewTest, ClearAllInterrupted) {
  579. AddNotification();
  580. AddNotification();
  581. AddNotification();
  582. CreateMessageListView();
  583. message_list_view()->ClearAllWithAnimation();
  584. AnimateToMiddle();
  585. auto new_id = AddNotification();
  586. EXPECT_EQ(1u, MessageCenter::Get()->GetVisibleNotifications().size());
  587. EXPECT_TRUE(MessageCenter::Get()->FindVisibleNotificationById(new_id));
  588. }
  589. TEST_P(ParameterizedUnifiedMessageListViewTest,
  590. ClearAllWithPinnedNotifications) {
  591. AddNotification(/*pinned=*/true);
  592. AddNotification();
  593. AddNotification();
  594. CreateMessageListView();
  595. message_list_view()->ClearAllWithAnimation();
  596. AnimateUntilIdle();
  597. EXPECT_EQ(1u, message_list_view()->children().size());
  598. }
  599. // Flaky: https://crbug.com/1292701.
  600. TEST_P(ParameterizedUnifiedMessageListViewTest,
  601. DISABLED_UserSwipesAwayNotification) {
  602. // Show message list with two notifications.
  603. AddNotification();
  604. auto id1 = AddNotification();
  605. CreateMessageListView();
  606. // Start swiping the notification away.
  607. GetMessageViewAt(1)->OnSlideStarted();
  608. GetMessageViewAt(1)->OnSlideChanged(true);
  609. EXPECT_EQ(2u, MessageCenter::Get()->GetVisibleNotifications().size());
  610. EXPECT_EQ(2u, message_list_view()->children().size());
  611. // Swiping away the notification should remove it both in the MessageCenter
  612. // and the MessageListView.
  613. MessageCenter::Get()->RemoveNotification(id1, true /* by_user */);
  614. FinishSlideOutAnimation();
  615. EXPECT_EQ(1u, MessageCenter::Get()->GetVisibleNotifications().size());
  616. EXPECT_EQ(1u, message_list_view()->children().size());
  617. // The next and only animation should be the move down animation.
  618. int previous_height = message_list_view()->GetPreferredSize().height();
  619. AnimateToEnd();
  620. EXPECT_GT(previous_height, message_list_view()->GetPreferredSize().height());
  621. EXPECT_FALSE(message_list_view()->IsAnimating());
  622. }
  623. TEST_P(ParameterizedUnifiedMessageListViewTest, InitInSortedOrder) {
  624. // MessageViews should be ordered, from top down: [ id1, id2, id0 ].
  625. auto id0 = AddNotification(/*pinned=*/true);
  626. OffsetNotificationTimestamp(id0, 2000 /* milliseconds */);
  627. auto id1 = AddNotification();
  628. OffsetNotificationTimestamp(id1, 1000 /* milliseconds */);
  629. auto id2 = AddNotification();
  630. CreateMessageListView();
  631. EXPECT_EQ(3u, message_list_view()->children().size());
  632. if (!features::IsNotificationsRefreshEnabled()) {
  633. EXPECT_EQ(id1, GetMessageViewAt(0)->notification_id());
  634. EXPECT_EQ(id2, GetMessageViewAt(1)->notification_id());
  635. EXPECT_EQ(id0, GetMessageViewAt(2)->notification_id());
  636. } else {
  637. EXPECT_EQ(id1, GetMessageViewAt(2)->notification_id());
  638. EXPECT_EQ(id2, GetMessageViewAt(1)->notification_id());
  639. EXPECT_EQ(id0, GetMessageViewAt(0)->notification_id());
  640. }
  641. }
  642. TEST_P(ParameterizedUnifiedMessageListViewTest,
  643. NotificationAddedInSortedOrder) {
  644. auto id0 = AddNotification(/*pinned=*/true);
  645. OffsetNotificationTimestamp(id0, 3000 /* milliseconds */);
  646. auto id1 = AddNotification();
  647. OffsetNotificationTimestamp(id1, 2000 /* milliseconds */);
  648. auto id2 = AddNotification();
  649. OffsetNotificationTimestamp(id2, 1000 /* milliseconds */);
  650. CreateMessageListView();
  651. auto id3 = AddNotification(/*pinned=*/true);
  652. EXPECT_EQ(4u, message_list_view()->children().size());
  653. if (!features::IsNotificationsRefreshEnabled()) {
  654. // New pinned notification should be added to the end.
  655. EXPECT_EQ(id3, GetMessageViewAt(3)->notification_id());
  656. } else {
  657. // New pinned notification should be added to the start.
  658. EXPECT_EQ(id3, GetMessageViewAt(0)->notification_id());
  659. }
  660. // New non-pinned notification should be added before pinned notifications.
  661. auto id4 = AddNotification();
  662. EXPECT_EQ(5u, message_list_view()->children().size());
  663. if (!features::IsNotificationsRefreshEnabled()) {
  664. EXPECT_EQ(id1, GetMessageViewAt(0)->notification_id());
  665. EXPECT_EQ(id2, GetMessageViewAt(1)->notification_id());
  666. EXPECT_EQ(id4, GetMessageViewAt(2)->notification_id());
  667. EXPECT_EQ(id0, GetMessageViewAt(3)->notification_id());
  668. EXPECT_EQ(id3, GetMessageViewAt(4)->notification_id());
  669. } else {
  670. EXPECT_EQ(id1, GetMessageViewAt(4)->notification_id());
  671. EXPECT_EQ(id2, GetMessageViewAt(3)->notification_id());
  672. EXPECT_EQ(id4, GetMessageViewAt(2)->notification_id());
  673. EXPECT_EQ(id0, GetMessageViewAt(1)->notification_id());
  674. EXPECT_EQ(id3, GetMessageViewAt(0)->notification_id());
  675. }
  676. }
  677. // Tests only with NotificationsRefresh enabled.
  678. class RefreshedUnifiedMessageListView : public UnifiedMessageListViewTest {
  679. public:
  680. RefreshedUnifiedMessageListView() = default;
  681. RefreshedUnifiedMessageListView(const RefreshedUnifiedMessageListView&) =
  682. delete;
  683. RefreshedUnifiedMessageListView& operator=(
  684. const RefreshedUnifiedMessageListView&) = delete;
  685. ~RefreshedUnifiedMessageListView() override = default;
  686. void SetUp() override {
  687. scoped_feature_list_ = std::make_unique<base::test::ScopedFeatureList>();
  688. scoped_feature_list_->InitAndEnableFeature(features::kNotificationsRefresh);
  689. UnifiedMessageListViewTest::SetUp();
  690. }
  691. // Start sliding the message view at the given index in the list.
  692. void StartSliding(size_t index) {
  693. auto* message_view = GetMessageViewAt(index);
  694. message_view->set_slide_amount(1);
  695. message_view->OnSlideChanged(/*in_progress=*/true);
  696. }
  697. private:
  698. std::unique_ptr<base::test::ScopedFeatureList> scoped_feature_list_;
  699. };
  700. // Tests that preferred size changes upon toggle of expand/collapse.
  701. TEST_F(RefreshedUnifiedMessageListView, PreferredSizeChangesOnToggle) {
  702. AddNotification(/*pinned=*/false, /*expandable=*/true);
  703. AddNotification(/*pinned=*/false, /*expandable=*/true);
  704. CreateMessageListView();
  705. auto* message_view = GetMessageViewAt(0);
  706. ASSERT_TRUE(message_view->IsExpanded());
  707. gfx::Size old_preferred_size =
  708. message_list_view()->children()[0]->GetPreferredSize();
  709. EXPECT_FALSE(IsAnimating());
  710. message_view->SetExpanded(/*expanded=*/false);
  711. EXPECT_TRUE(IsAnimating());
  712. EXPECT_TRUE(message_list_view()->IsAnimatingExpandOrCollapseContainer(
  713. message_list_view()->children()[0]));
  714. EXPECT_EQ(old_preferred_size.height(),
  715. message_list_view()->children()[0]->GetPreferredSize().height());
  716. old_preferred_size = message_list_view()->children()[0]->GetPreferredSize();
  717. AnimateToMiddle();
  718. EXPECT_GT(old_preferred_size.height(),
  719. message_list_view()->children()[0]->GetPreferredSize().height());
  720. AnimateToEnd();
  721. FinishSlideOutAnimation();
  722. EXPECT_FALSE(IsAnimating());
  723. EXPECT_FALSE(message_list_view()->IsAnimatingExpandOrCollapseContainer(
  724. message_list_view()->children()[0]));
  725. }
  726. // Tests that expanding a notification while a different notification is
  727. // expanding is handled gracefully.
  728. TEST_F(RefreshedUnifiedMessageListView, TwoExpandsInARow) {
  729. AddNotification(/*pinned=*/false, /*expandable=*/true);
  730. AddNotification(/*pinned=*/false, /*expandable=*/true);
  731. CreateMessageListView();
  732. // First expand the notification in `first_notification_container`.
  733. auto* first_notification_container = message_list_view()->children()[1];
  734. auto* message_view = GetMessageViewAt(1);
  735. ASSERT_FALSE(message_view->IsExpanded());
  736. message_view->SetExpanded(/*expanded=*/true);
  737. AnimateToMiddle();
  738. const gfx::Size first_notification_middle_of_animation_size =
  739. first_notification_container->GetPreferredSize();
  740. // Collapse the second notification as `message_view` is still animating.
  741. auto* second_notification_container = message_list_view()->children()[0];
  742. const gfx::Size second_notification_initial_size =
  743. second_notification_container->GetPreferredSize();
  744. message_view = GetMessageViewAt(0);
  745. message_view->SetExpanded(/*expanded=*/false);
  746. EXPECT_TRUE(IsAnimating());
  747. EXPECT_FALSE(message_list_view()->IsAnimatingExpandOrCollapseContainer(
  748. first_notification_container));
  749. EXPECT_TRUE(message_list_view()->IsAnimatingExpandOrCollapseContainer(
  750. second_notification_container));
  751. // The originally animating container should have been snapped to its final
  752. // bounds.
  753. EXPECT_LT(first_notification_middle_of_animation_size.height(),
  754. first_notification_container->GetPreferredSize().height());
  755. AnimateToEnd();
  756. FinishSlideOutAnimation();
  757. // `second_notification_container` should animate to its final bounds.
  758. EXPECT_GT(second_notification_initial_size.height(),
  759. second_notification_container->GetPreferredSize().height());
  760. }
  761. // Tests that collapsing/expanding is reversible.
  762. TEST_F(RefreshedUnifiedMessageListView, ReverseExpand) {
  763. AddNotification(/*pinned=*/false, /*expandable=*/true);
  764. AddNotification(/*pinned=*/false, /*expandable=*/true);
  765. CreateMessageListView();
  766. auto* message_view = GetMessageViewAt(0);
  767. auto* second_notification_container = message_list_view()->children()[0];
  768. message_view->SetExpanded(/*expanded=*/false);
  769. AnimateToMiddle();
  770. const gfx::Size middle_of_collapsed_size =
  771. second_notification_container->GetPreferredSize();
  772. // Animate to expanded in the middle of the collapse animation. This should
  773. // stop the collapse animation and set the view to its final bounds, then
  774. // animate to expanded.
  775. message_view->SetExpanded(/*expanded=*/true);
  776. const gfx::Size final_collapsed_size =
  777. second_notification_container->GetPreferredSize();
  778. EXPECT_LT(final_collapsed_size.height(), middle_of_collapsed_size.height());
  779. // Animate to the end. The container view should be fully expanded.
  780. AnimateToEnd();
  781. EXPECT_LT(middle_of_collapsed_size.height(),
  782. second_notification_container->GetPreferredSize().height());
  783. }
  784. // Tests that destroying during a collapse animation does not crash.
  785. TEST_F(RefreshedUnifiedMessageListView, DestroyMessageListViewDuringCollapse) {
  786. AddNotification(/*pinned=*/false, /*expandable=*/true);
  787. AddNotification(/*pinned=*/false, /*expandable=*/true);
  788. CreateMessageListView();
  789. auto* message_view = GetMessageViewAt(0);
  790. message_view->SetExpanded(/*expanded=*/false);
  791. AnimateToMiddle();
  792. DestroyMessageListView();
  793. }
  794. // Tests that closing a notification while its collapse animation is ongoing
  795. // works properly.
  796. TEST_F(RefreshedUnifiedMessageListView, RemoveNotificationDuringCollapse) {
  797. auto id1 = AddNotification(/*pinned=*/false, /*expandable=*/true);
  798. CreateMessageListView();
  799. auto* message_view = GetMessageViewAt(0);
  800. message_view->SetExpanded(/*expanded=*/false);
  801. AnimateToMiddle();
  802. auto* notification_container = message_list_view()->children()[0];
  803. const gfx::Size middle_of_collapsed_size =
  804. notification_container->GetPreferredSize();
  805. // Remove the notification for `message_view`. The view should snap to
  806. // collapsed bounds, then slide out.
  807. MessageCenter::Get()->RemoveNotification(id1, /*by_user=*/true);
  808. EXPECT_LE(notification_container->GetPreferredSize().height(),
  809. middle_of_collapsed_size.height());
  810. FinishSlideOutAnimation();
  811. AnimateUntilIdle();
  812. EXPECT_EQ(0u, message_list_view()->children().size());
  813. EXPECT_EQ(0, message_list_view()->GetPreferredSize().height());
  814. }
  815. // Tests that expanding a notification at various stages while it is being
  816. // closed does not result in an animation.
  817. // TODO(crbug.com/1292775): Test is flaky.
  818. TEST_F(RefreshedUnifiedMessageListView,
  819. DISABLED_CollapseDuringCloseResultsInNoCollapseAnimation) {
  820. auto id1 = AddNotification(/*pinned=*/false, /*expandable=*/true);
  821. AddNotification(/*pinned=*/false, /*expandable=*/true);
  822. CreateMessageListView();
  823. auto* notification_container = message_list_view()->children()[0];
  824. const gfx::Size pre_remove_size = notification_container->GetPreferredSize();
  825. // Remove the notification, this should activate the "slide out" animation.
  826. MessageCenter::Get()->RemoveNotification(id1, /*by_user=*/true);
  827. EXPECT_EQ(notification_container->GetPreferredSize(), pre_remove_size);
  828. // Removing the notification does not trigger an animation at the level of
  829. // UnifiedMessageListView
  830. EXPECT_FALSE(message_list_view()->IsAnimating());
  831. EXPECT_FALSE(message_list_view()->IsAnimatingExpandOrCollapseContainer(
  832. notification_container));
  833. // Trigger the collapse before slide out completes, this should not trigger an
  834. // animation for UnifiedMessageListView, and no animation should occur.
  835. // SlideOut animation happens at a lower level. Also, size changes should be
  836. // ignored when being removed.
  837. GetMessageViewAt(0)->SetExpanded(/*expanded=*/false);
  838. EXPECT_FALSE(message_list_view()->IsAnimating());
  839. EXPECT_FALSE(message_list_view()->IsAnimatingExpandOrCollapseContainer(
  840. notification_container));
  841. EXPECT_EQ(pre_remove_size, notification_container->GetPreferredSize());
  842. // Finish the slide out animation. Then an animation should begin to shrink
  843. // MessageListView to contain the remaining notifications via
  844. // State::MOVE_DOWN. Only one notification should remain.
  845. FinishSlideOutAnimation();
  846. EXPECT_TRUE(message_list_view()->IsAnimating());
  847. EXPECT_EQ(1u, message_list_view()->children().size());
  848. }
  849. // Tests that collapsing a notification while it is being moved automatically
  850. // completes both animations.
  851. // TODO(crbug.com/1292816): Test is flaky.
  852. TEST_F(RefreshedUnifiedMessageListView,
  853. DISABLED_CollapseDuringMoveNoAnimation) {
  854. auto to_be_removed_notification =
  855. AddNotification(/*pinned=*/false, /*expandable=*/true);
  856. auto to_be_collapsed_notification =
  857. AddNotification(/*pinned=*/false, /*expandable=*/true);
  858. CreateMessageListView();
  859. auto* to_be_collapsed_message_view_container =
  860. message_list_view()->children()[1];
  861. auto* to_be_collapsed_message_view = GetMessageViewAt(1);
  862. const gfx::Size pre_collapse_size =
  863. to_be_collapsed_message_view_container->GetPreferredSize();
  864. ASSERT_TRUE(to_be_collapsed_message_view->IsExpanded());
  865. // Delete the first notification. This should begin the slide out animation.
  866. // Let that finish, then State::MOVE_DOWN should begin.
  867. MessageCenter::Get()->RemoveNotification(to_be_removed_notification,
  868. /*by_user=*/true);
  869. FinishSlideOutAnimation();
  870. EXPECT_TRUE(message_list_view()->IsAnimating());
  871. EXPECT_FALSE(message_list_view()->IsAnimatingExpandOrCollapseContainer(
  872. to_be_collapsed_message_view_container));
  873. // Animate to the middle, then attempt to collapse an existing notification.
  874. // All animations should complete.
  875. AnimateToMiddle();
  876. to_be_collapsed_message_view->SetExpanded(false);
  877. EXPECT_FALSE(message_list_view()->IsAnimating());
  878. EXPECT_FALSE(message_list_view()->IsAnimatingExpandOrCollapseContainer(
  879. to_be_collapsed_message_view_container));
  880. EXPECT_GT(
  881. pre_collapse_size.height(),
  882. to_be_collapsed_message_view_container->GetPreferredSize().height());
  883. }
  884. // Tests that moving a notification while it is already collapsing completes
  885. // both animations.
  886. TEST_F(RefreshedUnifiedMessageListView, MoveDuringCollapseNoAnimation) {
  887. auto to_be_removed_notification =
  888. AddNotification(/*pinned=*/false, /*expandable=*/true);
  889. auto to_be_collapsed_notification =
  890. AddNotification(/*pinned=*/false, /*expandable=*/true);
  891. CreateMessageListView();
  892. auto* to_be_collapsed_message_view_container =
  893. message_list_view()->children()[0];
  894. auto* to_be_collapsed_message_view = GetMessageViewAt(0);
  895. const gfx::Size pre_collapse_size =
  896. to_be_collapsed_message_view_container->GetPreferredSize();
  897. ASSERT_TRUE(to_be_collapsed_message_view->IsExpanded());
  898. // Collapse the second notification, then delete the first.
  899. to_be_collapsed_message_view->SetExpanded(false);
  900. AnimateToMiddle();
  901. EXPECT_TRUE(message_list_view()->IsAnimatingExpandOrCollapseContainer(
  902. to_be_collapsed_message_view_container));
  903. EXPECT_TRUE(message_list_view()->IsAnimating());
  904. MessageCenter::Get()->RemoveNotification(to_be_removed_notification,
  905. /*by_user=*/true);
  906. EXPECT_FALSE(message_list_view()->IsAnimatingExpandOrCollapseContainer(
  907. to_be_collapsed_message_view_container));
  908. EXPECT_FALSE(message_list_view()->IsAnimating());
  909. EXPECT_GT(
  910. pre_collapse_size.height(),
  911. to_be_collapsed_message_view_container->GetPreferredSize().height());
  912. }
  913. TEST_F(RefreshedUnifiedMessageListView, SlideNotification) {
  914. // Show message list with four notifications.
  915. auto id0 = AddNotification();
  916. auto id1 = AddNotification();
  917. auto id2 = AddNotification();
  918. auto id3 = AddNotification();
  919. CreateMessageListView();
  920. // At first, there should be no fully rounded corners for the middle
  921. // notification.
  922. EXPECT_EQ(kMessageCenterNotificationCornerRadius,
  923. GetMessageViewAt(2)->top_radius());
  924. EXPECT_EQ(kMessageCenterNotificationCornerRadius,
  925. GetMessageViewAt(2)->bottom_radius());
  926. // Start sliding notification 2 away.
  927. StartSliding(2);
  928. EXPECT_EQ(kBubbleCornerRadius, GetMessageViewAt(2)->bottom_radius());
  929. // Notification 1's bottom corner and notification 3's top corner should also
  930. // be rounded.
  931. EXPECT_EQ(kMessageCenterNotificationCornerRadius,
  932. GetMessageViewAt(1)->top_radius());
  933. EXPECT_EQ(kBubbleCornerRadius, GetMessageViewAt(1)->bottom_radius());
  934. EXPECT_EQ(kBubbleCornerRadius, GetMessageViewAt(3)->top_radius());
  935. EXPECT_EQ(kMessageCenterNotificationCornerRadius,
  936. GetMessageViewAt(3)->bottom_radius());
  937. // Notification 0 should not change.
  938. EXPECT_EQ(kBubbleCornerRadius, GetMessageViewAt(0)->top_radius());
  939. EXPECT_EQ(kMessageCenterNotificationCornerRadius,
  940. GetMessageViewAt(0)->bottom_radius());
  941. // Slide out notification 2, the 3 notifications left should have no rounded
  942. // corner after slide out done.
  943. MessageCenter::Get()->RemoveNotification(id2, /*by_user=*/true);
  944. FinishSlideOutAnimation();
  945. AnimateUntilIdle();
  946. EXPECT_EQ(kMessageCenterNotificationCornerRadius,
  947. GetMessageViewAt(0)->bottom_radius());
  948. EXPECT_EQ(kMessageCenterNotificationCornerRadius,
  949. GetMessageViewAt(1)->top_radius());
  950. // Test with notification 1. Same behavior should happen.
  951. StartSliding(1);
  952. EXPECT_EQ(kBubbleCornerRadius, GetMessageViewAt(1)->top_radius());
  953. EXPECT_EQ(kBubbleCornerRadius, GetMessageViewAt(1)->bottom_radius());
  954. EXPECT_EQ(kMessageCenterNotificationCornerRadius,
  955. GetMessageViewAt(0)->top_radius());
  956. EXPECT_EQ(kBubbleCornerRadius, GetMessageViewAt(0)->bottom_radius());
  957. EXPECT_EQ(kBubbleCornerRadius, GetMessageViewAt(2)->top_radius());
  958. EXPECT_EQ(kMessageCenterNotificationCornerRadius,
  959. GetMessageViewAt(2)->bottom_radius());
  960. // Cancel the slide. Everything goes back to normal.
  961. GetMessageViewAt(1)->OnSlideChanged(/*in_progress=*/false);
  962. for (int i = 0; i <= 2; i++) {
  963. EXPECT_EQ(kMessageCenterNotificationCornerRadius,
  964. GetMessageViewAt(i)->top_radius());
  965. EXPECT_EQ(kMessageCenterNotificationCornerRadius,
  966. GetMessageViewAt(i)->bottom_radius());
  967. }
  968. // Test with the top notification.
  969. StartSliding(0);
  970. EXPECT_EQ(kBubbleCornerRadius, GetMessageViewAt(0)->top_radius());
  971. EXPECT_EQ(kBubbleCornerRadius, GetMessageViewAt(0)->bottom_radius());
  972. EXPECT_EQ(kBubbleCornerRadius, GetMessageViewAt(1)->top_radius());
  973. EXPECT_EQ(kMessageCenterNotificationCornerRadius,
  974. GetMessageViewAt(1)->bottom_radius());
  975. EXPECT_EQ(kMessageCenterNotificationCornerRadius,
  976. GetMessageViewAt(2)->top_radius());
  977. EXPECT_EQ(kMessageCenterNotificationCornerRadius,
  978. GetMessageViewAt(2)->bottom_radius());
  979. GetMessageViewAt(0)->OnSlideChanged(/*in_progress=*/false);
  980. // Test with the bottom notification.
  981. StartSliding(2);
  982. EXPECT_EQ(kMessageCenterNotificationCornerRadius,
  983. GetMessageViewAt(0)->top_radius());
  984. EXPECT_EQ(kMessageCenterNotificationCornerRadius,
  985. GetMessageViewAt(0)->bottom_radius());
  986. EXPECT_EQ(kMessageCenterNotificationCornerRadius,
  987. GetMessageViewAt(1)->top_radius());
  988. EXPECT_EQ(kBubbleCornerRadius, GetMessageViewAt(1)->bottom_radius());
  989. EXPECT_EQ(kBubbleCornerRadius, GetMessageViewAt(2)->top_radius());
  990. EXPECT_EQ(kBubbleCornerRadius, GetMessageViewAt(2)->bottom_radius());
  991. GetMessageViewAt(2)->OnSlideChanged(/*in_progress=*/false);
  992. }
  993. } // namespace ash