4
4
* You can obtain one at https://mozilla.org/MPL/2.0/. */
5
5
6
6
#include < memory>
7
+ #include < optional>
7
8
8
9
#include " base/files/file_path.h"
9
10
#include " base/memory/raw_ptr.h"
13
14
#include " base/test/bind.h"
14
15
#include " brave/components/ai_chat/content/browser/ai_chat_tab_helper.h"
15
16
#include " brave/components/ai_chat/core/browser/constants.h"
17
+ #include " brave/components/ai_chat/core/browser/types.h"
16
18
#include " brave/components/constants/brave_paths.h"
17
19
#include " brave/components/l10n/common/test/scoped_default_locale.h"
18
20
#include " brave/components/text_recognition/common/buildflags/buildflags.h"
32
34
#include " content/public/test/browser_test_utils.h"
33
35
#include " content/public/test/content_mock_cert_verifier.h"
34
36
#include " net/dns/mock_host_resolver.h"
37
+ #include " net/test/embedded_test_server/embedded_test_server.h"
38
+ #include " net/test/embedded_test_server/http_request.h"
39
+ #include " net/test/embedded_test_server/http_response.h"
35
40
#include " printing/buildflags/buildflags.h"
41
+ #include " services/network/public/cpp/network_switches.h"
36
42
#include " ui/compositor/compositor_switches.h"
43
+ #include " url/gurl.h"
37
44
38
45
#if BUILDFLAG(ENABLE_PRINT_PREVIEW)
39
46
#include " chrome/browser/printing/test_print_preview_observer.h"
42
49
namespace {
43
50
44
51
constexpr char kEmbeddedTestServerDirectory [] = " leo" ;
52
+
53
+ std::unique_ptr<net::test_server::HttpResponse> HandleSearchQuerySummaryRequest (
54
+ const net::test_server::HttpRequest& request) {
55
+ const GURL url = request.GetURL ();
56
+ if (url.path_piece () != " /api/chatllm/raw_data" ) {
57
+ return nullptr ;
58
+ }
59
+
60
+ auto query = url.query_piece ();
61
+ if (query == " key=%7Btest_key%7D" ) {
62
+ auto response = std::make_unique<net::test_server::BasicHttpResponse>();
63
+ response->set_code (net::HTTP_OK);
64
+ response->set_content_type (" application/json" );
65
+ response->set_content (
66
+ R"( {"conversation": [{"query": "test query",
67
+ "answer": [{"text": "test summary"}]}]})" );
68
+ return response;
69
+ }
70
+
71
+ if (query == " key=%7Bnot_object%7D" ) {
72
+ auto response = std::make_unique<net::test_server::BasicHttpResponse>();
73
+ response->set_code (net::HTTP_OK);
74
+ response->set_content_type (" application/json" );
75
+ response->set_content (R"( ["not_object"])" );
76
+ return response;
77
+ }
78
+
79
+ if (query == " key=%7Bempty_conversation%7D" ) {
80
+ auto response = std::make_unique<net::test_server::BasicHttpResponse>();
81
+ response->set_code (net::HTTP_OK);
82
+ response->set_content_type (" application/json" );
83
+ response->set_content (R"( {"conversation": []})" );
84
+ return response;
85
+ }
86
+
87
+ if (query == " key=%7Bempty_answer%7D" ) {
88
+ auto response = std::make_unique<net::test_server::BasicHttpResponse>();
89
+ response->set_code (net::HTTP_OK);
90
+ response->set_content_type (" application/json" );
91
+ response->set_content (R"( {"conversation": [{"query": "test query",
92
+ "answer": []}])" );
93
+ return response;
94
+ }
95
+
96
+ return nullptr ;
97
+ }
98
+
45
99
} // namespace
46
100
47
101
class AIChatUIBrowserTest : public InProcessBrowserTest {
@@ -57,7 +111,9 @@ class AIChatUIBrowserTest : public InProcessBrowserTest {
57
111
test_data_dir = base::PathService::CheckedGet (brave::DIR_TEST_DATA);
58
112
test_data_dir = test_data_dir.AppendASCII (kEmbeddedTestServerDirectory );
59
113
https_server_.ServeFilesFromDirectory (test_data_dir);
60
- ASSERT_TRUE (https_server_.Start ());
114
+ https_server_.RegisterRequestHandler (
115
+ base::BindRepeating (&HandleSearchQuerySummaryRequest));
116
+ https_server_.StartAcceptingConnections ();
61
117
62
118
// Set a smaller window size so we can have test data with more pages.
63
119
browser ()->window ()->SetContentsSize (gfx::Size (800 , 600 ));
@@ -71,6 +127,14 @@ class AIChatUIBrowserTest : public InProcessBrowserTest {
71
127
72
128
void SetUpCommandLine (base::CommandLine* command_line) override {
73
129
InProcessBrowserTest::SetUpCommandLine (command_line);
130
+
131
+ ASSERT_TRUE (https_server_.InitializeAndListen ());
132
+ // Add a host resolver rule to map all outgoing requests to the test server.
133
+ command_line->AppendSwitchASCII (
134
+ network::switches::kHostResolverRules ,
135
+ " MAP * " + https_server_.host_port_pair ().ToString () +
136
+ " ,EXCLUDE localhost" );
137
+
74
138
#if BUILDFLAG(ENABLE_TEXT_RECOGNITION)
75
139
command_line->AppendSwitch (::switches::kEnablePixelOutputInTests );
76
140
#endif
@@ -128,6 +192,20 @@ class AIChatUIBrowserTest : public InProcessBrowserTest {
128
192
run_loop.Run ();
129
193
}
130
194
195
+ void FetchSearchQuerySummary (const base::Location& location,
196
+ const std::optional<ai_chat::SearchQuerySummary>&
197
+ expected_search_query_summary) {
198
+ SCOPED_TRACE (testing::Message () << location.ToString ());
199
+ base::RunLoop run_loop;
200
+ chat_tab_helper_->FetchSearchQuerySummary (base::BindLambdaForTesting (
201
+ [&](const std::optional<ai_chat::SearchQuerySummary>&
202
+ search_query_summary) {
203
+ EXPECT_EQ (search_query_summary, expected_search_query_summary);
204
+ run_loop.Quit ();
205
+ }));
206
+ run_loop.Run ();
207
+ }
208
+
131
209
protected:
132
210
net::test_server::EmbeddedTestServer https_server_;
133
211
raw_ptr<ai_chat::AIChatTabHelper> chat_tab_helper_ = nullptr ;
@@ -253,3 +331,54 @@ IN_PROC_BROWSER_TEST_F(AIChatUIBrowserTest, PrintPreviewDisabled) {
253
331
NavigateURL (https_server_.GetURL (" docs.google.com" , " /long_canvas.html" ));
254
332
FetchPageContent (FROM_HERE, " " );
255
333
}
334
+
335
+ IN_PROC_BROWSER_TEST_F (AIChatUIBrowserTest, FetchSearchQuerySummary) {
336
+ NavigateURL (https_server_.GetURL (" search.brave.com" , " /search?q=query" ));
337
+
338
+ // Test when meta tag is not present, should return null result.
339
+ FetchSearchQuerySummary (FROM_HERE, std::nullopt);
340
+
341
+ // Test when summarizer-key meta tag is dynamically inserted, should return
342
+ // the search query summary from the mock response.
343
+ content::ExecuteScriptAsync (GetActiveWebContents ()->GetPrimaryMainFrame (),
344
+ " var meta = document.createElement('meta');"
345
+ " meta.name = 'summarizer-key';"
346
+ " meta.content = '{test_key}';"
347
+ " document.head.appendChild(meta);" );
348
+ FetchSearchQuerySummary (
349
+ FROM_HERE, ai_chat::SearchQuerySummary (" test query" , " test summary" ));
350
+
351
+ // Test empty summarizer-key meta tag, should return null result.
352
+ content::ExecuteScriptAsync (GetActiveWebContents ()->GetPrimaryMainFrame (),
353
+ " document.querySelector('meta[name=summarizer-"
354
+ " key').content = '';" );
355
+ FetchSearchQuerySummary (FROM_HERE, std::nullopt);
356
+
357
+ // Mock search query summary response to test parsing.
358
+ // Replace the meta tag value to another key.
359
+ content::ExecuteScriptAsync (GetActiveWebContents ()->GetPrimaryMainFrame (),
360
+ " document.querySelector('meta[name=summarizer-"
361
+ " key').content = '{not_object}';" );
362
+ FetchSearchQuerySummary (FROM_HERE, std::nullopt);
363
+
364
+ // Replace the meta tag value to error case: conversation empty.
365
+ content::ExecuteScriptAsync (GetActiveWebContents ()->GetPrimaryMainFrame (),
366
+ " document.querySelector('meta[name=summarizer-"
367
+ " key').content = '{empty_conversation}';" );
368
+ FetchSearchQuerySummary (FROM_HERE, std::nullopt);
369
+
370
+ // Replace the meta tag value to error case: answer empty.
371
+ content::ExecuteScriptAsync (GetActiveWebContents ()->GetPrimaryMainFrame (),
372
+ " document.querySelector('meta[name=summarizer-"
373
+ " key').content = '{empty_answer}';" );
374
+ FetchSearchQuerySummary (FROM_HERE, std::nullopt);
375
+
376
+ // Test non-brave search SERP URL, should return null result.
377
+ NavigateURL (https_server_.GetURL (" brave.com" , " /search?q=query" ));
378
+ content::ExecuteScriptAsync (GetActiveWebContents ()->GetPrimaryMainFrame (),
379
+ " var meta = document.createElement('meta');"
380
+ " meta.name = 'summarizer-key';"
381
+ " meta.content = '{test_key}';"
382
+ " document.head.appendChild(meta);" );
383
+ FetchSearchQuerySummary (FROM_HERE, std::nullopt);
384
+ }
0 commit comments