blob: 9b7cd993b1ce8be4d91b0ba5aabcc914fea4d058 [file] [log] [blame]
// Copyright 2025 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/startup/focus/focus_handler.h"
#include <memory>
#include <string>
#include <vector>
#include "base/command_line.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/test/scoped_feature_list.h"
#include "base/time/time.h"
#include "chrome/browser/ui/startup/focus/focus_result_file_writer.h"
#include "chrome/browser/ui/startup/focus/match_candidate.h"
#include "chrome/browser/ui/startup/focus/selector.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/test/base/testing_profile.h"
#include "content/public/test/browser_task_environment.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
namespace focus {
class FocusHandlerTest : public testing::Test {
public:
FocusHandlerTest() = default;
~FocusHandlerTest() override = default;
protected:
void SetUp() override {
ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
profile_ = std::make_unique<TestingProfile>();
}
void TearDown() override { profile_.reset(); }
base::FilePath GetTempFilePath(const std::string& filename) {
return temp_dir_.GetPath().AppendASCII(filename);
}
content::BrowserTaskEnvironment task_environment_;
base::ScopedTempDir temp_dir_;
std::unique_ptr<TestingProfile> profile_;
};
TEST_F(FocusHandlerTest, ProcessFocusRequestNoFlag) {
base::CommandLine command_line(base::CommandLine::NO_PROGRAM);
FocusResult result = ProcessFocusRequest(command_line, *profile_);
EXPECT_EQ(FocusStatus::kNoMatch,
result.status); // No flag = no match (nothing to focus)
}
TEST_F(FocusHandlerTest, ProcessFocusRequestEmptySelector) {
base::CommandLine command_line(base::CommandLine::NO_PROGRAM);
command_line.AppendSwitchASCII(switches::kFocus, "");
FocusResult result = ProcessFocusRequest(command_line, *profile_);
EXPECT_EQ(FocusStatus::kParseError, result.status);
}
TEST_F(FocusHandlerTest, ProcessFocusRequestInvalidSelector) {
base::CommandLine command_line(base::CommandLine::NO_PROGRAM);
command_line.AppendSwitchASCII(switches::kFocus, "not-a-valid-url");
FocusResult result = ProcessFocusRequest(command_line, *profile_);
EXPECT_EQ(FocusStatus::kParseError, result.status);
}
TEST_F(FocusHandlerTest, CreateFocusJsonString_Focused) {
FocusResult result(FocusStatus::kFocused, "https://example.com",
"https://example.com/path");
std::string json = CreateFocusJsonString(result);
EXPECT_TRUE(json.find("\"status\":\"focused\"") != std::string::npos);
EXPECT_TRUE(json.find("\"exit_code\":0") != std::string::npos);
}
TEST_F(FocusHandlerTest, CreateFocusJsonString_NoMatch) {
FocusResult result(FocusStatus::kNoMatch);
std::string json = CreateFocusJsonString(result);
EXPECT_TRUE(json.find("\"status\":\"no_match\"") != std::string::npos);
EXPECT_TRUE(json.find("\"exit_code\":1") != std::string::npos);
}
TEST_F(FocusHandlerTest, CreateFocusJsonString_ParseError) {
FocusResult result(FocusStatus::kParseError,
FocusResult::Error::kInvalidFormat);
std::string json = CreateFocusJsonString(result);
EXPECT_TRUE(json.find("\"status\":\"parse_error\"") != std::string::npos);
EXPECT_TRUE(json.find("\"error\":\"Invalid selector format\"") !=
std::string::npos);
EXPECT_TRUE(json.find("\"exit_code\":2") != std::string::npos);
}
TEST_F(FocusHandlerTest, CreateFocusJsonString_Opened) {
FocusResult result(FocusStatus::kOpenedFallback, "https://fallback.com");
std::string json = CreateFocusJsonString(result);
EXPECT_TRUE(json.find("\"status\":\"opened\"") != std::string::npos);
EXPECT_TRUE(json.find("\"exit_code\":0") != std::string::npos);
}
TEST_F(FocusHandlerTest, WriteResultToFile) {
base::FilePath test_file = GetTempFilePath("focus_result.json");
FocusResult result(FocusStatus::kFocused, "https://example.com",
"https://example.com/path");
WriteResultToFile(test_file.AsUTF8Unsafe(), result);
// Wait for async write to complete.
task_environment_.RunUntilIdle();
EXPECT_TRUE(base::PathExists(test_file));
std::string file_contents;
ASSERT_TRUE(base::ReadFileToString(test_file, &file_contents));
EXPECT_TRUE(file_contents.find("\"status\":\"focused\"") !=
std::string::npos);
EXPECT_TRUE(file_contents.find("\"exit_code\":0") != std::string::npos);
}
TEST_F(FocusHandlerTest, IncognitoDoesNotWriteResultFile) {
base::FilePath test_file = GetTempFilePath("incognito_result.json");
// Create an incognito profile
TestingProfile* incognito_profile =
TestingProfile::Builder().BuildIncognito(profile_.get());
base::CommandLine command_line(base::CommandLine::NO_PROGRAM);
command_line.AppendSwitchASCII(switches::kFocus, "https://example.com");
command_line.AppendSwitchASCII(switches::kFocusResultFile,
test_file.AsUTF8Unsafe());
FocusResult result =
ProcessFocusRequestWithResultFile(command_line, *incognito_profile);
// Result file should NOT be created in incognito mode
EXPECT_FALSE(base::PathExists(test_file));
EXPECT_EQ(FocusStatus::kNoMatch, result.status); // No tabs to match
}
} // namespace focus