use trust_tasks_rs::{specs::acl::grant::v0_1 as grant, Payload, TrustTask, TypeUri};
#[test]
fn acl_grant_request_round_trips() {
let json = r#"{
"id": "4f3c9e2a-1b81-4d3e-9b51-7a3c89e3d1f2",
"type": "https://trusttasks.org/spec/acl/grant/0.1",
"issuer": "did:web:org.example",
"recipient": "did:web:maintainer.example",
"issuedAt": "2026-05-16T10:00:00Z",
"payload": {
"entry": {
"subject": "did:web:alice.example",
"role": "admin",
"label": "Alice — primary admin"
}
}
}"#;
let doc: TrustTask<grant::Payload> = serde_json::from_str(json).unwrap();
assert_eq!(doc.payload.entry.subject, "did:web:alice.example");
assert_eq!(&*doc.payload.entry.role, "admin");
assert_eq!(
doc.payload.entry.label.as_deref().map(String::as_str),
Some("Alice — primary admin")
);
assert_eq!(doc.type_uri, grant::Payload::type_uri());
assert_eq!(
grant::Payload::TYPE_URI,
"https://trusttasks.org/spec/acl/grant/0.1"
);
let rendered = serde_json::to_value(&doc).unwrap();
let expected: serde_json::Value = serde_json::from_str(json).unwrap();
assert_eq!(rendered, expected);
}
#[test]
fn acl_grant_response_round_trips() {
let json = r#"{
"id": "5e3c9e2a-1b81-4d3e-9b51-7a3c89e3d1f3",
"type": "https://trusttasks.org/spec/acl/grant/0.1#response",
"threadId": "4f3c9e2a-1b81-4d3e-9b51-7a3c89e3d1f2",
"issuer": "did:web:maintainer.example",
"recipient": "did:web:org.example",
"issuedAt": "2026-05-16T10:00:01Z",
"payload": {
"entry": {
"subject": "did:web:alice.example",
"role": "admin",
"label": "Alice — primary admin",
"createdAt": "2026-05-16T10:00:01Z",
"createdBy": "did:web:org.example"
}
}
}"#;
let doc: TrustTask<grant::Response> = serde_json::from_str(json).unwrap();
assert_eq!(&*doc.payload.entry.role, "admin");
assert_eq!(
doc.payload.entry.created_by.as_deref(),
Some("did:web:org.example")
);
assert!(doc.type_uri.is_response());
assert_eq!(doc.type_uri, grant::Response::type_uri());
assert_eq!(
grant::Response::TYPE_URI,
"https://trusttasks.org/spec/acl/grant/0.1#response"
);
}
#[test]
fn for_payload_pulls_type_uri_from_trait() {
let entry: grant::AclEntry = grant::AclEntry::builder()
.subject("did:web:alice.example")
.role("admin")
.try_into()
.expect("acl entry builder");
let payload: grant::Payload = grant::Payload::builder()
.entry(entry)
.try_into()
.expect("acl grant payload builder");
let doc = TrustTask::for_payload("req-1", payload);
assert_eq!(doc.type_uri, TypeUri::canonical("acl/grant", 0, 1).unwrap());
}
#[test]
fn the_builder_names_only_the_required_members() {
let entry: grant::AclEntry = grant::AclEntry::builder()
.subject("did:web:alice.example")
.role("admin")
.try_into()
.expect("acl entry builder");
let payload: grant::Payload = grant::Payload::builder()
.entry(entry)
.try_into()
.expect("acl grant payload builder");
let json = serde_json::to_value(&payload).expect("serialise");
assert_eq!(
json,
serde_json::json!({
"entry": { "subject": "did:web:alice.example", "role": "admin" }
})
);
}
#[test]
fn the_builder_reports_a_missing_required_member() {
let err = grant::AclEntry::try_from(grant::AclEntry::builder().role("admin"))
.expect_err("subject is required");
assert!(
err.to_string().contains("subject"),
"error should name the missing member, got: {err}"
);
}
#[test]
fn request_payload_names_the_response_type() {
fn response_uri<P: trust_tasks_rs::RequestPayload>() -> &'static str {
<P::Response as Payload>::TYPE_URI
}
assert_eq!(
response_uri::<grant::Payload>(),
"https://trusttasks.org/spec/acl/grant/0.1#response"
);
}