Skip to content

Commit

Permalink
Add AIChatUIBrowserTest and fix existing tests
Browse files Browse the repository at this point in the history
  • Loading branch information
darkdh committed Mar 15, 2024
1 parent 7e1aecf commit f57bc2b
Show file tree
Hide file tree
Showing 10 changed files with 327 additions and 24 deletions.
2 changes: 2 additions & 0 deletions browser/ai_chat/BUILD.gn
Expand Up @@ -33,6 +33,7 @@ source_set("browser_tests") {
sources = [
"ai_chat_policy_browsertest.cc",
"ai_chat_profile_browsertest.cc",
"ai_chat_ui_browsertest.cc",
"page_content_fetcher_browsertest.cc",
]
deps = [
Expand All @@ -47,6 +48,7 @@ source_set("browser_tests") {
"//chrome/browser",
"//chrome/test:test_support",
"//chrome/test:test_support_ui",
"//printing/buildflags",
]
}
}
4 changes: 4 additions & 0 deletions browser/ai_chat/DEPS
@@ -0,0 +1,4 @@
include_rules = [
"+printing/buildflags",
]

221 changes: 221 additions & 0 deletions browser/ai_chat/ai_chat_ui_browsertest.cc
@@ -0,0 +1,221 @@
/* Copyright (c) 2024 The Brave Authors. All rights reserved.
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at https://mozilla.org/MPL/2.0/. */

#include "base/files/file_path.h"
#include "base/functional/bind.h"
#include "base/functional/callback_helpers.h"
#include "base/path_service.h"
#include "base/run_loop.h"
#include "base/strings/strcat.h"
#include "base/test/bind.h"
#include "brave/browser/ui/webui/ai_chat/ai_chat_ui.h"
#include "brave/browser/ui/webui/ai_chat/ai_chat_ui_page_handler.h"
#include "brave/components/ai_chat/content/browser/ai_chat_tab_helper.h"
#include "brave/components/constants/brave_paths.h"
#include "brave/components/l10n/common/test/scoped_default_locale.h"
#include "brave/components/text_recognition/common/buildflags/buildflags.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/side_panel/side_panel_ui.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/browser/ui/views/frame/browser_view.h"
#include "chrome/browser/ui/views/side_panel/side_panel_web_ui_view.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "chrome/test/base/ui_test_utils.h"
#include "content/public/browser/web_contents.h"
#include "content/public/test/browser_test.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/content_mock_cert_verifier.h"
#include "net/dns/mock_host_resolver.h"
#include "printing/buildflags/buildflags.h"
#include "ui/compositor/compositor_switches.h"

namespace {

constexpr char kEmbeddedTestServerDirectory[] = "leo";
} // namespace

class AIChatUIBrowserTest : public InProcessBrowserTest {
public:
AIChatUIBrowserTest() : https_server_(net::EmbeddedTestServer::TYPE_HTTPS) {}

void SetUpOnMainThread() override {
mock_cert_verifier_.mock_cert_verifier()->set_default_result(net::OK);
host_resolver()->AddRule("*", "127.0.0.1");
content::SetupCrossSiteRedirector(&https_server_);

brave::RegisterPathProvider();
base::FilePath test_data_dir;
test_data_dir = base::PathService::CheckedGet(brave::DIR_TEST_DATA);
test_data_dir = test_data_dir.AppendASCII(kEmbeddedTestServerDirectory);
https_server_.ServeFilesFromDirectory(test_data_dir);
ASSERT_TRUE(https_server_.Start());
}

void SetUpCommandLine(base::CommandLine* command_line) override {
InProcessBrowserTest::SetUpCommandLine(command_line);
#if BUILDFLAG(ENABLE_TEXT_RECOGNITION)
command_line->AppendSwitch(::switches::kEnablePixelOutputInTests);
#endif
mock_cert_verifier_.SetUpCommandLine(command_line);
}

void SetUpInProcessBrowserTestFixture() override {
InProcessBrowserTest::SetUpInProcessBrowserTestFixture();
mock_cert_verifier_.SetUpInProcessBrowserTestFixture();
}

void TearDownInProcessBrowserTestFixture() override {
mock_cert_verifier_.TearDownInProcessBrowserTestFixture();
InProcessBrowserTest::TearDownInProcessBrowserTestFixture();
}

content::WebContents* GetActiveWebContents() {
return browser()->tab_strip_model()->GetActiveWebContents();
}

void NavigateURL(const GURL& url) {
ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), url));
ASSERT_TRUE(WaitForLoadStop(GetActiveWebContents()));
}

void CreatePrintPreview(ai_chat::AIChatUIPageHandler* handler) {
#if BUILDFLAG(ENABLE_PRINT_PREVIEW)
handler->MaybeCreatePrintPreview();
#endif
}

ai_chat::AIChatUIPageHandler* OpenAIChatSidePanel() {
auto* side_panel_ui = SidePanelUI::GetSidePanelUIForBrowser(browser());
side_panel_ui->Show(SidePanelEntryId::kChatUI);
auto* browser_view = BrowserView::GetBrowserViewForBrowser(browser());
auto* side_panel = browser_view->unified_side_panel();
auto* ai_chat_side_panel =
side_panel->GetViewByID(SidePanelWebUIView::kSidePanelWebViewId);
if (!ai_chat_side_panel) {
return nullptr;
}
auto* side_panel_web_contents =
(static_cast<views::WebView*>(ai_chat_side_panel))->web_contents();
if (!side_panel_web_contents) {
return nullptr;
}
content::WaitForLoadStop(side_panel_web_contents);

auto* web_ui = side_panel_web_contents->GetWebUI();
if (!web_ui) {
return nullptr;
}
auto* ai_chat_ui = web_ui->GetController()->GetAs<AIChatUI>();
if (!ai_chat_ui) {
return nullptr;
}
return ai_chat_ui->GetPageHandlerForTesting();
}

void FetchPageContent(const base::Location& location,
ai_chat::AIChatTabHelper* helper,
std::string_view expected_text) {
SCOPED_TRACE(testing::Message() << location.ToString());
base::RunLoop run_loop;
helper->GetPageContent(
base::BindLambdaForTesting(
[&run_loop, expected_text](std::string text, bool is_video,
std::string invalidation_token) {
EXPECT_FALSE(is_video);
EXPECT_EQ(text, expected_text);
run_loop.Quit();
}),
"");
run_loop.Run();
}

protected:
net::test_server::EmbeddedTestServer https_server_;

private:
content::ContentMockCertVerifier mock_cert_verifier_;
};

IN_PROC_BROWSER_TEST_F(AIChatUIBrowserTest, PrintPreview) {
browser()->window()->SetContentsSize(gfx::Size(800, 600));

auto* chat_tab_helper =
ai_chat::AIChatTabHelper::FromWebContents(GetActiveWebContents());
ASSERT_TRUE(chat_tab_helper);
chat_tab_helper->SetUserOptedIn(true);
auto* ai_chat_page_handler = OpenAIChatSidePanel();
ASSERT_TRUE(ai_chat_page_handler);

NavigateURL(https_server_.GetURL("docs.google.com", "/long_canvas.html"));
CreatePrintPreview(ai_chat_page_handler);
#if BUILDFLAG(ENABLE_TEXT_RECOGNITION)
FetchPageContent(
FROM_HERE, chat_tab_helper,
"This is the way.\n\nI have spoken.\nWherever I Go, He Goes.");
// Panel is still active so we don't need to set it up again

// Page recognition host with a canvas element
NavigateURL(https_server_.GetURL("docs.google.com", "/canvas.html"));
CreatePrintPreview(ai_chat_page_handler);
FetchPageContent(FROM_HERE, chat_tab_helper, "this is the way");
#if BUILDFLAG(IS_WIN)
// Unsupported locale should return no content for Windows only
// Other platforms do not use locale for extraction
const brave_l10n::test::ScopedDefaultLocale locale("xx_XX");
NavigateURL(https_server_.GetURL("docs.google.com", "/canvas.html"));
CreatePrintPreview(ai_chat_page_handler);
FetchPageContent(FROM_HERE, chat_tab_helper, "");
#endif // #if BUILDFLAG(IS_WIN)
#else
FetchPageContent(FROM_HERE, chat_tab_helper, "");
#endif

// Not supported on other hosts
NavigateURL(https_server_.GetURL("a.com", "/long_canvas.html"));
CreatePrintPreview(ai_chat_page_handler);
FetchPageContent(FROM_HERE, chat_tab_helper, "");
}

#if BUILDFLAG(ENABLE_TEXT_RECOGNITION)
IN_PROC_BROWSER_TEST_F(AIChatUIBrowserTest, PrintPreviewPagesLimit) {
browser()->window()->SetContentsSize(gfx::Size(800, 600));

auto* chat_tab_helper =
ai_chat::AIChatTabHelper::FromWebContents(GetActiveWebContents());
ASSERT_TRUE(chat_tab_helper);
chat_tab_helper->SetUserOptedIn(true);
auto* ai_chat_page_handler = OpenAIChatSidePanel();
ASSERT_TRUE(ai_chat_page_handler);

NavigateURL(
https_server_.GetURL("docs.google.com", "/extra_long_canvas.html"));
CreatePrintPreview(ai_chat_page_handler);
std::string expected_string(19, '\n');
base::StrAppend(&expected_string, {"This is the way."});
FetchPageContent(FROM_HERE, chat_tab_helper, expected_string);
}

IN_PROC_BROWSER_TEST_F(AIChatUIBrowserTest, PrintPreviewContextLimit) {
browser()->window()->SetContentsSize(gfx::Size(800, 600));

auto* chat_tab_helper =
ai_chat::AIChatTabHelper::FromWebContents(GetActiveWebContents());
ASSERT_TRUE(chat_tab_helper);
chat_tab_helper->SetUserOptedIn(true);
auto* ai_chat_page_handler = OpenAIChatSidePanel();
ASSERT_TRUE(ai_chat_page_handler);

chat_tab_helper->SetMaxContentLengthForTesting(10);
NavigateURL(https_server_.GetURL("docs.google.com", "/long_canvas.html"));
CreatePrintPreview(ai_chat_page_handler);
FetchPageContent(FROM_HERE, chat_tab_helper, "This is the way.");

chat_tab_helper->SetMaxContentLengthForTesting(20);
NavigateURL(https_server_.GetURL("docs.google.com", "/long_canvas.html"));
CreatePrintPreview(ai_chat_page_handler);
FetchPageContent(FROM_HERE, chat_tab_helper,
"This is the way.\n\nI have spoken.");
}
#endif
21 changes: 2 additions & 19 deletions browser/ai_chat/page_content_fetcher_browsertest.cc
Expand Up @@ -14,8 +14,6 @@
#include "brave/components/ai_chat/content/browser/ai_chat_tab_helper.h"
#include "brave/components/ai_chat/content/browser/page_content_fetcher.h"
#include "brave/components/constants/brave_paths.h"
#include "brave/components/l10n/common/test/scoped_default_locale.h"
#include "brave/components/text_recognition/common/buildflags/buildflags.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/test/base/in_process_browser_test.h"
Expand All @@ -27,7 +25,6 @@
#include "net/dns/mock_host_resolver.h"
#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
#include "services/network/test/test_url_loader_factory.h"
#include "ui/compositor/compositor_switches.h"

namespace {

Expand Down Expand Up @@ -77,9 +74,6 @@ class PageContentFetcherBrowserTest : public InProcessBrowserTest {

void SetUpCommandLine(base::CommandLine* command_line) override {
InProcessBrowserTest::SetUpCommandLine(command_line);
#if BUILDFLAG(ENABLE_TEXT_RECOGNITION)
command_line->AppendSwitch(::switches::kEnablePixelOutputInTests);
#endif
mock_cert_verifier_.SetUpCommandLine(command_line);
}

Expand Down Expand Up @@ -109,7 +103,8 @@ class PageContentFetcherBrowserTest : public InProcessBrowserTest {
SCOPED_TRACE(testing::Message() << location.ToString());
base::RunLoop run_loop;
ai_chat::FetchPageContent(
browser()->tab_strip_model()->GetActiveWebContents(), "",
browser()->tab_strip_model()->GetActiveWebContents(), "", std::nullopt,
4096,
base::BindLambdaForTesting([&run_loop, &expected_text,
&expected_is_video, &trim_whitespace](
std::string text, bool is_video,
Expand Down Expand Up @@ -171,20 +166,8 @@ IN_PROC_BROWSER_TEST_F(PageContentFetcherBrowserTest, FetchPageContent) {
// Not a page extraction host and page with no text
NavigateURL(https_server_.GetURL("a.com", "/canvas.html"));
FetchPageContent(FROM_HERE, "", false);
#if BUILDFLAG(ENABLE_TEXT_RECOGNITION)
// Page recognition host with a canvas element
NavigateURL(https_server_.GetURL("docs.google.com", "/canvas.html"));
FetchPageContent(FROM_HERE, "this is the way", false);
#if BUILDFLAG(IS_WIN)
// Unsupported locale should return no content for Windows only
// Other platforms do not use locale for extraction
const brave_l10n::test::ScopedDefaultLocale locale("xx_XX");
NavigateURL(https_server_.GetURL("docs.google.com", "/canvas.html"));
FetchPageContent(FROM_HERE, "", false);
#endif // #if BUILDFLAG(IS_WIN)
NavigateURL(https_server_.GetURL("github.com", kGithubUrlPath));
FetchPageContent(FROM_HERE, kGithubPatch, false);
#endif // #if BUILDFLAG(ENABLE_TEXT_RECOGNITION)
}

IN_PROC_BROWSER_TEST_F(PageContentFetcherBrowserTest, FetchPageContentPDF) {
Expand Down
4 changes: 4 additions & 0 deletions browser/ui/webui/ai_chat/ai_chat_ui.h
Expand Up @@ -75,6 +75,10 @@ class AIChatUI : public ui::UntrustedWebUIController

static constexpr std::string GetWebUIName() { return "AIChatPanel"; }

ai_chat::AIChatUIPageHandler* GetPageHandlerForTesting() {
return page_handler_.get();
}

private:
#if BUILDFLAG(ENABLE_PRINT_PREVIEW)
// printing::mojo::PrintPreviewUI:
Expand Down
2 changes: 2 additions & 0 deletions browser/ui/webui/ai_chat/ai_chat_ui_page_handler.h
Expand Up @@ -42,6 +42,7 @@ class FaviconService;
} // namespace favicon

class AIChatUI;
class AIChatUIBrowserTest;
namespace ai_chat {
class AIChatUIPageHandler : public ai_chat::mojom::PageHandler,
public AIChatTabHelper::Observer,
Expand Down Expand Up @@ -105,6 +106,7 @@ class AIChatUIPageHandler : public ai_chat::mojom::PageHandler,
#endif

private:
friend class ::AIChatUIBrowserTest;
// AIChatTabHelper::Observer
void OnHistoryUpdate() override;
void OnAPIRequestInProgress(bool in_progress) override;
Expand Down
15 changes: 10 additions & 5 deletions components/ai_chat/content/browser/ai_chat_tab_helper.cc
Expand Up @@ -97,7 +97,7 @@ void AIChatTabHelper::OnPDFA11yInfoLoaded() {
is_pdf_a11y_info_loaded_ = true;
if (pending_get_page_content_callback_) {
FetchPageContent(web_contents(), "", std::nullopt,
GetCurrentModel().max_page_content_length,
GetMaxPageContentLength(),
std::move(pending_get_page_content_callback_));
}
pdf_load_observer_.reset();
Expand All @@ -109,8 +109,7 @@ void AIChatTabHelper::OnPDFA11yInfoLoaded() {
void AIChatTabHelper::OnPreviewReady(
const std::optional<std::vector<SkBitmap>>& bitmaps) {
if (pending_get_page_content_callback_) {
FetchPageContent(web_contents(), "", bitmaps,
GetCurrentModel().max_page_content_length,
FetchPageContent(web_contents(), "", bitmaps, GetMaxPageContentLength(),
std::move(pending_get_page_content_callback_));
}
}
Expand Down Expand Up @@ -222,8 +221,7 @@ void AIChatTabHelper::GetPageContent(GetPageContentCallback callback,
pending_get_page_content_callback_ = std::move(callback);
} else {
FetchPageContent(web_contents(), invalidation_token, std::nullopt,
GetCurrentModel().max_page_content_length,
std::move(callback));
GetMaxPageContentLength(), std::move(callback));
}
}
}
Expand All @@ -232,6 +230,13 @@ std::u16string AIChatTabHelper::GetPageTitle() const {
return web_contents()->GetTitle();
}

uint32_t AIChatTabHelper::GetMaxPageContentLength() {
if (max_page_content_length_for_testing_) {
return *max_page_content_length_for_testing_;
}
return GetCurrentModel().max_page_content_length;
}

WEB_CONTENTS_USER_DATA_KEY_IMPL(AIChatTabHelper);

} // namespace ai_chat

0 comments on commit f57bc2b

Please sign in to comment.