metrics_utils_unittest.cc 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590
  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/message_center/metrics_utils.h"
  5. #include "ash/constants/ash_features.h"
  6. #include "ash/system/message_center/ash_message_popup_collection.h"
  7. #include "ash/system/message_center/unified_message_center_bubble.h"
  8. #include "ash/system/message_center/unified_message_center_view.h"
  9. #include "ash/system/message_center/unified_message_list_view.h"
  10. #include "ash/system/unified/unified_system_tray.h"
  11. #include "ash/test/ash_test_base.h"
  12. #include "base/test/metrics/histogram_tester.h"
  13. #include "base/test/scoped_feature_list.h"
  14. #include "base/test/task_environment.h"
  15. #include "ui/events/test/event_generator.h"
  16. #include "ui/gfx/image/image.h"
  17. #include "ui/message_center/message_center.h"
  18. #include "ui/message_center/public/cpp/notification.h"
  19. #include "ui/message_center/public/cpp/notifier_id.h"
  20. #include "ui/views/widget/widget_utils.h"
  21. using message_center::Notification;
  22. namespace {
  23. constexpr char kNotificationViewTypeHistogramName[] =
  24. "Ash.NotificationView.NotificationAdded.Type";
  25. constexpr char kCountInOneGroupHistogramName[] =
  26. "Ash.Notification.CountOfNotificationsInOneGroup";
  27. constexpr char kGroupNotificationAddedHistogramName[] =
  28. "Ash.Notification.GroupNotificationAdded";
  29. constexpr char kSystemNotificationAddedHistogramName[] =
  30. "Ash.NotifierFramework.SystemNotification.Added";
  31. constexpr char kPinnedSystemNotificationAddedHistogramName[] =
  32. "Ash.NotifierFramework.PinnedSystemNotification.Added";
  33. constexpr char kSystemNotificationPopupShownHistogramName[] =
  34. "Ash.NotifierFramework.SystemNotification.Popup.ShownCount";
  35. constexpr char kSystemNotificationPopupUserJourneyTime[] =
  36. "Ash.NotifierFramework.SystemNotification.Popup.UserJourneyTime";
  37. constexpr char kSystemNotificationPopupDismissedWithin1s[] =
  38. "Ash.NotifierFramework.SystemNotification.Popup.Dismissed.Within1s";
  39. constexpr char kSystemNotificationPopupDismissedWithin7s[] =
  40. "Ash.NotifierFramework.SystemNotification.Popup.Dismissed.Within7s";
  41. constexpr char kSystemNotificationPopupDismissedAfter7s[] =
  42. "Ash.NotifierFramework.SystemNotification.Popup.Dismissed.After7s";
  43. const gfx::Image CreateTestImage() {
  44. SkBitmap bitmap;
  45. bitmap.allocN32Pixels(/*width=*/80, /*height=*/80);
  46. bitmap.eraseColor(SK_ColorGREEN);
  47. return gfx::Image::CreateFrom1xBitmap(bitmap);
  48. }
  49. void CheckNotificationViewTypeRecorded(
  50. std::unique_ptr<Notification> notification,
  51. ash::metrics_utils::NotificationViewType type) {
  52. base::HistogramTester histograms;
  53. // Add the notification. Expect that the corresponding notification type is
  54. // recorded.
  55. message_center::MessageCenter::Get()->AddNotification(
  56. std::move(notification));
  57. histograms.ExpectBucketCount(kNotificationViewTypeHistogramName, type, 1);
  58. }
  59. // A blocker that blocks a notification with the given ID.
  60. class IdNotificationBlocker : public message_center::NotificationBlocker {
  61. public:
  62. explicit IdNotificationBlocker(message_center::MessageCenter* message_center)
  63. : NotificationBlocker(message_center) {}
  64. IdNotificationBlocker(const IdNotificationBlocker&) = delete;
  65. IdNotificationBlocker& operator=(const IdNotificationBlocker&) = delete;
  66. ~IdNotificationBlocker() override = default;
  67. void SetTargetIdAndNotifyBlock(const std::string& target_id) {
  68. target_id_ = target_id;
  69. NotifyBlockingStateChanged();
  70. }
  71. // message_center::NotificationBlocker:
  72. bool ShouldShowNotification(
  73. const message_center::Notification& notification) const override {
  74. return notification.id() != target_id_;
  75. }
  76. bool ShouldShowNotificationAsPopup(
  77. const message_center::Notification& notification) const override {
  78. return notification.id() != target_id_;
  79. }
  80. private:
  81. std::string target_id_;
  82. };
  83. // Returns true if a notification with a given `id` is showing a notification in
  84. // the message center.
  85. bool NotificationVisible(const std::string& id) {
  86. return message_center::MessageCenter::Get()->FindVisibleNotificationById(
  87. id) != nullptr;
  88. }
  89. // Returns true if a notification with a given `id` has a pop-up.
  90. bool PopupVisible(const std::string& id) {
  91. return message_center::MessageCenter::Get()->FindPopupNotificationById(id) !=
  92. nullptr;
  93. }
  94. } // namespace
  95. namespace ash {
  96. // This serves as an unit test class for all metrics recording in
  97. // notification/message center.
  98. class MessageCenterMetricsUtilsTest : public AshTestBase {
  99. public:
  100. MessageCenterMetricsUtilsTest()
  101. : AshTestBase(base::test::TaskEnvironment::TimeSource::MOCK_TIME) {
  102. scoped_feature_list_ = std::make_unique<base::test::ScopedFeatureList>();
  103. scoped_feature_list_->InitAndEnableFeature(features::kNotificationsRefresh);
  104. }
  105. MessageCenterMetricsUtilsTest(const MessageCenterMetricsUtilsTest&) = delete;
  106. MessageCenterMetricsUtilsTest& operator=(
  107. const MessageCenterMetricsUtilsTest&) = delete;
  108. ~MessageCenterMetricsUtilsTest() override = default;
  109. // AshTestBase:
  110. void SetUp() override {
  111. AshTestBase::SetUp();
  112. test_delegate_ =
  113. base::MakeRefCounted<message_center::NotificationDelegate>();
  114. }
  115. // Create a test notification. Noted that the notifications are using the same
  116. // url and profile id so that they are grouped together.
  117. std::unique_ptr<Notification> CreateTestNotification() {
  118. message_center::RichNotificationData data;
  119. data.settings_button_handler =
  120. message_center::SettingsButtonHandler::INLINE;
  121. message_center::NotifierId notifier_id;
  122. notifier_id.profile_id = "a@b.com";
  123. notifier_id.type = message_center::NotifierType::WEB_PAGE;
  124. return std::make_unique<Notification>(
  125. message_center::NOTIFICATION_TYPE_SIMPLE,
  126. base::NumberToString(current_id_++), u"title", u"message",
  127. ui::ImageModel(), u"display source", GURL(u"http://test-url.com"),
  128. notifier_id, data,
  129. /*delegate=*/nullptr);
  130. }
  131. // Create a system notification with given `catalog_name`.
  132. std::unique_ptr<Notification> CreateNotificationWithCatalogName(
  133. NotificationCatalogName catalog_name) {
  134. const std::string id =
  135. "id" + base::NumberToString(static_cast<int>(catalog_name));
  136. message_center::RichNotificationData data;
  137. return std::make_unique<Notification>(
  138. message_center::NOTIFICATION_TYPE_SIMPLE, id, u"title", u"message",
  139. ui::ImageModel(), u"display source", GURL(u"http://test-url.com"),
  140. message_center::NotifierId(
  141. message_center::NotifierType::SYSTEM_COMPONENT, id, catalog_name),
  142. data, /*delegate=*/nullptr);
  143. }
  144. // Create a pinned system notification with given `catalog_name`.
  145. std::unique_ptr<Notification> CreatePinnedNotificationWithCatalogName(
  146. NotificationCatalogName catalog_name) {
  147. auto notification = CreateNotificationWithCatalogName(catalog_name);
  148. notification->set_pinned(true);
  149. return notification;
  150. }
  151. // Get the notification view from message center associated with `id`.
  152. views::View* GetNotificationViewFromMessageCenter(const std::string& id) {
  153. return GetPrimaryUnifiedSystemTray()
  154. ->message_center_bubble()
  155. ->message_center_view()
  156. ->message_list_view()
  157. ->GetMessageViewForNotificationId(id);
  158. }
  159. // Get the popup notification view associated with `id`.
  160. views::View* GetPopupNotificationView(const std::string& id) {
  161. return GetPrimaryUnifiedSystemTray()
  162. ->GetMessagePopupCollection()
  163. ->GetMessageViewForNotificationId(id);
  164. }
  165. void ClickView(views::View* view) {
  166. ui::test::EventGenerator generator(GetRootWindow(view->GetWidget()));
  167. gfx::Point cursor_location = view->GetBoundsInScreen().CenterPoint();
  168. generator.MoveMouseTo(cursor_location);
  169. generator.ClickLeftButton();
  170. }
  171. void HoverOnView(views::View* view) {
  172. ui::test::EventGenerator generator(GetRootWindow(view->GetWidget()));
  173. gfx::Point cursor_location = view->GetBoundsInScreen().CenterPoint();
  174. generator.MoveMouseTo(cursor_location);
  175. }
  176. scoped_refptr<message_center::NotificationDelegate> test_delegate() {
  177. return test_delegate_;
  178. }
  179. private:
  180. scoped_refptr<message_center::NotificationDelegate> test_delegate_;
  181. std::unique_ptr<base::test::ScopedFeatureList> scoped_feature_list_;
  182. // Used to create test notification. This represents the current available
  183. // number that we can use to create the next test notification. This id will
  184. // be incremented whenever we create a new test notification.
  185. int current_id_ = 0;
  186. };
  187. TEST_F(MessageCenterMetricsUtilsTest, RecordBadClicks) {
  188. base::HistogramTester histograms;
  189. auto notification = CreateTestNotification();
  190. // Add the notification and get its view in message center.
  191. message_center::MessageCenter::Get()->AddNotification(
  192. std::make_unique<message_center::Notification>(*notification));
  193. GetPrimaryUnifiedSystemTray()->ShowBubble();
  194. // A click to a notification without a delegate should record a bad click.
  195. ClickView(GetNotificationViewFromMessageCenter(notification->id()));
  196. histograms.ExpectTotalCount("Notifications.Cros.Actions.ClickedBody.BadClick",
  197. 1);
  198. histograms.ExpectTotalCount(
  199. "Notifications.Cros.Actions.ClickedBody.GoodClick", 0);
  200. }
  201. TEST_F(MessageCenterMetricsUtilsTest, RecordGoodClicks) {
  202. base::HistogramTester histograms;
  203. auto notification = CreateTestNotification();
  204. notification->set_delegate(test_delegate());
  205. // Add the notification and get its view in message center.
  206. message_center::MessageCenter::Get()->AddNotification(
  207. std::make_unique<message_center::Notification>(*notification));
  208. GetPrimaryUnifiedSystemTray()->ShowBubble();
  209. // A click to a notification with a delegate should record a good click.
  210. ClickView(GetNotificationViewFromMessageCenter(notification->id()));
  211. histograms.ExpectTotalCount(
  212. "Notifications.Cros.Actions.ClickedBody.GoodClick", 1);
  213. histograms.ExpectTotalCount("Notifications.Cros.Actions.ClickedBody.BadClick",
  214. 0);
  215. }
  216. TEST_F(MessageCenterMetricsUtilsTest, RecordHover) {
  217. base::HistogramTester histograms;
  218. auto notification = CreateTestNotification();
  219. // Add the notification and get its view in message center.
  220. message_center::MessageCenter::Get()->AddNotification(
  221. std::make_unique<message_center::Notification>(*notification));
  222. auto* popup = GetPopupNotificationView(notification->id());
  223. // Move the mouse hover on the popup notification view, expect hover action
  224. // recorded.
  225. HoverOnView(popup);
  226. histograms.ExpectTotalCount("Notifications.Cros.Actions.Popup.Hover", 1);
  227. GetPrimaryUnifiedSystemTray()->ShowBubble();
  228. auto* notification_view =
  229. GetNotificationViewFromMessageCenter(notification->id());
  230. // Move the mouse hover on the notification view, expect hover action
  231. // recorded.
  232. HoverOnView(notification_view);
  233. histograms.ExpectTotalCount("Notifications.Cros.Actions.Tray.Hover", 1);
  234. }
  235. TEST_F(MessageCenterMetricsUtilsTest, RecordNotificationViewTypeSimple) {
  236. message_center::MessageCenter::Get()->RemoveAllNotifications(
  237. /*by_user=*/true, message_center::MessageCenter::RemoveType::ALL);
  238. auto simple_notification = CreateTestNotification();
  239. CheckNotificationViewTypeRecorded(
  240. std::move(simple_notification),
  241. metrics_utils::NotificationViewType::SIMPLE);
  242. auto grouped_simple_notification = CreateTestNotification();
  243. CheckNotificationViewTypeRecorded(
  244. std::move(grouped_simple_notification),
  245. metrics_utils::NotificationViewType::GROUPED_SIMPLE);
  246. }
  247. TEST_F(MessageCenterMetricsUtilsTest, RecordNotificationViewTypeImage) {
  248. message_center::MessageCenter::Get()->RemoveAllNotifications(
  249. /*by_user=*/true, message_center::MessageCenter::RemoveType::ALL);
  250. auto image_notification = CreateTestNotification();
  251. image_notification->set_image(CreateTestImage());
  252. CheckNotificationViewTypeRecorded(
  253. std::move(image_notification),
  254. metrics_utils::NotificationViewType::HAS_IMAGE);
  255. auto grouped_image_notification = CreateTestNotification();
  256. grouped_image_notification->set_image(CreateTestImage());
  257. CheckNotificationViewTypeRecorded(
  258. std::move(grouped_image_notification),
  259. metrics_utils::NotificationViewType::GROUPED_HAS_IMAGE);
  260. }
  261. TEST_F(MessageCenterMetricsUtilsTest, RecordNotificationViewTypeActionButtons) {
  262. message_center::MessageCenter::Get()->RemoveAllNotifications(
  263. /*by_user=*/true, message_center::MessageCenter::RemoveType::ALL);
  264. auto notification = CreateTestNotification();
  265. notification->set_buttons({message_center::ButtonInfo(u"Test button")});
  266. CheckNotificationViewTypeRecorded(
  267. std::move(notification), metrics_utils::NotificationViewType::HAS_ACTION);
  268. auto grouped_notification = CreateTestNotification();
  269. grouped_notification->set_buttons(
  270. {message_center::ButtonInfo(u"Test button")});
  271. CheckNotificationViewTypeRecorded(
  272. std::move(grouped_notification),
  273. metrics_utils::NotificationViewType::GROUPED_HAS_ACTION);
  274. }
  275. TEST_F(MessageCenterMetricsUtilsTest, RecordNotificationViewTypeInlineReply) {
  276. message_center::MessageCenter::Get()->RemoveAllNotifications(
  277. /*by_user=*/true, message_center::MessageCenter::RemoveType::ALL);
  278. auto create_inline_reply_button = []() {
  279. message_center::ButtonInfo button(u"Test button");
  280. button.placeholder = std::u16string();
  281. return button;
  282. };
  283. auto notification = CreateTestNotification();
  284. notification->set_buttons({create_inline_reply_button()});
  285. CheckNotificationViewTypeRecorded(
  286. std::move(notification),
  287. metrics_utils::NotificationViewType::HAS_INLINE_REPLY);
  288. auto grouped_notification = CreateTestNotification();
  289. grouped_notification->set_buttons({create_inline_reply_button()});
  290. CheckNotificationViewTypeRecorded(
  291. std::move(grouped_notification),
  292. metrics_utils::NotificationViewType::GROUPED_HAS_INLINE_REPLY);
  293. }
  294. TEST_F(MessageCenterMetricsUtilsTest,
  295. RecordNotificationViewTypeImageActionButtons) {
  296. message_center::MessageCenter::Get()->RemoveAllNotifications(
  297. /*by_user=*/true, message_center::MessageCenter::RemoveType::ALL);
  298. auto notification = CreateTestNotification();
  299. notification->set_image(CreateTestImage());
  300. notification->set_buttons({message_center::ButtonInfo(u"Test button")});
  301. CheckNotificationViewTypeRecorded(
  302. std::move(notification),
  303. metrics_utils::NotificationViewType::HAS_IMAGE_AND_ACTION);
  304. auto grouped_notification = CreateTestNotification();
  305. grouped_notification->set_image(CreateTestImage());
  306. grouped_notification->set_buttons(
  307. {message_center::ButtonInfo(u"Test button")});
  308. CheckNotificationViewTypeRecorded(
  309. std::move(grouped_notification),
  310. metrics_utils::NotificationViewType::GROUPED_HAS_IMAGE_AND_ACTION);
  311. }
  312. TEST_F(MessageCenterMetricsUtilsTest,
  313. RecordNotificationViewTypeImageInlineReply) {
  314. message_center::MessageCenter::Get()->RemoveAllNotifications(
  315. /*by_user=*/true, message_center::MessageCenter::RemoveType::ALL);
  316. auto create_inline_reply_button = []() {
  317. message_center::ButtonInfo button(u"Test button");
  318. button.placeholder = std::u16string();
  319. return button;
  320. };
  321. auto notification = CreateTestNotification();
  322. notification->set_image(CreateTestImage());
  323. notification->set_buttons({create_inline_reply_button()});
  324. CheckNotificationViewTypeRecorded(
  325. std::move(notification),
  326. metrics_utils::NotificationViewType::HAS_IMAGE_AND_INLINE_REPLY);
  327. auto grouped_notification = CreateTestNotification();
  328. grouped_notification->set_image(CreateTestImage());
  329. grouped_notification->set_buttons({create_inline_reply_button()});
  330. CheckNotificationViewTypeRecorded(
  331. std::move(grouped_notification),
  332. metrics_utils::NotificationViewType::GROUPED_HAS_IMAGE_AND_INLINE_REPLY);
  333. }
  334. TEST_F(MessageCenterMetricsUtilsTest, RecordCountOfNotificationsInOneGroup) {
  335. base::HistogramTester histograms;
  336. auto notification1 = CreateTestNotification();
  337. std::string id1 = notification1->id();
  338. auto notification2 = CreateTestNotification();
  339. std::string id2 = notification2->id();
  340. auto notification3 = CreateTestNotification();
  341. message_center::MessageCenter::Get()->AddNotification(
  342. std::move(notification1));
  343. message_center::MessageCenter::Get()->AddNotification(
  344. std::move(notification2));
  345. histograms.ExpectBucketCount(kCountInOneGroupHistogramName, 2, 1);
  346. message_center::MessageCenter::Get()->AddNotification(
  347. std::move(notification3));
  348. histograms.ExpectBucketCount(kCountInOneGroupHistogramName, 3, 1);
  349. message_center::MessageCenter::Get()->RemoveNotification(id1,
  350. /*by_user=*/true);
  351. histograms.ExpectBucketCount(kCountInOneGroupHistogramName, 2, 2);
  352. }
  353. TEST_F(MessageCenterMetricsUtilsTest, RecordGroupNotificationAddedType) {
  354. base::HistogramTester histograms;
  355. auto notification1 = CreateTestNotification();
  356. auto notification2 = CreateTestNotification();
  357. auto notification3 = CreateTestNotification();
  358. message_center::MessageCenter::Get()->AddNotification(
  359. std::move(notification1));
  360. message_center::MessageCenter::Get()->AddNotification(
  361. std::move(notification2));
  362. // There should be 1 group parent that contains 2 group child notifications.
  363. histograms.ExpectBucketCount(
  364. kGroupNotificationAddedHistogramName,
  365. metrics_utils::GroupNotificationType::GROUP_PARENT, 1);
  366. histograms.ExpectBucketCount(
  367. kGroupNotificationAddedHistogramName,
  368. metrics_utils::GroupNotificationType::GROUP_CHILD, 2);
  369. message_center::MessageCenter::Get()->AddNotification(
  370. std::move(notification3));
  371. histograms.ExpectBucketCount(
  372. kGroupNotificationAddedHistogramName,
  373. metrics_utils::GroupNotificationType::GROUP_PARENT, 1);
  374. histograms.ExpectBucketCount(
  375. kGroupNotificationAddedHistogramName,
  376. metrics_utils::GroupNotificationType::GROUP_CHILD, 3);
  377. }
  378. TEST_F(MessageCenterMetricsUtilsTest, RecordSystemNotificationAdded) {
  379. base::HistogramTester histograms;
  380. // Create a system notification with `kTestCatalogName` for its catalog name.
  381. const NotificationCatalogName test_catalog_name =
  382. NotificationCatalogName::kTestCatalogName;
  383. auto test_notification = CreateNotificationWithCatalogName(test_catalog_name);
  384. message_center::MessageCenter::Get()->AddNotification(
  385. std::move(test_notification));
  386. // Check metrics are not recorded for `kTestCatalogName`.
  387. histograms.ExpectBucketCount(kSystemNotificationAddedHistogramName,
  388. test_catalog_name, 0);
  389. // Create system notifications with a valid catalog name, one for a non-pinned
  390. // notification and one for a pinned one (e.g. Full Restore and Caps Lock).
  391. const NotificationCatalogName catalog_name =
  392. NotificationCatalogName::kFullRestore;
  393. const NotificationCatalogName pinned_catalog_name =
  394. NotificationCatalogName::kCapsLock;
  395. auto notification = CreateNotificationWithCatalogName(catalog_name);
  396. auto pinned_notification =
  397. CreatePinnedNotificationWithCatalogName(pinned_catalog_name);
  398. // Add notifications to message center.
  399. auto* message_center = message_center::MessageCenter::Get();
  400. message_center->AddNotification(
  401. std::make_unique<message_center::Notification>(*notification));
  402. message_center->AddNotification(
  403. std::make_unique<message_center::Notification>(*pinned_notification));
  404. // Expect metric to be recorded for valid catalog names.
  405. histograms.ExpectBucketCount(kSystemNotificationAddedHistogramName,
  406. catalog_name, 1);
  407. histograms.ExpectBucketCount(kPinnedSystemNotificationAddedHistogramName,
  408. pinned_catalog_name, 1);
  409. }
  410. TEST_F(MessageCenterMetricsUtilsTest,
  411. RecordSystemNotificationAddedWithNotificationBlockers) {
  412. base::HistogramTester histograms;
  413. // Create a system notification with a valid catalog name (e.g. Full Restore).
  414. const NotificationCatalogName catalog_name =
  415. NotificationCatalogName::kFullRestore;
  416. auto notification = CreateNotificationWithCatalogName(catalog_name);
  417. // Add notification to message center.
  418. auto* message_center = message_center::MessageCenter::Get();
  419. message_center->AddNotification(
  420. std::make_unique<message_center::Notification>(*notification));
  421. // Verify notification was shown.
  422. EXPECT_TRUE(PopupVisible(notification->id()));
  423. EXPECT_TRUE(NotificationVisible(notification->id()));
  424. // Expect `Added` and `PopupShown` metrics to be recorded.
  425. histograms.ExpectBucketCount(kSystemNotificationAddedHistogramName,
  426. catalog_name, 1);
  427. histograms.ExpectBucketCount(kSystemNotificationPopupShownHistogramName,
  428. catalog_name, 1);
  429. // Apply a notification blocker.
  430. IdNotificationBlocker blocker(message_center);
  431. blocker.SetTargetIdAndNotifyBlock(notification->id());
  432. // Add more notification instances to the message center.
  433. message_center->RemoveNotification(notification->id(), /*by_user=*/false);
  434. message_center->AddNotification(
  435. std::make_unique<message_center::Notification>(*notification));
  436. // Verify notification wasn't shown with notification blockers.
  437. EXPECT_FALSE(PopupVisible(notification->id()));
  438. EXPECT_FALSE(NotificationVisible(notification->id()));
  439. // Verify the `Added` metric is recorded even with notification blockers.
  440. histograms.ExpectBucketCount(kSystemNotificationAddedHistogramName,
  441. catalog_name, 2);
  442. // Verify `Popup Shown` metric is not recorded with notification blockers.
  443. histograms.ExpectBucketCount(kSystemNotificationPopupShownHistogramName,
  444. catalog_name, 1);
  445. }
  446. TEST_F(MessageCenterMetricsUtilsTest, RecordPopupUserJourneyTime) {
  447. base::HistogramTester histograms;
  448. // Create a non-pinned system notification with a valid catalog name.
  449. const NotificationCatalogName catalog_name =
  450. NotificationCatalogName::kFullRestore;
  451. auto notification = CreateNotificationWithCatalogName(catalog_name);
  452. // Add notification to message center.
  453. auto* message_center = message_center::MessageCenter::Get();
  454. message_center->AddNotification(
  455. std::make_unique<message_center::Notification>(*notification));
  456. // Wait for notification popup to time out.
  457. base::TimeDelta popup_timeout_duration = base::Seconds(7);
  458. task_environment()->FastForwardBy(popup_timeout_duration);
  459. // Expect user journey time metric to record the popup duration due to timeout
  460. // (value is between 6 and 7 seconds).
  461. auto buckets =
  462. histograms.GetAllSamples(kSystemNotificationPopupUserJourneyTime);
  463. EXPECT_TRUE(buckets[0].min >= 6000 && buckets[0].min <= 7000);
  464. histograms.ExpectBucketCount(kSystemNotificationPopupDismissedWithin7s,
  465. catalog_name, 1);
  466. message_center->RemoveNotification(notification->id(), /*by_user=*/true);
  467. // Dismiss popup within 1s.
  468. notification->set_timestamp(base::Time::Now());
  469. message_center->AddNotification(
  470. std::make_unique<message_center::Notification>(*notification));
  471. message_center->RemoveNotification(notification->id(), /*by_user=*/true);
  472. task_environment()->FastForwardBy(popup_timeout_duration);
  473. histograms.ExpectBucketCount(kSystemNotificationPopupDismissedWithin1s,
  474. catalog_name, 1);
  475. // Dismiss "never timeout" popup after 7s.
  476. notification->set_timestamp(base::Time::Now());
  477. notification->set_never_timeout(true);
  478. message_center->AddNotification(
  479. std::make_unique<message_center::Notification>(*notification));
  480. task_environment()->FastForwardBy(popup_timeout_duration + base::Seconds(1));
  481. message_center->RemoveNotification(notification->id(), /*by_user=*/true);
  482. task_environment()->FastForwardBy(popup_timeout_duration);
  483. histograms.ExpectBucketCount(kSystemNotificationPopupDismissedAfter7s,
  484. catalog_name, 1);
  485. }
  486. } // namespace ash