mirror of
https://github.com/servo/servo.git
synced 2025-08-04 13:10:20 +01:00
Move style crate unit tests into the unit_tests crate.
This commit is contained in:
parent
e27c967f81
commit
e5466a34c5
9 changed files with 593 additions and 556 deletions
5
components/servo/Cargo.lock
generated
5
components/servo/Cargo.lock
generated
|
@ -926,11 +926,16 @@ name = "unit_tests"
|
||||||
version = "0.0.1"
|
version = "0.0.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cookie 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
"cookie 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"cssparser 0.2.0 (git+https://github.com/servo/rust-cssparser)",
|
||||||
"geom 0.1.0 (git+https://github.com/servo/rust-geom)",
|
"geom 0.1.0 (git+https://github.com/servo/rust-geom)",
|
||||||
"gfx 0.0.1",
|
"gfx 0.0.1",
|
||||||
"net 0.0.1",
|
"net 0.0.1",
|
||||||
"net_traits 0.0.1",
|
"net_traits 0.0.1",
|
||||||
"profile 0.0.1",
|
"profile 0.0.1",
|
||||||
|
"selectors 0.1.0 (git+https://github.com/servo/rust-selectors)",
|
||||||
|
"string_cache 0.0.0 (git+https://github.com/servo/string-cache)",
|
||||||
|
"string_cache_plugin 0.0.0 (git+https://github.com/servo/string-cache)",
|
||||||
|
"style 0.0.1",
|
||||||
"url 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)",
|
"url 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"util 0.0.1",
|
"util 0.0.1",
|
||||||
]
|
]
|
||||||
|
|
|
@ -13,7 +13,7 @@ use values::specified;
|
||||||
|
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
pub struct MediaQueryList {
|
pub struct MediaQueryList {
|
||||||
media_queries: Vec<MediaQuery>
|
pub media_queries: Vec<MediaQuery>
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, Eq, Copy, Debug)]
|
#[derive(PartialEq, Eq, Copy, Debug)]
|
||||||
|
@ -71,9 +71,9 @@ pub enum Qualifier {
|
||||||
|
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
pub struct MediaQuery {
|
pub struct MediaQuery {
|
||||||
qualifier: Option<Qualifier>,
|
pub qualifier: Option<Qualifier>,
|
||||||
media_type: MediaQueryType,
|
pub media_type: MediaQueryType,
|
||||||
expressions: Vec<Expression>,
|
pub expressions: Vec<Expression>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MediaQuery {
|
impl MediaQuery {
|
||||||
|
@ -230,415 +230,5 @@ impl MediaQueryList {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use geom::size::TypedSize2D;
|
|
||||||
use util::geometry::Au;
|
|
||||||
use stylesheets::{iter_stylesheet_media_rules, iter_stylesheet_style_rules, Stylesheet};
|
|
||||||
use stylesheets::Origin;
|
|
||||||
use super::*;
|
|
||||||
use url::Url;
|
|
||||||
use values::specified;
|
|
||||||
use std::borrow::ToOwned;
|
|
||||||
|
|
||||||
fn test_media_rule<F>(css: &str, callback: F) where F: Fn(&MediaQueryList, &str) {
|
|
||||||
let url = Url::parse("http://localhost").unwrap();
|
|
||||||
let stylesheet = Stylesheet::from_str(css, url, Origin::Author);
|
|
||||||
let mut rule_count: int = 0;
|
|
||||||
iter_stylesheet_media_rules(&stylesheet, |rule| {
|
|
||||||
rule_count += 1;
|
|
||||||
callback(&rule.media_queries, css);
|
|
||||||
});
|
|
||||||
assert!(rule_count > 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn media_query_test(device: &Device, css: &str, expected_rule_count: int) {
|
|
||||||
let url = Url::parse("http://localhost").unwrap();
|
|
||||||
let ss = Stylesheet::from_str(css, url, Origin::Author);
|
|
||||||
let mut rule_count: int = 0;
|
|
||||||
iter_stylesheet_style_rules(&ss, device, |_| rule_count += 1);
|
|
||||||
assert!(rule_count == expected_rule_count, css.to_owned());
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_mq_empty() {
|
|
||||||
test_media_rule("@media { }", |list, css| {
|
|
||||||
assert!(list.media_queries.len() == 1, css.to_owned());
|
|
||||||
let q = &list.media_queries[0];
|
|
||||||
assert!(q.qualifier == None, css.to_owned());
|
|
||||||
assert!(q.media_type == MediaQueryType::All, css.to_owned());
|
|
||||||
assert!(q.expressions.len() == 0, css.to_owned());
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_mq_screen() {
|
|
||||||
test_media_rule("@media screen { }", |list, css| {
|
|
||||||
assert!(list.media_queries.len() == 1, css.to_owned());
|
|
||||||
let q = &list.media_queries[0];
|
|
||||||
assert!(q.qualifier == None, css.to_owned());
|
|
||||||
assert!(q.media_type == MediaQueryType::MediaType(MediaType::Screen), css.to_owned());
|
|
||||||
assert!(q.expressions.len() == 0, css.to_owned());
|
|
||||||
});
|
|
||||||
|
|
||||||
test_media_rule("@media only screen { }", |list, css| {
|
|
||||||
assert!(list.media_queries.len() == 1, css.to_owned());
|
|
||||||
let q = &list.media_queries[0];
|
|
||||||
assert!(q.qualifier == Some(Qualifier::Only), css.to_owned());
|
|
||||||
assert!(q.media_type == MediaQueryType::MediaType(MediaType::Screen), css.to_owned());
|
|
||||||
assert!(q.expressions.len() == 0, css.to_owned());
|
|
||||||
});
|
|
||||||
|
|
||||||
test_media_rule("@media not screen { }", |list, css| {
|
|
||||||
assert!(list.media_queries.len() == 1, css.to_owned());
|
|
||||||
let q = &list.media_queries[0];
|
|
||||||
assert!(q.qualifier == Some(Qualifier::Not), css.to_owned());
|
|
||||||
assert!(q.media_type == MediaQueryType::MediaType(MediaType::Screen), css.to_owned());
|
|
||||||
assert!(q.expressions.len() == 0, css.to_owned());
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_mq_print() {
|
|
||||||
test_media_rule("@media print { }", |list, css| {
|
|
||||||
assert!(list.media_queries.len() == 1, css.to_owned());
|
|
||||||
let q = &list.media_queries[0];
|
|
||||||
assert!(q.qualifier == None, css.to_owned());
|
|
||||||
assert!(q.media_type == MediaQueryType::MediaType(MediaType::Print), css.to_owned());
|
|
||||||
assert!(q.expressions.len() == 0, css.to_owned());
|
|
||||||
});
|
|
||||||
|
|
||||||
test_media_rule("@media only print { }", |list, css| {
|
|
||||||
assert!(list.media_queries.len() == 1, css.to_owned());
|
|
||||||
let q = &list.media_queries[0];
|
|
||||||
assert!(q.qualifier == Some(Qualifier::Only), css.to_owned());
|
|
||||||
assert!(q.media_type == MediaQueryType::MediaType(MediaType::Print), css.to_owned());
|
|
||||||
assert!(q.expressions.len() == 0, css.to_owned());
|
|
||||||
});
|
|
||||||
|
|
||||||
test_media_rule("@media not print { }", |list, css| {
|
|
||||||
assert!(list.media_queries.len() == 1, css.to_owned());
|
|
||||||
let q = &list.media_queries[0];
|
|
||||||
assert!(q.qualifier == Some(Qualifier::Not), css.to_owned());
|
|
||||||
assert!(q.media_type == MediaQueryType::MediaType(MediaType::Print), css.to_owned());
|
|
||||||
assert!(q.expressions.len() == 0, css.to_owned());
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_mq_unknown() {
|
|
||||||
test_media_rule("@media fridge { }", |list, css| {
|
|
||||||
assert!(list.media_queries.len() == 1, css.to_owned());
|
|
||||||
let q = &list.media_queries[0];
|
|
||||||
assert!(q.qualifier == None, css.to_owned());
|
|
||||||
assert!(q.media_type == MediaQueryType::MediaType(MediaType::Unknown), css.to_owned());
|
|
||||||
assert!(q.expressions.len() == 0, css.to_owned());
|
|
||||||
});
|
|
||||||
|
|
||||||
test_media_rule("@media only glass { }", |list, css| {
|
|
||||||
assert!(list.media_queries.len() == 1, css.to_owned());
|
|
||||||
let q = &list.media_queries[0];
|
|
||||||
assert!(q.qualifier == Some(Qualifier::Only), css.to_owned());
|
|
||||||
assert!(q.media_type == MediaQueryType::MediaType(MediaType::Unknown), css.to_owned());
|
|
||||||
assert!(q.expressions.len() == 0, css.to_owned());
|
|
||||||
});
|
|
||||||
|
|
||||||
test_media_rule("@media not wood { }", |list, css| {
|
|
||||||
assert!(list.media_queries.len() == 1, css.to_owned());
|
|
||||||
let q = &list.media_queries[0];
|
|
||||||
assert!(q.qualifier == Some(Qualifier::Not), css.to_owned());
|
|
||||||
assert!(q.media_type == MediaQueryType::MediaType(MediaType::Unknown), css.to_owned());
|
|
||||||
assert!(q.expressions.len() == 0, css.to_owned());
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_mq_all() {
|
|
||||||
test_media_rule("@media all { }", |list, css| {
|
|
||||||
assert!(list.media_queries.len() == 1, css.to_owned());
|
|
||||||
let q = &list.media_queries[0];
|
|
||||||
assert!(q.qualifier == None, css.to_owned());
|
|
||||||
assert!(q.media_type == MediaQueryType::All, css.to_owned());
|
|
||||||
assert!(q.expressions.len() == 0, css.to_owned());
|
|
||||||
});
|
|
||||||
|
|
||||||
test_media_rule("@media only all { }", |list, css| {
|
|
||||||
assert!(list.media_queries.len() == 1, css.to_owned());
|
|
||||||
let q = &list.media_queries[0];
|
|
||||||
assert!(q.qualifier == Some(Qualifier::Only), css.to_owned());
|
|
||||||
assert!(q.media_type == MediaQueryType::All, css.to_owned());
|
|
||||||
assert!(q.expressions.len() == 0, css.to_owned());
|
|
||||||
});
|
|
||||||
|
|
||||||
test_media_rule("@media not all { }", |list, css| {
|
|
||||||
assert!(list.media_queries.len() == 1, css.to_owned());
|
|
||||||
let q = &list.media_queries[0];
|
|
||||||
assert!(q.qualifier == Some(Qualifier::Not), css.to_owned());
|
|
||||||
assert!(q.media_type == MediaQueryType::All, css.to_owned());
|
|
||||||
assert!(q.expressions.len() == 0, css.to_owned());
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_mq_or() {
|
|
||||||
test_media_rule("@media screen, print { }", |list, css| {
|
|
||||||
assert!(list.media_queries.len() == 2, css.to_owned());
|
|
||||||
let q0 = &list.media_queries[0];
|
|
||||||
assert!(q0.qualifier == None, css.to_owned());
|
|
||||||
assert!(q0.media_type == MediaQueryType::MediaType(MediaType::Screen), css.to_owned());
|
|
||||||
assert!(q0.expressions.len() == 0, css.to_owned());
|
|
||||||
|
|
||||||
let q1 = &list.media_queries[1];
|
|
||||||
assert!(q1.qualifier == None, css.to_owned());
|
|
||||||
assert!(q1.media_type == MediaQueryType::MediaType(MediaType::Print), css.to_owned());
|
|
||||||
assert!(q1.expressions.len() == 0, css.to_owned());
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_mq_default_expressions() {
|
|
||||||
test_media_rule("@media (min-width: 100px) { }", |list, css| {
|
|
||||||
assert!(list.media_queries.len() == 1, css.to_owned());
|
|
||||||
let q = &list.media_queries[0];
|
|
||||||
assert!(q.qualifier == None, css.to_owned());
|
|
||||||
assert!(q.media_type == MediaQueryType::All, css.to_owned());
|
|
||||||
assert!(q.expressions.len() == 1, css.to_owned());
|
|
||||||
match q.expressions[0] {
|
|
||||||
Expression::Width(Range::Min(w)) => assert!(w == specified::Length::Absolute(Au::from_px(100))),
|
|
||||||
_ => panic!("wrong expression type"),
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
test_media_rule("@media (max-width: 43px) { }", |list, css| {
|
|
||||||
assert!(list.media_queries.len() == 1, css.to_owned());
|
|
||||||
let q = &list.media_queries[0];
|
|
||||||
assert!(q.qualifier == None, css.to_owned());
|
|
||||||
assert!(q.media_type == MediaQueryType::All, css.to_owned());
|
|
||||||
assert!(q.expressions.len() == 1, css.to_owned());
|
|
||||||
match q.expressions[0] {
|
|
||||||
Expression::Width(Range::Max(w)) => assert!(w == specified::Length::Absolute(Au::from_px(43))),
|
|
||||||
_ => panic!("wrong expression type"),
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_mq_expressions() {
|
|
||||||
test_media_rule("@media screen and (min-width: 100px) { }", |list, css| {
|
|
||||||
assert!(list.media_queries.len() == 1, css.to_owned());
|
|
||||||
let q = &list.media_queries[0];
|
|
||||||
assert!(q.qualifier == None, css.to_owned());
|
|
||||||
assert!(q.media_type == MediaQueryType::MediaType(MediaType::Screen), css.to_owned());
|
|
||||||
assert!(q.expressions.len() == 1, css.to_owned());
|
|
||||||
match q.expressions[0] {
|
|
||||||
Expression::Width(Range::Min(w)) => assert!(w == specified::Length::Absolute(Au::from_px(100))),
|
|
||||||
_ => panic!("wrong expression type"),
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
test_media_rule("@media print and (max-width: 43px) { }", |list, css| {
|
|
||||||
assert!(list.media_queries.len() == 1, css.to_owned());
|
|
||||||
let q = &list.media_queries[0];
|
|
||||||
assert!(q.qualifier == None, css.to_owned());
|
|
||||||
assert!(q.media_type == MediaQueryType::MediaType(MediaType::Print), css.to_owned());
|
|
||||||
assert!(q.expressions.len() == 1, css.to_owned());
|
|
||||||
match q.expressions[0] {
|
|
||||||
Expression::Width(Range::Max(w)) => assert!(w == specified::Length::Absolute(Au::from_px(43))),
|
|
||||||
_ => panic!("wrong expression type"),
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
test_media_rule("@media fridge and (max-width: 52px) { }", |list, css| {
|
|
||||||
assert!(list.media_queries.len() == 1, css.to_owned());
|
|
||||||
let q = &list.media_queries[0];
|
|
||||||
assert!(q.qualifier == None, css.to_owned());
|
|
||||||
assert!(q.media_type == MediaQueryType::MediaType(MediaType::Unknown), css.to_owned());
|
|
||||||
assert!(q.expressions.len() == 1, css.to_owned());
|
|
||||||
match q.expressions[0] {
|
|
||||||
Expression::Width(Range::Max(w)) => assert!(w == specified::Length::Absolute(Au::from_px(52))),
|
|
||||||
_ => panic!("wrong expression type"),
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_mq_multiple_expressions() {
|
|
||||||
test_media_rule("@media (min-width: 100px) and (max-width: 200px) { }", |list, css| {
|
|
||||||
assert!(list.media_queries.len() == 1, css.to_owned());
|
|
||||||
let q = &list.media_queries[0];
|
|
||||||
assert!(q.qualifier == None, css.to_owned());
|
|
||||||
assert!(q.media_type == MediaQueryType::All, css.to_owned());
|
|
||||||
assert!(q.expressions.len() == 2, css.to_owned());
|
|
||||||
match q.expressions[0] {
|
|
||||||
Expression::Width(Range::Min(w)) => assert!(w == specified::Length::Absolute(Au::from_px(100))),
|
|
||||||
_ => panic!("wrong expression type"),
|
|
||||||
}
|
|
||||||
match q.expressions[1] {
|
|
||||||
Expression::Width(Range::Max(w)) => assert!(w == specified::Length::Absolute(Au::from_px(200))),
|
|
||||||
_ => panic!("wrong expression type"),
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
test_media_rule("@media not screen and (min-width: 100px) and (max-width: 200px) { }", |list, css| {
|
|
||||||
assert!(list.media_queries.len() == 1, css.to_owned());
|
|
||||||
let q = &list.media_queries[0];
|
|
||||||
assert!(q.qualifier == Some(Qualifier::Not), css.to_owned());
|
|
||||||
assert!(q.media_type == MediaQueryType::MediaType(MediaType::Screen), css.to_owned());
|
|
||||||
assert!(q.expressions.len() == 2, css.to_owned());
|
|
||||||
match q.expressions[0] {
|
|
||||||
Expression::Width(Range::Min(w)) => assert!(w == specified::Length::Absolute(Au::from_px(100))),
|
|
||||||
_ => panic!("wrong expression type"),
|
|
||||||
}
|
|
||||||
match q.expressions[1] {
|
|
||||||
Expression::Width(Range::Max(w)) => assert!(w == specified::Length::Absolute(Au::from_px(200))),
|
|
||||||
_ => panic!("wrong expression type"),
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_mq_malformed_expressions() {
|
|
||||||
test_media_rule("@media (min-width: 100blah) and (max-width: 200px) { }", |list, css| {
|
|
||||||
assert!(list.media_queries.len() == 1, css.to_owned());
|
|
||||||
let q = &list.media_queries[0];
|
|
||||||
assert!(q.qualifier == Some(Qualifier::Not), css.to_owned());
|
|
||||||
assert!(q.media_type == MediaQueryType::All, css.to_owned());
|
|
||||||
assert!(q.expressions.len() == 0, css.to_owned());
|
|
||||||
});
|
|
||||||
|
|
||||||
test_media_rule("@media screen and (height: 200px) { }", |list, css| {
|
|
||||||
assert!(list.media_queries.len() == 1, css.to_owned());
|
|
||||||
let q = &list.media_queries[0];
|
|
||||||
assert!(q.qualifier == Some(Qualifier::Not), css.to_owned());
|
|
||||||
assert!(q.media_type == MediaQueryType::All, css.to_owned());
|
|
||||||
assert!(q.expressions.len() == 0, css.to_owned());
|
|
||||||
});
|
|
||||||
|
|
||||||
test_media_rule("@media (min-width: 30em foo bar) {}", |list, css| {
|
|
||||||
assert!(list.media_queries.len() == 1, css.to_owned());
|
|
||||||
let q = &list.media_queries[0];
|
|
||||||
assert!(q.qualifier == Some(Qualifier::Not), css.to_owned());
|
|
||||||
assert!(q.media_type == MediaQueryType::All, css.to_owned());
|
|
||||||
assert!(q.expressions.len() == 0, css.to_owned());
|
|
||||||
});
|
|
||||||
|
|
||||||
test_media_rule("@media not {}", |list, css| {
|
|
||||||
assert!(list.media_queries.len() == 1, css.to_owned());
|
|
||||||
let q = &list.media_queries[0];
|
|
||||||
assert!(q.qualifier == Some(Qualifier::Not), css.to_owned());
|
|
||||||
assert!(q.media_type == MediaQueryType::All, css.to_owned());
|
|
||||||
assert!(q.expressions.len() == 0, css.to_owned());
|
|
||||||
});
|
|
||||||
|
|
||||||
test_media_rule("@media not (min-width: 300px) {}", |list, css| {
|
|
||||||
assert!(list.media_queries.len() == 1, css.to_owned());
|
|
||||||
let q = &list.media_queries[0];
|
|
||||||
assert!(q.qualifier == Some(Qualifier::Not), css.to_owned());
|
|
||||||
assert!(q.media_type == MediaQueryType::All, css.to_owned());
|
|
||||||
assert!(q.expressions.len() == 0, css.to_owned());
|
|
||||||
});
|
|
||||||
|
|
||||||
test_media_rule("@media , {}", |list, css| {
|
|
||||||
assert!(list.media_queries.len() == 2, css.to_owned());
|
|
||||||
let q = &list.media_queries[0];
|
|
||||||
assert!(q.qualifier == Some(Qualifier::Not), css.to_owned());
|
|
||||||
assert!(q.media_type == MediaQueryType::All, css.to_owned());
|
|
||||||
assert!(q.expressions.len() == 0, css.to_owned());
|
|
||||||
let q = &list.media_queries[1];
|
|
||||||
assert!(q.qualifier == Some(Qualifier::Not), css.to_owned());
|
|
||||||
assert!(q.media_type == MediaQueryType::All, css.to_owned());
|
|
||||||
assert!(q.expressions.len() == 0, css.to_owned());
|
|
||||||
});
|
|
||||||
|
|
||||||
test_media_rule("@media screen 4px, print {}", |list, css| {
|
|
||||||
assert!(list.media_queries.len() == 2, css.to_owned());
|
|
||||||
let q0 = &list.media_queries[0];
|
|
||||||
assert!(q0.qualifier == Some(Qualifier::Not), css.to_owned());
|
|
||||||
assert!(q0.media_type == MediaQueryType::All, css.to_owned());
|
|
||||||
assert!(q0.expressions.len() == 0, css.to_owned());
|
|
||||||
let q1 = &list.media_queries[1];
|
|
||||||
assert!(q1.qualifier == None, css.to_owned());
|
|
||||||
assert!(q1.media_type == MediaQueryType::MediaType(MediaType::Print), css.to_owned());
|
|
||||||
assert!(q1.expressions.len() == 0, css.to_owned());
|
|
||||||
});
|
|
||||||
|
|
||||||
test_media_rule("@media screen, {}", |list, css| {
|
|
||||||
assert!(list.media_queries.len() == 2, css.to_owned());
|
|
||||||
let q0 = &list.media_queries[0];
|
|
||||||
assert!(q0.qualifier == None, css.to_owned());
|
|
||||||
assert!(q0.media_type == MediaQueryType::MediaType(MediaType::Screen), css.to_owned());
|
|
||||||
assert!(q0.expressions.len() == 0, css.to_owned());
|
|
||||||
let q1 = &list.media_queries[1];
|
|
||||||
assert!(q1.qualifier == Some(Qualifier::Not), css.to_owned());
|
|
||||||
assert!(q1.media_type == MediaQueryType::All, css.to_owned());
|
|
||||||
assert!(q1.expressions.len() == 0, css.to_owned());
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_matching_simple() {
|
|
||||||
let device = Device {
|
|
||||||
media_type: MediaType::Screen,
|
|
||||||
viewport_size: TypedSize2D(200.0, 100.0),
|
|
||||||
};
|
|
||||||
|
|
||||||
media_query_test(&device, "@media not all { a { color: red; } }", 0);
|
|
||||||
media_query_test(&device, "@media not screen { a { color: red; } }", 0);
|
|
||||||
media_query_test(&device, "@media not print { a { color: red; } }", 1);
|
|
||||||
|
|
||||||
media_query_test(&device, "@media unknown { a { color: red; } }", 0);
|
|
||||||
media_query_test(&device, "@media not unknown { a { color: red; } }", 1);
|
|
||||||
|
|
||||||
media_query_test(&device, "@media { a { color: red; } }", 1);
|
|
||||||
media_query_test(&device, "@media screen { a { color: red; } }", 1);
|
|
||||||
media_query_test(&device, "@media print { a { color: red; } }", 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_matching_width() {
|
|
||||||
let device = Device {
|
|
||||||
media_type: MediaType::Screen,
|
|
||||||
viewport_size: TypedSize2D(200.0, 100.0),
|
|
||||||
};
|
|
||||||
|
|
||||||
media_query_test(&device, "@media { a { color: red; } }", 1);
|
|
||||||
|
|
||||||
media_query_test(&device, "@media (min-width: 50px) { a { color: red; } }", 1);
|
|
||||||
media_query_test(&device, "@media (min-width: 150px) { a { color: red; } }", 1);
|
|
||||||
media_query_test(&device, "@media (min-width: 300px) { a { color: red; } }", 0);
|
|
||||||
|
|
||||||
media_query_test(&device, "@media screen and (min-width: 50px) { a { color: red; } }", 1);
|
|
||||||
media_query_test(&device, "@media screen and (min-width: 150px) { a { color: red; } }", 1);
|
|
||||||
media_query_test(&device, "@media screen and (min-width: 300px) { a { color: red; } }", 0);
|
|
||||||
|
|
||||||
media_query_test(&device, "@media not screen and (min-width: 50px) { a { color: red; } }", 0);
|
|
||||||
media_query_test(&device, "@media not screen and (min-width: 150px) { a { color: red; } }", 0);
|
|
||||||
media_query_test(&device, "@media not screen and (min-width: 300px) { a { color: red; } }", 1);
|
|
||||||
|
|
||||||
media_query_test(&device, "@media (max-width: 50px) { a { color: red; } }", 0);
|
|
||||||
media_query_test(&device, "@media (max-width: 150px) { a { color: red; } }", 0);
|
|
||||||
media_query_test(&device, "@media (max-width: 300px) { a { color: red; } }", 1);
|
|
||||||
|
|
||||||
media_query_test(&device, "@media screen and (min-width: 50px) and (max-width: 100px) { a { color: red; } }", 0);
|
|
||||||
media_query_test(&device, "@media screen and (min-width: 250px) and (max-width: 300px) { a { color: red; } }", 0);
|
|
||||||
media_query_test(&device, "@media screen and (min-width: 50px) and (max-width: 250px) { a { color: red; } }", 1);
|
|
||||||
|
|
||||||
media_query_test(&device, "@media not screen and (min-width: 50px) and (max-width: 100px) { a { color: red; } }", 1);
|
|
||||||
media_query_test(&device, "@media not screen and (min-width: 250px) and (max-width: 300px) { a { color: red; } }", 1);
|
|
||||||
media_query_test(&device, "@media not screen and (min-width: 50px) and (max-width: 250px) { a { color: red; } }", 0);
|
|
||||||
|
|
||||||
media_query_test(&device, "@media not screen and (min-width: 3.1em) and (max-width: 6em) { a { color: red; } }", 1);
|
|
||||||
media_query_test(&device, "@media not screen and (min-width: 16em) and (max-width: 19.75em) { a { color: red; } }", 1);
|
|
||||||
media_query_test(&device, "@media not screen and (min-width: 3em) and (max-width: 250px) { a { color: red; } }", 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_matching_invalid() {
|
|
||||||
let device = Device {
|
|
||||||
media_type: MediaType::Screen,
|
|
||||||
viewport_size: TypedSize2D(200.0, 100.0),
|
|
||||||
};
|
|
||||||
|
|
||||||
media_query_test(&device, "@media fridge { a { color: red; } }", 0);
|
|
||||||
media_query_test(&device, "@media screen and (height: 100px) { a { color: red; } }", 0);
|
|
||||||
media_query_test(&device, "@media not print and (width: 100) { a { color: red; } }", 0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -4803,7 +4803,7 @@ impl ComputedValues {
|
||||||
|
|
||||||
|
|
||||||
/// Return a WritingMode bitflags from the relevant CSS properties.
|
/// Return a WritingMode bitflags from the relevant CSS properties.
|
||||||
fn get_writing_mode(inheritedbox_style: &style_structs::InheritedBox) -> WritingMode {
|
pub fn get_writing_mode(inheritedbox_style: &style_structs::InheritedBox) -> WritingMode {
|
||||||
use util::logical_geometry;
|
use util::logical_geometry;
|
||||||
let mut flags = WritingMode::empty();
|
let mut flags = WritingMode::empty();
|
||||||
match inheritedbox_style.direction {
|
match inheritedbox_style.direction {
|
||||||
|
@ -4839,7 +4839,7 @@ fn get_writing_mode(inheritedbox_style: &style_structs::InheritedBox) -> Writing
|
||||||
|
|
||||||
/// The initial values for all style structs as defined by the specification.
|
/// The initial values for all style structs as defined by the specification.
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
static ref INITIAL_VALUES: ComputedValues = ComputedValues {
|
pub static ref INITIAL_VALUES: ComputedValues = ComputedValues {
|
||||||
% for style_struct in STYLE_STRUCTS:
|
% for style_struct in STYLE_STRUCTS:
|
||||||
${style_struct.ident}: Arc::new(style_structs::${style_struct.name} {
|
${style_struct.ident}: Arc::new(style_structs::${style_struct.name} {
|
||||||
% for longhand in style_struct.longhands:
|
% for longhand in style_struct.longhands:
|
||||||
|
@ -4857,11 +4857,6 @@ lazy_static! {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn initial_writing_mode_is_empty() {
|
|
||||||
assert_eq!(get_writing_mode(INITIAL_VALUES.get_inheritedbox()), WritingMode::empty())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Fast path for the function below. Only computes new inherited styles.
|
/// Fast path for the function below. Only computes new inherited styles.
|
||||||
#[allow(unused_mut)]
|
#[allow(unused_mut)]
|
||||||
fn cascade_with_cached_declarations(
|
fn cascade_with_cached_declarations(
|
||||||
|
|
|
@ -31,7 +31,7 @@ pub enum Origin {
|
||||||
pub struct Stylesheet {
|
pub struct Stylesheet {
|
||||||
/// List of rules in the order they were found (important for
|
/// List of rules in the order they were found (important for
|
||||||
/// cascading order)
|
/// cascading order)
|
||||||
rules: Vec<CSSRule>,
|
pub rules: Vec<CSSRule>,
|
||||||
pub origin: Origin,
|
pub origin: Origin,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -322,136 +322,3 @@ pub fn iter_font_face_rules<F>(stylesheet: &Stylesheet, device: &Device, callbac
|
||||||
where F: Fn(&Atom, &Source) {
|
where F: Fn(&Atom, &Source) {
|
||||||
iter_font_face_rules_inner(&stylesheet.rules, device, callback)
|
iter_font_face_rules_inner(&stylesheet.rules, device, callback)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_parse_stylesheet() {
|
|
||||||
use std::sync::Arc;
|
|
||||||
use cssparser;
|
|
||||||
use selectors::parser::*;
|
|
||||||
use string_cache::Atom;
|
|
||||||
use properties::{PropertyDeclaration, DeclaredValue, longhands};
|
|
||||||
use std::borrow::ToOwned;
|
|
||||||
|
|
||||||
let css = r"
|
|
||||||
@namespace url(http://www.w3.org/1999/xhtml);
|
|
||||||
/* FIXME: only if scripting is enabled */
|
|
||||||
input[type=hidden i] { display: none !important; }
|
|
||||||
html , body /**/ { display: block; }
|
|
||||||
#d1 > .ok { background: blue; }
|
|
||||||
";
|
|
||||||
let url = Url::parse("about::test").unwrap();
|
|
||||||
let stylesheet = Stylesheet::from_str(css, url, Origin::UserAgent);
|
|
||||||
assert_eq!(stylesheet, Stylesheet {
|
|
||||||
origin: Origin::UserAgent,
|
|
||||||
rules: vec![
|
|
||||||
CSSRule::Namespace(None, ns!(HTML)),
|
|
||||||
CSSRule::Style(StyleRule {
|
|
||||||
selectors: vec![
|
|
||||||
Selector {
|
|
||||||
compound_selectors: Arc::new(CompoundSelector {
|
|
||||||
simple_selectors: vec![
|
|
||||||
SimpleSelector::Namespace(ns!(HTML)),
|
|
||||||
SimpleSelector::LocalName(LocalName {
|
|
||||||
name: atom!(input),
|
|
||||||
lower_name: atom!(input),
|
|
||||||
}),
|
|
||||||
SimpleSelector::AttrEqual(AttrSelector {
|
|
||||||
name: atom!(type),
|
|
||||||
lower_name: atom!(type),
|
|
||||||
namespace: NamespaceConstraint::Specific(ns!("")),
|
|
||||||
}, "hidden".to_owned(), CaseSensitivity::CaseInsensitive)
|
|
||||||
],
|
|
||||||
next: None,
|
|
||||||
}),
|
|
||||||
pseudo_element: None,
|
|
||||||
specificity: (0 << 20) + (1 << 10) + (1 << 0),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
declarations: PropertyDeclarationBlock {
|
|
||||||
normal: Arc::new(vec![]),
|
|
||||||
important: Arc::new(vec![
|
|
||||||
PropertyDeclaration::Display(DeclaredValue::SpecifiedValue(
|
|
||||||
longhands::display::SpecifiedValue::none)),
|
|
||||||
]),
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
CSSRule::Style(StyleRule {
|
|
||||||
selectors: vec![
|
|
||||||
Selector {
|
|
||||||
compound_selectors: Arc::new(CompoundSelector {
|
|
||||||
simple_selectors: vec![
|
|
||||||
SimpleSelector::Namespace(ns!(HTML)),
|
|
||||||
SimpleSelector::LocalName(LocalName {
|
|
||||||
name: atom!(html),
|
|
||||||
lower_name: atom!(html),
|
|
||||||
}),
|
|
||||||
],
|
|
||||||
next: None,
|
|
||||||
}),
|
|
||||||
pseudo_element: None,
|
|
||||||
specificity: (0 << 20) + (0 << 10) + (1 << 0),
|
|
||||||
},
|
|
||||||
Selector {
|
|
||||||
compound_selectors: Arc::new(CompoundSelector {
|
|
||||||
simple_selectors: vec![
|
|
||||||
SimpleSelector::Namespace(ns!(HTML)),
|
|
||||||
SimpleSelector::LocalName(LocalName {
|
|
||||||
name: atom!(body),
|
|
||||||
lower_name: atom!(body),
|
|
||||||
}),
|
|
||||||
],
|
|
||||||
next: None,
|
|
||||||
}),
|
|
||||||
pseudo_element: None,
|
|
||||||
specificity: (0 << 20) + (0 << 10) + (1 << 0),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
declarations: PropertyDeclarationBlock {
|
|
||||||
normal: Arc::new(vec![
|
|
||||||
PropertyDeclaration::Display(DeclaredValue::SpecifiedValue(
|
|
||||||
longhands::display::SpecifiedValue::block)),
|
|
||||||
]),
|
|
||||||
important: Arc::new(vec![]),
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
CSSRule::Style(StyleRule {
|
|
||||||
selectors: vec![
|
|
||||||
Selector {
|
|
||||||
compound_selectors: Arc::new(CompoundSelector {
|
|
||||||
simple_selectors: vec![
|
|
||||||
SimpleSelector::Class(Atom::from_slice("ok")),
|
|
||||||
],
|
|
||||||
next: Some((box CompoundSelector {
|
|
||||||
simple_selectors: vec![
|
|
||||||
SimpleSelector::ID(Atom::from_slice("d1")),
|
|
||||||
],
|
|
||||||
next: None,
|
|
||||||
}, Combinator::Child)),
|
|
||||||
}),
|
|
||||||
pseudo_element: None,
|
|
||||||
specificity: (1 << 20) + (1 << 10) + (0 << 0),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
declarations: PropertyDeclarationBlock {
|
|
||||||
normal: Arc::new(vec![
|
|
||||||
PropertyDeclaration::BackgroundSize(DeclaredValue::Initial),
|
|
||||||
PropertyDeclaration::BackgroundImage(DeclaredValue::Initial),
|
|
||||||
PropertyDeclaration::BackgroundAttachment(DeclaredValue::Initial),
|
|
||||||
PropertyDeclaration::BackgroundRepeat(DeclaredValue::Initial),
|
|
||||||
PropertyDeclaration::BackgroundPosition(DeclaredValue::Initial),
|
|
||||||
PropertyDeclaration::BackgroundColor(DeclaredValue::SpecifiedValue(
|
|
||||||
longhands::background_color::SpecifiedValue {
|
|
||||||
authored: Some("blue".to_owned()),
|
|
||||||
parsed: cssparser::Color::RGBA(cssparser::RGBA {
|
|
||||||
red: 0., green: 0., blue: 1., alpha: 1.
|
|
||||||
}),
|
|
||||||
}
|
|
||||||
)),
|
|
||||||
]),
|
|
||||||
important: Arc::new(vec![]),
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
],
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
|
@ -23,9 +23,24 @@ path = "../../components/net_traits"
|
||||||
[dependencies.profile]
|
[dependencies.profile]
|
||||||
path = "../../components/profile"
|
path = "../../components/profile"
|
||||||
|
|
||||||
|
[dependencies.style]
|
||||||
|
path = "../../components/style"
|
||||||
|
|
||||||
[dependencies.geom]
|
[dependencies.geom]
|
||||||
git = "https://github.com/servo/rust-geom"
|
git = "https://github.com/servo/rust-geom"
|
||||||
|
|
||||||
|
[dependencies.cssparser]
|
||||||
|
git = "https://github.com/servo/rust-cssparser"
|
||||||
|
|
||||||
|
[dependencies.selectors]
|
||||||
|
git = "https://github.com/servo/rust-selectors"
|
||||||
|
|
||||||
|
[dependencies.string_cache]
|
||||||
|
git = "https://github.com/servo/string-cache"
|
||||||
|
|
||||||
|
[dependencies.string_cache_plugin]
|
||||||
|
git = "https://github.com/servo/string-cache"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
cookie = "*"
|
cookie = "*"
|
||||||
url = "*"
|
url = "*"
|
||||||
|
|
|
@ -1,14 +1,21 @@
|
||||||
|
#![feature(plugin)]
|
||||||
#![cfg_attr(test, feature(net, alloc))]
|
#![cfg_attr(test, feature(net, alloc))]
|
||||||
|
|
||||||
|
#![plugin(string_cache_plugin)]
|
||||||
|
|
||||||
|
extern crate cssparser;
|
||||||
extern crate geom;
|
extern crate geom;
|
||||||
extern crate gfx;
|
extern crate gfx;
|
||||||
extern crate net;
|
extern crate net;
|
||||||
extern crate net_traits;
|
extern crate net_traits;
|
||||||
extern crate profile;
|
extern crate profile;
|
||||||
|
extern crate selectors;
|
||||||
|
extern crate string_cache;
|
||||||
|
extern crate style;
|
||||||
extern crate util;
|
extern crate util;
|
||||||
extern crate url;
|
extern crate url;
|
||||||
|
|
||||||
#[cfg(test)] #[path="gfx/mod.rs"] mod gfx_tests;
|
#[cfg(test)] #[path="gfx/mod.rs"] mod gfx_tests;
|
||||||
#[cfg(test)] #[path="net/mod.rs"] mod net_tests;
|
#[cfg(test)] #[path="net/mod.rs"] mod net_tests;
|
||||||
|
#[cfg(test)] #[path="style/mod.rs"] mod style_tests;
|
||||||
#[cfg(test)] #[path="util/mod.rs"] mod util_tests;
|
#[cfg(test)] #[path="util/mod.rs"] mod util_tests;
|
||||||
|
|
||||||
|
|
412
tests/unit/style/media_queries.rs
Normal file
412
tests/unit/style/media_queries.rs
Normal file
|
@ -0,0 +1,412 @@
|
||||||
|
use geom::size::TypedSize2D;
|
||||||
|
use style::stylesheets::{iter_stylesheet_media_rules, iter_stylesheet_style_rules, Stylesheet};
|
||||||
|
use style::stylesheets::Origin;
|
||||||
|
use style::media_queries::*;
|
||||||
|
use style::values::specified;
|
||||||
|
use std::borrow::ToOwned;
|
||||||
|
use url::Url;
|
||||||
|
use util::geometry::Au;
|
||||||
|
|
||||||
|
|
||||||
|
fn test_media_rule<F>(css: &str, callback: F) where F: Fn(&MediaQueryList, &str) {
|
||||||
|
let url = Url::parse("http://localhost").unwrap();
|
||||||
|
let stylesheet = Stylesheet::from_str(css, url, Origin::Author);
|
||||||
|
let mut rule_count = 0;
|
||||||
|
iter_stylesheet_media_rules(&stylesheet, |rule| {
|
||||||
|
rule_count += 1;
|
||||||
|
callback(&rule.media_queries, css);
|
||||||
|
});
|
||||||
|
assert!(rule_count > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn media_query_test(device: &Device, css: &str, expected_rule_count: u32) {
|
||||||
|
let url = Url::parse("http://localhost").unwrap();
|
||||||
|
let ss = Stylesheet::from_str(css, url, Origin::Author);
|
||||||
|
let mut rule_count: u32 = 0;
|
||||||
|
iter_stylesheet_style_rules(&ss, device, |_| rule_count += 1);
|
||||||
|
assert!(rule_count == expected_rule_count, css.to_owned());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_mq_empty() {
|
||||||
|
test_media_rule("@media { }", |list, css| {
|
||||||
|
assert!(list.media_queries.len() == 1, css.to_owned());
|
||||||
|
let q = &list.media_queries[0];
|
||||||
|
assert!(q.qualifier == None, css.to_owned());
|
||||||
|
assert!(q.media_type == MediaQueryType::All, css.to_owned());
|
||||||
|
assert!(q.expressions.len() == 0, css.to_owned());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_mq_screen() {
|
||||||
|
test_media_rule("@media screen { }", |list, css| {
|
||||||
|
assert!(list.media_queries.len() == 1, css.to_owned());
|
||||||
|
let q = &list.media_queries[0];
|
||||||
|
assert!(q.qualifier == None, css.to_owned());
|
||||||
|
assert!(q.media_type == MediaQueryType::MediaType(MediaType::Screen), css.to_owned());
|
||||||
|
assert!(q.expressions.len() == 0, css.to_owned());
|
||||||
|
});
|
||||||
|
|
||||||
|
test_media_rule("@media only screen { }", |list, css| {
|
||||||
|
assert!(list.media_queries.len() == 1, css.to_owned());
|
||||||
|
let q = &list.media_queries[0];
|
||||||
|
assert!(q.qualifier == Some(Qualifier::Only), css.to_owned());
|
||||||
|
assert!(q.media_type == MediaQueryType::MediaType(MediaType::Screen), css.to_owned());
|
||||||
|
assert!(q.expressions.len() == 0, css.to_owned());
|
||||||
|
});
|
||||||
|
|
||||||
|
test_media_rule("@media not screen { }", |list, css| {
|
||||||
|
assert!(list.media_queries.len() == 1, css.to_owned());
|
||||||
|
let q = &list.media_queries[0];
|
||||||
|
assert!(q.qualifier == Some(Qualifier::Not), css.to_owned());
|
||||||
|
assert!(q.media_type == MediaQueryType::MediaType(MediaType::Screen), css.to_owned());
|
||||||
|
assert!(q.expressions.len() == 0, css.to_owned());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_mq_print() {
|
||||||
|
test_media_rule("@media print { }", |list, css| {
|
||||||
|
assert!(list.media_queries.len() == 1, css.to_owned());
|
||||||
|
let q = &list.media_queries[0];
|
||||||
|
assert!(q.qualifier == None, css.to_owned());
|
||||||
|
assert!(q.media_type == MediaQueryType::MediaType(MediaType::Print), css.to_owned());
|
||||||
|
assert!(q.expressions.len() == 0, css.to_owned());
|
||||||
|
});
|
||||||
|
|
||||||
|
test_media_rule("@media only print { }", |list, css| {
|
||||||
|
assert!(list.media_queries.len() == 1, css.to_owned());
|
||||||
|
let q = &list.media_queries[0];
|
||||||
|
assert!(q.qualifier == Some(Qualifier::Only), css.to_owned());
|
||||||
|
assert!(q.media_type == MediaQueryType::MediaType(MediaType::Print), css.to_owned());
|
||||||
|
assert!(q.expressions.len() == 0, css.to_owned());
|
||||||
|
});
|
||||||
|
|
||||||
|
test_media_rule("@media not print { }", |list, css| {
|
||||||
|
assert!(list.media_queries.len() == 1, css.to_owned());
|
||||||
|
let q = &list.media_queries[0];
|
||||||
|
assert!(q.qualifier == Some(Qualifier::Not), css.to_owned());
|
||||||
|
assert!(q.media_type == MediaQueryType::MediaType(MediaType::Print), css.to_owned());
|
||||||
|
assert!(q.expressions.len() == 0, css.to_owned());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_mq_unknown() {
|
||||||
|
test_media_rule("@media fridge { }", |list, css| {
|
||||||
|
assert!(list.media_queries.len() == 1, css.to_owned());
|
||||||
|
let q = &list.media_queries[0];
|
||||||
|
assert!(q.qualifier == None, css.to_owned());
|
||||||
|
assert!(q.media_type == MediaQueryType::MediaType(MediaType::Unknown), css.to_owned());
|
||||||
|
assert!(q.expressions.len() == 0, css.to_owned());
|
||||||
|
});
|
||||||
|
|
||||||
|
test_media_rule("@media only glass { }", |list, css| {
|
||||||
|
assert!(list.media_queries.len() == 1, css.to_owned());
|
||||||
|
let q = &list.media_queries[0];
|
||||||
|
assert!(q.qualifier == Some(Qualifier::Only), css.to_owned());
|
||||||
|
assert!(q.media_type == MediaQueryType::MediaType(MediaType::Unknown), css.to_owned());
|
||||||
|
assert!(q.expressions.len() == 0, css.to_owned());
|
||||||
|
});
|
||||||
|
|
||||||
|
test_media_rule("@media not wood { }", |list, css| {
|
||||||
|
assert!(list.media_queries.len() == 1, css.to_owned());
|
||||||
|
let q = &list.media_queries[0];
|
||||||
|
assert!(q.qualifier == Some(Qualifier::Not), css.to_owned());
|
||||||
|
assert!(q.media_type == MediaQueryType::MediaType(MediaType::Unknown), css.to_owned());
|
||||||
|
assert!(q.expressions.len() == 0, css.to_owned());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_mq_all() {
|
||||||
|
test_media_rule("@media all { }", |list, css| {
|
||||||
|
assert!(list.media_queries.len() == 1, css.to_owned());
|
||||||
|
let q = &list.media_queries[0];
|
||||||
|
assert!(q.qualifier == None, css.to_owned());
|
||||||
|
assert!(q.media_type == MediaQueryType::All, css.to_owned());
|
||||||
|
assert!(q.expressions.len() == 0, css.to_owned());
|
||||||
|
});
|
||||||
|
|
||||||
|
test_media_rule("@media only all { }", |list, css| {
|
||||||
|
assert!(list.media_queries.len() == 1, css.to_owned());
|
||||||
|
let q = &list.media_queries[0];
|
||||||
|
assert!(q.qualifier == Some(Qualifier::Only), css.to_owned());
|
||||||
|
assert!(q.media_type == MediaQueryType::All, css.to_owned());
|
||||||
|
assert!(q.expressions.len() == 0, css.to_owned());
|
||||||
|
});
|
||||||
|
|
||||||
|
test_media_rule("@media not all { }", |list, css| {
|
||||||
|
assert!(list.media_queries.len() == 1, css.to_owned());
|
||||||
|
let q = &list.media_queries[0];
|
||||||
|
assert!(q.qualifier == Some(Qualifier::Not), css.to_owned());
|
||||||
|
assert!(q.media_type == MediaQueryType::All, css.to_owned());
|
||||||
|
assert!(q.expressions.len() == 0, css.to_owned());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_mq_or() {
|
||||||
|
test_media_rule("@media screen, print { }", |list, css| {
|
||||||
|
assert!(list.media_queries.len() == 2, css.to_owned());
|
||||||
|
let q0 = &list.media_queries[0];
|
||||||
|
assert!(q0.qualifier == None, css.to_owned());
|
||||||
|
assert!(q0.media_type == MediaQueryType::MediaType(MediaType::Screen), css.to_owned());
|
||||||
|
assert!(q0.expressions.len() == 0, css.to_owned());
|
||||||
|
|
||||||
|
let q1 = &list.media_queries[1];
|
||||||
|
assert!(q1.qualifier == None, css.to_owned());
|
||||||
|
assert!(q1.media_type == MediaQueryType::MediaType(MediaType::Print), css.to_owned());
|
||||||
|
assert!(q1.expressions.len() == 0, css.to_owned());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_mq_default_expressions() {
|
||||||
|
test_media_rule("@media (min-width: 100px) { }", |list, css| {
|
||||||
|
assert!(list.media_queries.len() == 1, css.to_owned());
|
||||||
|
let q = &list.media_queries[0];
|
||||||
|
assert!(q.qualifier == None, css.to_owned());
|
||||||
|
assert!(q.media_type == MediaQueryType::All, css.to_owned());
|
||||||
|
assert!(q.expressions.len() == 1, css.to_owned());
|
||||||
|
match q.expressions[0] {
|
||||||
|
Expression::Width(Range::Min(w)) => assert!(w == specified::Length::Absolute(Au::from_px(100))),
|
||||||
|
_ => panic!("wrong expression type"),
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
test_media_rule("@media (max-width: 43px) { }", |list, css| {
|
||||||
|
assert!(list.media_queries.len() == 1, css.to_owned());
|
||||||
|
let q = &list.media_queries[0];
|
||||||
|
assert!(q.qualifier == None, css.to_owned());
|
||||||
|
assert!(q.media_type == MediaQueryType::All, css.to_owned());
|
||||||
|
assert!(q.expressions.len() == 1, css.to_owned());
|
||||||
|
match q.expressions[0] {
|
||||||
|
Expression::Width(Range::Max(w)) => assert!(w == specified::Length::Absolute(Au::from_px(43))),
|
||||||
|
_ => panic!("wrong expression type"),
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_mq_expressions() {
|
||||||
|
test_media_rule("@media screen and (min-width: 100px) { }", |list, css| {
|
||||||
|
assert!(list.media_queries.len() == 1, css.to_owned());
|
||||||
|
let q = &list.media_queries[0];
|
||||||
|
assert!(q.qualifier == None, css.to_owned());
|
||||||
|
assert!(q.media_type == MediaQueryType::MediaType(MediaType::Screen), css.to_owned());
|
||||||
|
assert!(q.expressions.len() == 1, css.to_owned());
|
||||||
|
match q.expressions[0] {
|
||||||
|
Expression::Width(Range::Min(w)) => assert!(w == specified::Length::Absolute(Au::from_px(100))),
|
||||||
|
_ => panic!("wrong expression type"),
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
test_media_rule("@media print and (max-width: 43px) { }", |list, css| {
|
||||||
|
assert!(list.media_queries.len() == 1, css.to_owned());
|
||||||
|
let q = &list.media_queries[0];
|
||||||
|
assert!(q.qualifier == None, css.to_owned());
|
||||||
|
assert!(q.media_type == MediaQueryType::MediaType(MediaType::Print), css.to_owned());
|
||||||
|
assert!(q.expressions.len() == 1, css.to_owned());
|
||||||
|
match q.expressions[0] {
|
||||||
|
Expression::Width(Range::Max(w)) => assert!(w == specified::Length::Absolute(Au::from_px(43))),
|
||||||
|
_ => panic!("wrong expression type"),
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
test_media_rule("@media fridge and (max-width: 52px) { }", |list, css| {
|
||||||
|
assert!(list.media_queries.len() == 1, css.to_owned());
|
||||||
|
let q = &list.media_queries[0];
|
||||||
|
assert!(q.qualifier == None, css.to_owned());
|
||||||
|
assert!(q.media_type == MediaQueryType::MediaType(MediaType::Unknown), css.to_owned());
|
||||||
|
assert!(q.expressions.len() == 1, css.to_owned());
|
||||||
|
match q.expressions[0] {
|
||||||
|
Expression::Width(Range::Max(w)) => assert!(w == specified::Length::Absolute(Au::from_px(52))),
|
||||||
|
_ => panic!("wrong expression type"),
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_mq_multiple_expressions() {
|
||||||
|
test_media_rule("@media (min-width: 100px) and (max-width: 200px) { }", |list, css| {
|
||||||
|
assert!(list.media_queries.len() == 1, css.to_owned());
|
||||||
|
let q = &list.media_queries[0];
|
||||||
|
assert!(q.qualifier == None, css.to_owned());
|
||||||
|
assert!(q.media_type == MediaQueryType::All, css.to_owned());
|
||||||
|
assert!(q.expressions.len() == 2, css.to_owned());
|
||||||
|
match q.expressions[0] {
|
||||||
|
Expression::Width(Range::Min(w)) => assert!(w == specified::Length::Absolute(Au::from_px(100))),
|
||||||
|
_ => panic!("wrong expression type"),
|
||||||
|
}
|
||||||
|
match q.expressions[1] {
|
||||||
|
Expression::Width(Range::Max(w)) => assert!(w == specified::Length::Absolute(Au::from_px(200))),
|
||||||
|
_ => panic!("wrong expression type"),
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
test_media_rule("@media not screen and (min-width: 100px) and (max-width: 200px) { }", |list, css| {
|
||||||
|
assert!(list.media_queries.len() == 1, css.to_owned());
|
||||||
|
let q = &list.media_queries[0];
|
||||||
|
assert!(q.qualifier == Some(Qualifier::Not), css.to_owned());
|
||||||
|
assert!(q.media_type == MediaQueryType::MediaType(MediaType::Screen), css.to_owned());
|
||||||
|
assert!(q.expressions.len() == 2, css.to_owned());
|
||||||
|
match q.expressions[0] {
|
||||||
|
Expression::Width(Range::Min(w)) => assert!(w == specified::Length::Absolute(Au::from_px(100))),
|
||||||
|
_ => panic!("wrong expression type"),
|
||||||
|
}
|
||||||
|
match q.expressions[1] {
|
||||||
|
Expression::Width(Range::Max(w)) => assert!(w == specified::Length::Absolute(Au::from_px(200))),
|
||||||
|
_ => panic!("wrong expression type"),
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_mq_malformed_expressions() {
|
||||||
|
test_media_rule("@media (min-width: 100blah) and (max-width: 200px) { }", |list, css| {
|
||||||
|
assert!(list.media_queries.len() == 1, css.to_owned());
|
||||||
|
let q = &list.media_queries[0];
|
||||||
|
assert!(q.qualifier == Some(Qualifier::Not), css.to_owned());
|
||||||
|
assert!(q.media_type == MediaQueryType::All, css.to_owned());
|
||||||
|
assert!(q.expressions.len() == 0, css.to_owned());
|
||||||
|
});
|
||||||
|
|
||||||
|
test_media_rule("@media screen and (height: 200px) { }", |list, css| {
|
||||||
|
assert!(list.media_queries.len() == 1, css.to_owned());
|
||||||
|
let q = &list.media_queries[0];
|
||||||
|
assert!(q.qualifier == Some(Qualifier::Not), css.to_owned());
|
||||||
|
assert!(q.media_type == MediaQueryType::All, css.to_owned());
|
||||||
|
assert!(q.expressions.len() == 0, css.to_owned());
|
||||||
|
});
|
||||||
|
|
||||||
|
test_media_rule("@media (min-width: 30em foo bar) {}", |list, css| {
|
||||||
|
assert!(list.media_queries.len() == 1, css.to_owned());
|
||||||
|
let q = &list.media_queries[0];
|
||||||
|
assert!(q.qualifier == Some(Qualifier::Not), css.to_owned());
|
||||||
|
assert!(q.media_type == MediaQueryType::All, css.to_owned());
|
||||||
|
assert!(q.expressions.len() == 0, css.to_owned());
|
||||||
|
});
|
||||||
|
|
||||||
|
test_media_rule("@media not {}", |list, css| {
|
||||||
|
assert!(list.media_queries.len() == 1, css.to_owned());
|
||||||
|
let q = &list.media_queries[0];
|
||||||
|
assert!(q.qualifier == Some(Qualifier::Not), css.to_owned());
|
||||||
|
assert!(q.media_type == MediaQueryType::All, css.to_owned());
|
||||||
|
assert!(q.expressions.len() == 0, css.to_owned());
|
||||||
|
});
|
||||||
|
|
||||||
|
test_media_rule("@media not (min-width: 300px) {}", |list, css| {
|
||||||
|
assert!(list.media_queries.len() == 1, css.to_owned());
|
||||||
|
let q = &list.media_queries[0];
|
||||||
|
assert!(q.qualifier == Some(Qualifier::Not), css.to_owned());
|
||||||
|
assert!(q.media_type == MediaQueryType::All, css.to_owned());
|
||||||
|
assert!(q.expressions.len() == 0, css.to_owned());
|
||||||
|
});
|
||||||
|
|
||||||
|
test_media_rule("@media , {}", |list, css| {
|
||||||
|
assert!(list.media_queries.len() == 2, css.to_owned());
|
||||||
|
let q = &list.media_queries[0];
|
||||||
|
assert!(q.qualifier == Some(Qualifier::Not), css.to_owned());
|
||||||
|
assert!(q.media_type == MediaQueryType::All, css.to_owned());
|
||||||
|
assert!(q.expressions.len() == 0, css.to_owned());
|
||||||
|
let q = &list.media_queries[1];
|
||||||
|
assert!(q.qualifier == Some(Qualifier::Not), css.to_owned());
|
||||||
|
assert!(q.media_type == MediaQueryType::All, css.to_owned());
|
||||||
|
assert!(q.expressions.len() == 0, css.to_owned());
|
||||||
|
});
|
||||||
|
|
||||||
|
test_media_rule("@media screen 4px, print {}", |list, css| {
|
||||||
|
assert!(list.media_queries.len() == 2, css.to_owned());
|
||||||
|
let q0 = &list.media_queries[0];
|
||||||
|
assert!(q0.qualifier == Some(Qualifier::Not), css.to_owned());
|
||||||
|
assert!(q0.media_type == MediaQueryType::All, css.to_owned());
|
||||||
|
assert!(q0.expressions.len() == 0, css.to_owned());
|
||||||
|
let q1 = &list.media_queries[1];
|
||||||
|
assert!(q1.qualifier == None, css.to_owned());
|
||||||
|
assert!(q1.media_type == MediaQueryType::MediaType(MediaType::Print), css.to_owned());
|
||||||
|
assert!(q1.expressions.len() == 0, css.to_owned());
|
||||||
|
});
|
||||||
|
|
||||||
|
test_media_rule("@media screen, {}", |list, css| {
|
||||||
|
assert!(list.media_queries.len() == 2, css.to_owned());
|
||||||
|
let q0 = &list.media_queries[0];
|
||||||
|
assert!(q0.qualifier == None, css.to_owned());
|
||||||
|
assert!(q0.media_type == MediaQueryType::MediaType(MediaType::Screen), css.to_owned());
|
||||||
|
assert!(q0.expressions.len() == 0, css.to_owned());
|
||||||
|
let q1 = &list.media_queries[1];
|
||||||
|
assert!(q1.qualifier == Some(Qualifier::Not), css.to_owned());
|
||||||
|
assert!(q1.media_type == MediaQueryType::All, css.to_owned());
|
||||||
|
assert!(q1.expressions.len() == 0, css.to_owned());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_matching_simple() {
|
||||||
|
let device = Device {
|
||||||
|
media_type: MediaType::Screen,
|
||||||
|
viewport_size: TypedSize2D(200.0, 100.0),
|
||||||
|
};
|
||||||
|
|
||||||
|
media_query_test(&device, "@media not all { a { color: red; } }", 0);
|
||||||
|
media_query_test(&device, "@media not screen { a { color: red; } }", 0);
|
||||||
|
media_query_test(&device, "@media not print { a { color: red; } }", 1);
|
||||||
|
|
||||||
|
media_query_test(&device, "@media unknown { a { color: red; } }", 0);
|
||||||
|
media_query_test(&device, "@media not unknown { a { color: red; } }", 1);
|
||||||
|
|
||||||
|
media_query_test(&device, "@media { a { color: red; } }", 1);
|
||||||
|
media_query_test(&device, "@media screen { a { color: red; } }", 1);
|
||||||
|
media_query_test(&device, "@media print { a { color: red; } }", 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_matching_width() {
|
||||||
|
let device = Device {
|
||||||
|
media_type: MediaType::Screen,
|
||||||
|
viewport_size: TypedSize2D(200.0, 100.0),
|
||||||
|
};
|
||||||
|
|
||||||
|
media_query_test(&device, "@media { a { color: red; } }", 1);
|
||||||
|
|
||||||
|
media_query_test(&device, "@media (min-width: 50px) { a { color: red; } }", 1);
|
||||||
|
media_query_test(&device, "@media (min-width: 150px) { a { color: red; } }", 1);
|
||||||
|
media_query_test(&device, "@media (min-width: 300px) { a { color: red; } }", 0);
|
||||||
|
|
||||||
|
media_query_test(&device, "@media screen and (min-width: 50px) { a { color: red; } }", 1);
|
||||||
|
media_query_test(&device, "@media screen and (min-width: 150px) { a { color: red; } }", 1);
|
||||||
|
media_query_test(&device, "@media screen and (min-width: 300px) { a { color: red; } }", 0);
|
||||||
|
|
||||||
|
media_query_test(&device, "@media not screen and (min-width: 50px) { a { color: red; } }", 0);
|
||||||
|
media_query_test(&device, "@media not screen and (min-width: 150px) { a { color: red; } }", 0);
|
||||||
|
media_query_test(&device, "@media not screen and (min-width: 300px) { a { color: red; } }", 1);
|
||||||
|
|
||||||
|
media_query_test(&device, "@media (max-width: 50px) { a { color: red; } }", 0);
|
||||||
|
media_query_test(&device, "@media (max-width: 150px) { a { color: red; } }", 0);
|
||||||
|
media_query_test(&device, "@media (max-width: 300px) { a { color: red; } }", 1);
|
||||||
|
|
||||||
|
media_query_test(&device, "@media screen and (min-width: 50px) and (max-width: 100px) { a { color: red; } }", 0);
|
||||||
|
media_query_test(&device, "@media screen and (min-width: 250px) and (max-width: 300px) { a { color: red; } }", 0);
|
||||||
|
media_query_test(&device, "@media screen and (min-width: 50px) and (max-width: 250px) { a { color: red; } }", 1);
|
||||||
|
|
||||||
|
media_query_test(&device, "@media not screen and (min-width: 50px) and (max-width: 100px) { a { color: red; } }", 1);
|
||||||
|
media_query_test(&device, "@media not screen and (min-width: 250px) and (max-width: 300px) { a { color: red; } }", 1);
|
||||||
|
media_query_test(&device, "@media not screen and (min-width: 50px) and (max-width: 250px) { a { color: red; } }", 0);
|
||||||
|
|
||||||
|
media_query_test(&device, "@media not screen and (min-width: 3.1em) and (max-width: 6em) { a { color: red; } }", 1);
|
||||||
|
media_query_test(&device, "@media not screen and (min-width: 16em) and (max-width: 19.75em) { a { color: red; } }", 1);
|
||||||
|
media_query_test(&device, "@media not screen and (min-width: 3em) and (max-width: 250px) { a { color: red; } }", 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_matching_invalid() {
|
||||||
|
let device = Device {
|
||||||
|
media_type: MediaType::Screen,
|
||||||
|
viewport_size: TypedSize2D(200.0, 100.0),
|
||||||
|
};
|
||||||
|
|
||||||
|
media_query_test(&device, "@media fridge { a { color: red; } }", 0);
|
||||||
|
media_query_test(&device, "@media screen and (height: 100px) { a { color: red; } }", 0);
|
||||||
|
media_query_test(&device, "@media not print and (width: 100) { a { color: red; } }", 0);
|
||||||
|
}
|
12
tests/unit/style/mod.rs
Normal file
12
tests/unit/style/mod.rs
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
use util::logical_geometry::WritingMode;
|
||||||
|
use style::properties::{INITIAL_VALUES, get_writing_mode};
|
||||||
|
|
||||||
|
|
||||||
|
mod stylesheets;
|
||||||
|
mod media_queries;
|
||||||
|
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn initial_writing_mode_is_empty() {
|
||||||
|
assert_eq!(get_writing_mode(INITIAL_VALUES.get_inheritedbox()), WritingMode::empty())
|
||||||
|
}
|
134
tests/unit/style/stylesheets.rs
Normal file
134
tests/unit/style/stylesheets.rs
Normal file
|
@ -0,0 +1,134 @@
|
||||||
|
use std::borrow::ToOwned;
|
||||||
|
use std::sync::Arc;
|
||||||
|
use cssparser;
|
||||||
|
use selectors::parser::*;
|
||||||
|
use string_cache::Atom;
|
||||||
|
use style::properties::{PropertyDeclaration, PropertyDeclarationBlock, DeclaredValue, longhands};
|
||||||
|
use style::stylesheets::{CSSRule, StyleRule, Origin, Stylesheet};
|
||||||
|
use url::Url;
|
||||||
|
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_parse_stylesheet() {
|
||||||
|
let css = r"
|
||||||
|
@namespace url(http://www.w3.org/1999/xhtml);
|
||||||
|
/* FIXME: only if scripting is enabled */
|
||||||
|
input[type=hidden i] { display: none !important; }
|
||||||
|
html , body /**/ { display: block; }
|
||||||
|
#d1 > .ok { background: blue; }
|
||||||
|
";
|
||||||
|
let url = Url::parse("about::test").unwrap();
|
||||||
|
let stylesheet = Stylesheet::from_str(css, url, Origin::UserAgent);
|
||||||
|
assert_eq!(stylesheet, Stylesheet {
|
||||||
|
origin: Origin::UserAgent,
|
||||||
|
rules: vec![
|
||||||
|
CSSRule::Namespace(None, ns!(HTML)),
|
||||||
|
CSSRule::Style(StyleRule {
|
||||||
|
selectors: vec![
|
||||||
|
Selector {
|
||||||
|
compound_selectors: Arc::new(CompoundSelector {
|
||||||
|
simple_selectors: vec![
|
||||||
|
SimpleSelector::Namespace(ns!(HTML)),
|
||||||
|
SimpleSelector::LocalName(LocalName {
|
||||||
|
name: atom!(input),
|
||||||
|
lower_name: atom!(input),
|
||||||
|
}),
|
||||||
|
SimpleSelector::AttrEqual(AttrSelector {
|
||||||
|
name: atom!(type),
|
||||||
|
lower_name: atom!(type),
|
||||||
|
namespace: NamespaceConstraint::Specific(ns!("")),
|
||||||
|
}, "hidden".to_owned(), CaseSensitivity::CaseInsensitive)
|
||||||
|
],
|
||||||
|
next: None,
|
||||||
|
}),
|
||||||
|
pseudo_element: None,
|
||||||
|
specificity: (0 << 20) + (1 << 10) + (1 << 0),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
declarations: PropertyDeclarationBlock {
|
||||||
|
normal: Arc::new(vec![]),
|
||||||
|
important: Arc::new(vec![
|
||||||
|
PropertyDeclaration::Display(DeclaredValue::SpecifiedValue(
|
||||||
|
longhands::display::SpecifiedValue::none)),
|
||||||
|
]),
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
CSSRule::Style(StyleRule {
|
||||||
|
selectors: vec![
|
||||||
|
Selector {
|
||||||
|
compound_selectors: Arc::new(CompoundSelector {
|
||||||
|
simple_selectors: vec![
|
||||||
|
SimpleSelector::Namespace(ns!(HTML)),
|
||||||
|
SimpleSelector::LocalName(LocalName {
|
||||||
|
name: atom!(html),
|
||||||
|
lower_name: atom!(html),
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
next: None,
|
||||||
|
}),
|
||||||
|
pseudo_element: None,
|
||||||
|
specificity: (0 << 20) + (0 << 10) + (1 << 0),
|
||||||
|
},
|
||||||
|
Selector {
|
||||||
|
compound_selectors: Arc::new(CompoundSelector {
|
||||||
|
simple_selectors: vec![
|
||||||
|
SimpleSelector::Namespace(ns!(HTML)),
|
||||||
|
SimpleSelector::LocalName(LocalName {
|
||||||
|
name: atom!(body),
|
||||||
|
lower_name: atom!(body),
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
next: None,
|
||||||
|
}),
|
||||||
|
pseudo_element: None,
|
||||||
|
specificity: (0 << 20) + (0 << 10) + (1 << 0),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
declarations: PropertyDeclarationBlock {
|
||||||
|
normal: Arc::new(vec![
|
||||||
|
PropertyDeclaration::Display(DeclaredValue::SpecifiedValue(
|
||||||
|
longhands::display::SpecifiedValue::block)),
|
||||||
|
]),
|
||||||
|
important: Arc::new(vec![]),
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
CSSRule::Style(StyleRule {
|
||||||
|
selectors: vec![
|
||||||
|
Selector {
|
||||||
|
compound_selectors: Arc::new(CompoundSelector {
|
||||||
|
simple_selectors: vec![
|
||||||
|
SimpleSelector::Class(Atom::from_slice("ok")),
|
||||||
|
],
|
||||||
|
next: Some((Box::new(CompoundSelector {
|
||||||
|
simple_selectors: vec![
|
||||||
|
SimpleSelector::ID(Atom::from_slice("d1")),
|
||||||
|
],
|
||||||
|
next: None,
|
||||||
|
}), Combinator::Child)),
|
||||||
|
}),
|
||||||
|
pseudo_element: None,
|
||||||
|
specificity: (1 << 20) + (1 << 10) + (0 << 0),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
declarations: PropertyDeclarationBlock {
|
||||||
|
normal: Arc::new(vec![
|
||||||
|
PropertyDeclaration::BackgroundSize(DeclaredValue::Initial),
|
||||||
|
PropertyDeclaration::BackgroundImage(DeclaredValue::Initial),
|
||||||
|
PropertyDeclaration::BackgroundAttachment(DeclaredValue::Initial),
|
||||||
|
PropertyDeclaration::BackgroundRepeat(DeclaredValue::Initial),
|
||||||
|
PropertyDeclaration::BackgroundPosition(DeclaredValue::Initial),
|
||||||
|
PropertyDeclaration::BackgroundColor(DeclaredValue::SpecifiedValue(
|
||||||
|
longhands::background_color::SpecifiedValue {
|
||||||
|
authored: Some("blue".to_owned()),
|
||||||
|
parsed: cssparser::Color::RGBA(cssparser::RGBA {
|
||||||
|
red: 0., green: 0., blue: 1., alpha: 1.
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
)),
|
||||||
|
]),
|
||||||
|
important: Arc::new(vec![]),
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
});
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue