use skyscraper::{
html,
xpath::{
self,
grammar::data_model::{AnyAtomicType, XpathItem},
},
};
#[test]
fn instance_of_node_true() {
let text = r#"<html><body></body></html>"#;
let document = html::parse(text).unwrap();
let xpath = xpath::parse("/html instance of node()").unwrap();
let items = xpath.apply(&document).unwrap();
assert_eq!(items.len(), 1);
assert_eq!(
items[0],
XpathItem::AnyAtomicType(AnyAtomicType::Boolean(true))
);
}
#[test]
fn instance_of_node_false() {
let text = r#"<html><body></body></html>"#;
let document = html::parse(text).unwrap();
let xpath = xpath::parse("42 instance of node()").unwrap();
let items = xpath.apply(&document).unwrap();
assert_eq!(items.len(), 1);
assert_eq!(
items[0],
XpathItem::AnyAtomicType(AnyAtomicType::Boolean(false))
);
}
#[test]
fn instance_of_item_true() {
let text = r#"<html><body></body></html>"#;
let document = html::parse(text).unwrap();
let xpath = xpath::parse("42 instance of item()").unwrap();
let items = xpath.apply(&document).unwrap();
assert_eq!(items.len(), 1);
assert_eq!(
items[0],
XpathItem::AnyAtomicType(AnyAtomicType::Boolean(true))
);
}
#[test]
fn instance_of_text_true() {
let text = r#"<html><body>hello</body></html>"#;
let document = html::parse(text).unwrap();
let xpath = xpath::parse("//body/text() instance of text()").unwrap();
let items = xpath.apply(&document).unwrap();
assert_eq!(items.len(), 1);
assert_eq!(
items[0],
XpathItem::AnyAtomicType(AnyAtomicType::Boolean(true))
);
}
#[test]
fn instance_of_text_false() {
let text = r#"<html><body></body></html>"#;
let document = html::parse(text).unwrap();
let xpath = xpath::parse("/html instance of text()").unwrap();
let items = xpath.apply(&document).unwrap();
assert_eq!(items.len(), 1);
assert_eq!(
items[0],
XpathItem::AnyAtomicType(AnyAtomicType::Boolean(false))
);
}
#[test]
fn instance_of_empty_sequence_true() {
let text = r#"<html><body></body></html>"#;
let document = html::parse(text).unwrap();
let xpath = xpath::parse("//nonexistent instance of empty-sequence()").unwrap();
let items = xpath.apply(&document).unwrap();
assert_eq!(items.len(), 1);
assert_eq!(
items[0],
XpathItem::AnyAtomicType(AnyAtomicType::Boolean(true))
);
}
#[test]
fn instance_of_empty_sequence_false() {
let text = r#"<html><body></body></html>"#;
let document = html::parse(text).unwrap();
let xpath = xpath::parse("/html instance of empty-sequence()").unwrap();
let items = xpath.apply(&document).unwrap();
assert_eq!(items.len(), 1);
assert_eq!(
items[0],
XpathItem::AnyAtomicType(AnyAtomicType::Boolean(false))
);
}
#[test]
fn instance_of_with_if() {
let text = r#"<html><body></body></html>"#;
let document = html::parse(text).unwrap();
let xpath = xpath::parse("if (42 instance of item()) then 1 else 0").unwrap();
let items = xpath.apply(&document).unwrap();
assert_eq!(items.len(), 1);
assert_eq!(
items[0],
XpathItem::AnyAtomicType(AnyAtomicType::Integer(1))
);
}
#[test]
fn instance_of_typed_map_matching() {
let text = r#"<html><body></body></html>"#;
let document = html::parse(text).unwrap();
let xpath =
xpath::parse(r#"map { 1: "a", 2: "b" } instance of map(xs:integer, xs:string)"#)
.unwrap();
let items = xpath.apply(&document).unwrap();
assert_eq!(items.len(), 1);
assert_eq!(
items[0],
XpathItem::AnyAtomicType(AnyAtomicType::Boolean(true))
);
}
#[test]
fn instance_of_typed_map_wrong_key_type() {
let text = r#"<html><body></body></html>"#;
let document = html::parse(text).unwrap();
let xpath =
xpath::parse(r#"map { "x": "a", "y": "b" } instance of map(xs:integer, xs:string)"#)
.unwrap();
let items = xpath.apply(&document).unwrap();
assert_eq!(items.len(), 1);
assert_eq!(
items[0],
XpathItem::AnyAtomicType(AnyAtomicType::Boolean(false))
);
}
#[test]
fn instance_of_typed_map_wrong_value_type() {
let text = r#"<html><body></body></html>"#;
let document = html::parse(text).unwrap();
let xpath =
xpath::parse(r#"map { 1: 100, 2: 200 } instance of map(xs:integer, xs:string)"#)
.unwrap();
let items = xpath.apply(&document).unwrap();
assert_eq!(items.len(), 1);
assert_eq!(
items[0],
XpathItem::AnyAtomicType(AnyAtomicType::Boolean(false))
);
}
#[test]
fn instance_of_typed_map_empty() {
let text = r#"<html><body></body></html>"#;
let document = html::parse(text).unwrap();
let xpath =
xpath::parse(r#"map {} instance of map(xs:integer, xs:string)"#).unwrap();
let items = xpath.apply(&document).unwrap();
assert_eq!(items.len(), 1);
assert_eq!(
items[0],
XpathItem::AnyAtomicType(AnyAtomicType::Boolean(true))
);
}
#[test]
fn instance_of_any_map_test() {
let text = r#"<html><body></body></html>"#;
let document = html::parse(text).unwrap();
let xpath =
xpath::parse(r#"map { "a": 1, "b": 2 } instance of map(*)"#).unwrap();
let items = xpath.apply(&document).unwrap();
assert_eq!(items.len(), 1);
assert_eq!(
items[0],
XpathItem::AnyAtomicType(AnyAtomicType::Boolean(true))
);
}
#[test]
fn instance_of_typed_map_non_map() {
let text = r#"<html><body></body></html>"#;
let document = html::parse(text).unwrap();
let xpath =
xpath::parse(r#"[1, 2, 3] instance of map(xs:integer, xs:integer)"#).unwrap();
let items = xpath.apply(&document).unwrap();
assert_eq!(items.len(), 1);
assert_eq!(
items[0],
XpathItem::AnyAtomicType(AnyAtomicType::Boolean(false))
);
}
#[test]
fn instance_of_typed_array_matching() {
let text = r#"<html><body></body></html>"#;
let document = html::parse(text).unwrap();
let xpath = xpath::parse("[1, 2, 3] instance of array(xs:integer)").unwrap();
let items = xpath.apply(&document).unwrap();
assert_eq!(items.len(), 1);
assert_eq!(
items[0],
XpathItem::AnyAtomicType(AnyAtomicType::Boolean(true))
);
}
#[test]
fn instance_of_typed_array_wrong_member_type() {
let text = r#"<html><body></body></html>"#;
let document = html::parse(text).unwrap();
let xpath =
xpath::parse(r#"["a", "b", "c"] instance of array(xs:integer)"#).unwrap();
let items = xpath.apply(&document).unwrap();
assert_eq!(items.len(), 1);
assert_eq!(
items[0],
XpathItem::AnyAtomicType(AnyAtomicType::Boolean(false))
);
}
#[test]
fn instance_of_typed_array_empty() {
let text = r#"<html><body></body></html>"#;
let document = html::parse(text).unwrap();
let xpath = xpath::parse("[] instance of array(xs:string)").unwrap();
let items = xpath.apply(&document).unwrap();
assert_eq!(items.len(), 1);
assert_eq!(
items[0],
XpathItem::AnyAtomicType(AnyAtomicType::Boolean(true))
);
}
#[test]
fn instance_of_any_array_test() {
let text = r#"<html><body></body></html>"#;
let document = html::parse(text).unwrap();
let xpath =
xpath::parse(r#"["a", "b"] instance of array(*)"#).unwrap();
let items = xpath.apply(&document).unwrap();
assert_eq!(items.len(), 1);
assert_eq!(
items[0],
XpathItem::AnyAtomicType(AnyAtomicType::Boolean(true))
);
}
#[test]
fn instance_of_typed_array_non_array() {
let text = r#"<html><body></body></html>"#;
let document = html::parse(text).unwrap();
let xpath =
xpath::parse(r#"map { 1: 2 } instance of array(xs:integer)"#).unwrap();
let items = xpath.apply(&document).unwrap();
assert_eq!(items.len(), 1);
assert_eq!(
items[0],
XpathItem::AnyAtomicType(AnyAtomicType::Boolean(false))
);
}
#[test]
fn instance_of_typed_function_matching_arity() {
let text = r#"<html><body></body></html>"#;
let document = html::parse(text).unwrap();
let xpath = xpath::parse(
"fn:abs#1 instance of function(xs:integer) as xs:integer",
)
.unwrap();
let items = xpath.apply(&document).unwrap();
assert_eq!(items.len(), 1);
assert_eq!(
items[0],
XpathItem::AnyAtomicType(AnyAtomicType::Boolean(true))
);
}
#[test]
fn instance_of_typed_function_wrong_arity() {
let text = r#"<html><body></body></html>"#;
let document = html::parse(text).unwrap();
let xpath = xpath::parse(
"fn:abs#1 instance of function(xs:integer, xs:integer) as xs:integer",
)
.unwrap();
let items = xpath.apply(&document).unwrap();
assert_eq!(items.len(), 1);
assert_eq!(
items[0],
XpathItem::AnyAtomicType(AnyAtomicType::Boolean(false))
);
}
#[test]
fn instance_of_typed_function_inline() {
let text = r#"<html><body></body></html>"#;
let document = html::parse(text).unwrap();
let xpath = xpath::parse(
"function($x) { $x + 1 } instance of function(xs:integer) as xs:integer",
)
.unwrap();
let items = xpath.apply(&document).unwrap();
assert_eq!(items.len(), 1);
assert_eq!(
items[0],
XpathItem::AnyAtomicType(AnyAtomicType::Boolean(true))
);
}
#[test]
fn instance_of_typed_function_zero_arity() {
let text = r#"<html><body></body></html>"#;
let document = html::parse(text).unwrap();
let xpath = xpath::parse(
"function() { 42 } instance of function() as xs:integer",
)
.unwrap();
let items = xpath.apply(&document).unwrap();
assert_eq!(items.len(), 1);
assert_eq!(
items[0],
XpathItem::AnyAtomicType(AnyAtomicType::Boolean(true))
);
}
#[test]
fn instance_of_typed_function_map_as_function() {
let text = r#"<html><body></body></html>"#;
let document = html::parse(text).unwrap();
let xpath = xpath::parse(
r#"map { 1: "a" } instance of function(xs:integer) as xs:string"#,
)
.unwrap();
let items = xpath.apply(&document).unwrap();
assert_eq!(items.len(), 1);
assert_eq!(
items[0],
XpathItem::AnyAtomicType(AnyAtomicType::Boolean(true))
);
}
#[test]
fn instance_of_typed_function_map_wrong_arity() {
let text = r#"<html><body></body></html>"#;
let document = html::parse(text).unwrap();
let xpath = xpath::parse(
r#"map { 1: "a" } instance of function(xs:integer, xs:integer) as xs:string"#,
)
.unwrap();
let items = xpath.apply(&document).unwrap();
assert_eq!(items.len(), 1);
assert_eq!(
items[0],
XpathItem::AnyAtomicType(AnyAtomicType::Boolean(false))
);
}
#[test]
fn instance_of_any_function_test() {
let text = r#"<html><body></body></html>"#;
let document = html::parse(text).unwrap();
let xpath = xpath::parse(
"fn:abs#1 instance of function(*)",
)
.unwrap();
let items = xpath.apply(&document).unwrap();
assert_eq!(items.len(), 1);
assert_eq!(
items[0],
XpathItem::AnyAtomicType(AnyAtomicType::Boolean(true))
);
}
#[test]
fn instance_of_typed_function_non_function() {
let text = r#"<html><body></body></html>"#;
let document = html::parse(text).unwrap();
let xpath = xpath::parse(
"42 instance of function(xs:integer) as xs:integer",
)
.unwrap();
let items = xpath.apply(&document).unwrap();
assert_eq!(items.len(), 1);
assert_eq!(
items[0],
XpathItem::AnyAtomicType(AnyAtomicType::Boolean(false))
);
}
#[test]
fn instance_of_unknown_type_raises_xpst0051() {
let text = r#"<html><body></body></html>"#;
let document = html::parse(text).unwrap();
let xpath = xpath::parse("42 instance of xs:foobar").unwrap();
let err = xpath.apply(&document).unwrap_err();
assert!(
err.to_string().contains("XPST0051"),
"expected XPST0051, got: {}",
err
);
}
#[test]
fn instance_of_unknown_unprefixed_type_raises_xpst0051() {
let text = r#"<html><body></body></html>"#;
let document = html::parse(text).unwrap();
let xpath = xpath::parse("42 instance of foobar").unwrap();
let err = xpath.apply(&document).unwrap_err();
assert!(
err.to_string().contains("XPST0051"),
"expected XPST0051, got: {}",
err
);
}
#[test]
fn instance_of_any_atomic_type_integer() {
let text = r#"<html><body></body></html>"#;
let document = html::parse(text).unwrap();
let xpath = xpath::parse("42 instance of xs:anyAtomicType").unwrap();
let items = xpath.apply(&document).unwrap();
assert_eq!(items.len(), 1);
assert_eq!(
items[0],
XpathItem::AnyAtomicType(AnyAtomicType::Boolean(true))
);
}
#[test]
fn instance_of_any_atomic_type_string() {
let text = r#"<html><body></body></html>"#;
let document = html::parse(text).unwrap();
let xpath = xpath::parse(r#""hello" instance of xs:anyAtomicType"#).unwrap();
let items = xpath.apply(&document).unwrap();
assert_eq!(items.len(), 1);
assert_eq!(
items[0],
XpathItem::AnyAtomicType(AnyAtomicType::Boolean(true))
);
}
#[test]
fn instance_of_any_atomic_type_node_false() {
let text = r#"<html><body></body></html>"#;
let document = html::parse(text).unwrap();
let xpath = xpath::parse("/html instance of xs:anyAtomicType").unwrap();
let items = xpath.apply(&document).unwrap();
assert_eq!(items.len(), 1);
assert_eq!(
items[0],
XpathItem::AnyAtomicType(AnyAtomicType::Boolean(false))
);
}
#[test]
fn instance_of_decimal_integer() {
let text = r#"<html><body></body></html>"#;
let document = html::parse(text).unwrap();
let xpath = xpath::parse("42 instance of xs:decimal").unwrap();
let items = xpath.apply(&document).unwrap();
assert_eq!(items.len(), 1);
assert_eq!(
items[0],
XpathItem::AnyAtomicType(AnyAtomicType::Boolean(true))
);
}
#[test]
fn instance_of_decimal_string_false() {
let text = r#"<html><body></body></html>"#;
let document = html::parse(text).unwrap();
let xpath = xpath::parse(r#""hello" instance of xs:decimal"#).unwrap();
let items = xpath.apply(&document).unwrap();
assert_eq!(items.len(), 1);
assert_eq!(
items[0],
XpathItem::AnyAtomicType(AnyAtomicType::Boolean(false))
);
}
#[test]
fn instance_of_numeric_integer() {
let text = r#"<html><body></body></html>"#;
let document = html::parse(text).unwrap();
let xpath = xpath::parse("42 instance of xs:numeric").unwrap();
let items = xpath.apply(&document).unwrap();
assert_eq!(items.len(), 1);
assert_eq!(
items[0],
XpathItem::AnyAtomicType(AnyAtomicType::Boolean(true))
);
}
#[test]
fn instance_of_numeric_double() {
let text = r#"<html><body></body></html>"#;
let document = html::parse(text).unwrap();
let xpath = xpath::parse("3.14e0 instance of xs:numeric").unwrap();
let items = xpath.apply(&document).unwrap();
assert_eq!(items.len(), 1);
assert_eq!(
items[0],
XpathItem::AnyAtomicType(AnyAtomicType::Boolean(true))
);
}
#[test]
fn instance_of_numeric_string_false() {
let text = r#"<html><body></body></html>"#;
let document = html::parse(text).unwrap();
let xpath = xpath::parse(r#""hello" instance of xs:numeric"#).unwrap();
let items = xpath.apply(&document).unwrap();
assert_eq!(items.len(), 1);
assert_eq!(
items[0],
XpathItem::AnyAtomicType(AnyAtomicType::Boolean(false))
);
}
#[test]
fn instance_of_unimplemented_type_returns_false() {
let text = r#"<html><body></body></html>"#;
let document = html::parse(text).unwrap();
let xpath = xpath::parse("42 instance of xs:date").unwrap();
let items = xpath.apply(&document).unwrap();
assert_eq!(items.len(), 1);
assert_eq!(
items[0],
XpathItem::AnyAtomicType(AnyAtomicType::Boolean(false))
);
}
#[test]
fn instance_of_untyped_atomic_returns_true() {
let text = r#"<html><body></body></html>"#;
let document = html::parse(text).unwrap();
let xpath = xpath::parse(r#""hello" instance of xs:untypedAtomic"#).unwrap();
let items = xpath.apply(&document).unwrap();
assert_eq!(items.len(), 1);
assert_eq!(
items[0],
XpathItem::AnyAtomicType(AnyAtomicType::Boolean(true))
);
}