| // Copyright 2024 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/quick_insert/metrics/quick_insert_session_metrics.h" |
| |
| #include "ash/constants/ash_pref_names.h" |
| #include "base/test/metrics/histogram_tester.h" |
| #include "components/metrics/structured/structured_events.h" |
| #include "components/metrics/structured/test/test_structured_metrics_recorder.h" |
| #include "components/prefs/pref_registry_simple.h" |
| #include "components/prefs/testing_pref_service.h" |
| #include "testing/gmock/include/gmock/gmock.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| #include "ui/base/ime/fake_text_input_client.h" |
| |
| namespace ash { |
| namespace { |
| |
| namespace cros_events = metrics::structured::events::v2::cr_os_events; |
| |
| using ::testing::AllOf; |
| using ::testing::Contains; |
| using ::testing::Eq; |
| using ::testing::Property; |
| |
| class QuickInsertSessionMetricsTest : public testing::Test { |
| public: |
| void SetUp() override { |
| metrics_recorder_ = |
| std::make_unique<metrics::structured::TestStructuredMetricsRecorder>(); |
| metrics_recorder_->Initialize(); |
| } |
| |
| void TearDown() override { metrics_recorder_.reset(); } |
| |
| protected: |
| std::unique_ptr<metrics::structured::TestStructuredMetricsRecorder> |
| metrics_recorder_; |
| }; |
| |
| TEST_F(QuickInsertSessionMetricsTest, RecordsUmaSessionOutcomeOnce) { |
| base::HistogramTester histogram; |
| { |
| QuickInsertSessionMetrics metrics; |
| |
| metrics.SetOutcome( |
| QuickInsertSessionMetrics::SessionOutcome::kInsertedOrCopied); |
| metrics.SetOutcome( |
| QuickInsertSessionMetrics::SessionOutcome::kInsertedOrCopied); |
| metrics.SetOutcome(QuickInsertSessionMetrics::SessionOutcome::kAbandoned); |
| metrics.SetOutcome(QuickInsertSessionMetrics::SessionOutcome::kUnknown); |
| } |
| |
| histogram.ExpectUniqueSample( |
| "Ash.Picker.Session.Outcome", |
| QuickInsertSessionMetrics::SessionOutcome::kInsertedOrCopied, 1); |
| } |
| |
| TEST_F(QuickInsertSessionMetricsTest, RecordsUmaUnknownOutcomeOnDestruction) { |
| base::HistogramTester histogram; |
| { QuickInsertSessionMetrics metrics; } |
| |
| histogram.ExpectUniqueSample( |
| "Ash.Picker.Session.Outcome", |
| QuickInsertSessionMetrics::SessionOutcome::kUnknown, 1); |
| } |
| |
| auto ContainsEvent(const metrics::structured::Event& event) { |
| return Contains(AllOf( |
| Property("event name", &metrics::structured::Event::event_name, |
| Eq(event.event_name())), |
| Property("metric values", &metrics::structured::Event::metric_values, |
| Eq(std::ref(event.metric_values()))))); |
| } |
| |
| TEST_F(QuickInsertSessionMetricsTest, OnStartSessionMetricsOnPlainTextField) { |
| ui::FakeTextInputClient client(ui::TEXT_INPUT_TYPE_TEXT); |
| client.SetTextAndSelection(u"abcd", gfx::Range(1, 1)); |
| |
| QuickInsertSessionMetrics metrics; |
| |
| metrics.OnStartSession(&client); |
| |
| cros_events::Picker_StartSession expected_event; |
| expected_event |
| .SetInputFieldType(cros_events::PickerInputFieldType::PLAIN_TEXT) |
| .SetSelectionLength(0); |
| const std::vector<metrics::structured::Event>& events = |
| metrics_recorder_->GetEvents(); |
| ASSERT_EQ(events.size(), 1U); |
| EXPECT_THAT(events, ContainsEvent(expected_event)); |
| } |
| |
| TEST_F(QuickInsertSessionMetricsTest, OnStartSessionMetricsOnRichTextField) { |
| ui::FakeTextInputClient client( |
| {.type = ui::TEXT_INPUT_TYPE_TEXT, .can_insert_image = true}); |
| client.SetTextAndSelection(u"abcd", gfx::Range(1, 4)); |
| |
| QuickInsertSessionMetrics metrics; |
| |
| metrics.OnStartSession(&client); |
| |
| cros_events::Picker_StartSession expected_event; |
| expected_event.SetInputFieldType(cros_events::PickerInputFieldType::RICH_TEXT) |
| .SetSelectionLength(3); |
| const std::vector<metrics::structured::Event>& events = |
| metrics_recorder_->GetEvents(); |
| ASSERT_EQ(events.size(), 1U); |
| EXPECT_THAT(events, ContainsEvent(expected_event)); |
| } |
| |
| TEST_F(QuickInsertSessionMetricsTest, |
| OnStartSessionMetricsForNullTextInputClient) { |
| QuickInsertSessionMetrics metrics; |
| |
| metrics.OnStartSession(nullptr); |
| |
| EXPECT_EQ(metrics_recorder_->GetEvents().size(), 1U); |
| cros_events::Picker_StartSession expected_event; |
| expected_event.SetInputFieldType(cros_events::PickerInputFieldType::NONE) |
| .SetSelectionLength(0); |
| const std::vector<metrics::structured::Event>& events = |
| metrics_recorder_->GetEvents(); |
| ASSERT_EQ(events.size(), 1U); |
| EXPECT_THAT(events, ContainsEvent(expected_event)); |
| } |
| |
| TEST_F(QuickInsertSessionMetricsTest, RecordsDefaultFinishSessionEvent) { |
| { QuickInsertSessionMetrics metrics; } |
| |
| cros_events::Picker_FinishSession expected_event; |
| expected_event.SetOutcome(cros_events::PickerSessionOutcome::UNKNOWN) |
| .SetAction(cros_events::PickerAction::UNKNOWN) |
| .SetResultSource(cros_events::PickerResultSource::UNKNOWN) |
| .SetResultType(cros_events::PickerResultType::UNKNOWN) |
| .SetTotalEdits(0) |
| .SetFinalQuerySize(0) |
| .SetResultIndex(-1); |
| const std::vector<metrics::structured::Event>& events = |
| metrics_recorder_->GetEvents(); |
| ASSERT_EQ(events.size(), 1U); |
| EXPECT_THAT(events, ContainsEvent(expected_event)); |
| } |
| |
| TEST_F(QuickInsertSessionMetricsTest, RecordsFinishSessionEventForInsert) { |
| { |
| QuickInsertSessionMetrics metrics; |
| metrics.SetSelectedCategory(QuickInsertCategory::kDatesTimes); |
| metrics.UpdateSearchQuery(u"abc"); |
| metrics.UpdateSearchQuery(u"abcdef"); |
| metrics.UpdateSearchQuery(u"abcde"); |
| metrics.SetSelectedResult( |
| QuickInsertTextResult(u"primary", QuickInsertTextResult::Source::kDate), |
| 3); |
| metrics.SetOutcome( |
| QuickInsertSessionMetrics::SessionOutcome::kInsertedOrCopied); |
| } |
| |
| cros_events::Picker_FinishSession expected_event; |
| expected_event |
| .SetOutcome(cros_events::PickerSessionOutcome::INSERTED_OR_COPIED) |
| .SetAction(cros_events::PickerAction::OPEN_DATES_TIMES) |
| .SetResultSource(cros_events::PickerResultSource::DATES_TIMES) |
| .SetResultType(cros_events::PickerResultType::TEXT) |
| .SetTotalEdits(7) |
| .SetFinalQuerySize(5) |
| .SetResultIndex(3); |
| const std::vector<metrics::structured::Event>& events = |
| metrics_recorder_->GetEvents(); |
| ASSERT_EQ(events.size(), 1U); |
| EXPECT_THAT(events, ContainsEvent(expected_event)); |
| } |
| |
| TEST_F(QuickInsertSessionMetricsTest, |
| RecordsFinishSessionEventForCaseTransform) { |
| { |
| QuickInsertSessionMetrics metrics; |
| metrics.SetSelectedResult( |
| QuickInsertCaseTransformResult( |
| QuickInsertCaseTransformResult::Type::kUpperCase), |
| 0); |
| metrics.SetOutcome(QuickInsertSessionMetrics::SessionOutcome::kFormat); |
| } |
| |
| cros_events::Picker_FinishSession expected_event; |
| expected_event.SetOutcome(cros_events::PickerSessionOutcome::FORMAT) |
| .SetAction(cros_events::PickerAction::UNKNOWN) |
| .SetResultSource(cros_events::PickerResultSource::CASE_TRANSFORM) |
| .SetResultType(cros_events::PickerResultType::TEXT) |
| .SetTotalEdits(0) |
| .SetFinalQuerySize(0) |
| .SetResultIndex(0); |
| const std::vector<metrics::structured::Event>& events = |
| metrics_recorder_->GetEvents(); |
| ASSERT_EQ(events.size(), 1U); |
| EXPECT_THAT(events, ContainsEvent(expected_event)); |
| } |
| |
| TEST_F(QuickInsertSessionMetricsTest, UpdatesCapsLockPrefsWhenNotSelected) { |
| TestingPrefServiceSimple prefs; |
| prefs.registry()->RegisterIntegerPref( |
| prefs::kQuickInsertCapsLockDisplayedCountPrefName, 2); |
| prefs.registry()->RegisterIntegerPref( |
| prefs::kQuickInsertLockSelectedCountPrefName, 1); |
| |
| { |
| QuickInsertSessionMetrics metrics(&prefs); |
| metrics.SetCapsLockDisplayed(true); |
| metrics.SetSelectedResult( |
| QuickInsertCaseTransformResult( |
| QuickInsertCaseTransformResult::Type::kUpperCase), |
| 0); |
| metrics.SetOutcome(QuickInsertSessionMetrics::SessionOutcome::kFormat); |
| } |
| |
| EXPECT_EQ(prefs.GetInteger(prefs::kQuickInsertCapsLockDisplayedCountPrefName), |
| 3); |
| EXPECT_EQ(prefs.GetInteger(prefs::kQuickInsertLockSelectedCountPrefName), 1); |
| } |
| |
| TEST_F(QuickInsertSessionMetricsTest, UpdatesCapsLockPrefsWhenSelected) { |
| TestingPrefServiceSimple prefs; |
| prefs.registry()->RegisterIntegerPref( |
| prefs::kQuickInsertCapsLockDisplayedCountPrefName, 2); |
| prefs.registry()->RegisterIntegerPref( |
| prefs::kQuickInsertLockSelectedCountPrefName, 1); |
| |
| { |
| QuickInsertSessionMetrics metrics(&prefs); |
| metrics.SetCapsLockDisplayed(true); |
| metrics.SetSelectedResult( |
| QuickInsertCapsLockResult( |
| /*enabled=*/true, QuickInsertCapsLockResult::Shortcut::kAltSearch), |
| 0); |
| metrics.SetOutcome(QuickInsertSessionMetrics::SessionOutcome::kFormat); |
| } |
| |
| EXPECT_EQ(prefs.GetInteger(prefs::kQuickInsertCapsLockDisplayedCountPrefName), |
| 3); |
| EXPECT_EQ(prefs.GetInteger(prefs::kQuickInsertLockSelectedCountPrefName), 2); |
| } |
| |
| TEST_F(QuickInsertSessionMetricsTest, |
| DoesNotUpdateCapsLockPrefsWhenNotDisplayed) { |
| TestingPrefServiceSimple prefs; |
| prefs.registry()->RegisterIntegerPref( |
| prefs::kQuickInsertCapsLockDisplayedCountPrefName, 2); |
| prefs.registry()->RegisterIntegerPref( |
| prefs::kQuickInsertLockSelectedCountPrefName, 1); |
| |
| { |
| QuickInsertSessionMetrics metrics(&prefs); |
| metrics.SetSelectedResult( |
| QuickInsertCaseTransformResult( |
| QuickInsertCaseTransformResult::Type::kUpperCase), |
| 0); |
| metrics.SetOutcome(QuickInsertSessionMetrics::SessionOutcome::kFormat); |
| } |
| |
| EXPECT_EQ(prefs.GetInteger(prefs::kQuickInsertCapsLockDisplayedCountPrefName), |
| 2); |
| EXPECT_EQ(prefs.GetInteger(prefs::kQuickInsertLockSelectedCountPrefName), 1); |
| } |
| |
| TEST_F(QuickInsertSessionMetricsTest, HalvesCapsLockPrefs) { |
| TestingPrefServiceSimple prefs; |
| prefs.registry()->RegisterIntegerPref( |
| prefs::kQuickInsertCapsLockDisplayedCountPrefName, 19); |
| prefs.registry()->RegisterIntegerPref( |
| prefs::kQuickInsertLockSelectedCountPrefName, 9); |
| |
| { |
| QuickInsertSessionMetrics metrics(&prefs); |
| metrics.SetCapsLockDisplayed(true); |
| metrics.SetSelectedResult( |
| QuickInsertCapsLockResult( |
| /*enabled=*/true, QuickInsertCapsLockResult::Shortcut::kAltSearch), |
| 0); |
| metrics.SetOutcome(QuickInsertSessionMetrics::SessionOutcome::kFormat); |
| } |
| |
| EXPECT_EQ(prefs.GetInteger(prefs::kQuickInsertCapsLockDisplayedCountPrefName), |
| 10); |
| EXPECT_EQ(prefs.GetInteger(prefs::kQuickInsertLockSelectedCountPrefName), 5); |
| } |
| |
| } // namespace |
| } // namespace ash |