chromium/chrome/browser/ash/child_accounts/time_limit_notifier_unittest.cc

// Copyright 2018 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/ash/child_accounts/time_limit_notifier.h"

#include "base/memory/ref_counted.h"
#include "base/test/test_mock_time_task_runner.h"
#include "base/time/time.h"
#include "chrome/browser/notifications/notification_display_service_tester.h"
#include "chrome/test/base/testing_profile.h"
#include "content/public/test/browser_task_environment.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace ash {

class TimeLimitNotifierTest : public testing::Test {
 public:
  TimeLimitNotifierTest()
      : task_runner_(base::MakeRefCounted<base::TestMockTimeTaskRunner>()),
        notification_tester_(&profile_),
        notifier_(&profile_, task_runner_) {}

  TimeLimitNotifierTest(const TimeLimitNotifierTest&) = delete;
  TimeLimitNotifierTest& operator=(const TimeLimitNotifierTest&) = delete;

  ~TimeLimitNotifierTest() override = default;

 protected:
  bool HasLockNotification() {
    return notification_tester_.GetNotification("time-limit-lock-notification")
        .has_value();
  }

  bool HasPolicyUpdateNotification(TimeLimitNotifier::LimitType limit_type) {
    std::string notification_id;
    switch (limit_type) {
      case TimeLimitNotifier::LimitType::kScreenTime:
        notification_id = "time-limit-screen-time-updated";
        break;
      case TimeLimitNotifier::LimitType::kBedTime:
        notification_id = "time-limit-bedtime-updated";
        break;
      case TimeLimitNotifier::LimitType::kOverride:
        notification_id = "time-limit-override-updated";
        break;
      default:
        NOTREACHED_IN_MIGRATION();
    }
    return notification_tester_.GetNotification(notification_id).has_value();
  }

  void RemoveNotification() {
    notification_tester_.RemoveAllNotifications(
        NotificationHandler::Type::TRANSIENT, true /* by_user */);
  }

  scoped_refptr<base::TestMockTimeTaskRunner> task_runner_;
  content::BrowserTaskEnvironment task_environment_;
  TestingProfile profile_;
  NotificationDisplayServiceTester notification_tester_;
  TimeLimitNotifier notifier_;
};

TEST_F(TimeLimitNotifierTest, ShowLockNotifications) {
  notifier_.MaybeScheduleLockNotifications(
      TimeLimitNotifier::LimitType::kScreenTime, base::Minutes(20));

  // Fast forward a bit, but not far enough to show a notification.
  task_runner_->FastForwardBy(base::Minutes(10));
  EXPECT_FALSE(HasLockNotification());

  // Fast forward to the 5-minute warning time.
  task_runner_->FastForwardBy(base::Minutes(5));
  EXPECT_TRUE(HasLockNotification());

  // Fast forward to the 1-minute warning time.
  task_runner_->FastForwardBy(base::Minutes(4));
  EXPECT_TRUE(HasLockNotification());
}

TEST_F(TimeLimitNotifierTest, DismisLocksNotification) {
  notifier_.MaybeScheduleLockNotifications(
      TimeLimitNotifier::LimitType::kBedTime, base::Minutes(10));

  // Fast forward to the 5-minute warning time.
  task_runner_->FastForwardBy(base::Minutes(5));
  EXPECT_TRUE(HasLockNotification());
  RemoveNotification();

  // Fast forward one minute; the same notification is not reshown.
  task_runner_->FastForwardBy(base::Minutes(1));
  EXPECT_FALSE(HasLockNotification());

  // Fast forward to the 1-minute warning time.
  task_runner_->FastForwardBy(base::Minutes(3));
  EXPECT_TRUE(HasLockNotification());
}

TEST_F(TimeLimitNotifierTest, OnlyExiLocktNotification) {
  notifier_.MaybeScheduleLockNotifications(
      TimeLimitNotifier::LimitType::kScreenTime, base::Minutes(3));

  // Fast forward a bit, but not far enough to show a notification.
  task_runner_->FastForwardBy(base::Minutes(1));
  EXPECT_FALSE(HasLockNotification());

  // Fast forward to the 1-minute warning time.
  task_runner_->FastForwardBy(base::Minutes(1));
  EXPECT_TRUE(HasLockNotification());
  RemoveNotification();

  // Only one notification was shown.
  task_runner_->FastForwardUntilNoTasksRemain();
  EXPECT_FALSE(HasLockNotification());
}

TEST_F(TimeLimitNotifierTest, NoLockNotifications) {
  notifier_.MaybeScheduleLockNotifications(
      TimeLimitNotifier::LimitType::kBedTime, base::Seconds(30));

  task_runner_->FastForwardUntilNoTasksRemain();
  EXPECT_FALSE(HasLockNotification());
}

TEST_F(TimeLimitNotifierTest, UnscheduleLockNotifications) {
  notifier_.MaybeScheduleLockNotifications(
      TimeLimitNotifier::LimitType::kScreenTime, base::Minutes(10));

  // Fast forward to the 5-minute warning time.
  task_runner_->FastForwardBy(base::Minutes(5));
  EXPECT_TRUE(HasLockNotification());
  RemoveNotification();

  // Stop the timers.
  notifier_.UnscheduleNotifications();
  task_runner_->FastForwardUntilNoTasksRemain();
  EXPECT_FALSE(HasLockNotification());
}

TEST_F(TimeLimitNotifierTest, RescheduleLockNotifications) {
  notifier_.MaybeScheduleLockNotifications(
      TimeLimitNotifier::LimitType::kScreenTime, base::Minutes(20));

  // Update the notifier with a new limit.
  notifier_.MaybeScheduleLockNotifications(
      TimeLimitNotifier::LimitType::kScreenTime, base::Minutes(30));

  // Fast forward a bit, but not far enough to show a notification.
  task_runner_->FastForwardBy(base::Minutes(20));
  EXPECT_FALSE(HasLockNotification());

  // Fast forward to the 5-minute warning time.
  task_runner_->FastForwardBy(base::Minutes(5));
  EXPECT_TRUE(HasLockNotification());
  RemoveNotification();

  // Fast forward to the 1-minute warning time.
  task_runner_->FastForwardBy(base::Minutes(4));
  EXPECT_TRUE(HasLockNotification());
}

TEST_F(TimeLimitNotifierTest, NoOverriePolicyUpdateNotification) {
  notifier_.ShowPolicyUpdateNotification(
      TimeLimitNotifier::LimitType::kOverride, std::nullopt);

  EXPECT_FALSE(
      HasPolicyUpdateNotification(TimeLimitNotifier::LimitType::kOverride));
}

TEST_F(TimeLimitNotifierTest, ShowPolicyUpdateNotifications) {
  notifier_.ShowPolicyUpdateNotification(
      TimeLimitNotifier::LimitType::kScreenTime, std::nullopt);
  notifier_.ShowPolicyUpdateNotification(TimeLimitNotifier::LimitType::kBedTime,
                                         std::nullopt);
  base::Time lock_time;
  ASSERT_TRUE(base::Time::FromUTCString("1 Jan 2019 22:00 PST", &lock_time));
  notifier_.ShowPolicyUpdateNotification(
      TimeLimitNotifier::LimitType::kOverride, std::make_optional(lock_time));

  EXPECT_TRUE(
      HasPolicyUpdateNotification(TimeLimitNotifier::LimitType::kScreenTime));
  EXPECT_TRUE(
      HasPolicyUpdateNotification(TimeLimitNotifier::LimitType::kBedTime));
}

}  // namespace ash