text: // Copyright 2019 The Chromium Authors. All rights reserved.
  // Use of this source code is governed by a BSD-style license that can be
  // found in the LICENSE file.
  
  #include "base/test/metrics/histogram_tester.h"
  #include "base/test/metrics/user_action_tester.h"
  #include "base/test/scoped_feature_list.h"
  #include "base/test/test_mock_time_task_runner.h"
  #include "chrome/browser/ui/browser.h"
  #include "chrome/browser/ui/webui/chromeos/add_supervision/add_supervision.mojom.h"
  #include "chrome/browser/ui/webui/chromeos/add_supervision/add_supervision_handler.h"
  #include "chrome/browser/ui/webui/chromeos/add_supervision/add_supervision_handler_utils.h"
  #include "chrome/browser/ui/webui/chromeos/add_supervision/add_supervision_metrics_recorder.h"
  #include "chrome/browser/ui/webui/chromeos/add_supervision/add_supervision_ui.h"
  #include "chrome/test/base/in_process_browser_test.h"
  #include "chromeos/constants/chromeos_features.h"
  #include "components/signin/public/identity_manager/identity_test_environment.h"
  #include "content/public/test/browser_test.h"
  #include "content/public/test/test_web_ui.h"
  #include "mojo/public/cpp/bindings/pending_receiver.h"
  
  namespace chromeos {
  
  // This browser test class is for the Add Supervision metrics recorder.
  class AddSupervisionMetricsRecorderTest : public InProcessBrowserTest {
   public:
    AddSupervisionMetricsRecorderTest() = default;
    ~AddSupervisionMetricsRecorderTest() override = default;
  
    void SetUp() override {
      feature_list_.InitAndEnableFeature(
          chromeos::features::kParentalControlsSettings);
      InProcessBrowserTest::SetUp();
    }
  
    void SetUpOnMainThread() override {
      content::WebContents* web_contents =
          browser()->tab_strip_model()->GetActiveWebContents();
      test_web_ui_.set_web_contents(web_contents);
    }
  
    void ShowAddSupervisionDialog() {
      content::WebContents* web_contents = test_web_ui_.GetWebContents();
      AddSupervisionDialog::Show(web_contents->GetTopLevelNativeWindow());
    }
  
    void CloseNowForTesting() {
      AddSupervisionDialog* instance =
          static_cast<AddSupervisionDialog*>(AddSupervisionDialog::GetInstance());
      instance->CloseNowForTesting();
    }
  
    void CloseAddSupervisionDialog() {
      bool out_close_dialog =
          AddSupervisionDialog::GetInstance()->DeprecatedOnDialogCloseRequested();
      EXPECT_TRUE(out_close_dialog);
      CloseNowForTesting();
    }
  
    void NotifySupervisionEnabled() {
      signin::IdentityTestEnvironment identity_test_env;
      mojo::PendingReceiver<add_supervision::mojom::AddSupervisionHandler>
          receiver;
      AddSupervisionUI add_supervision_ui(&test_web_ui_);
      AddSupervisionHandler add_supervision_handler(
          std::move(receiver), &test_web_ui_,
          identity_test_env.identity_manager(), &add_supervision_ui);
      add_supervision_handler.NotifySupervisionEnabled();
    }
  
    void LogOutAndClose() {
      LogOutHelper();
      CloseNowForTesting();
    }
  
   private:
    DISALLOW_COPY_AND_ASSIGN(AddSupervisionMetricsRecorderTest);
  
    base::test::ScopedFeatureList feature_list_;
    content::TestWebUI test_web_ui_;
  };
  
  IN_PROC_BROWSER_TEST_F(AddSupervisionMetricsRecorderTest, HistogramTest) {
    base::HistogramTester histogram_tester;
  
    // Should see 0 Add Supervision enrollment metrics at first.
    histogram_tester.ExpectTotalCount("AddSupervisionDialog.Enrollment", 0);
  
    // Simulate the user opening the Add Supervision dialog and closing it.
    ShowAddSupervisionDialog();
  
    // Should see 1 Add Supervision process initiated.
    histogram_tester.ExpectUniqueSample(
        "AddSupervisionDialog.Enrollment",
        AddSupervisionMetricsRecorder::EnrollmentState::kInitiated, 1);
    histogram_tester.ExpectTotalCount("AddSupervisionDialog.Enrollment", 1);
  
    CloseAddSupervisionDialog();
  
    // Should see 1 Add Supervision process closed.
    histogram_tester.ExpectBucketCount(
        "AddSupervisionDialog.Enrollment",
        AddSupervisionMetricsRecorder::EnrollmentState::kClosed, 1);
    histogram_tester.ExpectTotalCount("AddSupervisionDialog.Enrollment", 2);
  
    // Simulate the user opening the Add Supervision dialog and signing out to
    // switch accounts.
    ShowAddSupervisionDialog();
  
    // Should see 2 Add Supervision processes initiated.
    histogram_tester.ExpectBucketCount(
        "AddSupervisionDialog.Enrollment",
        AddSupervisionMetricsRecorder::EnrollmentState::kInitiated, 2);
    histogram_tester.ExpectTotalCount("AddSupervisionDialog.Enrollment", 3);
  
    LogOutAndClose();
  
    // Should see 1 switch accounts attempt.
    histogram_tester.ExpectBucketCount(
        "AddSupervisionDialog.Enrollment",
        AddSupervisionMetricsRecorder::EnrollmentState::kSwitchedAccounts, 1);
    histogram_tester.ExpectTotalCount("AddSupervisionDialog.Enrollment", 4);
  
    // Simulate the user opening the Add Supervision dialog, enrolling in
    // supervision and signing out.
    ShowAddSupervisionDialog();
  
    // Should see 3 Add Supervision processes initiated.
    histogram_tester.ExpectBucketCount(
        "AddSupervisionDialog.Enrollment",
        AddSupervisionMetricsRecorder::EnrollmentState::kInitiated, 3);
    histogram_tester.ExpectTotalCount("AddSupervisionDialog.Enrollment", 5);
  
    NotifySupervisionEnabled();
  
    // Should see 1 Add Supervision process completed.
    histogram_tester.ExpectBucketCount(
        "AddSupervisionDialog.Enrollment",
        AddSupervisionMetricsRecorder::EnrollmentState::kCompleted, 1);
    histogram_tester.ExpectTotalCount("AddSupervisionDialog.Enrollment", 6);
  
    LogOutAndClose();
  
    // Should see 1 sign out attempt.
    histogram_tester.ExpectBucketCount(
        "AddSupervisionDialog.Enrollment",
        AddSupervisionMetricsRecorder::EnrollmentState::kSignedOut, 1);
    histogram_tester.ExpectTotalCount("AddSupervisionDialog.Enrollment", 7);
  }
  
  IN_PROC_BROWSER_TEST_F(AddSupervisionMetricsRecorderTest, UserActionTest) {
    base::UserActionTester user_action_tester;
    // Should see 0 user actions at first.
    EXPECT_EQ(user_action_tester.GetActionCount("AddSupervisionDialog_Launched"),
              0);
    EXPECT_EQ(user_action_tester.GetActionCount("AddSupervisionDialog_Closed"),
              0);
    EXPECT_EQ(user_action_tester.GetActionCount(
                  "AddSupervisionDialog_AttemptedSignoutAfterEnrollment"),
              0);
    EXPECT_EQ(user_action_tester.GetActionCount(
                  "AddSupervisionDialog_EnrollmentCompleted"),
              0);
  
    // Simulate the user opening the Add Supervision dialog and closing it.
    ShowAddSupervisionDialog();
  
    // Should see 1 Launched action.
    EXPECT_EQ(user_action_tester.GetActionCount("AddSupervisionDialog_Launched"),
              1);
  
    CloseAddSupervisionDialog();
  
    // Should see 1 Closed action.
    EXPECT_EQ(user_action_tester.GetActionCount("AddSupervisionDialog_Closed"),
              1);
  
    // Simulate the user opening the Add Supervision dialog and signing out to
    // switch accounts.
    ShowAddSupervisionDialog();
  
    // Should see 2 Launched actions.
    EXPECT_EQ(user_action_tester.GetActionCount("AddSupervisionDialog_Launched"),
              2);
  
    LogOutAndClose();
  
    // Should see 1 switch accounts attempt.
    EXPECT_EQ(user_action_tester.GetActionCount(
                  "AddSupervisionDialog_SwitchedAccounts"),
              1);
  
    // Simulate the user opening the Add Supervision dialog, enrolling in
    // supervision and signing out.
    ShowAddSupervisionDialog();
  
    // Should see 3 Launched actions.
    EXPECT_EQ(user_action_tester.GetActionCount("AddSupervisionDialog_Launched"),
              3);
  
    NotifySupervisionEnabled();
  
    // Should see 1 EnrollmentCompleted action.
    EXPECT_EQ(user_action_tester.GetActionCount(
                  "AddSupervisionDialog_EnrollmentCompleted"),
              1);
  
    LogOutAndClose();
  
    // Should see 1 AttemptedSignoutAfterEnrollment action.
    EXPECT_EQ(user_action_tester.GetActionCount(
                  "AddSupervisionDialog_AttemptedSignoutAfterEnrollment"),
              1);
  }
  
  // This browser test class is for the Add Supervision timing metrics.
  class AddSupervisionMetricsRecorderTimeTest
      : public AddSupervisionMetricsRecorderTest,
        public testing::WithParamInterface<int> {};
  
  INSTANTIATE_TEST_SUITE_P(AddSupervisionDialogUserTimeInSeconds,
                           AddSupervisionMetricsRecorderTimeTest,
                           ::testing::Values(0, 11, 120, 1800));
  
  IN_PROC_BROWSER_TEST_P(AddSupervisionMetricsRecorderTimeTest, UserTimingTest) {
    base::HistogramTester histogram_tester;
  
    // Should see 0 Add Supervision timing metrics at first.
    histogram_tester.ExpectTotalCount(
        "AddSupervisionDialog.EnrollmentNotCompletedUserTime", 0);
    histogram_tester.ExpectTotalCount(
        "AddSupervisionDialog.EnrollmentCompletedUserTime", 0);
    histogram_tester.ExpectTotalCount(
        "AddSupervisionDialog.SignoutCompletedUserTime", 0);
  
    // Simulate the user opening the Add Supervision dialog and closing it
    // after GetParam() seconds.
    scoped_refptr<base::TestMockTimeTaskRunner> task_runner_ =
        base::MakeRefCounted<base::TestMockTimeTaskRunner>();
    AddSupervisionMetricsRecorder::GetInstance()->SetClockForTesting(
        task_runner_->GetMockTickClock());
    base::TimeDelta duration(base::TimeDelta::FromSeconds(GetParam()));
  
    // We need to start at some non-zero point in time or else
    // DCHECK(!start_time_.is_null()) throws.
    task_runner_->FastForwardBy(base::TimeDelta::FromSeconds(1));
    ShowAddSupervisionDialog();
    task_runner_->FastForwardBy(duration);
    CloseAddSupervisionDialog();
  
    // Should see 1 new EnrollmentNotCompletedUserTime timing.
    histogram_tester.ExpectTimeBucketCount(
        "AddSupervisionDialog.EnrollmentNotCompletedUserTime", duration, 1);
    histogram_tester.ExpectTotalCount(
        "AddSupervisionDialog.EnrollmentNotCompletedUserTime", 1);
    histogram_tester.ExpectTotalCount(
        "AddSupervisionDialog.EnrollmentCompletedUserTime", 0);
    histogram_tester.ExpectTotalCount(
        "AddSupervisionDialog.SignoutCompletedUserTime", 0);
  
    // Simulate the user opening the Add Supervision dialog and signing out to
    // switch accounts after GetParam() seconds.
    ShowAddSupervisionDialog();
    task_runner_->FastForwardBy(duration);
    LogOutAndClose();
  
    // Should see 1 new EnrollmentNotCompletedUserTime timing.
    histogram_tester.ExpectTimeBucketCount(
        "AddSupervisionDialog.EnrollmentNotCompletedUserTime", duration, 2);
    histogram_tester.ExpectTotalCount(
        "AddSupervisionDialog.EnrollmentNotCompletedUserTime", 2);
    histogram_tester.ExpectTotalCount(
        "AddSupervisionDialog.EnrollmentCompletedUserTime", 0);
    histogram_tester.ExpectTotalCount(
        "AddSupervisionDialog.SignoutCompletedUserTime", 0);
  
    // Simulate the user opening the Add Supervision dialog, enrolling in
    // supervision after GetParam() seconds and signing out after GetParam()
    // seconds.
    ShowAddSupervisionDialog();
    task_runner_->FastForwardBy(duration);
    NotifySupervisionEnabled();
    task_runner_->FastForwardBy(duration);
    LogOutAndClose();
  
    histogram_tester.ExpectTotalCount(
        "AddSupervisionDialog.EnrollmentNotCompletedUserTime", 2);
    // Should see 1 new EnrollmentCompletedUserTime timing.
    histogram_tester.ExpectTimeBucketCount(
        "AddSupervisionDialog.EnrollmentCompletedUserTime", duration, 1);
    histogram_tester.ExpectTotalCount(
        "AddSupervisionDialog.EnrollmentCompletedUserTime", 1);
    // Should see 1 new SignoutCompletedUserTime timing.
    histogram_tester.ExpectTimeBucketCount(
        "AddSupervisionDialog.SignoutCompletedUserTime", 2 * duration, 1);
    histogram_tester.ExpectTotalCount(
        "AddSupervisionDialog.SignoutCompletedUserTime", 1);
  }
  
  }  // namespace chromeos
  