mirror of
https://github.com/servo/servo.git
synced 2025-08-03 12:40:06 +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"
|
||||
dependencies = [
|
||||
"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)",
|
||||
"gfx 0.0.1",
|
||||
"net 0.0.1",
|
||||
"net_traits 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)",
|
||||
"util 0.0.1",
|
||||
]
|
||||
|
|
|
@ -13,7 +13,7 @@ use values::specified;
|
|||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub struct MediaQueryList {
|
||||
media_queries: Vec<MediaQuery>
|
||||
pub media_queries: Vec<MediaQuery>
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Copy, Debug)]
|
||||
|
@ -71,9 +71,9 @@ pub enum Qualifier {
|
|||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub struct MediaQuery {
|
||||
qualifier: Option<Qualifier>,
|
||||
media_type: MediaQueryType,
|
||||
expressions: Vec<Expression>,
|
||||
pub qualifier: Option<Qualifier>,
|
||||
pub media_type: MediaQueryType,
|
||||
pub expressions: Vec<Expression>,
|
||||
}
|
||||
|
||||
impl MediaQuery {
|
||||
|
@ -230,415 +230,5 @@ impl MediaQueryList {
|
|||
|
||||
#[cfg(test)]
|
||||
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.
|
||||
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;
|
||||
let mut flags = WritingMode::empty();
|
||||
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.
|
||||
lazy_static! {
|
||||
static ref INITIAL_VALUES: ComputedValues = ComputedValues {
|
||||
pub static ref INITIAL_VALUES: ComputedValues = ComputedValues {
|
||||
% for style_struct in STYLE_STRUCTS:
|
||||
${style_struct.ident}: Arc::new(style_structs::${style_struct.name} {
|
||||
% 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.
|
||||
#[allow(unused_mut)]
|
||||
fn cascade_with_cached_declarations(
|
||||
|
|
|
@ -31,7 +31,7 @@ pub enum Origin {
|
|||
pub struct Stylesheet {
|
||||
/// List of rules in the order they were found (important for
|
||||
/// cascading order)
|
||||
rules: Vec<CSSRule>,
|
||||
pub rules: Vec<CSSRule>,
|
||||
pub origin: Origin,
|
||||
}
|
||||
|
||||
|
@ -322,136 +322,3 @@ pub fn iter_font_face_rules<F>(stylesheet: &Stylesheet, device: &Device, callbac
|
|||
where F: Fn(&Atom, &Source) {
|
||||
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]
|
||||
path = "../../components/profile"
|
||||
|
||||
[dependencies.style]
|
||||
path = "../../components/style"
|
||||
|
||||
[dependencies.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]
|
||||
cookie = "*"
|
||||
url = "*"
|
||||
|
|
|
@ -1,14 +1,21 @@
|
|||
#![feature(plugin)]
|
||||
#![cfg_attr(test, feature(net, alloc))]
|
||||
|
||||
#![plugin(string_cache_plugin)]
|
||||
|
||||
extern crate cssparser;
|
||||
extern crate geom;
|
||||
extern crate gfx;
|
||||
extern crate net;
|
||||
extern crate net_traits;
|
||||
extern crate profile;
|
||||
extern crate selectors;
|
||||
extern crate string_cache;
|
||||
extern crate style;
|
||||
extern crate util;
|
||||
extern crate url;
|
||||
|
||||
#[cfg(test)] #[path="gfx/mod.rs"] mod gfx_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;
|
||||
|
||||
|
|
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