Files
rust_browser/tests/regen_goldens.rs
Zachary D. Rowitsch dbadb659bc Add CSS cascade origin ordering per CSS Cascading Level 4
Author-origin declarations now always beat UA-origin declarations
regardless of specificity, fixing issues like `.btn-primary { color: white }`
failing to override UA `a:link { color: #0000EE }`. The cascade now checks
origin+importance weight before specificity: UA normal (0) < Author normal (1)
< Author !important (2) < UA !important (3).

The UA stylesheet is applied internally by compute_styles rather than being
prepended by callers, making origin structurally determined. Promotes 3 WPT
tests from known_fail to pass.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 16:35:44 -05:00

153 lines
4.8 KiB
Rust

//! Utility to regenerate all golden expected files.
//! Run with: cargo test --test regen_goldens -- --ignored
use std::fs;
use std::path::PathBuf;
mod pipeline_test {
use display_list::build_display_list;
use html::HtmlParser;
use image::{ImagePipeline, ImageStore};
use layout::LayoutEngine;
use std::collections::HashMap;
use std::path::Path;
use style::{Display, StyleContext};
pub fn run_pipeline(html: &str) -> (String, String) {
let html_parser = HtmlParser::new();
let style_context = StyleContext::new();
let layout_engine = LayoutEngine::new_proportional();
let document = html_parser.parse(html);
let stylesheets = style_context.extract_stylesheets(&document);
let inline_styles = style_context.extract_inline_styles(&document);
let computed_styles = style_context.compute_styles(
&document,
&stylesheets,
&inline_styles,
Some(&css::Viewport::new(800.0, 600.0)),
);
let layout_tree = layout_engine.layout(&document, &computed_styles, 800.0, 600.0);
let display_list = build_display_list(&layout_tree);
(layout_tree.dump(), display_list.dump())
}
pub fn run_pipeline_with_images(html: &str, fixture_dir: &Path) -> (String, String) {
let html_parser = HtmlParser::new();
let style_context = StyleContext::new();
let layout_engine = LayoutEngine::new_proportional();
let image_pipeline = ImagePipeline::new();
let document = html_parser.parse(html);
let stylesheets = style_context.extract_stylesheets(&document);
let inline_styles = style_context.extract_inline_styles(&document);
let computed_styles = style_context.compute_styles(
&document,
&stylesheets,
&inline_styles,
Some(&css::Viewport::new(800.0, 600.0)),
);
let mut image_store = ImageStore::new();
let mut image_map = HashMap::new();
for node_id in document.get_elements_by_tag_name("img") {
if let Some(styles) = computed_styles.get(&node_id) {
if styles.display == Display::None {
continue;
}
}
if let Some(src) = document.get_attribute(node_id, "src") {
let image_path = fixture_dir.join(src);
if let Ok(bytes) = std::fs::read(&image_path) {
if let Ok(decoded) = image_pipeline.decode(&bytes, None) {
let img_id = image_store.insert(decoded);
image_map.insert(node_id, img_id);
}
}
}
}
let layout_tree = layout_engine.layout_with_images(
&document,
&computed_styles,
800.0,
600.0,
&image_map,
&image_store,
);
let display_list = build_display_list(&layout_tree);
(layout_tree.dump(), display_list.dump())
}
}
fn get_goldens_dir() -> PathBuf {
PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("tests/goldens")
}
// Image fixtures that need the with_images pipeline
const IMAGE_FIXTURES: &[&str] = &[
"125-img-basic",
"126-img-width-attr",
"127-img-height-attr",
"128-img-both-attrs",
"129-img-css-width",
"130-img-css-both",
"131-img-in-div",
"132-img-inline",
"133-img-missing-src",
"134-img-broken-src",
"135-img-with-border",
"136-img-display-block",
"142-img-in-inline-wrapper",
"143-img-link-in-table",
"169-img-svg-basic",
];
#[test]
#[ignore]
fn regenerate_all_golden_files() {
let goldens_dir = get_goldens_dir();
let fixtures_dir = goldens_dir.join("fixtures");
let expected_dir = goldens_dir.join("expected");
let mut entries: Vec<_> = fs::read_dir(&fixtures_dir)
.unwrap()
.filter_map(|e| e.ok())
.filter(|e| e.path().extension().is_some_and(|ext| ext == "html"))
.collect();
entries.sort_by_key(|e| e.file_name());
let mut count = 0;
for entry in entries {
let fixture_name = entry
.path()
.file_stem()
.unwrap()
.to_string_lossy()
.to_string();
let html = fs::read_to_string(entry.path()).unwrap();
let (layout, dl) = if IMAGE_FIXTURES.contains(&fixture_name.as_str()) {
pipeline_test::run_pipeline_with_images(&html, &fixtures_dir)
} else {
pipeline_test::run_pipeline(&html)
};
fs::write(
expected_dir.join(format!("{}.layout.txt", fixture_name)),
&layout,
)
.unwrap();
fs::write(expected_dir.join(format!("{}.dl.txt", fixture_name)), &dl).unwrap();
count += 1;
}
println!("Regenerated {} golden test expected files", count);
}