chromium/chrome/browser/ui/ash/network/network_portal_notification_controller_unittest.cc

// Copyright 2014 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/ui/ash/network/network_portal_notification_controller.h"

#include "base/command_line.h"
#include "chrome/browser/notifications/notification_display_service_tester.h"
#include "chrome/browser/notifications/system_notification_helper.h"
#include "chrome/test/base/browser_with_test_window_test.h"
#include "chrome/test/base/testing_browser_process.h"
#include "chrome/test/base/testing_profile_manager.h"
#include "chromeos/ash/components/network/network_state.h"
#include "third_party/cros_system_api/dbus/shill/dbus-constants.h"

namespace ash {

namespace {

const char* const kNotificationId =
    NetworkPortalNotificationController::kNotificationId;

class TestWiFiNetworkState : public NetworkState {
 public:
  explicit TestWiFiNetworkState(const std::string& name) : NetworkState(name) {
    SetGuid(name);
    set_type(shill::kTypeWifi);
  }
};

}  // namespace

// A BrowserWithTestWindowTest will set up profiles for us.
class NetworkPortalNotificationControllerTest
    : public BrowserWithTestWindowTest {
 public:
  NetworkPortalNotificationControllerTest() : BrowserWithTestWindowTest() {}

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

  ~NetworkPortalNotificationControllerTest() override {}

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

    TestingBrowserProcess::GetGlobal()->SetSystemNotificationHelper(
        std::make_unique<SystemNotificationHelper>());
    display_service_ = std::make_unique<NotificationDisplayServiceTester>(
        nullptr /* profile */);
  }

 protected:
  void PortalStateChanged(const NetworkState* network,
                          NetworkState::PortalState portal_state) {
    controller_.PortalStateChanged(network, portal_state);
  }

  bool HasNotification() {
    return !!display_service_->GetNotification(kNotificationId);
  }

  std::unique_ptr<NotificationDisplayServiceTester> display_service_;
  NetworkPortalNotificationController controller_;
};

TEST_F(NetworkPortalNotificationControllerTest, NetworkStateChangedPortal) {
  TestWiFiNetworkState wifi("wifi");

  // Notification is not displayed for online state.
  PortalStateChanged(&wifi, NetworkState::PortalState::kOnline);
  EXPECT_FALSE(HasNotification());

  // Notification is displayed for portal state
  PortalStateChanged(&wifi, NetworkState::PortalState::kPortal);
  EXPECT_TRUE(HasNotification());

  // Notification is closed for online state.
  PortalStateChanged(&wifi, NetworkState::PortalState::kOnline);
  EXPECT_FALSE(HasNotification());
}

TEST_F(NetworkPortalNotificationControllerTest,
       NetworkStateChangedPortalSuspected) {
  TestWiFiNetworkState wifi("wifi");

  // Notification is not displayed for online state.
  PortalStateChanged(&wifi, NetworkState::PortalState::kOnline);
  EXPECT_FALSE(HasNotification());

  // Notification is displayed for portal-suspected state
  PortalStateChanged(&wifi, NetworkState::PortalState::kPortalSuspected);
  EXPECT_TRUE(HasNotification());

  // Notification is closed for online state.
  PortalStateChanged(&wifi, NetworkState::PortalState::kOnline);
  EXPECT_FALSE(HasNotification());
}

TEST_F(NetworkPortalNotificationControllerTest,
       NetworkStateChangedProxyAuthRequired) {
  TestWiFiNetworkState wifi("wifi");

  // Notification is not displayed for online state.
  PortalStateChanged(&wifi, NetworkState::PortalState::kOnline);
  EXPECT_FALSE(HasNotification());

  // Notification is closed for online state.
  PortalStateChanged(&wifi, NetworkState::PortalState::kOnline);
  EXPECT_FALSE(HasNotification());
}

TEST_F(NetworkPortalNotificationControllerTest, NetworkChanged) {
  TestWiFiNetworkState wifi1("wifi1");
  PortalStateChanged(&wifi1, NetworkState::PortalState::kPortal);
  EXPECT_TRUE(HasNotification());

  display_service_->RemoveNotification(NotificationHandler::Type::TRANSIENT,
                                       kNotificationId, true /* by_user */);
  EXPECT_FALSE(HasNotification());

  // User already closed notification about portal state for this network,
  // so notification shouldn't be displayed second time.
  PortalStateChanged(&wifi1, NetworkState::PortalState::kPortal);
  EXPECT_FALSE(HasNotification());

  TestWiFiNetworkState wifi2("wifi2");
  // Second network is in online state, so there shouldn't be any
  // notifications.
  PortalStateChanged(&wifi2, NetworkState::PortalState::kOnline);
  EXPECT_FALSE(HasNotification());

  // User switches back to the first network, so notification should
  // be displayed.
  PortalStateChanged(&wifi1, NetworkState::PortalState::kPortal);
  EXPECT_TRUE(HasNotification());
}

TEST_F(NetworkPortalNotificationControllerTest, NotificationUpdated) {
  // First network is behind a captive portal, so notification should
  // be displayed.
  TestWiFiNetworkState wifi1("wifi1");
  wifi1.PropertyChanged("Name", base::Value("wifi1"));
  PortalStateChanged(&wifi1, NetworkState::PortalState::kPortal);
  EXPECT_TRUE(HasNotification());
  EXPECT_EQ(1u, display_service_
                    ->GetDisplayedNotificationsForType(
                        NotificationHandler::Type::TRANSIENT)
                    .size());
  const std::u16string initial_message =
      display_service_->GetNotification(kNotificationId)->message();

  // Second network is also behind a captive portal, so notification
  // should be updated.
  TestWiFiNetworkState wifi2("wifi2");
  wifi2.PropertyChanged("Name", base::Value("wifi2"));
  PortalStateChanged(&wifi2, NetworkState::PortalState::kPortal);
  EXPECT_TRUE(HasNotification());
  EXPECT_EQ(1u, display_service_
                    ->GetDisplayedNotificationsForType(
                        NotificationHandler::Type::TRANSIENT)
                    .size());
  EXPECT_NE(initial_message,
            display_service_->GetNotification(kNotificationId)->message());

  // User closes the notification.
  display_service_->RemoveNotification(NotificationHandler::Type::TRANSIENT,
                                       kNotificationId, true /* by_user */);
  EXPECT_FALSE(HasNotification());

  // Portal detector notified that second network is still behind captive
  // portal, but user already closed the notification, so there should
  // not be any notifications.
  PortalStateChanged(&wifi2, NetworkState::PortalState::kPortal);
  EXPECT_FALSE(HasNotification());

  // Network was switched (by shill or by user) to wifi1. Notification
  // should be displayed.
  PortalStateChanged(&wifi1, NetworkState::PortalState::kPortal);
  EXPECT_TRUE(HasNotification());
}

}  // namespace ash