#![allow(clippy::unwrap_used, clippy::expect_used, clippy::needless_collect)]
use omni_dev::atlassian::adf::AdfDocument;
use omni_dev::atlassian::adf_schema::{
permits_child, validate_document, AdfSchemaViolation, Quantifier, SCHEMA_VERSION,
};
#[test]
fn schema_version_constant_is_populated() {
assert!(!SCHEMA_VERSION.is_empty());
}
#[test]
fn well_formed_document_has_no_violations() {
let json = r#"{
"version": 1,
"type": "doc",
"content": [
{"type": "paragraph", "content": [{"type": "text", "text": "hello"}]},
{"type": "heading", "attrs": {"level": 1}, "content": [{"type": "text", "text": "world"}]}
]
}"#;
let doc = AdfDocument::from_json_str(json).unwrap();
assert_eq!(validate_document(&doc), vec![]);
}
#[test]
fn expand_inside_panel_is_flagged_via_public_api() {
let json = r#"{
"version": 1,
"type": "doc",
"content": [
{
"type": "panel",
"attrs": {"panelType": "info"},
"content": [
{
"type": "expand",
"attrs": {"title": "details"},
"content": [
{"type": "paragraph", "content": [{"type": "text", "text": "x"}]}
]
}
]
}
]
}"#;
let doc = AdfDocument::from_json_str(json).unwrap();
let violations = validate_document(&doc);
let disallowed: Vec<&AdfSchemaViolation> = violations
.iter()
.filter(|v| matches!(v, AdfSchemaViolation::DisallowedChild { .. }))
.collect();
assert_eq!(disallowed.len(), 1);
match disallowed[0] {
AdfSchemaViolation::DisallowedChild {
child_type,
parent_type,
path,
} => {
assert_eq!(child_type, "expand");
assert_eq!(parent_type, "panel");
assert_eq!(path, &vec![0_usize, 0]);
}
other => unreachable!("filtered to DisallowedChild, got {other:?}"),
}
}
#[test]
fn empty_bullet_list_flagged_arity_via_public_api() {
let json = r#"{
"version": 1,
"type": "doc",
"content": [
{"type": "bulletList", "content": []}
]
}"#;
let doc = AdfDocument::from_json_str(json).unwrap();
let violations = validate_document(&doc);
assert_eq!(violations.len(), 1);
match &violations[0] {
AdfSchemaViolation::Arity {
parent_type,
atoms,
expected,
actual,
path,
} => {
assert_eq!(parent_type, "bulletList");
assert_eq!(atoms, &vec!["listItem"]);
assert_eq!(expected, &Quantifier::OneOrMore);
assert_eq!(*actual, 0);
assert_eq!(path, &vec![0_usize]);
}
other => panic!("expected Arity, got {other:?}"),
}
}
#[test]
fn media_single_with_two_media_flagged_via_public_api() {
let json = r#"{
"version": 1,
"type": "doc",
"content": [
{
"type": "mediaSingle",
"content": [
{"type": "media", "attrs": {"id": "a", "type": "file", "collection": "x"}},
{"type": "media", "attrs": {"id": "b", "type": "file", "collection": "x"}}
]
}
]
}"#;
let doc = AdfDocument::from_json_str(json).unwrap();
let violations = validate_document(&doc);
let arity: Vec<&AdfSchemaViolation> = violations
.iter()
.filter(|v| matches!(v, AdfSchemaViolation::Arity { .. }))
.collect();
assert_eq!(arity.len(), 1, "got: {violations:?}");
match arity[0] {
AdfSchemaViolation::Arity {
parent_type,
expected,
actual,
..
} => {
assert_eq!(parent_type, "mediaSingle");
assert_eq!(expected, &Quantifier::Exactly(1));
assert_eq!(*actual, 2);
}
other => unreachable!("filtered to Arity, got {other:?}"),
}
}
#[test]
fn permits_child_is_callable_externally() {
assert!(permits_child("tableCell", "nestedExpand"));
assert!(!permits_child("tableCell", "expand"));
}
#[test]
fn invalid_panel_type_flagged_via_public_api() {
let json = r#"{
"version": 1,
"type": "doc",
"content": [
{
"type": "panel",
"attrs": {"panelType": "purple"},
"content": [{"type": "paragraph", "content": [{"type": "text", "text": "x"}]}]
}
]
}"#;
let doc = AdfDocument::from_json_str(json).unwrap();
let violations = validate_document(&doc);
let invalid = violations
.iter()
.filter(|v| matches!(v, AdfSchemaViolation::InvalidAttr { .. }))
.collect::<Vec<_>>();
assert_eq!(invalid.len(), 1, "got: {violations:?}");
let _ = &invalid;
match invalid[0] {
AdfSchemaViolation::InvalidAttr {
node_type,
attr_name,
..
} => {
assert_eq!(node_type, "panel");
assert_eq!(attr_name, "panelType");
}
other => unreachable!("filtered to InvalidAttr, got {other:?}"),
}
}
#[test]
fn missing_panel_type_flagged_via_public_api() {
let json = r#"{
"version": 1,
"type": "doc",
"content": [
{
"type": "panel",
"content": [{"type": "paragraph", "content": [{"type": "text", "text": "x"}]}]
}
]
}"#;
let doc = AdfDocument::from_json_str(json).unwrap();
let violations = validate_document(&doc);
let missing: Vec<&AdfSchemaViolation> = violations
.iter()
.filter(|v| matches!(v, AdfSchemaViolation::MissingAttr { .. }))
.collect();
assert_eq!(missing.len(), 1, "got: {violations:?}");
match missing[0] {
AdfSchemaViolation::MissingAttr {
node_type,
attr_name,
..
} => {
assert_eq!(node_type, "panel");
assert_eq!(attr_name, "panelType");
}
other => unreachable!("filtered to MissingAttr, got {other:?}"),
}
}
#[test]
fn code_mark_on_heading_text_flagged_via_public_api() {
let json = r#"{
"version": 1,
"type": "doc",
"content": [
{
"type": "heading",
"attrs": {"level": 2},
"content": [
{"type": "text", "text": "hi", "marks": [{"type": "code"}]}
]
}
]
}"#;
let doc = AdfDocument::from_json_str(json).unwrap();
let violations = validate_document(&doc);
let disallowed_marks: Vec<&AdfSchemaViolation> = violations
.iter()
.filter(|v| matches!(v, AdfSchemaViolation::DisallowedMark { .. }))
.collect();
assert_eq!(disallowed_marks.len(), 1, "got: {violations:?}");
match disallowed_marks[0] {
AdfSchemaViolation::DisallowedMark {
mark_type,
parent_type,
..
} => {
assert_eq!(mark_type, "code");
assert_eq!(parent_type, "heading");
}
other => unreachable!("filtered to DisallowedMark, got {other:?}"),
}
}
#[test]
fn link_mark_with_invalid_href_flagged_via_public_api() {
let json = r#"{
"version": 1,
"type": "doc",
"content": [
{
"type": "paragraph",
"content": [
{"type": "text", "text": "click",
"marks": [{"type": "link", "attrs": {"href": "not a url"}}]}
]
}
]
}"#;
let doc = AdfDocument::from_json_str(json).unwrap();
let violations = validate_document(&doc);
let invalid_marks: Vec<&AdfSchemaViolation> = violations
.iter()
.filter(|v| matches!(v, AdfSchemaViolation::InvalidMarkAttr { .. }))
.collect();
assert_eq!(invalid_marks.len(), 1, "got: {violations:?}");
}
#[test]
fn heading_level_out_of_range_flagged_via_public_api() {
let json = r#"{
"version": 1,
"type": "doc",
"content": [
{"type": "heading", "attrs": {"level": 7}, "content": [{"type": "text", "text": "x"}]}
]
}"#;
let doc = AdfDocument::from_json_str(json).unwrap();
let violations = validate_document(&doc);
let invalid: Vec<&AdfSchemaViolation> = violations
.iter()
.filter(|v| matches!(v, AdfSchemaViolation::InvalidAttr { .. }))
.collect();
assert_eq!(invalid.len(), 1, "got: {violations:?}");
}