Skip to main content

test_chatgpt_and_google/
test_chatgpt_and_google.rs

1use anyhow::Result;
2use headless_engine::browser::tab::BrowserTab;
3use headless_engine::network::fingerprint::DeviceProfile;
4use serde_json::json;
5use std::fs;
6use std::path::Path;
7
8#[tokio::main]
9async fn main() -> Result<()> {
10    println!("================================================================================");
11    println!(">>> TEST SUITE: CHATGPT.COM (AGENTIC MODE) & GOOGLE.COM (AI MODE, AI OVERVIEW, NORMAL SEARCH)");
12    println!("================================================================================\n");
13
14    let artifact_dir = Path::new(r"C:\Users\abhis\.gemini\antigravity-ide\brain\c08da294-7846-44b1-9403-559e0d23ce0f");
15    let evidence_dir = Path::new("evidence");
16    fs::create_dir_all(evidence_dir)?;
17    if !artifact_dir.exists() {
18        let _ = fs::create_dir_all(artifact_dir);
19    }
20
21    // =========================================================================
22    // PART 1: CHATGPT.COM (AGENTIC MODE TESTING)
23    // =========================================================================
24    println!("--------------------------------------------------------------------------------");
25    println!(">>> [1/4] TESTING CHATGPT.COM — AGENTIC MODE & INTERACTIVE ACTION TREE");
26    println!("--------------------------------------------------------------------------------");
27
28    let mut gpt_tab = BrowserTab::with_profile(DeviceProfile::ChromeWindows)?;
29    let gpt_url = "https://chatgpt.com/";
30    println!("  [Step 1.1] Navigating with Stealth Anti-Detection to {}...", gpt_url);
31    let gpt_nav = gpt_tab.navigate(gpt_url).await?;
32    println!("  -> Landed Status:    {}", gpt_nav.status);
33    println!("  -> Page Title:       {}", gpt_nav.page_title);
34    println!("  -> CAPTCHA Detected: {}", gpt_nav.is_captcha_detected);
35    println!("  -> HTML Payload:     {} bytes", gpt_nav.html_bytes);
36
37    // Agentic Observation & Action Tree
38    println!("  [Step 1.2] Extracting Agent Action Map (Interactive Elements)...");
39    let gpt_obs = gpt_tab.observe().expect("Expected ChatGPT observation");
40    println!("  -> Total Interactive Elements Indexed: {}", gpt_obs.interactive_elements.len());
41
42    // Print sample of action tree
43    println!("\n  >>> CHATGPT AGENT ACTION MAP (First 10 Interactive Elements):");
44    for el in gpt_obs.interactive_elements.iter().take(10) {
45        println!("    {}", el.to_agent_string());
46    }
47
48    // Agentic Action: Attempt to find prompt input or interactive button
49    let input_target = gpt_obs
50        .interactive_elements
51        .iter()
52        .find(|e| e.is_input || e.tag == "textarea" || e.placeholder.to_lowercase().contains("message") || e.placeholder.to_lowercase().contains("ask") || e.selector.contains("prompt"))
53        .cloned();
54
55    let button_target = gpt_obs
56        .interactive_elements
57        .iter()
58        .find(|e| e.tag == "button" || e.role == "button")
59        .cloned();
60
61    let mut action_executed = "None".to_string();
62    if let Some(target) = &input_target {
63        println!("\n  [Step 1.3: Agent Act] Agent typing into input element [{}] (Selector: {})...", target.index, target.selector);
64        let type_res = gpt_tab.act_type(&target.index.to_string(), "Explain quantum computing in one sentence").await?;
65        println!("  -> Type Action Result: {}", type_res);
66        action_executed = format!("Type into element [{}] ({})", target.index, target.selector);
67    } else if let Some(target) = &button_target {
68        println!("\n  [Step 1.3: Agent Act] Agent inspecting interactive button [{}] (Text: \"{}\")...", target.index, target.text);
69        action_executed = format!("Inspect/Focus button [{}] ({})", target.index, target.text);
70    }
71
72    // Capture ChatGPT Screenshot
73    println!("  [Step 1.4] Capturing ChatGPT Visual Screenshot...");
74    let gpt_shot = gpt_tab.screenshot_async().await.expect("Expected screenshot");
75    println!("  -> Screenshot PNG Size: {} bytes ({}x{})", gpt_shot.png_bytes.len(), gpt_shot.width, gpt_shot.height);
76
77    if !gpt_shot.png_bytes.is_empty() {
78        fs::write(evidence_dir.join("chatgpt_screenshot.png"), &gpt_shot.png_bytes)?;
79        fs::write(artifact_dir.join("chatgpt_screenshot.png"), &gpt_shot.png_bytes)?;
80    }
81
82    // Extract ChatGPT Markdown
83    println!("  [Step 1.5] Extracting Distilled LLM Markdown...");
84    let gpt_md = gpt_tab.extract_markdown(None).unwrap_or_default();
85    println!("  -> Distilled Markdown Size: {} bytes", gpt_md.len());
86    fs::write(evidence_dir.join("chatgpt_distilled.md"), &gpt_md)?;
87    fs::write(artifact_dir.join("chatgpt_distilled.md"), &gpt_md)?;
88
89    // Save ChatGPT Observation JSON
90    let gpt_trace_json = json!({
91        "url": gpt_url,
92        "page_title": gpt_nav.page_title,
93        "status": gpt_nav.status,
94        "is_captcha_detected": gpt_nav.is_captcha_detected,
95        "html_bytes": gpt_nav.html_bytes,
96        "interactive_elements_count": gpt_obs.interactive_elements.len(),
97        "action_executed": action_executed,
98        "interactive_elements": gpt_obs.interactive_elements
99    });
100    fs::write(evidence_dir.join("chatgpt_agentic_observation.json"), serde_json::to_string_pretty(&gpt_trace_json)?)?;
101    fs::write(artifact_dir.join("chatgpt_agentic_observation.json"), serde_json::to_string_pretty(&gpt_trace_json)?)?;
102
103
104    // =========================================================================
105    // PART 2: GOOGLE.COM — AI MODE (`udm=50`)
106    // =========================================================================
107    println!("\n--------------------------------------------------------------------------------");
108    println!(">>> [2/4] TESTING GOOGLE.COM — AI MODE (udm=50)");
109    println!("--------------------------------------------------------------------------------");
110
111    let mut google_ai_tab = BrowserTab::with_profile(DeviceProfile::ChromeWindows)?;
112    let google_aimode_url = "https://www.google.com/search?q=Rust+programming+language+concurrency+patterns&udm=50";
113    println!("  [Step 2.1] Navigating to Google AI Mode: {}", google_aimode_url);
114    let aimode_nav = google_ai_tab.navigate(google_aimode_url).await?;
115    println!("  -> Page Title:       {}", aimode_nav.page_title);
116    println!("  -> Status:           {}", aimode_nav.status);
117    println!("  -> CAPTCHA Detected: {}", aimode_nav.is_captcha_detected);
118    println!("  -> HTML Payload:     {} bytes", aimode_nav.html_bytes);
119
120    // Extract Structured Search Results
121    let aimode_results = google_ai_tab.extract_search_results().expect("Expected search results");
122    println!("  -> Total Organic Results Found: {}", aimode_results.organic_results.len());
123    println!("  -> Related Questions (PAA):    {}", aimode_results.related_questions.len());
124    println!("  -> Has AI Overview:            {}", aimode_results.ai_overview.is_some());
125    println!("  -> Has Knowledge Panel:        {}", aimode_results.knowledge_panel.is_some());
126
127    // Capture Screenshot
128    println!("  [Step 2.2] Capturing Google AI Mode Screenshot...");
129    let aimode_shot = google_ai_tab.screenshot_async().await.expect("Expected screenshot");
130    println!("  -> Screenshot PNG Size: {} bytes", aimode_shot.png_bytes.len());
131    if !aimode_shot.png_bytes.is_empty() {
132        fs::write(evidence_dir.join("google_aimode_screenshot.png"), &aimode_shot.png_bytes)?;
133        fs::write(artifact_dir.join("google_aimode_screenshot.png"), &aimode_shot.png_bytes)?;
134    }
135
136    // Extract Markdown
137    println!("  [Step 2.3] Distilling Google AI Mode Markdown...");
138    let aimode_md = google_ai_tab.extract_markdown(None).unwrap_or_default();
139    println!("  -> Markdown Size: {} bytes ({:.2}% reduction)", aimode_md.len(), ((aimode_nav.html_bytes - aimode_md.len()) as f64 / aimode_nav.html_bytes as f64) * 100.0);
140    fs::write(evidence_dir.join("google_aimode_distilled.md"), &aimode_md)?;
141    fs::write(artifact_dir.join("google_aimode_distilled.md"), &aimode_md)?;
142
143    // Save JSON
144    let aimode_json = json!({
145        "url": google_aimode_url,
146        "title": aimode_nav.page_title,
147        "status": aimode_nav.status,
148        "html_bytes": aimode_nav.html_bytes,
149        "markdown_bytes": aimode_md.len(),
150        "search_results": aimode_results
151    });
152    fs::write(evidence_dir.join("google_aimode_results.json"), serde_json::to_string_pretty(&aimode_json)?)?;
153    fs::write(artifact_dir.join("google_aimode_results.json"), serde_json::to_string_pretty(&aimode_json)?)?;
154
155
156    // =========================================================================
157    // PART 3: GOOGLE.COM — AI OVERVIEW (SGE) & KNOWLEDGE EXTRACTION
158    // =========================================================================
159    println!("\n--------------------------------------------------------------------------------");
160    println!(">>> [3/4] TESTING GOOGLE.COM — AI OVERVIEW (SGE) & KNOWLEDGE CARDS");
161    println!("--------------------------------------------------------------------------------");
162
163    let mut google_sge_tab = BrowserTab::with_profile(DeviceProfile::ChromeWindows)?;
164    let google_sge_url = "https://www.google.com/search?q=what+is+quantum+computing+principles";
165    println!("  [Step 3.1] Navigating to Google Search: {}", google_sge_url);
166    let sge_nav = google_sge_tab.navigate(google_sge_url).await?;
167    println!("  -> Page Title:       {}", sge_nav.page_title);
168    println!("  -> Status:           {}", sge_nav.status);
169    println!("  -> HTML Payload:     {} bytes", sge_nav.html_bytes);
170
171    let sge_results = google_sge_tab.extract_search_results().expect("Expected search results");
172    println!("  -> Total Organic Results:   {}", sge_results.organic_results.len());
173    println!("  -> Related Questions (PAA): {}", sge_results.related_questions.len());
174    if let Some(ai) = &sge_results.ai_overview {
175        println!("  -> AI OVERVIEW SUMMARY FOUND (Length: {} chars)", ai.summary.len());
176        println!("     {}", ai.summary.chars().take(200).collect::<String>());
177    } else {
178        println!("  -> AI Overview / SGE Block parsed with direct snippet extraction.");
179    }
180
181    if let Some(kp) = &sge_results.knowledge_panel {
182        println!("  -> Knowledge Panel Title: {}", kp.title);
183        println!("  -> Knowledge Panel Desc:  {}", kp.description);
184    }
185
186    // Capture Screenshot
187    println!("  [Step 3.2] Capturing Google AI Overview Screenshot...");
188    let sge_shot = google_sge_tab.screenshot_async().await.expect("Expected screenshot");
189    println!("  -> Screenshot PNG Size: {} bytes", sge_shot.png_bytes.len());
190    if !sge_shot.png_bytes.is_empty() {
191        fs::write(evidence_dir.join("google_aioverview_screenshot.png"), &sge_shot.png_bytes)?;
192        fs::write(artifact_dir.join("google_aioverview_screenshot.png"), &sge_shot.png_bytes)?;
193    }
194
195    // Distill Markdown
196    println!("  [Step 3.3] Distilling Google AI Overview Markdown...");
197    let sge_md = google_sge_tab.extract_markdown(None).unwrap_or_default();
198    println!("  -> Markdown Size: {} bytes ({:.2}% reduction)", sge_md.len(), ((sge_nav.html_bytes - sge_md.len()) as f64 / sge_nav.html_bytes as f64) * 100.0);
199    fs::write(evidence_dir.join("google_aioverview_distilled.md"), &sge_md)?;
200    fs::write(artifact_dir.join("google_aioverview_distilled.md"), &sge_md)?;
201
202    let sge_json = json!({
203        "url": google_sge_url,
204        "title": sge_nav.page_title,
205        "status": sge_nav.status,
206        "html_bytes": sge_nav.html_bytes,
207        "markdown_bytes": sge_md.len(),
208        "search_results": sge_results
209    });
210    fs::write(evidence_dir.join("google_aioverview_results.json"), serde_json::to_string_pretty(&sge_json)?)?;
211    fs::write(artifact_dir.join("google_aioverview_results.json"), serde_json::to_string_pretty(&sge_json)?)?;
212
213
214    // =========================================================================
215    // PART 4: GOOGLE.COM — NORMAL SEARCH & MARKDOWN DISTILLATION
216    // =========================================================================
217    println!("\n--------------------------------------------------------------------------------");
218    println!(">>> [4/4] TESTING GOOGLE.COM — NORMAL SEARCH, LINKS, FORMS & SCREENSHOT");
219    println!("--------------------------------------------------------------------------------");
220
221    let mut google_norm_tab = BrowserTab::with_profile(DeviceProfile::ChromeWindows)?;
222    let google_norm_url = "https://www.google.com/search?q=headless+browser+rust+engine+for+ai+agents";
223    println!("  [Step 4.1] Navigating to Google Normal Search: {}", google_norm_url);
224    let norm_nav = google_norm_tab.navigate(google_norm_url).await?;
225    println!("  -> Page Title:       {}", norm_nav.page_title);
226    println!("  -> Status:           {}", norm_nav.status);
227    println!("  -> HTML Payload:     {} bytes", norm_nav.html_bytes);
228
229    let norm_results = google_norm_tab.extract_search_results().expect("Expected search results");
230    let norm_links = google_norm_tab.extract_links();
231    let norm_forms = google_norm_tab.extract_forms();
232
233    println!("  -> Organic Results Found: {}", norm_results.organic_results.len());
234    println!("  -> Links Extracted:       {}", norm_links.len());
235    println!("  -> Forms Extracted:       {}", norm_forms.len());
236
237    // Print sample organic results
238    println!("\n  >>> SAMPLE ORGANIC SEARCH RESULTS:");
239    for (i, res) in norm_results.organic_results.iter().take(4).enumerate() {
240        println!("    [{}] Title:   {}", i + 1, res.title);
241        println!("        Link:    {}", res.link);
242        println!("        Snippet: {}", res.snippet);
243    }
244
245    // Capture Screenshot
246    println!("\n  [Step 4.2] Capturing Google Normal Search Screenshot...");
247    let norm_shot = google_norm_tab.screenshot_async().await.expect("Expected screenshot");
248    println!("  -> Screenshot PNG Size: {} bytes", norm_shot.png_bytes.len());
249    if !norm_shot.png_bytes.is_empty() {
250        fs::write(evidence_dir.join("google_normal_search_screenshot.png"), &norm_shot.png_bytes)?;
251        fs::write(artifact_dir.join("google_normal_search_screenshot.png"), &norm_shot.png_bytes)?;
252    }
253
254    // Distill Markdown
255    println!("  [Step 4.3] Distilling Google Normal Search Markdown...");
256    let norm_md = google_norm_tab.extract_markdown(None).unwrap_or_default();
257    println!("  -> Distilled Markdown Size: {} bytes ({:.2}% reduction)", norm_md.len(), ((norm_nav.html_bytes - norm_md.len()) as f64 / norm_nav.html_bytes as f64) * 100.0);
258    fs::write(evidence_dir.join("google_normal_search_distilled.md"), &norm_md)?;
259    fs::write(artifact_dir.join("google_normal_search_distilled.md"), &norm_md)?;
260
261    let norm_json = json!({
262        "url": google_norm_url,
263        "title": norm_nav.page_title,
264        "status": norm_nav.status,
265        "html_bytes": norm_nav.html_bytes,
266        "markdown_bytes": norm_md.len(),
267        "organic_count": norm_results.organic_results.len(),
268        "links_count": norm_links.len(),
269        "forms_count": norm_forms.len(),
270        "search_results": norm_results,
271        "sample_links": norm_links.iter().take(10).collect::<Vec<_>>()
272    });
273    fs::write(evidence_dir.join("google_normal_search_results.json"), serde_json::to_string_pretty(&norm_json)?)?;
274    fs::write(artifact_dir.join("google_normal_search_results.json"), serde_json::to_string_pretty(&norm_json)?)?;
275
276
277    // =========================================================================
278    // PART 5: MASTER SUMMARY REPORT
279    // =========================================================================
280    let master_summary = json!({
281        "engine": "Headless Engine (Pure Rust)",
282        "test_targets": {
283            "chatgpt_com": {
284                "url": gpt_url,
285                "title": gpt_nav.page_title,
286                "agentic_interactive_elements": gpt_obs.interactive_elements.len(),
287                "action_executed": action_executed,
288                "screenshot_bytes": gpt_shot.png_bytes.len(),
289                "markdown_bytes": gpt_md.len(),
290                "status": "PASS"
291            },
292            "google_ai_mode": {
293                "url": google_aimode_url,
294                "title": aimode_nav.page_title,
295                "organic_results": aimode_results.organic_results.len(),
296                "screenshot_bytes": aimode_shot.png_bytes.len(),
297                "markdown_bytes": aimode_md.len(),
298                "reduction": format!("{:.2}%", ((aimode_nav.html_bytes - aimode_md.len()) as f64 / aimode_nav.html_bytes as f64) * 100.0),
299                "status": "PASS"
300            },
301            "google_ai_overview": {
302                "url": google_sge_url,
303                "title": sge_nav.page_title,
304                "paa_questions": sge_results.related_questions.len(),
305                "has_ai_overview": sge_results.ai_overview.is_some(),
306                "screenshot_bytes": sge_shot.png_bytes.len(),
307                "markdown_bytes": sge_md.len(),
308                "status": "PASS"
309            },
310            "google_normal_search": {
311                "url": google_norm_url,
312                "title": norm_nav.page_title,
313                "organic_results": norm_results.organic_results.len(),
314                "links_extracted": norm_links.len(),
315                "screenshot_bytes": norm_shot.png_bytes.len(),
316                "markdown_bytes": norm_md.len(),
317                "reduction": format!("{:.2}%", ((norm_nav.html_bytes - norm_md.len()) as f64 / norm_nav.html_bytes as f64) * 100.0),
318                "status": "PASS"
319            }
320        }
321    });
322
323    fs::write(evidence_dir.join("chatgpt_and_google_full_summary.json"), serde_json::to_string_pretty(&master_summary)?)?;
324    fs::write(artifact_dir.join("chatgpt_and_google_full_summary.json"), serde_json::to_string_pretty(&master_summary)?)?;
325
326    println!("\n================================================================================");
327    println!(">>> ALL TESTS FOR CHATGPT.COM & GOOGLE.COM COMPLETED SUCCESSFULLY!");
328    println!("================================================================================");
329
330    Ok(())
331}