#![cfg(feature = "alloc")]
use std::borrow::Cow;
use ccss::parse::declaration::DeclarationParseListError;
use util::{error::MaybeError, TestSuite, TestSuites};
pub mod util;
type Expected<S> = MaybeError<util::declaration::Declaration<S>, S>;
const TEST: &str = include_str!("../css-parsing-tests/one_declaration.json");
#[test]
fn test_all() {
let test_suites =
serde_json::from_str::<TestSuites<Cow<str>, Expected<Cow<str>>>>(TEST).unwrap();
for TestSuite { input, expected } in test_suites.0 {
if input.contains("/*") {
continue;
}
if input.contains(";") {
eprintln!("Tests with semicolon are skipped: {input:?}");
continue;
}
let res = parse_one(&input);
match expected.result {
Ok(mut expected) => {
while expected.value.last().is_some_and(|v| v.is_whitespace()) {
_ = expected.value.pop().unwrap();
}
{
let start_whitespace_count =
expected.value.iter().try_fold(0, |count, item| {
if item.is_whitespace() {
Ok(count + 1)
} else {
Err(count)
}
});
let start_whitespace_count =
start_whitespace_count.unwrap_or_else(std::convert::identity);
expected.value.drain(..start_whitespace_count)
};
let Ok(Some(d)) = res else {
panic!(
"expect declaration: {expected:?}\nUnexpected: {res:?}\ninput: {input:?}"
)
};
assert_eq!(
util::declaration::Declaration::from_parsed(d),
expected,
"\ninput: {input:?}"
);
}
Err(err) => match &*err.reason {
"empty" => {
assert!(
matches!(res, Ok(None)),
"Expect empty declaration\nUnexpected: {res:?}\ninput: {input:?}"
)
}
"invalid" => {
assert!(
res.is_err(),
"Expect error declaration\nUnexpected: {res:?}\ninput: {input:?}"
)
}
reason => {
panic!("unknown error reason: {reason}\ninput: {input:?}")
}
},
}
}
}
type Parsed<'a> = util::declaration::Parsed<'a, 10>;
const fn parse_one(input: &str) -> Result<Option<Parsed>, DeclarationParseListError> {
let parse_list = Parsed::parse_list_from_str(input);
let (v, parse_list) = match parse_list.try_into_next() {
Ok(v) => v,
Err(err) => return Err(err),
};
assert!(matches!(parse_list.try_into_next(), Ok((None, _))));
Ok(v)
}