6 let set_up = "set_up", `Quick
, (fun () ->
7 Unix.chdir
"../../../test/"
10 let tc_err = "tc_err", `Quick
, (fun () ->
12 |> Ezjsonm.from_string
13 |> As2_vocab.Activitypub.Decode.obj
with
14 | Error
(e
: Decoders_ezjsonm.Decode.error
) ->
15 e
|> Format.asprintf
"%a" Decoders_ezjsonm.Decode.pp_error
16 |> check
string __LOC__
{|I tried the following decoders but they all failed
:
17 "core_obj" decoder
: Expected a
string, but got
[]
18 "core_obj event" decoder
:
19 Expected an
object with an attribute
"type", but got
[] |};
20 e
|> Decoders_ezjsonm.Decode.string_of_error
21 |> check
string __LOC__
{|I tried the following decoders but they all failed
:
22 "core_obj" decoder
: Expected a
string, but got
[]
23 "core_obj event" decoder
:
24 Expected an
object with an attribute
"type", but got
[] |};
25 | _
-> failwith __LOC__
27 (* diaspora profile json e.g.
29 https://pod.diaspora.software/u/hq
30 https://pod.diaspora.software/people/7bca7c80311b01332d046c626dd55703
34 let tc_person = "tc_person", `Quick
, (fun () ->
35 let empty : As2_vocab.Types.person
= {
46 manually_approves_followers
= false;
49 preferred_username
= None
;
50 preferred_username_map
= [];
55 signatureAlgorithm
= None
;
57 published
= Some
Ptime.epoch
;
62 let base = (Uri.of_string
"https://example.com/su/") in
63 let lang = As2_vocab.Constants.ActivityStreams.und
in
64 {empty with id
=Uri.make ~path
:"id/" ()}
65 |> As2_vocab.Encode.person ~
lang ~
base
66 |> Ezjsonm.value_to_string ~minify
:false
67 |> check
string __LOC__
{|{
69 "https://www.w3.org/ns/activitystreams",
70 "https://w3id.org/security/v1",
72 "schema": "http://schema.org#",
73 "PropertyValue": "schema:PropertyValue",
74 "value": "schema:value",
79 "id": "https://example.com/su/id/",
80 "inbox": "https://example.com/su/",
81 "outbox": "https://example.com/su/",
88 "id": "https://example.com/su/",
91 "published": "1970-01-01T00:00:00Z",
92 "manuallyApprovesFollowers": false,
97 "https://www.w3.org/ns/activitystreams",
98 "https://w3id.org/security/v1",
100 "schema": "http://schema.org#",
101 "PropertyValue": "schema:PropertyValue",
102 "value": "schema:value",
107 "id": "https://example.com/su/id/",
108 "inbox": "https://example.com/su/",
109 "outbox": "https://example.com/su/",
111 "id": "https://example.com/su/",
112 "owner": "https://example.com/su/",
115 "published": "1970-01-01T00:00:00Z",
116 "manuallyApprovesFollowers": false,
117 "discoverable": false,
120 |> Ezjsonm.value_from_string
121 |> As2_vocab.Decode.person
125 |> check
string __LOC__
"https://example.com/su/id/"
128 let tc_actor_3rd = "tc_actor_3rd", `Quick
, (fun () ->
129 Logr.info
(fun m
-> m
"%s.%s" "As2_vocab" "actor_3rd");
131 let j = fn
|> File.in_channel
Ezjsonm.from_channel
in
132 let p = j |> As2_vocab.Decode.person
|> Result.get_ok
in
133 p.name
|> Option.get
|> check
string loc na
135 let j = fn
|> File.in_channel
Ezjsonm.from_channel
in
136 let p = j |> As2_vocab.Decode.person
|> Result.get_ok
in
137 p.id
|> Uri.to_string
|> check
string loc
(id
)
139 let j = fn
|> File.in_channel
Ezjsonm.from_channel
in
140 j |> As2_vocab.Decode.person
|> Result.get_error
141 |> Decoders_ezjsonm.Decode.string_of_error
142 |> check
string loc e
144 let j = fn
|> File.in_channel
Ezjsonm.from_channel
in
145 assert (j |> As2_vocab.Decode.person
|> Result.is_error
)
147 (* ok __LOC__ "data/ap/actor/lemmy.0.json" ""; *)
148 ok __LOC__
"data/ap/actor/akkoma.0.json" "Sean Tilley";
149 ok __LOC__
"data/ap/actor/akkoma.1.json" "Kinetix";
150 ok __LOC__
"data/ap/actor/bonfire.0.json" "stpaultim";
151 ok __LOC__
"data/ap/actor/bridgy.0.json" "Tantek รelik";
152 ok __LOC__
"data/ap/actor/friendica.0.json" "Michael Vogel";
153 ok __LOC__
"data/ap/actor/gnusocial.0.json" "Diogo Peralta Cordeiro";
154 ok __LOC__
"data/ap/actor/gnusocial.1.json" "admin de gnusocial.net";
155 ok __LOC__
"data/ap/actor/gnusocial.2.json" "diogo";
156 ok __LOC__
"data/ap/actor/gotosocial.0.json" "Gerben";
157 ok __LOC__
"data/ap/actor/gotosocial.1.json" "Gerben";
158 oki __LOC__
"data/ap/actor/gotosocial.1b.json" "https://social.nlnet.nl/users/gerben";
159 ok __LOC__
"data/ap/actor/honk.0.json" "boyter";
160 ok __LOC__
"data/ap/actor/mastodon.0.json" "Yet Another #Seppo! ๐ป";
161 ok __LOC__
"data/ap/actor/mastodon.1.json" "#Seppo";
162 ok __LOC__
"data/ap/actor/mastodon.2.json" "Marcus Rohrmoser ๐";
163 ok __LOC__
"data/ap/actor/mini.0.json" "Yet Another #Seppo! ๐ป";
164 ok __LOC__
"data/ap/actor/misskey.0.json" "ใใ
ใใ";
165 ok __LOC__
"data/ap/actor/peertube.0.json" "edps";
166 ok __LOC__
"data/ap/actor/peertube.1.json" {|Q3 Marcus
|};
167 ok __LOC__
"data/ap/actor/peertube.2.json" {|edps
|};
168 ok __LOC__
"data/ap/actor/peertube.3.json" {|Framasoft
|};
169 ok __LOC__
"data/ap/actor/pixelfed.0.json" {|#Seppo
|};
170 ok __LOC__
"data/ap/actor/pleroma.0.json" "@fediverse@mro.name";
171 ok __LOC__
"data/ap/actor/smithereen.0.json" {|ะัะธะณะพัะธะน ะะปััะฝะธะบะพะฒ
|};
172 ok __LOC__
"data/ap/actor/snac.0.json" {|The Real Grunfink
|};
173 ok __LOC__
"data/ap/actor/threads.0.json" "Ben Savage";
174 ok __LOC__
"data/ap/actor/tootik.0.json" {|EOIN GAIRLEOG
|};
175 ok __LOC__
"data/ap/actor/zap.0.json" "mike";
176 ok __LOC__
"data/ap/profile/@actapopuli@fediverse.blog.json" "actapopuli";
177 ok __LOC__
"data/ap/profile/@administrator@gnusocial.net.json" {|admin de gnusocial
.net
|};
178 ok __LOC__
"data/ap/profile/@dansup@pixelfed.social.json" {|dansup
|};
179 ok __LOC__
"data/ap/profile/@gargron@mastodon.social.json" {|Eugen Rochko
|};
180 ok __LOC__
"data/ap/profile/@kainoa@calckey.social.json" {|Kainoa
|};
181 ok __LOC__
"data/ap/profile/@karolat@stereophonic.space.json" {|karolat
|};
182 ok __LOC__
"data/ap/profile/@manton@manton.org.json" {|Manton Reece
|};
183 ok __LOC__
"data/ap/profile/@matt@write.as.json" {|Matt
|};
184 ok __LOC__
"data/ap/profile/@mike@macgirvin.com.json" {|Mike Macgirvin
|};
185 ok __LOC__
"data/ap/profile/@peertube@framapiaf.org.json" {|PeerTube
|};
186 ok __LOC__
"data/ap/profile/@syuilo@misskey.io.json" {|:peroro_sama
:ใใ
ใใ
:peroro_sama
:|};
187 ok __LOC__
"data/ap/profile/@tobias@friendi.ca.json" {|Tobias
|};
189 err __LOC__ "data/ap/actor/gotosocial.1b.json" {|Expected an object with an attribute "inbox", but got
190 {"@context":["https://www.w3.org/ns/activitystreams","https://w3id.org/security/v1"],"id":"https://social.nlnet.nl/users/gerben","preferredUsername":"gerben","publicKey":{"id":"https://social.nlnet.nl/users/gerben/main-key","owner":"https://social.nlnet.nl/users/gerben","publicKeyPem":"-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA35UDYAz/pgrIi4O1UDf9\n9W1RnEPVtj730gfujlIQtzWIsBs/8n6zQbK0QBtRSYKhwzkUDMpNUh+Mm/CONjKI\nSwps6mEknlmi3VbyviGYs7LX7SuJAfLIl1hT2eftXQLObKgzkbUcVbS0zwNlBeIX\nPJpHyAVphuI4a02Be458g3y3nSK7Imb4dN2GUhLX2FDOZ6s/EC9HcglZiiz+9hI2\n0Rb4tXjsjbBXe6ofowdXDPmD20Al3v816m4kYfgGmLK86ItFGj8u+hoK8tcC0yWk\ni7KUL3bg9iqp7wBhkjTZ/vVVIf7RG8q2gPRe1BVsi+GBDmV7dmupgicT6UbmAi5h\nTwIDAQAB\n-----END PUBLIC KEY-----\n"},"type":"Person"}|};
192 err __LOC__
"data/ap/actor/friendica.1.json" {|I tried the following decoders but they all failed
:
195 expected Person
(received Organization
), but got
"Organization"
198 expected Service
(received Organization
), but got
"Organization" |};
199 err __LOC__
"data/ap/profile/@lemmy_support@lemmy.ml.json" {|I tried the following decoders but they all failed
:
201 in field
"type": expected Person
(received Group
), but got
"Group"
203 in field
"type": expected Service
(received Group
), but got
"Group" |};
204 err __LOC__
"data/ap/actor/mobilizon.0.json" {|I tried the following decoders but they all failed
:
206 in field
"type": expected Person
(received Group
), but got
"Group"
208 in field
"type": expected Service
(received Group
), but got
"Group" |};
209 fal __LOC__
"data/ap/actor/diaspora.0.json";
212 ok __LOC__ "data/ap/actor/natur.0.json" "ใใ
ใใ";
213 ok __LOC__ "data/ap/actor/natur.1.json" "ใใ
ใใ";
214 ok __LOC__ "data/ap/actor/sharkey.0.json" {||};
215 ok __LOC__ "data/ap/actor/sharkey.1.json" {||};
217 ok __LOC__ "data/ap/profile/@framasoft@mobilizon.fr.json" {||};
218 ok __LOC__ "data/ap/profile/@Greensky@open.audio.json" {||};
222 let tc_actor_decode = "tc_actor_decode", `Quick
, (fun () ->
223 let fn = "data/ap/actor/peertube.3.json" in
224 let j = fn |> File.in_channel
Ezjsonm.from_channel
in
225 let p = j |> As2_vocab.Decode.person
|> Result.get_ok
in
226 p.name
|> Option.get
|> check
string __LOC__
"Framasoft";
227 p.icon
|> List.length
|> check
int __LOC__
2;
231 let tc_actor_encode = "tc_actor_encode", `Quick
, (fun () ->
236 let s = "data/ap/actor/peertube.3.json"
237 |> File.in_channel
Ezjsonm.from_channel
238 |> As2_vocab.Decode.person
|> Result.get_ok
239 |> As2_vocab.Encode.person ~
base ~
lang
240 |> Ezjsonm.value_to_string ~minify
in
248 "id": "https://framatube.org/accounts/framasoft",
249 "inbox": "https://framatube.org/accounts/framasoft/inbox",
250 "outbox": "https://framatube.org/accounts/framasoft/outbox",
251 "followers": "https://framatube.org/accounts/framasoft/followers",
252 "following": "https://framatube.org/accounts/framasoft/following",
254 "url": "https://framatube.org/accounts/framasoft",
255 "preferredUsername": "framasoft",
262 "id": "https://framatube.org/accounts/framasoft#main-key",
263 "owner": "https://framatube.org/accounts/framasoft",
264 "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuRh3frgIg866D0y0FThp\nSUkJImMcHGkUvpYQYv2iUgarZZtEbwT8PfQf0bJazy+cP8KqQmMDf5PBhT7dfdny\nf/GKGMw9Olc+QISeKDj3sqZ3Csrm4KV4avMGCfth6eSU7LozojeSGCXdUFz/8UgE\nfhV4mJjEX/FbwRYoKlagv5rY9mkX5XomzZU+z9j6ZVXyofwOwJvmI1hq0SYDv2bc\neB/RgIh/H0nyMtF8o+0CT42FNEET9j9m1BKOBtPzwZHmitKRkEmui5cK256s1laB\nT61KHpcD9gQKkQ+I3sFEzCBUJYfVo6fUe+GehBZuAfq4qDhd15SfE4K9veDscDFI\nTwIDAQAB\n-----END PUBLIC KEY-----"
266 "published": "2018-03-01T15:16:17Z",
267 "manuallyApprovesFollowers": false,
268 "discoverable": false,
272 "url": "https://framatube.org/lazy-static/avatars/1dbda4f0-1f7f-40f2-b962-85fd0c144661.png"
276 "url": "https://framatube.org/lazy-static/avatars/f73876f5-1d45-4f8a-942a-d3d5d5ac5dc1.png"
282 let tc_actor_encode_issue35 = "tc_actor_encode", `Quick
, (fun () ->
284 and url
= [ "https://example.com" |> Uri.of_string
]
287 | (_
, None
) -> fun _
-> []
288 | (field
, Some vl
) -> fun ty
-> [field
, ty vl
] in
289 let (@?
.) field vl
= (field
, match vl
with | [] -> None
| l
-> Some l
) in
290 let list (a
: 'a
Decoders_ezjsonm.Encode.encoder
) (b
: 'a
list) : Ezjsonm.value = match b
with
291 | [] -> Decoders_ezjsonm.Encode.null
(* none => omit *)
292 | [b
] -> Decoders_ezjsonm.Encode.encode_value a b
(* single => value *)
293 | b
-> Decoders_ezjsonm.Encode.list a b
in
294 let uri ~
base u
= u
|> Uri.resolve
"https" base |> Uri.to_string
|> Decoders_ezjsonm.Encode.string in
296 "url" @?
. url
<: list (uri ~
base);
299 |> Ezjsonm.value_to_string
300 |> check
string __LOC__
{|"https://example.com"|}
304 let tc_note_decode = "tc_note_dcode", `Quick
, (fun () ->
305 let j = "data/ap/note/mastodon.json" |> File.in_channel
Ezjsonm.from_channel
in
306 let n = j |> As2_vocab.Decode.note
|> Result.get_ok
in
307 n.id
|> Uri.to_string
|> check
string __LOC__
"https://digitalcourage.social/users/mro/statuses/111403080326863922";
308 (match n.in_reply_to
with
309 | [u
] -> u
|> Uri.to_string
|> check
string __LOC__
"https://chaos.social/users/qyliss/statuses/111403054651938519"
310 | _
-> failwith
"none");
311 let n = "data/ap/inbox/create/note/akkoma.json" |> File.in_channel
Ezjsonm.from_channel
312 |> As2_vocab.Decode.(create note
) |> Result.get_ok
in
313 let _,co
= n.obj
.content_map
|> List.hd
in
315 |> Assrt.equals_string __LOC__
316 {|<p>Oh yeah
! Also
: trying
to flip the pencil over
to use an eraser doesnโt work
. You have
to select an eraser first
. </p><p>What the fuck? My shitty Wacom Bamboo tablet
from ten years ago can
do that
!</p>|}
319 let tc_create_article_decode = "tc_create_article_decode", `Quick
, (fun () ->
320 "data/ap/inbox/create/article/friendica.json"
321 |> File.in_channel
Ezjsonm.from_channel
322 |> As2_vocab.Decode.(create note
) |> Result.get_error
323 |> Decoders_ezjsonm.Decode.string_of_error
324 |> check
string __LOC__
"in field \"object\":\n in field \"type\": expected Note (received Article), but got \"Article\""
327 let tc_reject_decode = "tc_reject_decode", `Quick
, (fun () ->
328 Logr.info
(fun m
-> m
"%s.%s" "As2_vocab" "reject_decode");
329 let j = "data/ap/inbox/reject/follow/2024-08-17-124924-steve.json" |> File.in_channel
Ezjsonm.from_channel
in
330 let n = j |> As2_vocab.Decode.(reject follow
) |> Result.get_ok
in
333 |> check
string __LOC__
{|https
://social
.technoetic
.com
/users
/steve#rejects
/follows
/|};
336 |> check
string __LOC__
{|https
://social
.technoetic
.com
/users
/steve#subscribe
|}
339 let tc_webfinger_sunshine = "tc_webfinger_sunshine", `Quick
, (fun () ->
340 let q = "data/webfinger/mini.json" |> File.in_channel
Ezjsonm.from_channel
341 |> As2_vocab.Activitypub.Decode.Webfinger.query_result
343 q.subject
|> check
string __LOC__
"acct:ursi@example.com";
344 q.links
|> List.length
|> check
int __LOC__
3;
345 let q = "data/webfinger/zap.json" |> File.in_channel
Ezjsonm.from_channel
346 |> As2_vocab.Activitypub.Decode.Webfinger.query_result
348 q.subject
|> check
string __LOC__
"acct:mike@macgirvin.com";
349 q.links
|> List.length
|> check
int __LOC__
3;
350 let q = "data/webfinger/atom.json" |> File.in_channel
Ezjsonm.from_channel
351 |> As2_vocab.Activitypub.Decode.Webfinger.query_result
353 q.subject
|> check
string __LOC__
"acct:ursi@example.com";
354 q.links
|> List.length
|> check
int __LOC__
3
357 let tc_profile_sunshine = "tc_profile_sunshine", `Quick
, (fun () ->
358 let q = "data/ap/actor/mini.0.json" |> File.in_channel
Ezjsonm.from_channel
359 |> As2_vocab.Activitypub.Decode.person
361 q.name
|> Option.get
|> check
string __LOC__
"Yet Another #Seppo! ๐ป";
362 q.preferred_username
|> Option.get
|> check
string __LOC__
"ursi";
363 q.attachment
|> List.length
|> check
int "" 0;
364 let q = "data/ap/actor/mastodon.0.json" |> File.in_channel
Ezjsonm.from_channel
365 |> As2_vocab.Activitypub.Decode.person
367 (match q.attachment
with
369 a
.name
|> check
string __LOC__
"Support";
370 b
.value |> check
string __LOC__
{|<a href
="https://seppo.social">Seppo.Social
</a
>|};
371 | _ -> check
int "" 0 1
373 q.image
|> Option.get
|> Uri.to_string
|> check
string __LOC__
"https://example.com/me-banner.jpg";
374 "" |> check
string __LOC__
"";
375 let q = "data/ap/actor/akkoma.0.json" |> File.in_channel
Ezjsonm.from_channel
376 |> As2_vocab.Activitypub.Decode.person
378 q.name
|> Option.get
|> check
string __LOC__
"Sean Tilley";
379 let q = "data/ap/actor/gnusocial.0.json" |> File.in_channel
Ezjsonm.from_channel
380 |> As2_vocab.Activitypub.Decode.person
382 q.preferred_username
|> Option.get
|> check
string __LOC__
"diogo";
383 let q = "data/ap/actor/lemmy.0.json" |> File.in_channel
Ezjsonm.from_channel
384 |> As2_vocab.Activitypub.Decode.person
386 q.preferred_username
|> Option.get
|> check
string __LOC__
"nutomic";
387 let q = "data/ap/actor/mastodon.0.json" |> File.in_channel
Ezjsonm.from_channel
388 |> As2_vocab.Activitypub.Decode.person
390 q.preferred_username
|> Option.get
|> check
string __LOC__
"ursi";
391 let q = "data/ap/actor/peertube.0.json" |> File.in_channel
Ezjsonm.from_channel
392 |> As2_vocab.Activitypub.Decode.person
394 q.preferred_username
|> Option.get
|> check
string __LOC__
"edps";
395 let q = "data/ap/actor/zap.0.json" |> File.in_channel
Ezjsonm.from_channel
396 |> As2_vocab.Activitypub.Decode.person
398 q.preferred_username
|> Option.get
|> check
string __LOC__
"mike";
399 let q = "data/ap/actor/bridgy.0.json" |> File.in_channel
Ezjsonm.from_channel
400 |> As2_vocab.Activitypub.Decode.person
402 q.preferred_username
|> Option.get
|> check
string __LOC__
"tantek.com";
406 let tc_encode = "tc_encode", `Quick
, (fun () ->
407 let minify = false in
408 let base = Uri.of_string
"http://example.com/foo/" in
409 let module E
= Decoders_ezjsonm.Encode
in
410 E.encode_string
E.obj
[("k", `String
"v")]
411 |> check
string __LOC__
{|{"k":"v"}|};
412 Ezjsonm.value_to_string
(E.obj
[("k", `String
"v")])
413 |> check
string __LOC__
{|{"k":"v"}|};
415 let e = {Rfc4287.Entry.empty with
416 id
= Uri.make ~path
:"a/b/" ?fragment
:(Some
"c") ();
417 lang = Rfc4287.Rfc4646
"de";
419 published
= (Rfc3339.T
"2023-03-07T01:23:45Z") ;
420 updated
= (Rfc3339.T
"2023-03-07T01:23:46Z");
422 ((Label
(Single
"lbl")),(Term
(Single
"term")),Uri.make ~path
:"t/" ());
424 content
= "Das war aber einfach";
426 let n = e |> Ap.Note.of_rfc4287
in
427 let j = n |> As2_vocab.Encode.note ~
base in
428 j |> Ezjsonm.value_to_string ~
minify
429 |> Assrt.equals_string __LOC__
432 "id": "http://example.com/foo/a/b/#c",
433 "attributedTo": "http://example.com/foo/activitypub/actor.jsa",
434 "to": "https://www.w3.org/ns/activitystreams#Public",
435 "cc": "http://example.com/foo/activitypub/subscribers/index.jsa",
436 "mediaType": "text/plain; charset=utf8",
438 "de": "Das war aber einfach"
444 "published": "2023-03-07T01:23:45Z",
447 "href": "http://example.com/foo/t/term/",
452 let co : 'a
As2_vocab.Types.collection_page
= {
453 id
= Uri.of_string
"http://example.com/foo/";
457 items
= [Ap.Note.Create.make
n];
464 let j = As2_vocab.Encode.collection_page ~
base
465 (As2_vocab.Encode.create ~
base
466 (As2_vocab.Encode.note ~
base))
468 j |> Ezjsonm.value_to_string ~
minify
469 |> Assrt.equals_string __LOC__
{|{
471 "https://www.w3.org/ns/activitystreams",
472 "https://w3id.org/security/v1",
474 "schema": "http://schema.org#",
475 "PropertyValue": "schema:PropertyValue",
476 "value": "schema:value",
480 "type": "OrderedCollectionPage",
481 "id": "http://example.com/foo/",
485 "id": "http://example.com/foo/a/b/#c/Create",
486 "actor": "http://example.com/foo/activitypub/actor.jsa",
487 "published": "2023-03-07T01:23:45Z",
488 "to": "https://www.w3.org/ns/activitystreams#Public",
489 "cc": "http://example.com/foo/activitypub/subscribers/index.jsa",
490 "directMessage": false,
493 "id": "http://example.com/foo/a/b/#c",
494 "attributedTo": "http://example.com/foo/activitypub/actor.jsa",
495 "to": "https://www.w3.org/ns/activitystreams#Public",
496 "cc": "http://example.com/foo/activitypub/subscribers/index.jsa",
497 "mediaType": "text/plain; charset=utf8",
499 "de": "Das war aber einfach"
505 "published": "2023-03-07T01:23:45Z",
508 "href": "http://example.com/foo/t/term/",
518 (* https://www.w3.org/TR/activitystreams-core/#ex17-jsonld *)
519 let tc_ex15_note = "tc_ex15_note", `Quick
, (fun () ->
520 let j = "data/ap/note/as2_core.ex15.json" |> File.in_channel
Ezjsonm.value_from_channel
in
525 "type", `String
"Create" ;
528 "type", `String
"Note" ;
531 | _ -> assert false);
533 |> As2_vocab.Decode.(create note
)
534 |> Result.is_error
in
538 _p.obj.summary |> Option.get |> check string "" "";
541 (* https://github.com/mattjbray/ocaml-decoders *)
542 type role
= Admin
| User
549 let tc_example= "tc_exampl", `Quick
, (fun () ->
550 Logr.info
(fun m
-> m
"%s.%s" "As2_vocab" "example");
551 let module My_encoders
(E
: Decoders.Encode.S
) = struct
554 let user : role encoder
=
556 | Admin
-> string "ADMIN"
557 | User
-> string "USER"
559 let user : user encoder
=
562 [ ("name", string u
.lang)
563 ; ("roles", list user u
.txt
)
566 let module E
= Decoders_ezjsonm.Encode
in
567 let module My_ezjson_encoders
= My_encoders
(Decoders_ezjsonm.Encode
) in
568 let open My_ezjson_encoders
in
570 [ {lang = "Alice"; txt
= [Admin
; User
]}
571 ; {lang = "Bob"; txt
= [User
]}
573 E.encode_string
E.obj
[("users", E.list user users)]
574 |> check
string __LOC__
{|{"users":[{"name":"Alice","roles":["ADMIN","USER"]},{"name":"Bob","roles":["USER"]}]}|}
582 let tc_encode_content_map = "tc_encode_content_map", `Quick
, (fun () ->
583 Logr.info
(fun m
-> m
"%s.%s" "As2_vocab" "encode_content_map");
584 let l = [("a","A");("b","B")] in
585 let module E
= Decoders_ezjsonm.Encode
in
586 let j = l |> List.map
(fun (k
,v
) -> (k
,E.string v
)) in
587 E.encode_string
E.obj
j
588 |> check
string __LOC__
{|{"a":"A","b":"B"}|}
591 let tc_decode_content_map = "tc_decode_content_map", `Quick
, (fun () ->
592 Logr.info
(fun m
-> m
"%s.%s" "As2_vocab" "decode_content_map");
593 let s = Ezjsonm.value_from_string
{|{"a":"A","b":"B"}|} in
594 let module D
= Decoders_ezjsonm.Decode
in
595 let l = D.key_value_pairs
D.string s
598 | [("a","A");("b","B")] -> ()
599 | _ -> "" |> check
string __LOC__
{|{"a":"A","b":"B"}|});
600 let s = Ezjsonm.value_from_string
{|{"contentMap":{"a":"A","b":"B","b":"C"}}|} in
601 let l = D.field
"contentMap" (D.key_value_pairs
D.string) s
604 | [("a","A");("b","B");("b","C")] -> ()
605 | _ -> "" |> check
string __LOC__
{|{"a":"A","b":"B"}|}
608 let tc_decode_natur = "tc_decode_natur", `Quick
, (fun () ->
609 (* https://codeberg.org/seppo/seppo/issues/5 *)
610 Logr.info
(fun m
-> m
"%s.%s" "As2_vocab" "decode_natur");
611 let j = "data/ap/actor/natur.0.json" |> File.in_channel
Ezjsonm.from_channel
in
612 let e = j |> As2_vocab.Decode.person
|> Result.get_error
in
613 let s = e |> Decoders_ezjsonm.Decode.string_of_error
in
614 s |> check
string __LOC__
{|Expected an
object with an attribute
"publicKey", but got
615 {"id":"https://dev.rdf-pub.org/d613b246-8984-4654-903d-8d44143aca40","type":"Person","inboxSparql":"https://dev.rdf-pub.org/d613b246-8984-4654-903d-8d44143aca40/inbox/sparql","rdfpub:oauth2Issuer":"https://login.m4h.network/auth/realms/LOA","rdfpub:oauth2IssuerPreferredUserName":"max@login.m4h.network","rdfpub:oauth2IssuerUserId":"1813bdc1-152c-4c27-92a6-6cdfe401ef3d@login.m4h.network","outboxSparql":"https://dev.rdf-pub.org/d613b246-8984-4654-903d-8d44143aca40/outbox/sparql","identifier":"52ff7eb2-0b7c-4388-9894-b40a27714c1b","version":{"type":"xsd:integer","@value":"1"},"owl:sameAs":{"id":"https://dev.rdf-pub.org/05a75688-c517-4ae1-842c-5da3d8460627"},"inbox":"https://dev.rdf-pub.org/d613b246-8984-4654-903d-8d44143aca40/inbox","endpoints":{"oauthAuthorizationEndpoint":"https://dev.rdf-pub.org/oauth/oauthAuthorizationEndpoint","oauthTokenEndpoint":"https://dev.rdf-pub.org/oauth/oauthTokenEndpoint"},"name":"max","outbox":"https://dev.rdf-pub.org/d613b246-8984-4654-903d-8d44143aca40/outbox","published":"2024-01-14T15:59:42.102+01:00","@context":["https://schema.org/docs/jsonldcontext.json","https://rdf-pub.org/schema/rdf-pub-context.json","https://www.w3.org/ns/activitystreams"]}|}
618 let tc_decode_sharkey= "tc_decode_sharke", `Quick
, (fun () ->
619 (* https://joinsharkey.org *)
620 Logr.info
(fun m
-> m
"%s.%s" "As2_vocab" "decode_sharkey");
621 let j = "data/ap/actor/sharkey.0.json" |> File.in_channel
Ezjsonm.from_channel
in
622 let p = j |> As2_vocab.Decode.person
|> Result.get_ok
in
624 |> Option.value ~default
:"-"
625 |> check
string __LOC__
{|-|};
626 ("data/ap/actor/sharkey.1.json" |> File.in_channel
Ezjsonm.from_channel
627 |> As2_vocab.Decode.person
630 |> Option.value ~default
:"-"
631 |> check
string __LOC__
{|wakest the shark possum
|}
642 tc_actor_encode_issue35;
645 tc_create_article_decode;
649 tc_webfinger_sunshine;
653 tc_encode_content_map;
654 tc_decode_content_map;