| // Copyright 2023 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "ash/capture_mode/capture_mode_education_controller.h" |
| |
| #include "ash/accelerators/accelerator_tracker.h" |
| #include "ash/capture_mode/capture_mode_controller.h" |
| #include "ash/constants/ash_features.h" |
| #include "ash/constants/ash_pref_names.h" |
| #include "ash/constants/notifier_catalogs.h" |
| #include "ash/public/cpp/ash_view_ids.h" |
| #include "ash/root_window_controller.h" |
| #include "ash/shell.h" |
| #include "ash/style/keyboard_shortcut_view.h" |
| #include "ash/system/toast/anchored_nudge.h" |
| #include "ash/system/toast/anchored_nudge_manager_impl.h" |
| #include "ash/test/ash_test_base.h" |
| #include "base/test/metrics/histogram_tester.h" |
| #include "base/test/scoped_feature_list.h" |
| #include "base/test/simple_test_clock.h" |
| #include "base/test/task_environment.h" |
| #include "base/time/time.h" |
| #include "ui/events/event_constants.h" |
| #include "ui/events/keycodes/keyboard_codes_posix.h" |
| |
| namespace ash { |
| |
| namespace { |
| |
| constexpr char kCaptureModeNudgeId[] = "kCaptureModeNudge"; |
| |
| constexpr char kNudgeTimeToActionWithin1m[] = |
| "Ash.NotifierFramework.Nudge.TimeToAction.Within1m"; |
| constexpr char kNudgeTimeToActionWithin1h[] = |
| "Ash.NotifierFramework.Nudge.TimeToAction.Within1h"; |
| constexpr char kNudgeTimeToActionWithinSession[] = |
| "Ash.NotifierFramework.Nudge.TimeToAction.WithinSession"; |
| |
| constexpr float kKeyboardImageWidth = 448; |
| constexpr int kNudgeWorkAreaSpacing = 8; |
| |
| PrefService* GetPrefService() { |
| return Shell::Get()->session_controller()->GetActivePrefService(); |
| } |
| |
| void CancelNudge(const std::string& id) { |
| Shell::Get()->anchored_nudge_manager()->Cancel(id); |
| } |
| |
| } // namespace |
| |
| class CaptureModeEducationControllerTest : public AshTestBase { |
| public: |
| CaptureModeEducationControllerTest(const std::string& arm_name = "") |
| : AshTestBase(base::test::TaskEnvironment::TimeSource::MOCK_TIME) { |
| scoped_feature_list_.InitWithFeaturesAndParameters( |
| /*enabled_features=*/ |
| {{features::kCaptureModeEducation, |
| {{"CaptureModeEducationParam", arm_name}}}}, |
| /*disabled_features=*/{}); |
| } |
| CaptureModeEducationControllerTest( |
| const CaptureModeEducationControllerTest&) = delete; |
| CaptureModeEducationControllerTest& operator=( |
| const CaptureModeEducationControllerTest&) = delete; |
| ~CaptureModeEducationControllerTest() override = default; |
| |
| static void SetOverrideClock(base::Clock* test_clock) { |
| CaptureModeEducationController::SetOverrideClockForTesting(test_clock); |
| } |
| |
| // By default, attempts to use the Windows Snipping Tool (capture bar) |
| // shortcut to activate the nudge. |
| void ActivateNudgeAndCheckVisibility(ui::KeyboardCode key_code = ui::VKEY_S, |
| int flags = ui::EF_COMMAND_DOWN | |
| ui::EF_SHIFT_DOWN) { |
| // Attempt to use the Windows Snipping Tool (capture bar) shortcut. |
| PressAndReleaseKey(key_code, flags); |
| |
| // Get the list of visible nudges from the nudge manager and make sure our |
| // education nudge is in the list and visible. |
| const AnchoredNudge* nudge = |
| Shell::Get()->anchored_nudge_manager()->GetNudgeIfShown( |
| kCaptureModeNudgeId); |
| ASSERT_TRUE(nudge); |
| EXPECT_TRUE(nudge->GetVisible()); |
| } |
| |
| // Starts a capture session using the screenshot shortcut, and verifies that |
| // the nudge and tutorial are both closed. Stops the session afterwards. |
| void StartSessionAndCheckEducationClosed() { |
| // Use the screenshot shortcut to start a capture session. |
| PressAndReleaseKey(ui::VKEY_MEDIA_LAUNCH_APP1, |
| ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN); |
| |
| auto* capture_mode_controller = CaptureModeController::Get(); |
| ASSERT_TRUE(capture_mode_controller->IsActive()); |
| |
| // Get the list of visible nudges from the nudge manager and make sure our |
| // education nudge is no longer in the list. |
| const AnchoredNudge* nudge = |
| Shell::Get()->anchored_nudge_manager()->GetNudgeIfShown( |
| kCaptureModeNudgeId); |
| EXPECT_FALSE(nudge); |
| |
| // The tutorial should also be closed. |
| EXPECT_FALSE(capture_mode_controller->education_controller() |
| ->tutorial_widget_for_test()); |
| |
| // Stop the session in case we start a new one later. |
| capture_mode_controller->Stop(); |
| ASSERT_FALSE(capture_mode_controller->IsActive()); |
| } |
| |
| // Skip the 3 times/24 hours show limit for testing. |
| void SkipNudgePrefs() { |
| CaptureModeController::Get()->education_controller()->skip_prefs_for_test_ = |
| true; |
| } |
| |
| protected: |
| base::test::ScopedFeatureList scoped_feature_list_; |
| }; |
| |
| TEST_F(CaptureModeEducationControllerTest, Exists) { |
| // Check that the default arm is enabled. |
| ASSERT_EQ(features::kCaptureModeEducationParam.Get(), |
| features::CaptureModeEducationParam::kShortcutNudge); |
| ASSERT_TRUE(CaptureModeController::Get()->education_controller()); |
| } |
| |
| TEST_F(CaptureModeEducationControllerTest, NudgeAppearsOnAcceleratorPressed) { |
| base::SimpleTestClock test_clock; |
| CaptureModeEducationControllerTest::SetOverrideClock(&test_clock); |
| |
| // We will need to show the nudge more than three times, so ignore pref |
| // limits. |
| SkipNudgePrefs(); |
| |
| for (auto [tracker_data, metadata] : kAcceleratorTrackerList) { |
| // We only want to test capture mode related misinputs. |
| if (metadata.type != TrackerType::kCaptureMode) { |
| continue; |
| } |
| |
| ActivateNudgeAndCheckVisibility(tracker_data.key_code, tracker_data.flags); |
| |
| // Close nudge to get ready for the next input. |
| CancelNudge(kCaptureModeNudgeId); |
| } |
| } |
| |
| // Test fixture to verify the behaviour of Arm 1, the shortcut nudge. |
| class CaptureModeEducationShortcutNudgeTest |
| : public CaptureModeEducationControllerTest { |
| public: |
| CaptureModeEducationShortcutNudgeTest() |
| : CaptureModeEducationControllerTest("ShortcutNudge") {} |
| CaptureModeEducationShortcutNudgeTest( |
| const CaptureModeEducationShortcutNudgeTest&) = delete; |
| CaptureModeEducationShortcutNudgeTest& operator=( |
| const CaptureModeEducationShortcutNudgeTest&) = delete; |
| ~CaptureModeEducationShortcutNudgeTest() override = default; |
| }; |
| |
| TEST_F(CaptureModeEducationShortcutNudgeTest, KeyboardShortcutVisible) { |
| base::SimpleTestClock test_clock; |
| CaptureModeEducationControllerTest::SetOverrideClock(&test_clock); |
| |
| // Advance clock so we aren't at zero time. |
| test_clock.Advance(base::Hours(25)); |
| |
| // Attempt to use the Windows Snipping Tool (capture bar) shortcut. |
| PressAndReleaseKey(ui::VKEY_S, ui::EF_COMMAND_DOWN | ui::EF_SHIFT_DOWN); |
| |
| // Get the list of visible nudges from the nudge manager and make sure our |
| // education nudge is in the list and visible. |
| AnchoredNudge* nudge = |
| Shell::Get()->anchored_nudge_manager()->GetNudgeIfShown( |
| kCaptureModeNudgeId); |
| ASSERT_TRUE(nudge); |
| EXPECT_TRUE(nudge->GetVisible()); |
| |
| // The keyboard shortcut view should be visible. |
| auto* shortcut_view = views::AsViewClass<KeyboardShortcutView>( |
| nudge->GetContentsView()->GetViewByID( |
| VIEW_ID_SYSTEM_NUDGE_SHORTCUT_VIEW)); |
| ASSERT_TRUE(shortcut_view); |
| EXPECT_TRUE(shortcut_view->GetVisible()); |
| |
| StartSessionAndCheckEducationClosed(); |
| |
| CaptureModeEducationControllerTest::SetOverrideClock(nullptr); |
| } |
| |
| TEST_F(CaptureModeEducationShortcutNudgeTest, EducationPreferencesShowLimit) { |
| base::SimpleTestClock test_clock; |
| CaptureModeEducationControllerTest::SetOverrideClock(&test_clock); |
| |
| // Advance clock so we aren't at zero time. |
| test_clock.Advance(base::Hours(25)); |
| |
| AnchoredNudgeManagerImpl* nudge_manager = |
| Shell::Get()->anchored_nudge_manager(); |
| for (int i = 0; i < 3; i++) { |
| ActivateNudgeAndCheckVisibility(); |
| |
| // Showing the nudge should also update the preferences. |
| EXPECT_EQ( |
| GetPrefService()->GetInteger(prefs::kCaptureModeEducationShownCount), |
| i + 1); |
| |
| // Close the nudge. |
| CancelNudge(kCaptureModeNudgeId); |
| |
| // Advance the clock so we can show the nudge again. |
| test_clock.Advance(base::Hours(25)); |
| } |
| |
| // Activate the nudge once more. |
| PressAndReleaseKey(ui::VKEY_S, ui::EF_COMMAND_DOWN | ui::EF_SHIFT_DOWN); |
| |
| // The nudge should not be visible. |
| const AnchoredNudge* nudge = |
| nudge_manager->GetNudgeIfShown(kCaptureModeNudgeId); |
| ASSERT_FALSE(nudge); |
| |
| // The nudge count should not increment as the nudge was not shown. |
| EXPECT_EQ( |
| GetPrefService()->GetInteger(prefs::kCaptureModeEducationShownCount), 3); |
| |
| CaptureModeEducationControllerTest::SetOverrideClock(nullptr); |
| } |
| |
| TEST_F(CaptureModeEducationShortcutNudgeTest, EducationPreferencesTimeLimit) { |
| base::SimpleTestClock test_clock; |
| CaptureModeEducationControllerTest::SetOverrideClock(&test_clock); |
| |
| // Advance clock so we aren't at zero time. |
| test_clock.Advance(base::Hours(25)); |
| |
| ActivateNudgeAndCheckVisibility(); |
| |
| // Showing the nudge should also update the preferences. |
| EXPECT_EQ( |
| GetPrefService()->GetInteger(prefs::kCaptureModeEducationShownCount), 1); |
| |
| // Close the nudge. |
| CancelNudge(kCaptureModeNudgeId); |
| |
| // Advance the clock, but not more than 24 hours. |
| test_clock.Advance(base::Hours(20)); |
| |
| // Activate the nudge once more. |
| PressAndReleaseKey(ui::VKEY_S, ui::EF_COMMAND_DOWN | ui::EF_SHIFT_DOWN); |
| |
| // The nudge should not be visible. |
| const AnchoredNudge* null_nudge = |
| Shell::Get()->anchored_nudge_manager()->GetNudgeIfShown( |
| kCaptureModeNudgeId); |
| ASSERT_FALSE(null_nudge); |
| |
| // The nudge count should not increment as the nudge was not shown. |
| EXPECT_EQ( |
| GetPrefService()->GetInteger(prefs::kCaptureModeEducationShownCount), 1); |
| |
| CaptureModeEducationControllerTest::SetOverrideClock(nullptr); |
| } |
| |
| // Tests that metrics relating to the shortcut nudge (Arm 1) are properly |
| // recorded. |
| TEST_F(CaptureModeEducationShortcutNudgeTest, ShortcutNudgeMetrics) { |
| base::HistogramTester histogram_tester; |
| |
| // For this test, we do not care about pref limits. |
| SkipNudgePrefs(); |
| |
| // The nudge has not been activated, so all related buckets should be at 0. |
| Shell::Get()->anchored_nudge_manager()->ResetNudgeRegistryForTesting(); |
| histogram_tester.ExpectBucketCount( |
| kNudgeTimeToActionWithin1m, |
| NudgeCatalogName::kCaptureModeEducationShortcutNudge, 0); |
| histogram_tester.ExpectBucketCount( |
| kNudgeTimeToActionWithin1h, |
| NudgeCatalogName::kCaptureModeEducationShortcutNudge, 0); |
| histogram_tester.ExpectBucketCount( |
| kNudgeTimeToActionWithinSession, |
| NudgeCatalogName::kCaptureModeEducationShortcutNudge, 0); |
| |
| // The other nudge buckets should be empty as well. |
| histogram_tester.ExpectBucketCount( |
| kNudgeTimeToActionWithin1m, |
| NudgeCatalogName::kCaptureModeEducationShortcutTutorial, 0); |
| histogram_tester.ExpectBucketCount( |
| kNudgeTimeToActionWithin1m, |
| NudgeCatalogName::kCaptureModeEducationQuickSettingsNudge, 0); |
| |
| ActivateNudgeAndCheckVisibility(); |
| // Attempt to use the screenshot shortcut as soon as possible. |
| PressAndReleaseKey(ui::VKEY_MEDIA_LAUNCH_APP1, |
| ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN); |
| auto* capture_mode_controller = CaptureModeController::Get(); |
| ASSERT_TRUE(capture_mode_controller->IsActive()); |
| capture_mode_controller->Stop(); |
| |
| // The buckets do not cascade, so a nudge that has been activated within 1m |
| // will not show up in the `kNudgeTimeToActionWithin1h` bucket or session |
| // bucket. |
| histogram_tester.ExpectBucketCount( |
| kNudgeTimeToActionWithin1m, |
| NudgeCatalogName::kCaptureModeEducationShortcutNudge, 1); |
| histogram_tester.ExpectBucketCount( |
| kNudgeTimeToActionWithin1h, |
| NudgeCatalogName::kCaptureModeEducationShortcutNudge, 0); |
| histogram_tester.ExpectBucketCount( |
| kNudgeTimeToActionWithinSession, |
| NudgeCatalogName::kCaptureModeEducationShortcutNudge, 0); |
| |
| // The other nudge buckets should still be empty. |
| histogram_tester.ExpectBucketCount( |
| kNudgeTimeToActionWithin1m, |
| NudgeCatalogName::kCaptureModeEducationShortcutTutorial, 0); |
| histogram_tester.ExpectBucketCount( |
| kNudgeTimeToActionWithin1m, |
| NudgeCatalogName::kCaptureModeEducationQuickSettingsNudge, 0); |
| |
| ActivateNudgeAndCheckVisibility(); |
| // Attempt to use the screenshot shortcut after more than 1 minute, but less |
| // than 1 hour. |
| task_environment()->FastForwardBy(base::Minutes(30)); |
| PressAndReleaseKey(ui::VKEY_MEDIA_LAUNCH_APP1, |
| ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN); |
| ASSERT_TRUE(capture_mode_controller->IsActive()); |
| capture_mode_controller->Stop(); |
| |
| histogram_tester.ExpectBucketCount( |
| kNudgeTimeToActionWithin1m, |
| NudgeCatalogName::kCaptureModeEducationShortcutNudge, 1); |
| histogram_tester.ExpectBucketCount( |
| kNudgeTimeToActionWithin1h, |
| NudgeCatalogName::kCaptureModeEducationShortcutNudge, 1); |
| histogram_tester.ExpectBucketCount( |
| kNudgeTimeToActionWithinSession, |
| NudgeCatalogName::kCaptureModeEducationShortcutNudge, 0); |
| |
| ActivateNudgeAndCheckVisibility(); |
| // Attempt to use the screenshot shortcut after more than 1 hour. |
| task_environment()->FastForwardBy(base::Hours(2)); |
| PressAndReleaseKey(ui::VKEY_MEDIA_LAUNCH_APP1, |
| ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN); |
| ASSERT_TRUE(capture_mode_controller->IsActive()); |
| capture_mode_controller->Stop(); |
| |
| histogram_tester.ExpectBucketCount( |
| kNudgeTimeToActionWithin1m, |
| NudgeCatalogName::kCaptureModeEducationShortcutNudge, 1); |
| histogram_tester.ExpectBucketCount( |
| kNudgeTimeToActionWithin1h, |
| NudgeCatalogName::kCaptureModeEducationShortcutNudge, 1); |
| histogram_tester.ExpectBucketCount( |
| kNudgeTimeToActionWithinSession, |
| NudgeCatalogName::kCaptureModeEducationShortcutNudge, 1); |
| } |
| |
| // Test fixture to verify the behaviour of Arm 2, the shortcut tutorial. |
| class CaptureModeEducationShortcutTutorialTest |
| : public CaptureModeEducationControllerTest { |
| public: |
| CaptureModeEducationShortcutTutorialTest() |
| : CaptureModeEducationControllerTest("ShortcutTutorial") {} |
| CaptureModeEducationShortcutTutorialTest( |
| const CaptureModeEducationShortcutTutorialTest&) = delete; |
| CaptureModeEducationShortcutTutorialTest& operator=( |
| const CaptureModeEducationShortcutTutorialTest&) = delete; |
| ~CaptureModeEducationShortcutTutorialTest() override = default; |
| }; |
| |
| TEST_F(CaptureModeEducationShortcutTutorialTest, DialogOpensAndCloses) { |
| base::SimpleTestClock test_clock; |
| CaptureModeEducationControllerTest::SetOverrideClock(&test_clock); |
| |
| // Advance clock so we aren't at zero time. |
| test_clock.Advance(base::Hours(25)); |
| |
| // Attempt to use the Windows Snipping Tool (capture bar) shortcut. |
| PressAndReleaseKey(ui::VKEY_S, ui::EF_COMMAND_DOWN | ui::EF_SHIFT_DOWN); |
| |
| // Click the "Show me how" button on the nudge. |
| AnchoredNudgeManagerImpl* nudge_manager = |
| Shell::Get()->anchored_nudge_manager(); |
| LeftClickOn(nudge_manager->GetNudgePrimaryButtonForTest(kCaptureModeNudgeId)); |
| |
| // The nudge should not be visible. |
| EXPECT_FALSE(nudge_manager->GetNudgeIfShown(kCaptureModeNudgeId)); |
| |
| // The tutorial widget should be visible. |
| auto* tutorial_widget = CaptureModeController::Get() |
| ->education_controller() |
| ->tutorial_widget_for_test(); |
| ASSERT_TRUE(tutorial_widget); |
| |
| // The keyboard image should be scaled to the the correct width. |
| auto* image_view = tutorial_widget->GetContentsView()->GetViewByID( |
| VIEW_ID_SCREEN_CAPTURE_EDUCATION_KEYBOARD_IMAGE); |
| ASSERT_TRUE(image_view); |
| EXPECT_EQ(kKeyboardImageWidth, image_view->width()); |
| |
| StartSessionAndCheckEducationClosed(); |
| } |
| |
| // Tests that metrics relating to the shortcut tutorial (Arm 2) are properly |
| // recorded. |
| TEST_F(CaptureModeEducationShortcutTutorialTest, ShortcutTutorialMetrics) { |
| base::HistogramTester histogram_tester; |
| |
| // For this test, we do not care about pref limits. |
| SkipNudgePrefs(); |
| |
| // The nudge has not been activated, so all related buckets should be at 0. |
| Shell::Get()->anchored_nudge_manager()->ResetNudgeRegistryForTesting(); |
| histogram_tester.ExpectBucketCount( |
| kNudgeTimeToActionWithin1m, |
| NudgeCatalogName::kCaptureModeEducationShortcutTutorial, 0); |
| |
| // The other nudge buckets should be empty as well. |
| histogram_tester.ExpectBucketCount( |
| kNudgeTimeToActionWithin1m, |
| NudgeCatalogName::kCaptureModeEducationShortcutNudge, 0); |
| histogram_tester.ExpectBucketCount( |
| kNudgeTimeToActionWithin1m, |
| NudgeCatalogName::kCaptureModeEducationQuickSettingsNudge, 0); |
| |
| ActivateNudgeAndCheckVisibility(); |
| |
| // Attempt to use the screenshot shortcut as soon as possible. |
| PressAndReleaseKey(ui::VKEY_MEDIA_LAUNCH_APP1, |
| ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN); |
| |
| // The nudge bucket should now show a user action. |
| histogram_tester.ExpectBucketCount( |
| kNudgeTimeToActionWithin1m, |
| NudgeCatalogName::kCaptureModeEducationShortcutTutorial, 1); |
| |
| // The other nudge buckets should still be empty. |
| histogram_tester.ExpectBucketCount( |
| kNudgeTimeToActionWithin1m, |
| NudgeCatalogName::kCaptureModeEducationShortcutNudge, 0); |
| histogram_tester.ExpectBucketCount( |
| kNudgeTimeToActionWithin1m, |
| NudgeCatalogName::kCaptureModeEducationQuickSettingsNudge, 0); |
| } |
| |
| // Test fixture to verify the behaviour of Arm 3, the settings nudge. |
| class CaptureModeEducationQuickSettingsNudgeTest |
| : public CaptureModeEducationControllerTest { |
| public: |
| CaptureModeEducationQuickSettingsNudgeTest() |
| : CaptureModeEducationControllerTest("QuickSettingsNudge") {} |
| CaptureModeEducationQuickSettingsNudgeTest( |
| const CaptureModeEducationQuickSettingsNudgeTest&) = delete; |
| CaptureModeEducationQuickSettingsNudgeTest& operator=( |
| const CaptureModeEducationQuickSettingsNudgeTest&) = delete; |
| ~CaptureModeEducationQuickSettingsNudgeTest() override = default; |
| }; |
| |
| TEST_F(CaptureModeEducationQuickSettingsNudgeTest, NudgeLocation) { |
| UpdateDisplay("800x600"); |
| base::SimpleTestClock test_clock; |
| CaptureModeEducationControllerTest::SetOverrideClock(&test_clock); |
| |
| // Advance clock so we aren't at zero time. |
| test_clock.Advance(base::Hours(25)); |
| |
| // Attempt to use the Windows Snipping Tool (capture bar) shortcut. |
| PressAndReleaseKey(ui::VKEY_S, ui::EF_COMMAND_DOWN | ui::EF_SHIFT_DOWN); |
| |
| // Get the list of visible nudges from the nudge manager and make sure our |
| // education nudge is in the list and visible. |
| AnchoredNudge* nudge = |
| Shell::Get()->anchored_nudge_manager()->GetNudgeIfShown( |
| kCaptureModeNudgeId); |
| ASSERT_TRUE(nudge); |
| EXPECT_TRUE(nudge->GetVisible()); |
| |
| // Test the shelf in horizontal (bottom) alignment. |
| ASSERT_TRUE(Shell::GetPrimaryRootWindowController() |
| ->shelf() |
| ->IsHorizontalAlignment()); |
| |
| // The nudge should appear on the bottom right side of the screen. Compare the |
| // positions of the bottom right corners of the nudge and the work area. |
| const auto nudge_corner = nudge->GetBoundsInScreen().bottom_right(); |
| auto work_area_corner = |
| nudge->GetWidget()->GetWorkAreaBoundsInScreen().bottom_right(); |
| EXPECT_EQ(work_area_corner.x() - kNudgeWorkAreaSpacing, nudge_corner.x()); |
| EXPECT_EQ(work_area_corner.y() - kNudgeWorkAreaSpacing, nudge_corner.y()); |
| |
| StartSessionAndCheckEducationClosed(); |
| |
| // TODO(hewer): Test shelf in vertical positions. |
| |
| CaptureModeEducationControllerTest::SetOverrideClock(nullptr); |
| } |
| |
| // Tests that metrics relating to the settings nudge (Arm 3) are properly |
| // recorded. |
| TEST_F(CaptureModeEducationQuickSettingsNudgeTest, SettingsNudgeMetrics) { |
| base::HistogramTester histogram_tester; |
| |
| // For this test, we do not care about pref limits. |
| SkipNudgePrefs(); |
| |
| // The nudge has not been activated, so all related buckets should be at 0. |
| Shell::Get()->anchored_nudge_manager()->ResetNudgeRegistryForTesting(); |
| histogram_tester.ExpectBucketCount( |
| kNudgeTimeToActionWithin1m, |
| NudgeCatalogName::kCaptureModeEducationQuickSettingsNudge, 0); |
| |
| // The other nudge buckets should be empty as well. |
| histogram_tester.ExpectBucketCount( |
| kNudgeTimeToActionWithin1m, |
| NudgeCatalogName::kCaptureModeEducationShortcutNudge, 0); |
| histogram_tester.ExpectBucketCount( |
| kNudgeTimeToActionWithin1m, |
| NudgeCatalogName::kCaptureModeEducationShortcutTutorial, 0); |
| |
| ActivateNudgeAndCheckVisibility(); |
| |
| // Attempt to use the screenshot shortcut as soon as possible. |
| PressAndReleaseKey(ui::VKEY_MEDIA_LAUNCH_APP1, |
| ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN); |
| |
| histogram_tester.ExpectBucketCount( |
| kNudgeTimeToActionWithin1m, |
| NudgeCatalogName::kCaptureModeEducationQuickSettingsNudge, 1); |
| |
| // The other nudge buckets should still be empty. |
| histogram_tester.ExpectBucketCount( |
| kNudgeTimeToActionWithin1m, |
| NudgeCatalogName::kCaptureModeEducationShortcutNudge, 0); |
| histogram_tester.ExpectBucketCount( |
| kNudgeTimeToActionWithin1m, |
| NudgeCatalogName::kCaptureModeEducationShortcutTutorial, 0); |
| } |
| |
| class CaptureModeEducationControllerBypassLimitsFlagTest |
| : public CaptureModeEducationControllerTest { |
| public: |
| CaptureModeEducationControllerBypassLimitsFlagTest() { |
| scoped_feature_list_.InitWithFeaturesAndParameters( |
| /*enabled_features=*/ |
| {{features::kCaptureModeEducation, |
| {{"CaptureModeEducationParam", "ShortcutNudge"}}}, |
| {features::kCaptureModeEducationBypassLimits, {}}}, |
| /*disabled_features=*/{}); |
| } |
| CaptureModeEducationControllerBypassLimitsFlagTest( |
| const CaptureModeEducationControllerBypassLimitsFlagTest&) = delete; |
| CaptureModeEducationControllerBypassLimitsFlagTest& operator=( |
| const CaptureModeEducationControllerBypassLimitsFlagTest&) = delete; |
| ~CaptureModeEducationControllerBypassLimitsFlagTest() override = default; |
| |
| protected: |
| base::test::ScopedFeatureList scoped_feature_list_; |
| }; |
| |
| TEST_F(CaptureModeEducationControllerBypassLimitsFlagTest, NoShowLimits) { |
| // Show the nudge more than three times without advancing the clock, |
| // it should be visible each time. |
| for (int i = 0; i < 4; i++) { |
| ActivateNudgeAndCheckVisibility(); |
| CancelNudge(kCaptureModeNudgeId); |
| } |
| } |
| |
| } // namespace ash |