use crate::{parse_schema_diagnostics, parse_schema_named};
const THREE_UNKNOWN_TYPES: &str = r#"datasource db {
provider = "postgresql"
}
model User {
id Int @id
role Rolle
}
model Post {
id Int @id
status Statuss
}
model Comment {
id Int @id
kind Kindd
}
"#;
fn diagnostics(source: &str) -> Vec<String> {
parse_schema_diagnostics("t.cstack", source)
.1
.into_iter()
.map(|error| error.message().to_owned())
.collect()
}
#[test]
fn independent_declaration_errors_are_all_reported() {
let messages = diagnostics(THREE_UNKNOWN_TYPES);
assert_eq!(messages.len(), 3, "{messages:?}");
assert!(messages[0].contains("Rolle"));
assert!(messages[1].contains("Statuss"));
assert!(messages[2].contains("Kindd"));
}
#[test]
fn the_first_collected_error_is_the_one_the_fail_fast_path_returns() {
let expected =
parse_schema_named("t.cstack", THREE_UNKNOWN_TYPES).expect_err("fixture should be invalid");
let messages = diagnostics(THREE_UNKNOWN_TYPES);
assert_eq!(
messages.first().map(String::as_str),
Some(expected.message())
);
}
#[test]
fn a_syntax_error_yields_exactly_one_diagnostic() {
let messages = diagnostics("mode User {\n id Int @id\n}\n");
assert_eq!(messages.len(), 1, "{messages:?}");
}
#[test]
fn a_stage_two_failure_suppresses_the_per_declaration_stage() {
let source = r#"datasource db {
provider = "mysql"
}
model User {
id Int @id
role Rolle
}
"#;
let messages = diagnostics(source);
assert_eq!(messages.len(), 1, "{messages:?}");
assert!(messages[0].contains("unsupported datasource provider"));
assert!(
!messages[0].contains("Rolle"),
"the per-declaration stage must not have run",
);
}
#[test]
fn a_stage_one_failure_stops_everything() {
let source = r#"datasource db {
provider = "postgresql"
}
model User {
id Int @id
role Rolle
}
model User {
id Int @id
}
"#;
let messages = diagnostics(source);
assert_eq!(messages.len(), 1, "{messages:?}");
assert!(messages.iter().all(|message| !message.contains("Rolle")));
}
#[test]
fn a_valid_schema_reports_nothing_and_returns_the_schema() {
let source = r#"datasource db {
provider = "postgresql"
}
model User {
id Int @id
}
"#;
let (schema, errors) = parse_schema_diagnostics("t.cstack", source);
assert!(errors.is_empty(), "{errors:?}");
assert_eq!(schema.expect("schema should parse").models.len(), 1);
}
#[test]
fn each_collected_error_keeps_its_own_position() {
let (_, errors) = parse_schema_diagnostics("t.cstack", THREE_UNKNOWN_TYPES);
let lines = errors.iter().map(|error| error.line()).collect::<Vec<_>>();
assert_eq!(lines.len(), 3);
assert!(
lines.windows(2).all(|pair| pair[0] < pair[1]),
"expected three distinct, increasing positions, got {lines:?}",
);
}