blob: 8e029ae3c8fb005c24d4194d83c663c08a5eb9ad [file] [log] [blame]
// Copyright 2017 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 "chrome/browser/ui/ash/network/tether_notification_presenter.h"
#include <memory>
#include "base/memory/ptr_util.h"
#include "base/observer_list.h"
#include "base/test/metrics/histogram_tester.h"
#include "chrome/browser/notifications/notification_display_service_tester.h"
#include "chrome/common/url_constants.h"
#include "chrome/test/base/browser_with_test_window_test.h"
#include "chrome/test/base/testing_profile.h"
#include "chromeos/components/multidevice/remote_device_test_util.h"
#include "chromeos/network/network_connect.h"
namespace {
const int kTestNetworkSignalStrength = 50;
} // namespace
namespace chromeos {
namespace tether {
namespace {
const char kTetherSettingsSubpage[] = "networks?type=Tether";
} // namespace
class TetherNotificationPresenterTest : public BrowserWithTestWindowTest {
public:
class TestNetworkConnect : public NetworkConnect {
public:
TestNetworkConnect() {}
~TestNetworkConnect() override {}
std::string network_id_to_connect() { return network_id_to_connect_; }
// NetworkConnect:
void DisconnectFromNetworkId(const std::string& network_id) override {}
void SetTechnologyEnabled(const chromeos::NetworkTypePattern& technology,
bool enabled_state) override {}
void ShowMobileSetup(const std::string& network_id) override {}
void ConfigureNetworkIdAndConnect(
const std::string& network_id,
const base::DictionaryValue& shill_properties,
bool shared) override {}
void CreateConfigurationAndConnect(base::DictionaryValue* shill_properties,
bool shared) override {}
void CreateConfiguration(base::DictionaryValue* shill_properties,
bool shared) override {}
void ConnectToNetworkId(const std::string& network_id) override {
network_id_to_connect_ = network_id;
}
private:
std::string network_id_to_connect_;
};
class TestSettingsUiDelegate
: public TetherNotificationPresenter::SettingsUiDelegate {
public:
TestSettingsUiDelegate() {}
~TestSettingsUiDelegate() override {}
Profile* last_profile() { return last_profile_; }
std::string last_settings_subpage() { return last_settings_subpage_; }
// TetherNotificationPresenter::SettingsUiDelegate:
void ShowSettingsSubPageForProfile(Profile* profile,
const std::string& sub_page) override {
last_profile_ = profile;
last_settings_subpage_ = sub_page;
}
private:
Profile* last_profile_ = nullptr;
std::string last_settings_subpage_;
};
protected:
TetherNotificationPresenterTest()
: test_device_(multidevice::CreateRemoteDeviceRefListForTest(1)[0]) {}
void SetUp() override {
BrowserWithTestWindowTest::SetUp();
display_service_ =
std::make_unique<NotificationDisplayServiceTester>(profile());
test_network_connect_ = base::WrapUnique(new TestNetworkConnect());
notification_presenter_ = std::make_unique<TetherNotificationPresenter>(
profile(), test_network_connect_.get());
test_settings_ui_delegate_ = new TestSettingsUiDelegate();
notification_presenter_->SetSettingsUiDelegateForTesting(
base::WrapUnique(test_settings_ui_delegate_));
has_verified_metrics_ = false;
}
void TearDown() override {
if (!has_verified_metrics_) {
VerifyNotificationInteractionMetrics(
0u /* num_expected_body_tapped_single_host_nearby */,
0u /* num_expected_body_tapped_multiple_hosts_nearby */,
0u /* num_expected_body_tapped_setup_required */,
0u /* num_expected_body_tapped_connection_failed */,
0u /* num_expected_button_tapped_single_host_nearby */);
}
BrowserWithTestWindowTest::TearDown();
}
std::string GetActiveHostNotificationId() {
return std::string(TetherNotificationPresenter::kActiveHostNotificationId);
}
std::string GetPotentialHotspotNotificationId() {
return std::string(
TetherNotificationPresenter::kPotentialHotspotNotificationId);
}
std::string GetSetupRequiredNotificationId() {
return std::string(
TetherNotificationPresenter::kSetupRequiredNotificationId);
}
void VerifySettingsOpened(const std::string& expected_subpage) {
EXPECT_EQ(profile(), test_settings_ui_delegate_->last_profile());
EXPECT_EQ(expected_subpage,
test_settings_ui_delegate_->last_settings_subpage());
}
void VerifySettingsNotOpened() {
EXPECT_FALSE(test_settings_ui_delegate_->last_profile());
EXPECT_TRUE(test_settings_ui_delegate_->last_settings_subpage().empty());
}
void VerifyNotificationInteractionMetrics(
size_t num_expected_body_tapped_single_host_nearby,
size_t num_expected_body_tapped_multiple_hosts_nearby,
size_t num_expected_body_tapped_setup_required,
size_t num_expected_body_tapped_connection_failed,
size_t num_expected_button_tapped_single_host_nearby) {
if (num_expected_body_tapped_single_host_nearby +
num_expected_body_tapped_multiple_hosts_nearby +
num_expected_body_tapped_setup_required +
num_expected_body_tapped_connection_failed +
num_expected_button_tapped_single_host_nearby ==
0u) {
histogram_tester_.ExpectTotalCount(
"InstantTethering.NotificationInteractionType", 0u);
return;
}
histogram_tester_.ExpectBucketCount(
"InstantTethering.NotificationInteractionType",
TetherNotificationPresenter::
NOTIFICATION_BODY_TAPPED_SINGLE_HOST_NEARBY,
num_expected_body_tapped_single_host_nearby);
histogram_tester_.ExpectBucketCount(
"InstantTethering.NotificationInteractionType",
TetherNotificationPresenter::
NOTIFICATION_BODY_TAPPED_MULTIPLE_HOSTS_NEARBY,
num_expected_body_tapped_multiple_hosts_nearby);
histogram_tester_.ExpectBucketCount(
"InstantTethering.NotificationInteractionType",
TetherNotificationPresenter::NOTIFICATION_BODY_TAPPED_SETUP_REQUIRED,
num_expected_body_tapped_setup_required);
histogram_tester_.ExpectBucketCount(
"InstantTethering.NotificationInteractionType",
TetherNotificationPresenter::NOTIFICATION_BODY_TAPPED_CONNECTION_FAILED,
num_expected_body_tapped_connection_failed);
histogram_tester_.ExpectBucketCount(
"InstantTethering.NotificationInteractionType",
TetherNotificationPresenter::NOTIFICATION_BUTTON_TAPPED_HOST_NEARBY,
num_expected_button_tapped_single_host_nearby);
has_verified_metrics_ = true;
}
multidevice::RemoteDeviceRef test_device_;
base::HistogramTester histogram_tester_;
bool has_verified_metrics_;
std::unique_ptr<TestNetworkConnect> test_network_connect_;
TestSettingsUiDelegate* test_settings_ui_delegate_;
std::unique_ptr<TetherNotificationPresenter> notification_presenter_;
std::unique_ptr<NotificationDisplayServiceTester> display_service_;
private:
DISALLOW_COPY_AND_ASSIGN(TetherNotificationPresenterTest);
};
TEST_F(TetherNotificationPresenterTest,
TestHostConnectionFailedNotification_RemoveProgrammatically) {
EXPECT_FALSE(
display_service_->GetNotification(GetActiveHostNotificationId()));
notification_presenter_->NotifyConnectionToHostFailed();
base::Optional<message_center::Notification> notification =
display_service_->GetNotification(GetActiveHostNotificationId());
ASSERT_TRUE(notification);
EXPECT_EQ(GetActiveHostNotificationId(), notification->id());
notification_presenter_->RemoveConnectionToHostFailedNotification();
EXPECT_FALSE(
display_service_->GetNotification(GetActiveHostNotificationId()));
VerifySettingsNotOpened();
}
TEST_F(TetherNotificationPresenterTest,
TestHostConnectionFailedNotification_TapNotification) {
EXPECT_FALSE(
display_service_->GetNotification(GetActiveHostNotificationId()));
notification_presenter_->NotifyConnectionToHostFailed();
base::Optional<message_center::Notification> notification =
display_service_->GetNotification(GetActiveHostNotificationId());
ASSERT_TRUE(notification);
EXPECT_EQ(GetActiveHostNotificationId(), notification->id());
// Tap the notification.
ASSERT_TRUE(notification->delegate());
notification->delegate()->Click(base::nullopt, base::nullopt);
VerifySettingsOpened(kTetherSettingsSubpage);
EXPECT_FALSE(
display_service_->GetNotification(GetActiveHostNotificationId()));
VerifyNotificationInteractionMetrics(
0u /* num_expected_body_tapped_single_host_nearby */,
0u /* num_expected_body_tapped_multiple_hosts_nearby */,
0u /* num_expected_body_tapped_setup_required */,
1u /* num_expected_body_tapped_connection_failed */,
0u /* num_expected_button_tapped_single_host_nearby */);
}
TEST_F(TetherNotificationPresenterTest,
TestSetupRequiredNotification_RemoveProgrammatically) {
EXPECT_FALSE(
display_service_->GetNotification(GetSetupRequiredNotificationId()));
notification_presenter_->NotifySetupRequired(test_device_.name(),
kTestNetworkSignalStrength);
base::Optional<message_center::Notification> notification =
display_service_->GetNotification(GetSetupRequiredNotificationId());
ASSERT_TRUE(notification);
EXPECT_EQ(GetSetupRequiredNotificationId(), notification->id());
notification_presenter_->RemoveSetupRequiredNotification();
EXPECT_FALSE(
display_service_->GetNotification(GetSetupRequiredNotificationId()));
VerifySettingsNotOpened();
}
TEST_F(TetherNotificationPresenterTest,
TestSetupRequiredNotification_TapNotification) {
EXPECT_FALSE(
display_service_->GetNotification(GetSetupRequiredNotificationId()));
notification_presenter_->NotifySetupRequired(test_device_.name(),
kTestNetworkSignalStrength);
base::Optional<message_center::Notification> notification =
display_service_->GetNotification(GetSetupRequiredNotificationId());
ASSERT_TRUE(notification);
EXPECT_EQ(GetSetupRequiredNotificationId(), notification->id());
// Tap the notification.
ASSERT_TRUE(notification->delegate());
notification->delegate()->Click(base::nullopt, base::nullopt);
VerifySettingsOpened(kTetherSettingsSubpage);
EXPECT_FALSE(
display_service_->GetNotification(GetSetupRequiredNotificationId()));
VerifyNotificationInteractionMetrics(
0u /* num_expected_body_tapped_single_host_nearby */,
0u /* num_expected_body_tapped_multiple_hosts_nearby */,
1u /* num_expected_body_tapped_setup_required */,
0u /* num_expected_body_tapped_connection_failed */,
0u /* num_expected_button_tapped_single_host_nearby */);
}
TEST_F(TetherNotificationPresenterTest,
TestPotentialHotspotNotification_RemoveProgrammatically) {
EXPECT_FALSE(
display_service_->GetNotification(GetPotentialHotspotNotificationId()));
notification_presenter_->NotifyPotentialHotspotNearby(
test_device_, kTestNetworkSignalStrength);
base::Optional<message_center::Notification> notification =
display_service_->GetNotification(GetPotentialHotspotNotificationId());
ASSERT_TRUE(notification);
EXPECT_EQ(GetPotentialHotspotNotificationId(), notification->id());
notification_presenter_->RemovePotentialHotspotNotification();
EXPECT_FALSE(
display_service_->GetNotification(GetPotentialHotspotNotificationId()));
VerifySettingsNotOpened();
}
TEST_F(TetherNotificationPresenterTest,
TestPotentialHotspotNotification_TapNotification) {
EXPECT_FALSE(
display_service_->GetNotification(GetPotentialHotspotNotificationId()));
notification_presenter_->NotifyPotentialHotspotNearby(
test_device_, kTestNetworkSignalStrength);
base::Optional<message_center::Notification> notification =
display_service_->GetNotification(GetPotentialHotspotNotificationId());
ASSERT_TRUE(notification);
EXPECT_EQ(GetPotentialHotspotNotificationId(), notification->id());
// Tap the notification.
ASSERT_TRUE(notification->delegate());
notification->delegate()->Click(base::nullopt, base::nullopt);
VerifySettingsOpened(kTetherSettingsSubpage);
EXPECT_FALSE(
display_service_->GetNotification(GetPotentialHotspotNotificationId()));
VerifyNotificationInteractionMetrics(
1u /* num_expected_body_tapped_single_host_nearby */,
0u /* num_expected_body_tapped_multiple_hosts_nearby */,
0u /* num_expected_body_tapped_setup_required */,
0u /* num_expected_body_tapped_connection_failed */,
0u /* num_expected_button_tapped_single_host_nearby */);
}
TEST_F(TetherNotificationPresenterTest,
TestSinglePotentialHotspotNotification_TapNotificationButton) {
EXPECT_FALSE(
display_service_->GetNotification(GetPotentialHotspotNotificationId()));
notification_presenter_->NotifyPotentialHotspotNearby(
test_device_, kTestNetworkSignalStrength);
base::Optional<message_center::Notification> notification =
display_service_->GetNotification(GetPotentialHotspotNotificationId());
ASSERT_TRUE(notification);
EXPECT_EQ(GetPotentialHotspotNotificationId(), notification->id());
// Tap the notification's button.
ASSERT_TRUE(notification->delegate());
notification->delegate()->Click(0, base::nullopt);
EXPECT_FALSE(
display_service_->GetNotification(GetPotentialHotspotNotificationId()));
EXPECT_EQ(test_device_.GetDeviceId(),
test_network_connect_->network_id_to_connect());
VerifyNotificationInteractionMetrics(
0u /* num_expected_body_tapped_single_host_nearby */,
0u /* num_expected_body_tapped_multiple_hosts_nearby */,
0u /* num_expected_body_tapped_setup_required */,
0u /* num_expected_body_tapped_connection_failed */,
1u /* num_expected_button_tapped_single_host_nearby */);
}
TEST_F(TetherNotificationPresenterTest,
TestMultiplePotentialHotspotNotification_RemoveProgrammatically) {
EXPECT_FALSE(
display_service_->GetNotification(GetPotentialHotspotNotificationId()));
notification_presenter_->NotifyMultiplePotentialHotspotsNearby();
base::Optional<message_center::Notification> notification =
display_service_->GetNotification(GetPotentialHotspotNotificationId());
ASSERT_TRUE(notification);
EXPECT_EQ(GetPotentialHotspotNotificationId(), notification->id());
notification_presenter_->RemovePotentialHotspotNotification();
EXPECT_FALSE(
display_service_->GetNotification(GetPotentialHotspotNotificationId()));
VerifySettingsNotOpened();
}
TEST_F(TetherNotificationPresenterTest,
TestMultiplePotentialHotspotNotification_TapNotification) {
EXPECT_FALSE(
display_service_->GetNotification(GetPotentialHotspotNotificationId()));
notification_presenter_->NotifyMultiplePotentialHotspotsNearby();
base::Optional<message_center::Notification> notification =
display_service_->GetNotification(GetPotentialHotspotNotificationId());
ASSERT_TRUE(notification);
EXPECT_EQ(GetPotentialHotspotNotificationId(), notification->id());
// Tap the notification.
ASSERT_TRUE(notification->delegate());
notification->delegate()->Click(base::nullopt, base::nullopt);
VerifySettingsOpened(kTetherSettingsSubpage);
EXPECT_FALSE(
display_service_->GetNotification(GetPotentialHotspotNotificationId()));
VerifyNotificationInteractionMetrics(
0u /* num_expected_body_tapped_single_host_nearby */,
1u /* num_expected_body_tapped_multiple_hosts_nearby */,
0u /* num_expected_body_tapped_setup_required */,
0u /* num_expected_body_tapped_connection_failed */,
0u /* num_expected_button_tapped_single_host_nearby */);
}
TEST_F(TetherNotificationPresenterTest,
TestPotentialHotspotNotifications_UpdatesOneNotification) {
EXPECT_FALSE(
display_service_->GetNotification(GetPotentialHotspotNotificationId()));
notification_presenter_->NotifyPotentialHotspotNearby(
test_device_, kTestNetworkSignalStrength);
base::Optional<message_center::Notification> notification =
display_service_->GetNotification(GetPotentialHotspotNotificationId());
ASSERT_TRUE(notification);
EXPECT_EQ(GetPotentialHotspotNotificationId(), notification->id());
// Simulate more device results coming in. Display the potential hotspots
// notification for multiple devices.
notification_presenter_->NotifyMultiplePotentialHotspotsNearby();
// The existing notification should have been updated instead of creating a
// new one.
notification =
display_service_->GetNotification(GetPotentialHotspotNotificationId());
ASSERT_TRUE(notification);
EXPECT_EQ(GetPotentialHotspotNotificationId(), notification->id());
notification_presenter_->RemovePotentialHotspotNotification();
EXPECT_FALSE(
display_service_->GetNotification(GetPotentialHotspotNotificationId()));
VerifySettingsNotOpened();
}
TEST_F(TetherNotificationPresenterTest,
TestGetPotentialHotspotNotificationState) {
EXPECT_EQ(notification_presenter_->GetPotentialHotspotNotificationState(),
NotificationPresenter::PotentialHotspotNotificationState::
NO_HOTSPOT_NOTIFICATION_SHOWN);
// Notify single host available and remove.
notification_presenter_->NotifyPotentialHotspotNearby(
test_device_, kTestNetworkSignalStrength);
EXPECT_EQ(notification_presenter_->GetPotentialHotspotNotificationState(),
NotificationPresenter::PotentialHotspotNotificationState::
SINGLE_HOTSPOT_NEARBY_SHOWN);
notification_presenter_->RemovePotentialHotspotNotification();
EXPECT_EQ(notification_presenter_->GetPotentialHotspotNotificationState(),
NotificationPresenter::PotentialHotspotNotificationState::
NO_HOTSPOT_NOTIFICATION_SHOWN);
// Notify single host available and remove by tapping notification.
notification_presenter_->NotifyPotentialHotspotNearby(
test_device_, kTestNetworkSignalStrength);
EXPECT_EQ(notification_presenter_->GetPotentialHotspotNotificationState(),
NotificationPresenter::PotentialHotspotNotificationState::
SINGLE_HOTSPOT_NEARBY_SHOWN);
display_service_->GetNotification(GetPotentialHotspotNotificationId())
->delegate()
->Click(base::nullopt, base::nullopt);
EXPECT_EQ(notification_presenter_->GetPotentialHotspotNotificationState(),
NotificationPresenter::PotentialHotspotNotificationState::
NO_HOTSPOT_NOTIFICATION_SHOWN);
// Notify single host available and remove by tapping notification button.
notification_presenter_->NotifyPotentialHotspotNearby(
test_device_, kTestNetworkSignalStrength);
EXPECT_EQ(notification_presenter_->GetPotentialHotspotNotificationState(),
NotificationPresenter::PotentialHotspotNotificationState::
SINGLE_HOTSPOT_NEARBY_SHOWN);
display_service_->GetNotification(GetPotentialHotspotNotificationId())
->delegate()
->Click(0, base::nullopt);
EXPECT_EQ(notification_presenter_->GetPotentialHotspotNotificationState(),
NotificationPresenter::PotentialHotspotNotificationState::
NO_HOTSPOT_NOTIFICATION_SHOWN);
// Notify single, then multiple hosts available and remove.
notification_presenter_->NotifyPotentialHotspotNearby(
test_device_, kTestNetworkSignalStrength);
EXPECT_EQ(notification_presenter_->GetPotentialHotspotNotificationState(),
NotificationPresenter::PotentialHotspotNotificationState::
SINGLE_HOTSPOT_NEARBY_SHOWN);
notification_presenter_->NotifyMultiplePotentialHotspotsNearby();
EXPECT_EQ(notification_presenter_->GetPotentialHotspotNotificationState(),
NotificationPresenter::PotentialHotspotNotificationState::
MULTIPLE_HOTSPOTS_NEARBY_SHOWN);
notification_presenter_->RemovePotentialHotspotNotification();
EXPECT_EQ(notification_presenter_->GetPotentialHotspotNotificationState(),
NotificationPresenter::PotentialHotspotNotificationState::
NO_HOTSPOT_NOTIFICATION_SHOWN);
// Notify single, then multiple hosts available and remove by tapping
// notification.
notification_presenter_->NotifyPotentialHotspotNearby(
test_device_, kTestNetworkSignalStrength);
EXPECT_EQ(notification_presenter_->GetPotentialHotspotNotificationState(),
NotificationPresenter::PotentialHotspotNotificationState::
SINGLE_HOTSPOT_NEARBY_SHOWN);
notification_presenter_->NotifyMultiplePotentialHotspotsNearby();
EXPECT_EQ(notification_presenter_->GetPotentialHotspotNotificationState(),
NotificationPresenter::PotentialHotspotNotificationState::
MULTIPLE_HOTSPOTS_NEARBY_SHOWN);
display_service_->GetNotification(GetPotentialHotspotNotificationId())
->delegate()
->Click(base::nullopt, base::nullopt);
EXPECT_EQ(notification_presenter_->GetPotentialHotspotNotificationState(),
NotificationPresenter::PotentialHotspotNotificationState::
NO_HOTSPOT_NOTIFICATION_SHOWN);
VerifyNotificationInteractionMetrics(
1u /* num_expected_body_tapped_single_host_nearby */,
1u /* num_expected_body_tapped_multiple_hosts_nearby */,
0u /* num_expected_body_tapped_setup_required */,
0u /* num_expected_body_tapped_connection_failed */,
1u /* num_expected_button_tapped_single_host_nearby */);
}
} // namespace tether
} // namespace chromeos