a textual notation to locate fields within atproto records (draft spec)
microcosm.tngl.io/RecordPath/
1{
2 "description": "RecordPath match tests. Each test provides a record, a path, and the expected matched values. For vector paths, matched values are compared as unordered sets.",
3 "tests": [
4 {
5 "description": "simple top-level scalar field",
6 "record": {
7 "$type": "app.bsky.feed.like",
8 "createdAt": "2024-01-15T00:00:00.000Z",
9 "subject": {
10 "uri": "at://did:plc:example/app.bsky.feed.post/abc",
11 "cid": "bafyreiabc"
12 }
13 },
14 "path": "createdAt",
15 "expected": ["2024-01-15T00:00:00.000Z"]
16 },
17 {
18 "description": "nested scalar field",
19 "record": {
20 "$type": "app.bsky.feed.like",
21 "subject": {
22 "uri": "at://did:plc:example/app.bsky.feed.post/abc",
23 "cid": "bafyreiabc"
24 }
25 },
26 "path": "subject.uri",
27 "expected": ["at://did:plc:example/app.bsky.feed.post/abc"]
28 },
29 {
30 "description": "select sub-object",
31 "record": {
32 "$type": "app.bsky.feed.like",
33 "subject": {
34 "uri": "at://did:plc:example/app.bsky.feed.post/abc",
35 "cid": "bafyreiabc"
36 }
37 },
38 "path": "subject",
39 "expected": [
40 {
41 "uri": "at://did:plc:example/app.bsky.feed.post/abc",
42 "cid": "bafyreiabc"
43 }
44 ]
45 },
46 {
47 "description": "select $type as regular field",
48 "record": {
49 "$type": "app.bsky.feed.like",
50 "subject": { "uri": "at://example", "cid": "bafyreiabc" }
51 },
52 "path": "$type",
53 "expected": ["app.bsky.feed.like"]
54 },
55 {
56 "description": "non-existent field returns empty",
57 "record": {
58 "$type": "app.bsky.feed.like",
59 "subject": { "uri": "at://example" }
60 },
61 "path": "missing",
62 "expected": []
63 },
64 {
65 "description": "non-existent nested field returns empty",
66 "record": {
67 "subject": { "uri": "at://example" }
68 },
69 "path": "subject.missing",
70 "expected": []
71 },
72 {
73 "description": "path into scalar returns empty",
74 "record": {
75 "text": "hello"
76 },
77 "path": "text.nested",
78 "expected": []
79 },
80 {
81 "description": "array of scalars",
82 "record": {
83 "tags": ["art", "science"]
84 },
85 "path": "tags[]",
86 "expected": ["art", "science"]
87 },
88 {
89 "description": "array of objects, select field",
90 "record": {
91 "references": [
92 { "title": "paper one" },
93 { "title": "paper two" }
94 ]
95 },
96 "path": "references[].title",
97 "expected": ["paper one", "paper two"]
98 },
99 {
100 "description": "nested array traversal",
101 "record": {
102 "references": [
103 { "urls": ["https://a.example.com", "https://b.example.com"] },
104 { "urls": ["https://c.example.com"] }
105 ]
106 },
107 "path": "references[].urls[]",
108 "expected": [
109 "https://a.example.com",
110 "https://b.example.com",
111 "https://c.example.com"
112 ]
113 },
114 {
115 "description": "array path on non-array returns empty",
116 "record": {
117 "tags": "not-an-array"
118 },
119 "path": "tags[]",
120 "expected": []
121 },
122 {
123 "description": "empty array returns empty",
124 "record": {
125 "tags": []
126 },
127 "path": "tags[]",
128 "expected": []
129 },
130 {
131 "description": "array of unions, filter by $type",
132 "record": {
133 "facets": [
134 {
135 "features": [
136 { "$type": "app.bsky.richtext.facet#link", "uri": "https://example.com" },
137 { "$type": "app.bsky.richtext.facet#mention", "did": "did:plc:alice" }
138 ]
139 }
140 ]
141 },
142 "path": "facets[].features[app.bsky.richtext.facet#link].uri",
143 "expected": ["https://example.com"]
144 },
145 {
146 "description": "array of unions, different $type filter",
147 "record": {
148 "facets": [
149 {
150 "features": [
151 { "$type": "app.bsky.richtext.facet#link", "uri": "https://example.com" },
152 { "$type": "app.bsky.richtext.facet#mention", "did": "did:plc:alice" }
153 ]
154 }
155 ]
156 },
157 "path": "facets[].features[app.bsky.richtext.facet#mention].did",
158 "expected": ["did:plc:alice"]
159 },
160 {
161 "description": "array of unions, wrong $type returns empty",
162 "record": {
163 "features": [
164 { "$type": "app.bsky.richtext.facet#link", "uri": "https://example.com" }
165 ]
166 },
167 "path": "features[app.bsky.richtext.facet#mention].did",
168 "expected": []
169 },
170 {
171 "description": "array of unions, multiple matching elements",
172 "record": {
173 "features": [
174 { "$type": "app.bsky.richtext.facet#link", "uri": "https://a.example.com" },
175 { "$type": "app.bsky.richtext.facet#mention", "did": "did:plc:alice" },
176 { "$type": "app.bsky.richtext.facet#link", "uri": "https://b.example.com" }
177 ]
178 },
179 "path": "features[app.bsky.richtext.facet#link].uri",
180 "expected": ["https://a.example.com", "https://b.example.com"]
181 },
182 {
183 "description": "scalar union field",
184 "record": {
185 "$type": "app.bsky.feed.post",
186 "embed": {
187 "$type": "app.bsky.embed.external",
188 "external": {
189 "uri": "https://example.com",
190 "title": "Example"
191 }
192 }
193 },
194 "path": "embed{app.bsky.embed.external}.external.uri",
195 "expected": ["https://example.com"]
196 },
197 {
198 "description": "scalar union, wrong $type returns empty",
199 "record": {
200 "$type": "app.bsky.feed.post",
201 "embed": {
202 "$type": "app.bsky.embed.external",
203 "external": { "uri": "https://example.com" }
204 }
205 },
206 "path": "embed{app.bsky.embed.record}.record.uri",
207 "expected": []
208 },
209 {
210 "description": "scalar union, select the union object itself",
211 "record": {
212 "embed": {
213 "$type": "app.bsky.embed.external",
214 "external": { "uri": "https://example.com" }
215 }
216 },
217 "path": "embed{app.bsky.embed.external}",
218 "expected": [
219 {
220 "$type": "app.bsky.embed.external",
221 "external": { "uri": "https://example.com" }
222 }
223 ]
224 },
225 {
226 "description": "escaped dot in field name",
227 "record": {
228 "dot.key": "dotted"
229 },
230 "path": "dot!.key",
231 "expected": ["dotted"]
232 },
233 {
234 "description": "escaped bang in field name",
235 "record": {
236 "a!b": "banged"
237 },
238 "path": "a!!b",
239 "expected": ["banged"]
240 },
241 {
242 "description": "escaped bracket in field name",
243 "record": {
244 "a[0]": "bracketed"
245 },
246 "path": "a![0!]",
247 "expected": ["bracketed"]
248 },
249 {
250 "description": "escaped brace in field name",
251 "record": {
252 "a{b}": "braced"
253 },
254 "path": "a!{b!}",
255 "expected": ["braced"]
256 },
257 {
258 "description": "$-prefixed key is ordinary",
259 "record": {
260 "$custom": "value"
261 },
262 "path": "$custom",
263 "expected": ["value"]
264 },
265 {
266 "description": "root-level $type is not treated as union qualifier",
267 "record": {
268 "$type": "app.bsky.feed.like",
269 "subject": { "uri": "at://example" }
270 },
271 "path": "subject.uri",
272 "expected": ["at://example"]
273 },
274 {
275 "description": "boolean value",
276 "record": { "active": true },
277 "path": "active",
278 "expected": [true]
279 },
280 {
281 "description": "null value",
282 "record": { "deleted": null },
283 "path": "deleted",
284 "expected": [null]
285 },
286 {
287 "description": "numeric value",
288 "record": { "count": 42 },
289 "path": "count",
290 "expected": [42]
291 }
292 ]
293}