RFC6901 JSON Pointer implementation in OCaml using jsont
at main 5.9 kB view raw
1JMAP Extended JSON Pointer Tests (RFC 8620 Section 3.7) 2 3This tests the wildcard (*) extension to JSON Pointer for JMAP result references. 4 5Parsing JMAP extended pointers: 6 7Basic pointers (no wildcards, same as RFC 6901): 8 $ ./test_pointer.exe jmap-parse "" 9 OK: (root) 10 $ ./test_pointer.exe jmap-parse "/foo" 11 OK: /foo 12 $ ./test_pointer.exe jmap-parse "/foo/0" 13 OK: /foo/0 14 $ ./test_pointer.exe jmap-parse "/a~1b" 15 OK: /a~1b 16 17Wildcard pointers: 18 $ ./test_pointer.exe jmap-parse "/*" 19 OK: /* 20 $ ./test_pointer.exe jmap-parse "/list/*" 21 OK: /list/* 22 $ ./test_pointer.exe jmap-parse "/list/*/id" 23 OK: /list/*/id 24 $ ./test_pointer.exe jmap-parse "/list/*/emailIds" 25 OK: /list/*/emailIds 26 $ ./test_pointer.exe jmap-parse "/a/*/b/*/c" 27 OK: /a/*/b/*/c 28 29Error: "-" not allowed in JMAP pointers: 30 $ ./test_pointer.exe jmap-parse "/-" 31 ERROR: Invalid JMAP Pointer: '-' not supported in result reference paths 32 $ ./test_pointer.exe jmap-parse "/foo/-" 33 ERROR: Invalid JMAP Pointer: '-' not supported in result reference paths 34 35Error: Invalid syntax: 36 $ ./test_pointer.exe jmap-parse "foo" 37 ERROR: Invalid JMAP Pointer: must be empty or start with '/': foo 38 $ ./test_pointer.exe jmap-parse "/~" 39 ERROR: Invalid JSON Pointer: incomplete escape sequence at end 40 41Evaluation without wildcards: 42 43Root pointer: 44 $ ./test_pointer.exe jmap-eval '{"foo":"bar"}' "" 45 OK: {"foo":"bar"} 46 47Simple member access: 48 $ ./test_pointer.exe jmap-eval '{"foo":"bar"}' "/foo" 49 OK: "bar" 50 51Array index: 52 $ ./test_pointer.exe jmap-eval '{"arr":[1,2,3]}' "/arr/1" 53 OK: 2 54 55Nested access: 56 $ ./test_pointer.exe jmap-eval '{"a":{"b":{"c":"deep"}}}' "/a/b/c" 57 OK: "deep" 58 59Evaluation with wildcards (RFC 8620 examples): 60 61Extract single field from each object in array: 62 $ ./test_pointer.exe jmap-eval '{"list":[{"id":"a"},{"id":"b"},{"id":"c"}]}' "/list/*/id" 63 OK: ["a","b","c"] 64 65Extract threadId from Email/get response (RFC 8620 pattern): 66 $ ./test_pointer.exe jmap-eval-file data/jmap_emails.json "/list/*/threadId" 67 OK: ["trd194","trd114","trd99"] 68 69Extract emailIds from Thread/get response (RFC 8620 pattern) - results flattened: 70 $ ./test_pointer.exe jmap-eval-file data/jmap_threads.json "/list/*/emailIds" 71 OK: ["msg1020","msg1021","msg1023","msg201","msg223","msg42"] 72 73Extract nested field: 74 $ ./test_pointer.exe jmap-eval '{"items":[{"data":{"value":1}},{"data":{"value":2}}]}' "/items/*/data/value" 75 OK: [1,2] 76 77Wildcard on empty array: 78 $ ./test_pointer.exe jmap-eval '{"list":[]}' "/list/*/id" 79 OK: [] 80 81Multiple wildcards (nested arrays): 82 $ ./test_pointer.exe jmap-eval '{"a":[{"b":[{"c":1},{"c":2}]},{"b":[{"c":3}]}]}' "/a/*/b/*/c" 83 OK: [1,2,3] 84 85Wildcard returning non-arrays (no flattening needed): 86 $ ./test_pointer.exe jmap-eval '{"list":[{"name":"alice"},{"name":"bob"}]}' "/list/*/name" 87 OK: ["alice","bob"] 88 89Flattening behavior - arrays of arrays become flat: 90 $ ./test_pointer.exe jmap-eval '{"items":[{"tags":["a","b"]},{"tags":["c"]},{"tags":["d","e","f"]}]}' "/items/*/tags" 91 OK: ["a","b","c","d","e","f"] 92 93Error cases: 94 95Wildcard on non-array: 96 $ ./test_pointer.exe jmap-eval '{"obj":{"a":1}}' "/obj/*" 97 ERROR: JMAP Pointer: '*' can only be used on arrays, got object 98 File "-": 99 $ ./test_pointer.exe jmap-eval '"string"' "/*" 100 ERROR: JMAP Pointer: '*' can only be used on arrays, got string 101 File "-": 102 103Member not found: 104 $ ./test_pointer.exe jmap-eval '{"foo":"bar"}' "/baz" 105 ERROR: JMAP Pointer: member 'baz' not found 106 File "-": 107 108Index out of bounds: 109 $ ./test_pointer.exe jmap-eval '{"arr":[1,2]}' "/arr/5" 110 ERROR: JMAP Pointer: index 5 out of bounds (array has 2 elements) 111 File "-": 112 113Member not found after wildcard: 114 $ ./test_pointer.exe jmap-eval '{"list":[{"a":1},{"b":2}]}' "/list/*/a" 115 ERROR: JMAP Pointer: member 'a' not found 116 File "-": 117 118Real JMAP patterns: 119 120Get IDs from query response: 121 $ ./test_pointer.exe jmap-eval '{"queryState":"abc","ids":["id1","id2","id3"]}' "/ids" 122 OK: ["id1","id2","id3"] 123 124Get created IDs from changes response: 125 $ ./test_pointer.exe jmap-eval '{"oldState":"a","newState":"b","created":["f1","f4"],"updated":[],"destroyed":[]}' "/created" 126 OK: ["f1","f4"] 127 128Complex nested extraction: 129 $ ./test_pointer.exe jmap-eval '{"results":[{"emails":[{"from":"a@b.com"},{"from":"c@d.com"}]},{"emails":[{"from":"e@f.com"}]}]}' "/results/*/emails/*/from" 130 OK: ["a@b.com","c@d.com","e@f.com"] 131 132Typed extraction with Jmap.path combinator: 133 134Extract string list with wildcard: 135 $ ./test_pointer.exe jmap-path-strings '{"list":[{"id":"a"},{"id":"b"},{"id":"c"}]}' "/list/*/id" 136 OK: [a, b, c] 137 138Extract IDs from JMAP-style response: 139 $ ./test_pointer.exe jmap-path-strings '{"ids":["id1","id2","id3"]}' "/ids" 140 OK: [id1, id2, id3] 141 142Extract threadIds (JMAP Email/get pattern): 143 $ ./test_pointer.exe jmap-path-strings '{"list":[{"threadId":"t1"},{"threadId":"t2"}]}' "/list/*/threadId" 144 OK: [t1, t2] 145 146Extract integers: 147 $ ./test_pointer.exe jmap-path-ints '{"items":[{"count":10},{"count":20},{"count":30}]}' "/items/*/count" 148 OK: [10, 20, 30] 149 150Extract single string value: 151 $ ./test_pointer.exe jmap-path-single '{"account":{"id":"acc123"}}' "/account/id" 152 OK: acc123 153 154Extract with absent default (path exists): 155 $ ./test_pointer.exe jmap-path-absent '{"name":"alice"}' "/name" "default" 156 OK: alice 157 158Extract with absent default (path missing): 159 $ ./test_pointer.exe jmap-path-absent '{"other":"value"}' "/name" "default" 160 OK: default 161 162Nested wildcard extraction: 163 $ ./test_pointer.exe jmap-path-strings '{"a":[{"b":[{"c":"x"},{"c":"y"}]},{"b":[{"c":"z"}]}]}' "/a/*/b/*/c" 164 OK: [x, y, z] 165 166Empty array result: 167 $ ./test_pointer.exe jmap-path-strings '{"list":[]}' "/list/*/id" 168 OK: [] 169 170Type mismatch error (expecting strings, got ints): 171 $ ./test_pointer.exe jmap-path-strings '{"list":[{"id":1},{"id":2}]}' "/list/*/id" 172 ERROR: Expected string but found number 173 File "-": 174 File "-": at index 0 of 175 File "-": array<string>