This repository has no description
1use crate::grant::grant_set_cob;
2
3grant_set_cob! {
4 change = MembersChange,
5 cob = MembersCob,
6 state = Members,
7 type_name = "sh.tangled.knot.member",
8 add = add_member,
9 remove = remove_member,
10}
11
12#[cfg(test)]
13mod tests {
14 use knot_cob::{ChangePayload, Evaluate};
15 use knot_types::{AccountDid, ActorId, UnixSeconds};
16
17 use super::*;
18 use crate::grant::{Grant, Removal};
19
20 fn did(suffix: &str) -> AccountDid {
21 AccountDid::new(format!("did:plc:{suffix}")).unwrap()
22 }
23
24 fn grant(subject: &str, added_by: &str, at: i64) -> Grant {
25 Grant {
26 subject: did(subject),
27 added_by: did(added_by),
28 created_at: UnixSeconds::new(at),
29 }
30 }
31
32 fn fold(changes: Vec<MembersChange>) -> Members {
33 let author = ActorId::from_secp256k1(&[0x02; 33]);
34 changes
35 .into_iter()
36 .fold(MembersCob::initial(), |state, change| {
37 MembersCob::apply(state, change, &author)
38 })
39 }
40
41 #[test]
42 fn members_fold_add_then_remove() {
43 let state = fold(vec![
44 MembersChange::Add(grant("nel", "nel", 1)),
45 MembersChange::Add(grant("olaren", "nel", 2)),
46 MembersChange::Remove(Removal {
47 subject: did("nel"),
48 }),
49 ]);
50 assert!(state.contains(&did("olaren")));
51 assert!(!state.contains(&did("nel")));
52 assert_eq!(state.len(), 1);
53 }
54
55 #[test]
56 fn change_payload_roundtrips_through_dag_cbor() {
57 assert_eq!(MembersChange::TYPE, "sh.tangled.knot.member");
58 let change = MembersChange::Add(grant("nel", "olaren", 9));
59 let bytes = change.encode().unwrap();
60 assert_eq!(MembersChange::decode(&bytes).unwrap(), change);
61 }
62}