All checks were successful
ci / fast (linux) (push) Successful in 6m20s
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>
127 lines
3.6 KiB
Rust
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"));
|
|
}
|