mirror of
https://github.com/servo/servo.git
synced 2025-08-06 22:15:33 +01:00
Import SelectorMap unit tests from the selectors crate.
This commit is contained in:
parent
dec28a13ea
commit
5e4bdac2bd
3 changed files with 113 additions and 9 deletions
|
@ -609,16 +609,16 @@ impl PerPseudoElementSelectorMap {
|
|||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||
pub struct SelectorMap {
|
||||
// TODO: Tune the initial capacity of the HashMap
|
||||
id_hash: FnvHashMap<Atom, Vec<Rule>>,
|
||||
class_hash: FnvHashMap<Atom, Vec<Rule>>,
|
||||
local_name_hash: FnvHashMap<Atom, Vec<Rule>>,
|
||||
pub id_hash: FnvHashMap<Atom, Vec<Rule>>,
|
||||
pub class_hash: FnvHashMap<Atom, Vec<Rule>>,
|
||||
pub local_name_hash: FnvHashMap<Atom, Vec<Rule>>,
|
||||
/// Same as local_name_hash, but keys are lower-cased.
|
||||
/// For HTML elements in HTML documents.
|
||||
lower_local_name_hash: FnvHashMap<Atom, Vec<Rule>>,
|
||||
pub lower_local_name_hash: FnvHashMap<Atom, Vec<Rule>>,
|
||||
/// Rules that don't have ID, class, or element selectors.
|
||||
other_rules: Vec<Rule>,
|
||||
pub other_rules: Vec<Rule>,
|
||||
/// Whether this hash is empty.
|
||||
empty: bool,
|
||||
pub empty: bool,
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
@ -783,7 +783,7 @@ impl SelectorMap {
|
|||
}
|
||||
|
||||
/// Retrieve the first ID name in Rule, or None otherwise.
|
||||
fn get_id_name(rule: &Rule) -> Option<Atom> {
|
||||
pub fn get_id_name(rule: &Rule) -> Option<Atom> {
|
||||
for ss in &rule.selector.compound_selector {
|
||||
// TODO(pradeep): Implement case-sensitivity based on the
|
||||
// document type and quirks mode.
|
||||
|
@ -796,7 +796,7 @@ impl SelectorMap {
|
|||
}
|
||||
|
||||
/// Retrieve the FIRST class name in Rule, or None otherwise.
|
||||
fn get_class_name(rule: &Rule) -> Option<Atom> {
|
||||
pub fn get_class_name(rule: &Rule) -> Option<Atom> {
|
||||
for ss in &rule.selector.compound_selector {
|
||||
// TODO(pradeep): Implement case-sensitivity based on the
|
||||
// document type and quirks mode.
|
||||
|
@ -809,7 +809,7 @@ impl SelectorMap {
|
|||
}
|
||||
|
||||
/// Retrieve the name if it is a type selector, or None otherwise.
|
||||
fn get_local_name(rule: &Rule) -> Option<LocalName<TheSelectorImpl>> {
|
||||
pub fn get_local_name(rule: &Rule) -> Option<LocalName<TheSelectorImpl>> {
|
||||
for ss in &rule.selector.compound_selector {
|
||||
if let SimpleSelector::LocalName(ref n) = *ss {
|
||||
return Some(LocalName {
|
||||
|
|
|
@ -23,6 +23,7 @@ mod logical_geometry;
|
|||
mod media_queries;
|
||||
mod parsing;
|
||||
mod properties;
|
||||
mod selector_matching;
|
||||
mod str;
|
||||
mod stylesheets;
|
||||
mod value;
|
||||
|
|
103
tests/unit/style/selector_matching.rs
Normal file
103
tests/unit/style/selector_matching.rs
Normal file
|
@ -0,0 +1,103 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use cssparser::Parser;
|
||||
use selectors::parser::{LocalName, ParserContext, parse_selector_list};
|
||||
use std::sync::Arc;
|
||||
use string_cache::Atom;
|
||||
use style::properties::Importance;
|
||||
use style::selector_matching::{DeclarationBlock, Rule, SelectorMap};
|
||||
|
||||
/// Helper method to get some Rules from selector strings.
|
||||
/// Each sublist of the result contains the Rules for one StyleRule.
|
||||
fn get_mock_rules(css_selectors: &[&str]) -> Vec<Vec<Rule>> {
|
||||
css_selectors.iter().enumerate().map(|(i, selectors)| {
|
||||
let context = ParserContext::new();
|
||||
parse_selector_list(&context, &mut Parser::new(*selectors))
|
||||
.unwrap().into_iter().map(|s| {
|
||||
Rule {
|
||||
selector: s.complex_selector.clone(),
|
||||
declarations: DeclarationBlock {
|
||||
mixed_declarations: Arc::new(Vec::new()),
|
||||
importance: Importance::Normal,
|
||||
specificity: s.specificity,
|
||||
source_order: i,
|
||||
}
|
||||
}
|
||||
}).collect()
|
||||
}).collect()
|
||||
}
|
||||
|
||||
fn get_mock_map(selectors: &[&str]) -> SelectorMap {
|
||||
let mut map = SelectorMap::new();
|
||||
let selector_rules = get_mock_rules(selectors);
|
||||
|
||||
for rules in selector_rules.into_iter() {
|
||||
for rule in rules.into_iter() {
|
||||
map.insert(rule)
|
||||
}
|
||||
}
|
||||
|
||||
map
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rule_ordering_same_specificity() {
|
||||
let rules_list = get_mock_rules(&["a.intro", "img.sidebar"]);
|
||||
let a = &rules_list[0][0].declarations;
|
||||
let b = &rules_list[1][0].declarations;
|
||||
assert!((a.specificity, a.source_order) < ((b.specificity, b.source_order)),
|
||||
"The rule that comes later should win.");
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn test_get_id_name() {
|
||||
let rules_list = get_mock_rules(&[".intro", "#top"]);
|
||||
assert_eq!(SelectorMap::get_id_name(&rules_list[0][0]), None);
|
||||
assert_eq!(SelectorMap::get_id_name(&rules_list[1][0]), Some(Atom::from("top")));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_get_class_name() {
|
||||
let rules_list = get_mock_rules(&[".intro.foo", "#top"]);
|
||||
assert_eq!(SelectorMap::get_class_name(&rules_list[0][0]), Some(Atom::from("intro")));
|
||||
assert_eq!(SelectorMap::get_class_name(&rules_list[1][0]), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_get_local_name() {
|
||||
let rules_list = get_mock_rules(&["img.foo", "#top", "IMG", "ImG"]);
|
||||
let check = |i: usize, names: Option<(&str, &str)>| {
|
||||
assert!(SelectorMap::get_local_name(&rules_list[i][0])
|
||||
== names.map(|(name, lower_name)| LocalName {
|
||||
name: Atom::from(name),
|
||||
lower_name: Atom::from(lower_name) }))
|
||||
};
|
||||
check(0, Some(("img", "img")));
|
||||
check(1, None);
|
||||
check(2, Some(("IMG", "img")));
|
||||
check(3, Some(("ImG", "img")));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_insert() {
|
||||
let rules_list = get_mock_rules(&[".intro.foo", "#top"]);
|
||||
let mut selector_map = SelectorMap::new();
|
||||
selector_map.insert(rules_list[1][0].clone());
|
||||
assert_eq!(1, selector_map.id_hash.get(&atom!("top")).unwrap()[0].declarations.source_order);
|
||||
selector_map.insert(rules_list[0][0].clone());
|
||||
assert_eq!(0, selector_map.class_hash.get(&Atom::from("intro")).unwrap()[0].declarations.source_order);
|
||||
assert!(selector_map.class_hash.get(&Atom::from("foo")).is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_get_universal_rules() {
|
||||
let map = get_mock_map(&["*|*", "#foo > *|*", ".klass", "#id"]);
|
||||
let mut decls = vec![];
|
||||
|
||||
map.get_universal_rules(&mut decls);
|
||||
|
||||
assert_eq!(decls.len(), 1);
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue