My agentic slop goes here. Not intended for anyone else!
1(** Tests for the Sortal library *)
2
3open Eio.Std
4
5let test_contact_creation () =
6 let c = Sortal.Contact.make
7 ~handle:"test"
8 ~names:["Test User"; "T. User"]
9 ~email:"test@example.com"
10 ~github:"testuser"
11 () in
12 assert (Sortal.Contact.handle c = "test");
13 assert (Sortal.Contact.name c = "Test User");
14 assert (List.length (Sortal.Contact.names c) = 2);
15 assert (Sortal.Contact.email c = Some "test@example.com");
16 assert (Sortal.Contact.github c = Some "testuser");
17 assert (Sortal.Contact.twitter c = None);
18 traceln "✓ Contact creation works"
19
20let test_best_url () =
21 let c1 = Sortal.Contact.make
22 ~handle:"test1"
23 ~names:["Test 1"]
24 ~url:"https://example.com"
25 ~github:"test1"
26 () in
27 assert (Sortal.Contact.best_url c1 = Some "https://example.com");
28
29 let c2 = Sortal.Contact.make
30 ~handle:"test2"
31 ~names:["Test 2"]
32 ~github:"test2"
33 () in
34 assert (Sortal.Contact.best_url c2 = Some "https://github.com/test2");
35
36 let c3 = Sortal.Contact.make
37 ~handle:"test3"
38 ~names:["Test 3"]
39 ~email:"test3@example.com"
40 () in
41 assert (Sortal.Contact.best_url c3 = Some "mailto:test3@example.com");
42
43 let c4 = Sortal.Contact.make
44 ~handle:"test4"
45 ~names:["Test 4"]
46 () in
47 assert (Sortal.Contact.best_url c4 = None);
48
49 traceln "✓ Best URL selection works"
50
51let test_json_encoding () =
52 let c = Sortal.Contact.make
53 ~handle:"json_test"
54 ~names:["JSON Test"]
55 ~email:"json@example.com"
56 ~github:"jsontest"
57 ~orcid:"0000-0001-2345-6789"
58 () in
59
60 match Jsont_bytesrw.encode_string Sortal.Contact.json_t c with
61 | Ok json_str ->
62 (match Jsont_bytesrw.decode_string Sortal.Contact.json_t json_str with
63 | Ok decoded ->
64 assert (Sortal.Contact.handle decoded = "json_test");
65 assert (Sortal.Contact.email decoded = Some "json@example.com");
66 assert (Sortal.Contact.github decoded = Some "jsontest");
67 assert (Sortal.Contact.orcid decoded = Some "0000-0001-2345-6789");
68 traceln "✓ JSON encoding/decoding works"
69 | Error err ->
70 failwith ("JSON decode failed: " ^ err))
71 | Error err ->
72 failwith ("JSON encode failed: " ^ err)
73
74let test_handle_generation () =
75 assert (Sortal.handle_of_name "John Smith" = "jssmith");
76 assert (Sortal.handle_of_name "Alice Barbara Cooper" = "abccooper");
77 assert (Sortal.handle_of_name "Bob" = "bbob");
78 traceln "✓ Handle generation works"
79
80let test_store_operations () =
81 Eio_main.run @@ fun env ->
82
83 (* Create a store with a test app name *)
84 let store = Sortal.create env#fs "sortal-test" in
85
86 (* Create test contacts *)
87 let c1 = Sortal.Contact.make
88 ~handle:"alice"
89 ~names:["Alice Anderson"]
90 ~email:"alice@example.com"
91 () in
92
93 let c2 = Sortal.Contact.make
94 ~handle:"bob"
95 ~names:["Bob Brown"; "Robert Brown"]
96 ~github:"bobbrown"
97 () in
98
99 (* Test save *)
100 Sortal.save store c1;
101 Sortal.save store c2;
102 traceln "✓ Saving contacts works";
103
104 (* Test lookup *)
105 (match Sortal.lookup store "alice" with
106 | Some c ->
107 assert (Sortal.Contact.name c = "Alice Anderson");
108 traceln "✓ Lookup works"
109 | None -> failwith "Lookup failed to find saved contact");
110
111 (* Test lookup of non-existent contact *)
112 (match Sortal.lookup store "nonexistent" with
113 | None -> traceln "✓ Lookup correctly returns None for missing contact"
114 | Some _ -> failwith "Lookup should return None for non-existent contact");
115
116 (* Test list *)
117 let all = Sortal.list store in
118 assert (List.length all >= 2);
119 traceln "✓ List returns saved contacts (%d total)" (List.length all);
120
121 (* Test find_by_name *)
122 let found = Sortal.find_by_name store "Bob Brown" in
123 assert (Sortal.Contact.handle found = "bob");
124 traceln "✓ Find by name works";
125
126 (* Test find_by_name_opt *)
127 (match Sortal.find_by_name_opt store "Alice Anderson" with
128 | Some c ->
129 assert (Sortal.Contact.handle c = "alice");
130 traceln "✓ Find by name (optional) works"
131 | None -> failwith "find_by_name_opt failed");
132
133 (match Sortal.find_by_name_opt store "Nobody" with
134 | None -> traceln "✓ Find by name (optional) returns None for missing"
135 | Some _ -> failwith "find_by_name_opt should return None");
136
137 (* Test delete *)
138 Sortal.delete store "alice";
139 (match Sortal.lookup store "alice" with
140 | None -> traceln "✓ Delete works"
141 | Some _ -> failwith "Contact should have been deleted");
142
143 (* Clean up remaining test contact *)
144 Sortal.delete store "bob";
145 traceln "✓ Test cleanup complete"
146
147let test_contact_compare () =
148 let c1 = Sortal.Contact.make ~handle:"alice" ~names:["Alice"] () in
149 let c2 = Sortal.Contact.make ~handle:"bob" ~names:["Bob"] () in
150 let c3 = Sortal.Contact.make ~handle:"alice" ~names:["Alice2"] () in
151
152 assert (Sortal.Contact.compare c1 c2 < 0);
153 assert (Sortal.Contact.compare c2 c1 > 0);
154 assert (Sortal.Contact.compare c1 c3 = 0);
155 traceln "✓ Contact comparison works"
156
157let test_urls () =
158 (* Test with only url set *)
159 let c1 = Sortal.Contact.make
160 ~handle:"test1"
161 ~names:["Test 1"]
162 ~url:"https://example.com"
163 () in
164 assert (Sortal.Contact.url c1 = Some "https://example.com");
165 assert (Sortal.Contact.urls c1 = ["https://example.com"]);
166
167 (* Test with only urls set *)
168 let c2 = Sortal.Contact.make
169 ~handle:"test2"
170 ~names:["Test 2"]
171 ~urls:["https://one.com"; "https://two.com"]
172 () in
173 assert (Sortal.Contact.url c2 = Some "https://one.com");
174 assert (Sortal.Contact.urls c2 = ["https://one.com"; "https://two.com"]);
175
176 (* Test with both url and urls set *)
177 let c3 = Sortal.Contact.make
178 ~handle:"test3"
179 ~names:["Test 3"]
180 ~url:"https://primary.com"
181 ~urls:["https://secondary.com"; "https://tertiary.com"]
182 () in
183 assert (Sortal.Contact.url c3 = Some "https://primary.com");
184 assert (Sortal.Contact.urls c3 = ["https://primary.com"; "https://secondary.com"; "https://tertiary.com"]);
185
186 (* Test with neither set *)
187 let c4 = Sortal.Contact.make
188 ~handle:"test4"
189 ~names:["Test 4"]
190 () in
191 assert (Sortal.Contact.url c4 = None);
192 assert (Sortal.Contact.urls c4 = []);
193
194 traceln "✓ URLs field works correctly"
195
196let () =
197 traceln "\n=== Running Sortal Tests ===\n";
198
199 test_contact_creation ();
200 test_best_url ();
201 test_json_encoding ();
202 test_handle_generation ();
203 test_contact_compare ();
204 test_urls ();
205 test_store_operations ();
206
207 traceln "\n=== All Tests Passed ===\n"