blob: e19432f3a828c628c627cf2a7f2fdcc7370e61c3 [file] [log] [blame]
// Copyright 2018 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/webui/dark_mode_handler.h"
#include "base/test/scoped_feature_list.h"
#include "base/token.h"
#include "base/values.h"
#include "chrome/browser/browser_features.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/test/base/testing_profile.h"
#include "content/public/browser/web_ui_data_source.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "content/public/test/test_web_ui.h"
#include "content/public/test/test_web_ui_data_source.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/native_theme/test_native_theme.h"
class TestDarkModeHandler : public DarkModeHandler {
public:
using DarkModeHandler::InitializeInternal;
};
class DarkModeHandlerTest : public testing::Test {
public:
DarkModeHandlerTest()
: source_(content::TestWebUIDataSource::Create(
base::Token::CreateRandom().ToString())) {
// We use a random source_name here as calling Add() can replace existing
// sources with the same name (which might destroy the memory addressed by
// |source()->GetWebUIDataSource()|.
content::WebUIDataSource::Add(&profile_, source()->GetWebUIDataSource());
}
content::TestBrowserThreadBundle* bundle() { return &bundle_; }
content::TestWebUI* web_ui() { return &web_ui_; }
ui::TestNativeTheme* theme() { return &theme_; }
base::test::ScopedFeatureList* features() { return &features_; }
content::TestWebUIDataSource* source() { return source_.get(); }
void InitializeHandler() {
TestDarkModeHandler::InitializeInternal(
web_ui(), source()->GetWebUIDataSource(), theme(), &profile_);
}
bool IsSourceDark() {
const auto* replacements = source()->GetReplacements();
const auto dark_it = replacements->find("dark");
const auto* local_strings = source()->GetLocalizedStrings();
const auto* dark_mode =
local_strings->FindKeyOfType("darkMode", base::Value::Type::BOOLEAN);
if (dark_it == replacements->end() || !dark_mode) {
ADD_FAILURE();
return false;
}
return dark_it->second == "dark" && dark_mode->GetBool();
}
private:
content::TestBrowserThreadBundle bundle_;
TestingProfile profile_;
base::test::ScopedFeatureList features_;
content::TestWebUI web_ui_;
ui::TestNativeTheme theme_;
std::unique_ptr<content::TestWebUIDataSource> source_;
};
TEST_F(DarkModeHandlerTest, WebUIDarkModeDisabledLightMode) {
features()->InitAndDisableFeature(features::kWebUIDarkMode);
theme()->SetDarkMode(false);
InitializeHandler();
EXPECT_EQ(web_ui()->GetHandlersForTesting()->size(), 1u);
EXPECT_EQ(web_ui()->call_data().size(), 0u);
EXPECT_FALSE(IsSourceDark());
}
TEST_F(DarkModeHandlerTest, WebUIDarkModeDisabledDarkMode) {
features()->InitAndDisableFeature(features::kWebUIDarkMode);
theme()->SetDarkMode(true);
InitializeHandler();
EXPECT_EQ(web_ui()->GetHandlersForTesting()->size(), 1u);
EXPECT_EQ(web_ui()->call_data().size(), 0u);
// Even if in dark mode, if the feature's disabled we shouldn't be telling the
// page to be dark.
EXPECT_FALSE(IsSourceDark());
}
TEST_F(DarkModeHandlerTest, WebUIDarkModeDisabledNoNotifications) {
features()->InitAndDisableFeature(features::kWebUIDarkMode);
theme()->SetDarkMode(false);
InitializeHandler();
EXPECT_EQ(web_ui()->GetHandlersForTesting()->size(), 1u);
EXPECT_EQ(web_ui()->call_data().size(), 0u);
EXPECT_FALSE(IsSourceDark());
theme()->SetDarkMode(true);
theme()->NotifyObservers();
EXPECT_EQ(web_ui()->call_data().size(), 0u);
EXPECT_FALSE(IsSourceDark());
}
TEST_F(DarkModeHandlerTest, WebUIDarkModeEnabledInLightMode) {
features()->InitAndEnableFeature(features::kWebUIDarkMode);
theme()->SetDarkMode(false);
InitializeHandler();
EXPECT_EQ(web_ui()->GetHandlersForTesting()->size(), 1u);
EXPECT_EQ(web_ui()->call_data().size(), 0u);
EXPECT_FALSE(IsSourceDark());
}
TEST_F(DarkModeHandlerTest, WebUIDarkModeEnabledInDarkMode) {
features()->InitAndEnableFeature(features::kWebUIDarkMode);
theme()->SetDarkMode(true);
InitializeHandler();
EXPECT_EQ(web_ui()->GetHandlersForTesting()->size(), 1u);
EXPECT_EQ(web_ui()->call_data().size(), 0u);
EXPECT_TRUE(IsSourceDark());
}
TEST_F(DarkModeHandlerTest, NotifiesAndUpdatesOnChange) {
features()->InitAndEnableFeature(features::kWebUIDarkMode);
theme()->SetDarkMode(false);
InitializeHandler();
ASSERT_EQ(web_ui()->GetHandlersForTesting()->size(), 1u);
EXPECT_EQ(web_ui()->call_data().size(), 0u);
EXPECT_FALSE(IsSourceDark());
web_ui()->HandleReceivedMessage("observeDarkMode", /*args=*/nullptr);
EXPECT_EQ(web_ui()->call_data().size(), 0u);
// Theme changes unrelated to dark mode should not notify.
theme()->NotifyObservers();
EXPECT_EQ(web_ui()->call_data().size(), 0u);
theme()->SetDarkMode(true);
theme()->NotifyObservers();
bundle()->RunUntilIdle();
EXPECT_TRUE(IsSourceDark());
ASSERT_EQ(web_ui()->call_data().size(), 1u);
EXPECT_STREQ(web_ui()->call_data()[0]->function_name().c_str(),
"cr.webUIListenerCallback");
ASSERT_TRUE(web_ui()->call_data()[0]->arg1());
ASSERT_TRUE(web_ui()->call_data()[0]->arg1()->is_string());
EXPECT_STREQ(web_ui()->call_data()[0]->arg1()->GetString().c_str(),
"dark-mode-changed");
ASSERT_TRUE(web_ui()->call_data()[0]->arg2());
ASSERT_TRUE(web_ui()->call_data()[0]->arg2()->is_bool());
EXPECT_TRUE(web_ui()->call_data()[0]->arg2()->GetBool());
}