From 03e266ee38b88cd145eaccaf24cd2e581d8b5165 Mon Sep 17 00:00:00 2001 From: Chris Tate Date: Mon, 12 Jan 2026 11:26:45 -0600 Subject: [PATCH] add tests --- cli/src/commands.rs | 36 +++++++++++++++++++++ cli/src/flags.rs | 77 +++++++++++++++++++++++++++++++++++++++++++++ src/browser.test.ts | 55 ++++++++++++++++++++++++++++++++ 3 files changed, 168 insertions(+) diff --git a/cli/src/commands.rs b/cli/src/commands.rs index dec6e0e..6cf0964 100644 --- a/cli/src/commands.rs +++ b/cli/src/commands.rs @@ -1020,6 +1020,42 @@ mod tests { assert_eq!(cmd["url"], "https://example.com"); } + #[test] + fn test_navigate_with_headers() { + let mut flags = default_flags(); + flags.headers = Some(r#"{"Authorization": "Bearer token"}"#.to_string()); + let cmd = parse_command(&args("open api.example.com"), &flags).unwrap(); + assert_eq!(cmd["action"], "navigate"); + assert_eq!(cmd["url"], "https://api.example.com"); + assert_eq!(cmd["headers"]["Authorization"], "Bearer token"); + } + + #[test] + fn test_navigate_with_multiple_headers() { + let mut flags = default_flags(); + flags.headers = Some(r#"{"Authorization": "Bearer token", "X-Custom": "value"}"#.to_string()); + let cmd = parse_command(&args("open api.example.com"), &flags).unwrap(); + assert_eq!(cmd["headers"]["Authorization"], "Bearer token"); + assert_eq!(cmd["headers"]["X-Custom"], "value"); + } + + #[test] + fn test_navigate_without_headers_flag() { + let cmd = parse_command(&args("open example.com"), &default_flags()).unwrap(); + assert_eq!(cmd["action"], "navigate"); + // headers should not be present when flag is not set + assert!(cmd.get("headers").is_none()); + } + + #[test] + fn test_navigate_with_invalid_headers_json() { + let mut flags = default_flags(); + flags.headers = Some("not valid json".to_string()); + let cmd = parse_command(&args("open api.example.com"), &flags).unwrap(); + // Invalid JSON should result in no headers field (graceful handling) + assert!(cmd.get("headers").is_none()); + } + #[test] fn test_back() { let cmd = parse_command(&args("back"), &default_flags()).unwrap(); diff --git a/cli/src/flags.rs b/cli/src/flags.rs index c22da33..6eb6393 100644 --- a/cli/src/flags.rs +++ b/cli/src/flags.rs @@ -71,3 +71,80 @@ pub fn clean_args(args: &[String]) -> Vec { } result } + +#[cfg(test)] +mod tests { + use super::*; + + fn args(s: &str) -> Vec { + s.split_whitespace().map(String::from).collect() + } + + #[test] + fn test_parse_headers_flag() { + let flags = parse_flags(&args(r#"open example.com --headers {"Auth":"token"}"#)); + assert_eq!(flags.headers, Some(r#"{"Auth":"token"}"#.to_string())); + } + + #[test] + fn test_parse_headers_flag_with_spaces() { + // Headers JSON is passed as a single quoted argument in shell + let input: Vec = vec![ + "open".to_string(), + "example.com".to_string(), + "--headers".to_string(), + r#"{"Authorization": "Bearer token"}"#.to_string(), + ]; + let flags = parse_flags(&input); + assert_eq!(flags.headers, Some(r#"{"Authorization": "Bearer token"}"#.to_string())); + } + + #[test] + fn test_parse_no_headers_flag() { + let flags = parse_flags(&args("open example.com")); + assert!(flags.headers.is_none()); + } + + #[test] + fn test_clean_args_removes_headers() { + let input: Vec = vec![ + "open".to_string(), + "example.com".to_string(), + "--headers".to_string(), + r#"{"Auth":"token"}"#.to_string(), + ]; + let clean = clean_args(&input); + assert_eq!(clean, vec!["open", "example.com"]); + } + + #[test] + fn test_clean_args_removes_headers_at_start() { + let input: Vec = vec![ + "--headers".to_string(), + r#"{"Auth":"token"}"#.to_string(), + "open".to_string(), + "example.com".to_string(), + ]; + let clean = clean_args(&input); + assert_eq!(clean, vec!["open", "example.com"]); + } + + #[test] + fn test_headers_with_other_flags() { + let input: Vec = vec![ + "open".to_string(), + "example.com".to_string(), + "--headers".to_string(), + r#"{"Auth":"token"}"#.to_string(), + "--json".to_string(), + "--headed".to_string(), + ]; + let flags = parse_flags(&input); + assert_eq!(flags.headers, Some(r#"{"Auth":"token"}"#.to_string())); + assert!(flags.json); + assert!(flags.headed); + + let clean = clean_args(&input); + assert_eq!(clean, vec!["open", "example.com"]); + } +} diff --git a/src/browser.test.ts b/src/browser.test.ts index 9d40926..6b88a3a 100644 --- a/src/browser.test.ts +++ b/src/browser.test.ts @@ -294,4 +294,59 @@ describe('BrowserManager', () => { expect(h1).toBe('Example Domain'); }); }); + + describe('scoped headers', () => { + it('should register route for scoped headers', async () => { + // Test that setScopedHeaders doesn't throw and completes successfully + await browser.clearScopedHeaders(); + await expect( + browser.setScopedHeaders('https://example.com', { 'X-Test': 'value' }) + ).resolves.not.toThrow(); + await browser.clearScopedHeaders(); + }); + + it('should handle full URL origin', async () => { + await browser.clearScopedHeaders(); + await expect( + browser.setScopedHeaders('https://api.example.com/path', { Authorization: 'Bearer token' }) + ).resolves.not.toThrow(); + await browser.clearScopedHeaders(); + }); + + it('should handle hostname-only origin', async () => { + await browser.clearScopedHeaders(); + await expect( + browser.setScopedHeaders('example.com', { 'X-Custom': 'value' }) + ).resolves.not.toThrow(); + await browser.clearScopedHeaders(); + }); + + it('should clear scoped headers for specific origin', async () => { + await browser.clearScopedHeaders(); + await browser.setScopedHeaders('https://example.com', { 'X-Test': 'value' }); + await expect(browser.clearScopedHeaders('https://example.com')).resolves.not.toThrow(); + }); + + it('should clear all scoped headers', async () => { + await browser.setScopedHeaders('https://example.com', { 'X-Test-1': 'value1' }); + await browser.setScopedHeaders('https://example.org', { 'X-Test-2': 'value2' }); + await expect(browser.clearScopedHeaders()).resolves.not.toThrow(); + }); + + it('should replace headers when called twice for same origin', async () => { + await browser.clearScopedHeaders(); + await browser.setScopedHeaders('https://example.com', { 'X-First': 'first' }); + // Second call should replace, not add + await expect( + browser.setScopedHeaders('https://example.com', { 'X-Second': 'second' }) + ).resolves.not.toThrow(); + await browser.clearScopedHeaders(); + }); + + it('should handle clearing non-existent origin gracefully', async () => { + await browser.clearScopedHeaders(); + // Should not throw when clearing headers that were never set + await expect(browser.clearScopedHeaders('https://never-set.com')).resolves.not.toThrow(); + }); + }); });