Files
rust_browser/tests/external_css_test.rs
Zachary D. Rowitsch 7f767b4589
All checks were successful
ci / fast (linux) (push) Successful in 6m20s
Add @font-face support for web font loading through the full pipeline
Parse @font-face blocks (font-family, src with url()/format(), font-weight,
font-style), fetch font files via NetworkStack, and register them in FontDb
before layout runs. Font URLs resolve relative to the declaring stylesheet's
URL, not the page URL. Dynamic fonts are cleared on navigation to prevent
cross-page leaking.

Includes safety limits (MAX_FONT_FACE_RULES=64, MAX_FONT_FACE_LOADS=64),
cross-scheme protection (HTTP pages can't load file:// fonts), WOFF2
skipping with query-string-aware extension detection, and font-weight
clamping to [1,1000]. TTF and OTF formats are supported natively via
ab_glyph; WOFF2 decompression is deferred to a follow-up.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 20:47:26 -05:00

127 lines
3.6 KiB
Rust

//! End-to-end tests for external CSS stylesheet loading via the pipeline.
use app_browser::Pipeline;
use net::NetworkStack;
use shared::BrowserUrl;
use std::fs;
use std::io::Write;
use tempfile::TempDir;
fn create_temp_file(dir: &TempDir, name: &str, content: &str) -> std::path::PathBuf {
let path = dir.path().join(name);
let mut file = fs::File::create(&path).unwrap();
file.write_all(content.as_bytes()).unwrap();
path
}
fn run_pipeline(html: &str, base_url: &BrowserUrl, network: &NetworkStack) -> (String, String) {
let mut pipeline = Pipeline::new(800.0, 600.0);
let result = pipeline.run_with_url(html, base_url, network).unwrap();
(result.layout_dump, result.display_list_dump)
}
#[test]
fn test_pipeline_with_external_stylesheet() {
let dir = TempDir::new().unwrap();
let _css_path = create_temp_file(&dir, "style.css", "div { background-color: blue; }");
let html = r#"
<html>
<head>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div>Hello World</div>
</body>
</html>
"#;
let html_path = create_temp_file(&dir, "test.html", html);
let base_url = BrowserUrl::from_file_path(&html_path).unwrap();
let network = NetworkStack::new();
let (_layout_dump, display_list_dump) = run_pipeline(html, &base_url, &network);
assert!(display_list_dump.contains("SolidRect"));
assert!(display_list_dump.contains("#0000ff"));
}
#[test]
fn test_cascade_order_link_then_style() {
let dir = TempDir::new().unwrap();
let _css_path = create_temp_file(&dir, "first.css", "div { color: red; }");
let html = r#"
<html>
<head>
<link rel="stylesheet" href="first.css">
<style>div { color: blue; }</style>
</head>
<body>
<div>Text</div>
</body>
</html>
"#;
let html_path = create_temp_file(&dir, "test.html", html);
let base_url = BrowserUrl::from_file_path(&html_path).unwrap();
let network = NetworkStack::new();
let (_layout_dump, display_list_dump) = run_pipeline(html, &base_url, &network);
assert!(display_list_dump.contains("#0000ff"));
assert!(!display_list_dump.contains("#ff0000"));
}
#[test]
fn test_cascade_order_style_then_link() {
let dir = TempDir::new().unwrap();
let _css_path = create_temp_file(&dir, "second.css", "div { color: blue; }");
let html = r#"
<html>
<head>
<style>div { color: red; }</style>
<link rel="stylesheet" href="second.css">
</head>
<body>
<div>Text</div>
</body>
</html>
"#;
let html_path = create_temp_file(&dir, "test.html", html);
let base_url = BrowserUrl::from_file_path(&html_path).unwrap();
let network = NetworkStack::new();
let (_layout_dump, display_list_dump) = run_pipeline(html, &base_url, &network);
assert!(display_list_dump.contains("#0000ff"));
assert!(!display_list_dump.contains("#ff0000"));
}
#[test]
fn test_failed_stylesheet_continues() {
let dir = TempDir::new().unwrap();
let html = r#"
<html>
<head>
<link rel="stylesheet" href="missing.css">
<style>div { color: green; }</style>
</head>
<body>
<div>Text</div>
</body>
</html>
"#;
let html_path = create_temp_file(&dir, "test.html", html);
let base_url = BrowserUrl::from_file_path(&html_path).unwrap();
let network = NetworkStack::new();
let (_layout_dump, display_list_dump) = run_pipeline(html, &base_url, &network);
assert!(display_list_dump.contains("#008000"));
}