@graffiti-garden/api 0.1.7 → 0.1.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/tests/src/crud.ts CHANGED
@@ -19,457 +19,458 @@ export const graffitiCRUDTests = (
19
19
  useSession1: () => GraffitiSession,
20
20
  useSession2: () => GraffitiSession,
21
21
  ) => {
22
- describe("CRUD", () => {
23
- it("put, get, delete", async () => {
24
- const graffiti = useGraffiti();
25
- const session = useSession1();
26
- const value = {
27
- something: "hello, world~ c:",
28
- };
29
- const channels = [randomString(), randomString()];
30
-
31
- // Put the object
32
- const previous = await graffiti.put({ value, channels }, session);
33
- expect(previous.value).toEqual({});
34
- expect(previous.channels).toEqual([]);
35
- expect(previous.allowed).toBeUndefined();
36
- expect(previous.actor).toEqual(session.actor);
37
-
38
- // Get it back
39
- const gotten = await graffiti.get(previous, {});
40
- expect(gotten.value).toEqual(value);
41
- expect(gotten.channels).toEqual([]);
42
- expect(gotten.allowed).toBeUndefined();
43
- expect(gotten.name).toEqual(previous.name);
44
- expect(gotten.actor).toEqual(previous.actor);
45
- expect(gotten.source).toEqual(previous.source);
46
- expect(gotten.lastModified).toEqual(previous.lastModified);
47
-
48
- // Replace it
49
- const newValue = {
50
- something: "goodbye, world~ :c",
51
- };
52
- const beforeReplaced = await graffiti.put(
53
- { ...previous, value: newValue, channels: [] },
54
- session,
55
- );
56
- expect(beforeReplaced.value).toEqual(value);
57
- expect(beforeReplaced.tombstone).toEqual(true);
58
- expect(beforeReplaced.name).toEqual(previous.name);
59
- expect(beforeReplaced.actor).toEqual(previous.actor);
60
- expect(beforeReplaced.source).toEqual(previous.source);
61
- expect(beforeReplaced.lastModified).toBeGreaterThan(gotten.lastModified);
62
-
63
- // Get it again
64
- const afterReplaced = await graffiti.get(previous, {});
65
- expect(afterReplaced.value).toEqual(newValue);
66
- expect(afterReplaced.lastModified).toEqual(beforeReplaced.lastModified);
67
- expect(afterReplaced.tombstone).toEqual(false);
68
-
69
- // Delete it
70
- const beforeDeleted = await graffiti.delete(afterReplaced, session);
71
- expect(beforeDeleted.tombstone).toEqual(true);
72
- expect(beforeDeleted.value).toEqual(newValue);
73
- expect(beforeDeleted.lastModified).toBeGreaterThan(
74
- beforeReplaced.lastModified,
75
- );
76
-
77
- // Try to get it and fail
78
- await expect(graffiti.get(afterReplaced, {})).rejects.toThrow(
79
- GraffitiErrorNotFound,
80
- );
81
- });
82
-
83
- it("put, get, delete with wrong actor", async () => {
84
- const graffiti = useGraffiti();
85
- const session1 = useSession1();
86
- const session2 = useSession2();
87
-
88
- await expect(
89
- graffiti.put(
90
- { value: {}, channels: [], actor: session2.actor },
91
- session1,
92
- ),
93
- ).rejects.toThrow(GraffitiErrorForbidden);
22
+ describe(
23
+ "CRUD",
24
+ () => {
25
+ it("put, get, delete", async () => {
26
+ const graffiti = useGraffiti();
27
+ const session = useSession1();
28
+ const value = {
29
+ something: "hello, world~ c:",
30
+ };
31
+ const channels = [randomString(), randomString()];
32
+
33
+ // Put the object
34
+ const previous = await graffiti.put({ value, channels }, session);
35
+ expect(previous.value).toEqual({});
36
+ expect(previous.channels).toEqual([]);
37
+ expect(previous.allowed).toBeUndefined();
38
+ expect(previous.actor).toEqual(session.actor);
39
+
40
+ // Get it back
41
+ const gotten = await graffiti.get(previous, {});
42
+ expect(gotten.value).toEqual(value);
43
+ expect(gotten.channels).toEqual([]);
44
+ expect(gotten.allowed).toBeUndefined();
45
+ expect(gotten.name).toEqual(previous.name);
46
+ expect(gotten.actor).toEqual(previous.actor);
47
+ expect(gotten.source).toEqual(previous.source);
48
+ expect(gotten.lastModified).toEqual(previous.lastModified);
49
+
50
+ // Replace it
51
+ const newValue = {
52
+ something: "goodbye, world~ :c",
53
+ };
54
+ const beforeReplaced = await graffiti.put(
55
+ { ...previous, value: newValue, channels: [] },
56
+ session,
57
+ );
58
+ expect(beforeReplaced.value).toEqual(value);
59
+ expect(beforeReplaced.tombstone).toEqual(true);
60
+ expect(beforeReplaced.name).toEqual(previous.name);
61
+ expect(beforeReplaced.actor).toEqual(previous.actor);
62
+ expect(beforeReplaced.source).toEqual(previous.source);
63
+ expect(beforeReplaced.lastModified).toBeGreaterThanOrEqual(
64
+ gotten.lastModified,
65
+ );
94
66
 
95
- await expect(
96
- graffiti.delete(
97
- {
98
- name: "asdf",
99
- source: "asdf",
100
- actor: session2.actor,
67
+ // Get it again
68
+ const afterReplaced = await graffiti.get(previous, {});
69
+ expect(afterReplaced.value).toEqual(newValue);
70
+ expect(afterReplaced.lastModified).toEqual(beforeReplaced.lastModified);
71
+ expect(afterReplaced.tombstone).toEqual(false);
72
+
73
+ // Delete it
74
+ const beforeDeleted = await graffiti.delete(afterReplaced, session);
75
+ expect(beforeDeleted.tombstone).toEqual(true);
76
+ expect(beforeDeleted.value).toEqual(newValue);
77
+ expect(beforeDeleted.lastModified).toBeGreaterThanOrEqual(
78
+ beforeReplaced.lastModified,
79
+ );
80
+
81
+ // Try to get it and fail
82
+ await expect(graffiti.get(afterReplaced, {})).rejects.toThrow(
83
+ GraffitiErrorNotFound,
84
+ );
85
+ });
86
+
87
+ it("put, get, delete with wrong actor", async () => {
88
+ const graffiti = useGraffiti();
89
+ const session1 = useSession1();
90
+ const session2 = useSession2();
91
+
92
+ await expect(
93
+ graffiti.put(
94
+ { value: {}, channels: [], actor: session2.actor },
95
+ session1,
96
+ ),
97
+ ).rejects.toThrow(GraffitiErrorForbidden);
98
+
99
+ const putted = await graffiti.put(
100
+ { value: {}, channels: [] },
101
+ session2,
102
+ );
103
+
104
+ await expect(graffiti.delete(putted, session1)).rejects.toThrow(
105
+ GraffitiErrorForbidden,
106
+ );
107
+
108
+ await expect(graffiti.patch({}, putted, session1)).rejects.toThrow(
109
+ GraffitiErrorForbidden,
110
+ );
111
+ });
112
+
113
+ it("put and get with schema", async () => {
114
+ const graffiti = useGraffiti();
115
+ const session = useSession1();
116
+
117
+ const schema = {
118
+ properties: {
119
+ value: {
120
+ properties: {
121
+ something: {
122
+ type: "string",
123
+ },
124
+ another: {
125
+ type: "integer",
126
+ },
127
+ },
128
+ },
101
129
  },
102
- session1,
103
- ),
104
- ).rejects.toThrow(GraffitiErrorForbidden);
130
+ } as const;
105
131
 
106
- await expect(
107
- graffiti.patch(
108
- {},
132
+ const goodValue = {
133
+ something: "hello",
134
+ another: 42,
135
+ } as const;
136
+
137
+ const putted = await graffiti.put<typeof schema>(
109
138
  {
110
- name: "asdf",
111
- source: "asdf",
112
- actor: session2.actor,
139
+ value: goodValue,
140
+ channels: [],
113
141
  },
114
- session1,
115
- ),
116
- ).rejects.toThrow(GraffitiErrorForbidden);
117
- });
142
+ session,
143
+ );
118
144
 
119
- it("put and get with schema", async () => {
120
- const graffiti = useGraffiti();
121
- const session = useSession1();
145
+ const gotten = await graffiti.get(putted, schema);
146
+ expect(gotten.value.something).toEqual(goodValue.something);
147
+ expect(gotten.value.another).toEqual(goodValue.another);
148
+ });
149
+
150
+ it("put and get with invalid schema", async () => {
151
+ const graffiti = useGraffiti();
152
+ const session = useSession1();
122
153
 
123
- const schema = {
124
- properties: {
125
- value: {
154
+ const putted = await graffiti.put({ value: {}, channels: [] }, session);
155
+ await expect(
156
+ graffiti.get(putted, {
126
157
  properties: {
127
- something: {
128
- type: "string",
129
- },
130
- another: {
131
- type: "integer",
158
+ value: {
159
+ //@ts-ignore
160
+ type: "asdf",
132
161
  },
133
162
  },
134
- },
135
- },
136
- } as const;
137
-
138
- const goodValue = {
139
- something: "hello",
140
- another: 42,
141
- } as const;
142
-
143
- const putted = await graffiti.put<typeof schema>(
144
- {
145
- value: goodValue,
146
- channels: [],
147
- },
148
- session,
149
- );
150
-
151
- const gotten = await graffiti.get(putted, schema);
152
- expect(gotten.value.something).toEqual(goodValue.something);
153
- expect(gotten.value.another).toEqual(goodValue.another);
154
- });
155
-
156
- it("put and get with invalid schema", async () => {
157
- const graffiti = useGraffiti();
158
- const session = useSession1();
159
-
160
- const putted = await graffiti.put({ value: {}, channels: [] }, session);
161
- await expect(
162
- graffiti.get(putted, {
163
- properties: {
163
+ }),
164
+ ).rejects.toThrow(GraffitiErrorInvalidSchema);
165
+ });
166
+
167
+ it("put and get with wrong schema", async () => {
168
+ const graffiti = useGraffiti();
169
+ const session = useSession1();
170
+
171
+ const putted = await graffiti.put(
172
+ {
164
173
  value: {
165
- //@ts-ignore
166
- type: "asdf",
174
+ hello: "world",
167
175
  },
176
+ channels: [],
168
177
  },
169
- }),
170
- ).rejects.toThrow(GraffitiErrorInvalidSchema);
171
- });
172
-
173
- it("put and get with wrong schema", async () => {
174
- const graffiti = useGraffiti();
175
- const session = useSession1();
176
-
177
- const putted = await graffiti.put(
178
- {
179
- value: {
180
- hello: "world",
181
- },
182
- channels: [],
183
- },
184
- session,
185
- );
178
+ session,
179
+ );
186
180
 
187
- await expect(
188
- graffiti.get(putted, {
189
- properties: {
190
- value: {
191
- properties: {
192
- hello: {
193
- type: "number",
181
+ await expect(
182
+ graffiti.get(putted, {
183
+ properties: {
184
+ value: {
185
+ properties: {
186
+ hello: {
187
+ type: "number",
188
+ },
194
189
  },
195
190
  },
196
191
  },
197
- },
198
- }),
199
- ).rejects.toThrow(GraffitiErrorSchemaMismatch);
200
- });
201
-
202
- it("put and get with empty access control", async () => {
203
- const graffiti = useGraffiti();
204
- const session1 = useSession1();
205
- const session2 = useSession2();
206
-
207
- const value = {
208
- um: "hi",
209
- };
210
- const allowed = [randomString()];
211
- const channels = [randomString()];
212
- const putted = await graffiti.put({ value, allowed, channels }, session1);
213
-
214
- // Get it with authenticated session
215
- const gotten = await graffiti.get(putted, {}, session1);
216
- expect(gotten.value).toEqual(value);
217
- expect(gotten.allowed).toEqual(allowed);
218
- expect(gotten.channels).toEqual(channels);
219
-
220
- // But not without session
221
- await expect(graffiti.get(putted, {})).rejects.toThrow();
222
-
223
- // Or the wrong session
224
- await expect(graffiti.get(putted, {}, session2)).rejects.toThrow();
225
- });
226
-
227
- it("put and get with specific access control", async () => {
228
- const graffiti = useGraffiti();
229
- const session1 = useSession1();
230
- const session2 = useSession2();
231
-
232
- const value = {
233
- um: "hi",
234
- };
235
- const allowed = [randomString(), session2.actor, randomString()];
236
- const channels = [randomString()];
237
- const putted = await graffiti.put(
238
- {
239
- value,
240
- allowed,
241
- channels,
242
- },
243
- session1,
244
- );
245
-
246
- // Get it with authenticated session
247
- const gotten = await graffiti.get(putted, {}, session1);
248
- expect(gotten.value).toEqual(value);
249
- expect(gotten.allowed).toEqual(allowed);
250
- expect(gotten.channels).toEqual(channels);
251
-
252
- // But not without session
253
- await expect(graffiti.get(putted, {})).rejects.toThrow();
254
-
255
- const gotten2 = await graffiti.get(putted, {}, session2);
256
- expect(gotten2.value).toEqual(value);
257
- // They should only see that is is private to them
258
- expect(gotten2.allowed).toEqual([session2.actor]);
259
- // And not see any channels
260
- expect(gotten2.channels).toEqual([]);
261
- });
262
-
263
- it("patch value", async () => {
264
- const graffiti = useGraffiti();
265
- const session = useSession1();
266
-
267
- const value = {
268
- something: "hello, world~ c:",
269
- };
270
- const putted = await graffiti.put({ value, channels: [] }, session);
271
-
272
- const patch: GraffitiPatch = {
273
- value: [
274
- { op: "replace", path: "/something", value: "goodbye, world~ :c" },
275
- ],
276
- };
277
- const beforePatched = await graffiti.patch(patch, putted, session);
278
- expect(beforePatched.value).toEqual(value);
279
- expect(beforePatched.tombstone).toBe(true);
280
-
281
- const gotten = await graffiti.get(putted, {});
282
- expect(gotten.value).toEqual({
283
- something: "goodbye, world~ :c",
192
+ }),
193
+ ).rejects.toThrow(GraffitiErrorSchemaMismatch);
284
194
  });
285
- expect(beforePatched.lastModified).toBe(gotten.lastModified);
286
195
 
287
- await graffiti.delete(putted, session);
288
- });
196
+ it("put and get with empty access control", async () => {
197
+ const graffiti = useGraffiti();
198
+ const session1 = useSession1();
199
+ const session2 = useSession2();
200
+
201
+ const value = {
202
+ um: "hi",
203
+ };
204
+ const allowed = [randomString()];
205
+ const channels = [randomString()];
206
+ const putted = await graffiti.put(
207
+ { value, allowed, channels },
208
+ session1,
209
+ );
289
210
 
290
- it("deep patch", async () => {
291
- const graffiti = useGraffiti();
292
- const session = useSession1();
211
+ // Get it with authenticated session
212
+ const gotten = await graffiti.get(putted, {}, session1);
213
+ expect(gotten.value).toEqual(value);
214
+ expect(gotten.allowed).toEqual(allowed);
215
+ expect(gotten.channels).toEqual(channels);
293
216
 
294
- const value = {
295
- something: {
296
- another: {
297
- somethingElse: "hello",
298
- },
299
- },
300
- };
301
- const putted = await graffiti.put(
302
- { value: value, channels: [] },
303
- session,
304
- );
305
-
306
- const beforePatch = await graffiti.patch(
307
- {
308
- value: [
309
- {
310
- op: "replace",
311
- path: "/something/another/somethingElse",
312
- value: "goodbye",
313
- },
314
- ],
315
- },
316
- putted,
317
- session,
318
- );
319
- const gotten = await graffiti.get(putted, {});
320
-
321
- expect(beforePatch.value).toEqual(value);
322
- expect(gotten.value).toEqual({
323
- something: {
324
- another: {
325
- somethingElse: "goodbye",
326
- },
327
- },
217
+ // But not without session
218
+ await expect(graffiti.get(putted, {})).rejects.toThrow();
219
+
220
+ // Or the wrong session
221
+ await expect(graffiti.get(putted, {}, session2)).rejects.toThrow();
328
222
  });
329
- });
330
-
331
- it("patch channels", async () => {
332
- const graffiti = useGraffiti();
333
- const session = useSession1();
334
-
335
- const channelsBefore = [randomString()];
336
- const channelsAfter = [randomString()];
337
-
338
- const putted = await graffiti.put(
339
- { value: {}, channels: channelsBefore },
340
- session,
341
- );
342
-
343
- const patch: GraffitiPatch = {
344
- channels: [{ op: "replace", path: "/0", value: channelsAfter[0] }],
345
- };
346
- const patched = await graffiti.patch(patch, putted, session);
347
- expect(patched.channels).toEqual(channelsBefore);
348
- const gotten = await graffiti.get(putted, {}, session);
349
- expect(gotten.channels).toEqual(channelsAfter);
350
- await graffiti.delete(putted, session);
351
- });
352
-
353
- it("patch 'increment' with test", async () => {
354
- const graffiti = useGraffiti();
355
- const session = useSession1();
356
-
357
- const putted = await graffiti.put(
358
- {
359
- value: {
360
- counter: 1,
223
+
224
+ it("put and get with specific access control", async () => {
225
+ const graffiti = useGraffiti();
226
+ const session1 = useSession1();
227
+ const session2 = useSession2();
228
+
229
+ const value = {
230
+ um: "hi",
231
+ };
232
+ const allowed = [randomString(), session2.actor, randomString()];
233
+ const channels = [randomString()];
234
+ const putted = await graffiti.put(
235
+ {
236
+ value,
237
+ allowed,
238
+ channels,
361
239
  },
362
- channels: [],
363
- },
364
- session,
365
- );
240
+ session1,
241
+ );
242
+
243
+ // Get it with authenticated session
244
+ const gotten = await graffiti.get(putted, {}, session1);
245
+ expect(gotten.value).toEqual(value);
246
+ expect(gotten.allowed).toEqual(allowed);
247
+ expect(gotten.channels).toEqual(channels);
248
+
249
+ // But not without session
250
+ await expect(graffiti.get(putted, {})).rejects.toThrow();
251
+
252
+ const gotten2 = await graffiti.get(putted, {}, session2);
253
+ expect(gotten2.value).toEqual(value);
254
+ // They should only see that is is private to them
255
+ expect(gotten2.allowed).toEqual([session2.actor]);
256
+ // And not see any channels
257
+ expect(gotten2.channels).toEqual([]);
258
+ });
259
+
260
+ it("patch value", async () => {
261
+ const graffiti = useGraffiti();
262
+ const session = useSession1();
366
263
 
367
- const previous = await graffiti.patch(
368
- {
264
+ const value = {
265
+ something: "hello, world~ c:",
266
+ };
267
+ const putted = await graffiti.put({ value, channels: [] }, session);
268
+
269
+ const patch: GraffitiPatch = {
369
270
  value: [
370
- { op: "test", path: "/counter", value: 1 },
371
- { op: "replace", path: "/counter", value: 2 },
271
+ { op: "replace", path: "/something", value: "goodbye, world~ :c" },
372
272
  ],
373
- },
374
- putted,
375
- session,
376
- );
377
- expect(previous.value).toEqual({ counter: 1 });
378
- const result = await graffiti.get(previous, {
379
- properties: {
380
- value: {
381
- properties: {
382
- counter: {
383
- type: "integer",
384
- },
273
+ };
274
+ const beforePatched = await graffiti.patch(patch, putted, session);
275
+ expect(beforePatched.value).toEqual(value);
276
+ expect(beforePatched.tombstone).toBe(true);
277
+
278
+ const gotten = await graffiti.get(putted, {});
279
+ expect(gotten.value).toEqual({
280
+ something: "goodbye, world~ :c",
281
+ });
282
+ expect(beforePatched.lastModified).toBe(gotten.lastModified);
283
+
284
+ await graffiti.delete(putted, session);
285
+ });
286
+
287
+ it("deep patch", async () => {
288
+ const graffiti = useGraffiti();
289
+ const session = useSession1();
290
+
291
+ const value = {
292
+ something: {
293
+ another: {
294
+ somethingElse: "hello",
385
295
  },
386
296
  },
387
- },
388
- });
389
- expect(result.value.counter).toEqual(2);
297
+ };
298
+ const putted = await graffiti.put(
299
+ { value: value, channels: [] },
300
+ session,
301
+ );
390
302
 
391
- await expect(
392
- graffiti.patch(
303
+ const beforePatch = await graffiti.patch(
393
304
  {
394
305
  value: [
395
- { op: "test", path: "/counter", value: 1 },
396
- { op: "replace", path: "/counter", value: 3 },
306
+ {
307
+ op: "replace",
308
+ path: "/something/another/somethingElse",
309
+ value: "goodbye",
310
+ },
397
311
  ],
398
312
  },
399
313
  putted,
400
314
  session,
401
- ),
402
- ).rejects.toThrow(GraffitiErrorPatchTestFailed);
403
- });
404
-
405
- it("invalid patch", async () => {
406
- const graffiti = useGraffiti();
407
- const session = useSession1();
408
- const object = randomPutObject();
409
- const putted = await graffiti.put(object, session);
410
-
411
- await expect(
412
- graffiti.patch(
315
+ );
316
+ const gotten = await graffiti.get(putted, {});
317
+
318
+ expect(beforePatch.value).toEqual(value);
319
+ expect(gotten.value).toEqual({
320
+ something: {
321
+ another: {
322
+ somethingElse: "goodbye",
323
+ },
324
+ },
325
+ });
326
+ });
327
+
328
+ it("patch channels", async () => {
329
+ const graffiti = useGraffiti();
330
+ const session = useSession1();
331
+
332
+ const channelsBefore = [randomString()];
333
+ const channelsAfter = [randomString()];
334
+
335
+ const putted = await graffiti.put(
336
+ { value: {}, channels: channelsBefore },
337
+ session,
338
+ );
339
+
340
+ const patch: GraffitiPatch = {
341
+ channels: [{ op: "replace", path: "/0", value: channelsAfter[0] }],
342
+ };
343
+ const patched = await graffiti.patch(patch, putted, session);
344
+ expect(patched.channels).toEqual(channelsBefore);
345
+ const gotten = await graffiti.get(putted, {}, session);
346
+ expect(gotten.channels).toEqual(channelsAfter);
347
+ await graffiti.delete(putted, session);
348
+ });
349
+
350
+ it("patch 'increment' with test", async () => {
351
+ const graffiti = useGraffiti();
352
+ const session = useSession1();
353
+
354
+ const putted = await graffiti.put(
355
+ {
356
+ value: {
357
+ counter: 1,
358
+ },
359
+ channels: [],
360
+ },
361
+ session,
362
+ );
363
+
364
+ const previous = await graffiti.patch(
413
365
  {
414
366
  value: [
415
- { op: "add", path: "/root", value: [] },
416
- { op: "add", path: "/root/2", value: 2 }, // out of bounds
367
+ { op: "test", path: "/counter", value: 1 },
368
+ { op: "replace", path: "/counter", value: 2 },
417
369
  ],
418
370
  },
419
371
  putted,
420
372
  session,
421
- ),
422
- ).rejects.toThrow(GraffitiErrorPatchError);
423
- });
424
-
425
- it("patch channels to be wrong", async () => {
426
- const graffiti = useGraffiti();
427
- const session = useSession1();
428
- const object = randomPutObject();
429
- object.allowed = [randomString()];
430
- const putted = await graffiti.put(object, session);
431
-
432
- const patches: GraffitiPatch[] = [
433
- {
434
- channels: [{ op: "replace", path: "", value: null }],
435
- },
436
- {
437
- channels: [{ op: "replace", path: "", value: {} }],
438
- },
439
- {
440
- channels: [{ op: "replace", path: "", value: ["hello", ["hi"]] }],
441
- },
442
- {
443
- channels: [{ op: "add", path: "/0", value: 1 }],
444
- },
445
- {
446
- value: [{ op: "replace", path: "", value: "not an object" }],
447
- },
448
- {
449
- value: [{ op: "replace", path: "", value: null }],
450
- },
451
- {
452
- value: [{ op: "replace", path: "", value: [] }],
453
- },
454
- {
455
- allowed: [{ op: "replace", path: "", value: {} }],
456
- },
457
- {
458
- allowed: [{ op: "replace", path: "", value: ["hello", ["hi"]] }],
459
- },
460
- ];
461
-
462
- for (const patch of patches) {
463
- await expect(graffiti.patch(patch, putted, session)).rejects.toThrow(
464
- GraffitiErrorPatchError,
465
373
  );
466
- }
467
-
468
- const gotten = await graffiti.get(putted, {}, session);
469
- expect(gotten.value).toEqual(object.value);
470
- expect(gotten.channels).toEqual(object.channels);
471
- expect(gotten.allowed).toEqual(object.allowed);
472
- expect(gotten.lastModified).toEqual(putted.lastModified);
473
- });
474
- });
374
+ expect(previous.value).toEqual({ counter: 1 });
375
+ const result = await graffiti.get(previous, {
376
+ properties: {
377
+ value: {
378
+ properties: {
379
+ counter: {
380
+ type: "integer",
381
+ },
382
+ },
383
+ },
384
+ },
385
+ });
386
+ expect(result.value.counter).toEqual(2);
387
+
388
+ await expect(
389
+ graffiti.patch(
390
+ {
391
+ value: [
392
+ { op: "test", path: "/counter", value: 1 },
393
+ { op: "replace", path: "/counter", value: 3 },
394
+ ],
395
+ },
396
+ putted,
397
+ session,
398
+ ),
399
+ ).rejects.toThrow(GraffitiErrorPatchTestFailed);
400
+ });
401
+
402
+ it("invalid patch", async () => {
403
+ const graffiti = useGraffiti();
404
+ const session = useSession1();
405
+ const object = randomPutObject();
406
+ const putted = await graffiti.put(object, session);
407
+
408
+ await expect(
409
+ graffiti.patch(
410
+ {
411
+ value: [
412
+ { op: "add", path: "/root", value: [] },
413
+ { op: "add", path: "/root/2", value: 2 }, // out of bounds
414
+ ],
415
+ },
416
+ putted,
417
+ session,
418
+ ),
419
+ ).rejects.toThrow(GraffitiErrorPatchError);
420
+ });
421
+
422
+ it("patch channels to be wrong", async () => {
423
+ const graffiti = useGraffiti();
424
+ const session = useSession1();
425
+ const object = randomPutObject();
426
+ object.allowed = [randomString()];
427
+ const putted = await graffiti.put(object, session);
428
+
429
+ const patches: GraffitiPatch[] = [
430
+ {
431
+ channels: [{ op: "replace", path: "", value: null }],
432
+ },
433
+ {
434
+ channels: [{ op: "replace", path: "", value: {} }],
435
+ },
436
+ {
437
+ channels: [{ op: "replace", path: "", value: ["hello", ["hi"]] }],
438
+ },
439
+ {
440
+ channels: [{ op: "add", path: "/0", value: 1 }],
441
+ },
442
+ {
443
+ value: [{ op: "replace", path: "", value: "not an object" }],
444
+ },
445
+ {
446
+ value: [{ op: "replace", path: "", value: null }],
447
+ },
448
+ {
449
+ value: [{ op: "replace", path: "", value: [] }],
450
+ },
451
+ {
452
+ allowed: [{ op: "replace", path: "", value: {} }],
453
+ },
454
+ {
455
+ allowed: [{ op: "replace", path: "", value: ["hello", ["hi"]] }],
456
+ },
457
+ ];
458
+
459
+ for (const patch of patches) {
460
+ await expect(graffiti.patch(patch, putted, session)).rejects.toThrow(
461
+ GraffitiErrorPatchError,
462
+ );
463
+ }
464
+
465
+ const gotten = await graffiti.get(putted, {}, session);
466
+ expect(gotten.value).toEqual(object.value);
467
+ expect(gotten.channels).toEqual(object.channels);
468
+ expect(gotten.allowed).toEqual(object.allowed);
469
+ expect(gotten.lastModified).toEqual(putted.lastModified);
470
+ });
471
+ },
472
+ {
473
+ timeout: 20000,
474
+ },
475
+ );
475
476
  };