chromium/chrome/browser/ash/eche_app/eche_app_notification_controller_unittest.cc

// Copyright 2021 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/eche_app/eche_app_notification_controller.h"

#include "ash/public/cpp/test/test_new_window_delegate.h"
#include "ash/webui/eche_app_ui/eche_alert_generator.h"
#include "base/memory/raw_ptr.h"
#include "chrome/browser/notifications/notification_display_service_tester.h"
#include "chrome/test/base/browser_with_test_window_test.h"
#include "testing/gmock/include/gmock/gmock.h"

namespace ash {
namespace eche_app {

namespace {

void RelaunchEcheApp(Profile* profile) {}

}  // namespace

class TestableNotificationController : public EcheAppNotificationController {
 public:
  explicit TestableNotificationController(
      Profile* profile,
      const base::RepeatingCallback<void(Profile*)>& relaunch_callback)
      : EcheAppNotificationController(profile, relaunch_callback) {}
  ~TestableNotificationController() override = default;
  TestableNotificationController(const TestableNotificationController&) =
      delete;
  TestableNotificationController& operator=(
      const TestableNotificationController&) = delete;

  // EcheAppNotificationController:
  MOCK_METHOD0(LaunchSettings, void());
  MOCK_METHOD0(LaunchTryAgain, void());
  MOCK_METHOD0(LaunchNetworkSettings, void());
};

class MockNewWindowDelegate : public testing::NiceMock<TestNewWindowDelegate> {
 public:
  // TestNewWindowDelegate:
  MOCK_METHOD(void,
              OpenUrl,
              (const GURL& url, OpenUrlFrom from, Disposition disposition),
              (override));
};

class EcheAppNotificationControllerTest : public BrowserWithTestWindowTest {
 protected:
  EcheAppNotificationControllerTest() {
    auto delegate = std::make_unique<MockNewWindowDelegate>();
    new_window_delegate_ = delegate.get();
    delegate_provider_ =
        std::make_unique<TestNewWindowDelegateProvider>(std::move(delegate));
  }

  ~EcheAppNotificationControllerTest() override = default;
  EcheAppNotificationControllerTest(const EcheAppNotificationControllerTest&) =
      delete;
  EcheAppNotificationControllerTest& operator=(
      const EcheAppNotificationControllerTest&) = delete;

  void SetUp() override {
    BrowserWithTestWindowTest::SetUp();

    display_service_ =
        std::make_unique<NotificationDisplayServiceTester>(profile());
    notification_controller_ =
        std::make_unique<testing::StrictMock<TestableNotificationController>>(
            profile(), base::BindRepeating(&RelaunchEcheApp));
  }

  std::unique_ptr<testing::StrictMock<TestableNotificationController>>
      notification_controller_;
  std::unique_ptr<NotificationDisplayServiceTester> display_service_;

  void Initialize(mojom::WebNotificationType type) {
    std::optional<std::u16string> title = u"title";
    std::optional<std::u16string> message = u"message";
    notification_controller_->ShowNotificationFromWebUI(title, message, type);
  }

  void VerifyNotificationHasAction(
      std::optional<message_center::Notification>& notification) {
    ASSERT_TRUE(notification);
    ASSERT_EQ(2u, notification->buttons().size());
    EXPECT_EQ(message_center::SYSTEM_PRIORITY, notification->priority());

    // Clicking the notification button should launch try again.
    EXPECT_CALL(*notification_controller_, LaunchTryAgain());
    notification->delegate()->Click(0, std::nullopt);
  }

  raw_ptr<MockNewWindowDelegate, DanglingUntriaged> new_window_delegate_;

 private:
  std::unique_ptr<TestNewWindowDelegateProvider> delegate_provider_;
};

TEST_F(EcheAppNotificationControllerTest, ShowNotificationFromWebUI) {
  std::optional<std::u16string> title = u"Connection Fail Title";
  std::optional<std::u16string> message = u"Connection Fail Message";
  notification_controller_->ShowNotificationFromWebUI(
      title, message, mojom::WebNotificationType::CONNECTION_FAILED);
  std::optional<message_center::Notification> notification =
      display_service_->GetNotification(kEcheAppRetryConnectionNotifierId);
  ASSERT_TRUE(notification);
  ASSERT_EQ(1u, notification->buttons().size());
  EXPECT_EQ(message_center::SYSTEM_PRIORITY, notification->priority());
  EXPECT_EQ(notification->title(), title);
  EXPECT_EQ(notification->message(), message);

  // Clicking the notification button should relaunch again.
  EXPECT_CALL(*notification_controller_, LaunchTryAgain());
  notification->delegate()->Click(std::nullopt, std::nullopt);

  title = u"Connection Lost Title";
  message = u"Connection Lost Message";
  notification_controller_->ShowNotificationFromWebUI(
      title, message, mojom::WebNotificationType::CONNECTION_LOST);
  notification =
      display_service_->GetNotification(kEcheAppRetryConnectionNotifierId);
  ASSERT_TRUE(notification.has_value());
  ASSERT_EQ(1u, notification->buttons().size());
  EXPECT_EQ(message_center::SYSTEM_PRIORITY, notification->priority());
  EXPECT_EQ(notification->title(), title);
  EXPECT_EQ(notification->message(), message);

  // Clicking the notification button should relaunch again.
  EXPECT_CALL(*notification_controller_, LaunchTryAgain());
  notification->delegate()->Click(std::nullopt, std::nullopt);

  title = u"Inactivity Title";
  message = u"Inactivity Message";
  notification_controller_->ShowNotificationFromWebUI(
      title, message, mojom::WebNotificationType::DEVICE_IDLE);
  notification =
      display_service_->GetNotification(kEcheAppInactivityNotifierId);
  ASSERT_TRUE(notification.has_value());
  ASSERT_EQ(1u, notification->buttons().size());
  EXPECT_EQ(message_center::SYSTEM_PRIORITY, notification->priority());
  EXPECT_EQ(notification->title(), title);
  EXPECT_EQ(notification->message(), message);

  // Clicking the first notification button should relaunch again.
  EXPECT_CALL(*notification_controller_, LaunchTryAgain());
  notification->delegate()->Click(std::nullopt, std::nullopt);

  title = u"Check WIFI Title";
  message = u"Check WIFI Message";
  notification_controller_->ShowNotificationFromWebUI(
      title, message, mojom::WebNotificationType::WIFI_NOT_READY);
  notification =
      display_service_->GetNotification(kEcheAppNetworkSettingNotifierId);
  ASSERT_TRUE(notification.has_value());
  ASSERT_EQ(1u, notification->buttons().size());
  EXPECT_EQ(message_center::SYSTEM_PRIORITY, notification->priority());
  EXPECT_EQ(notification->title(), title);
  EXPECT_EQ(notification->message(), message);

  // Clicking the notification button should launch network settings.
  EXPECT_CALL(*notification_controller_, LaunchNetworkSettings());
  notification->delegate()->Click(std::nullopt, std::nullopt);
}

TEST_F(EcheAppNotificationControllerTest, ShowScreenLockNotification) {
  std::u16string title = u"title";
  notification_controller_->ShowScreenLockNotification(title);
  std::optional<message_center::Notification> notification =
      display_service_->GetNotification(kEcheAppScreenLockNotifierId);
  ASSERT_TRUE(notification.has_value());
  ASSERT_TRUE(notification->title().size() > 0);
  ASSERT_TRUE(notification->message().size() > 0);
  ASSERT_EQ(1u, notification->buttons().size());
  EXPECT_EQ(message_center::SYSTEM_PRIORITY, notification->priority());

  // Clicking the notification button should launch settings.
  EXPECT_CALL(*notification_controller_, LaunchSettings());
  notification->delegate()->Click(std::nullopt, std::nullopt);
}

TEST_F(EcheAppNotificationControllerTest,
       ShowScreenLockNotificationWithNullValue) {
  // Null value for title should still show a degraded message.
  std::u16string title;
  notification_controller_->ShowScreenLockNotification(title);
  std::optional<message_center::Notification> notification =
      display_service_->GetNotification(kEcheAppScreenLockNotifierId);
  ASSERT_TRUE(notification.has_value());
  ASSERT_TRUE(notification->title().size() > 0);
  ASSERT_TRUE(notification->message().size() > 0);
  ASSERT_EQ(1u, notification->buttons().size());
  EXPECT_EQ(message_center::SYSTEM_PRIORITY, notification->priority());

  // Clicking the notification button should launch settings.
  EXPECT_CALL(*notification_controller_, LaunchSettings());
  notification->delegate()->Click(std::nullopt, std::nullopt);
}

TEST_F(EcheAppNotificationControllerTest, CloseNotification) {
  std::u16string title = u"title";
  notification_controller_->ShowScreenLockNotification(title);
  notification_controller_->CloseNotification(kEcheAppScreenLockNotifierId);
  std::optional<message_center::Notification> notification =
      display_service_->GetNotification(kEcheAppScreenLockNotifierId);
  ASSERT_FALSE(notification.has_value());

  std::optional<std::u16string> message = u"message";
  notification_controller_->ShowNotificationFromWebUI(
      title, message, mojom::WebNotificationType::CONNECTION_FAILED);
  notification_controller_->CloseNotification(
      kEcheAppRetryConnectionNotifierId);
  notification =
      display_service_->GetNotification(kEcheAppRetryConnectionNotifierId);
  ASSERT_FALSE(notification.has_value());

  notification_controller_->ShowNotificationFromWebUI(
      title, message, mojom::WebNotificationType::DEVICE_IDLE);
  notification_controller_->CloseNotification(kEcheAppInactivityNotifierId);
  notification =
      display_service_->GetNotification(kEcheAppInactivityNotifierId);
  ASSERT_FALSE(notification.has_value());

  notification_controller_->ShowNotificationFromWebUI(
      title, message, mojom::WebNotificationType::INVALID_NOTIFICATION);
  notification_controller_->CloseNotification(
      kEcheAppFromWebWithoutButtonNotifierId);
  notification =
      display_service_->GetNotification(kEcheAppFromWebWithoutButtonNotifierId);
  ASSERT_FALSE(notification.has_value());

  notification_controller_->ShowNotificationFromWebUI(
      title, message, mojom::WebNotificationType::WIFI_NOT_READY);
  notification_controller_->CloseNotification(
      kEcheAppFromWebWithoutButtonNotifierId);
  notification =
      display_service_->GetNotification(kEcheAppFromWebWithoutButtonNotifierId);
  ASSERT_FALSE(notification.has_value());
}

TEST_F(EcheAppNotificationControllerTest,
       CloseConnectionOrLaunchErrorNotifications) {
  std::u16string title = u"title";
  std::optional<std::u16string> message = u"message";
  notification_controller_->ShowScreenLockNotification(title);
  notification_controller_->ShowNotificationFromWebUI(
      title, message, mojom::WebNotificationType::CONNECTION_FAILED);
  notification_controller_->ShowNotificationFromWebUI(
      title, message, mojom::WebNotificationType::DEVICE_IDLE);
  notification_controller_->ShowNotificationFromWebUI(
      title, message, mojom::WebNotificationType::INVALID_NOTIFICATION);
  notification_controller_->ShowNotificationFromWebUI(
      title, message, mojom::WebNotificationType::WIFI_NOT_READY);
  notification_controller_->CloseConnectionOrLaunchErrorNotifications();

  std::optional<message_center::Notification> notification =
      display_service_->GetNotification(kEcheAppScreenLockNotifierId);
  ASSERT_TRUE(notification.has_value());
  notification =
      display_service_->GetNotification(kEcheAppRetryConnectionNotifierId);
  ASSERT_FALSE(notification.has_value());
  notification =
      display_service_->GetNotification(kEcheAppInactivityNotifierId);
  ASSERT_FALSE(notification.has_value());
  notification =
      display_service_->GetNotification(kEcheAppFromWebWithoutButtonNotifierId);
  ASSERT_FALSE(notification.has_value());
  notification =
      display_service_->GetNotification(kEcheAppNetworkSettingNotifierId);
  ASSERT_FALSE(notification.has_value());
}

}  // namespace eche_app
}  // namespace ash