@graffiti-garden/api 0.6.3 → 1.0.0

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/crud.ts CHANGED
@@ -2,7 +2,6 @@ import { it, expect, describe, beforeAll } from "vitest";
2
2
  import type {
3
3
  Graffiti,
4
4
  GraffitiSession,
5
- GraffitiPatch,
6
5
  JSONSchema,
7
6
  } from "@graffiti-garden/api";
8
7
  import {
@@ -10,13 +9,11 @@ import {
10
9
  GraffitiErrorSchemaMismatch,
11
10
  GraffitiErrorInvalidSchema,
12
11
  GraffitiErrorForbidden,
13
- GraffitiErrorPatchTestFailed,
14
- GraffitiErrorPatchError,
15
12
  } from "@graffiti-garden/api";
16
- import { randomPutObject, randomString } from "./utils";
13
+ import { randomPostObject, randomString } from "./utils";
17
14
 
18
15
  export const graffitiCRUDTests = (
19
- useGraffiti: () => Pick<Graffiti, "put" | "get" | "delete" | "patch">,
16
+ useGraffiti: () => Pick<Graffiti, "post" | "get" | "delete">,
20
17
  useSession1: () => GraffitiSession | Promise<GraffitiSession>,
21
18
  useSession2: () => GraffitiSession | Promise<GraffitiSession>,
22
19
  ) => {
@@ -37,17 +34,17 @@ export const graffitiCRUDTests = (
37
34
  session2 = await useSession2();
38
35
  });
39
36
 
40
- it("put, get, delete", async () => {
37
+ it("post, get, delete", async () => {
41
38
  const value = {
42
39
  something: "hello, world~ c:",
43
40
  };
44
41
  const channels = [randomString(), randomString()];
45
42
 
46
- // Put the object
47
- const previous = await graffiti.put<{}>({ value, channels }, session);
48
- expect(previous.value).toEqual({});
49
- expect(previous.channels).toEqual([]);
50
- expect(previous.allowed).toEqual([]);
43
+ // Post the object
44
+ const previous = await graffiti.post<{}>({ value, channels }, session);
45
+ expect(previous.value).toEqual(value);
46
+ expect(previous.channels).toEqual(channels);
47
+ expect(previous.allowed).toEqual(undefined);
51
48
  expect(previous.actor).toEqual(session.actor);
52
49
 
53
50
  // Get it back
@@ -57,93 +54,34 @@ export const graffitiCRUDTests = (
57
54
  expect(gotten.allowed).toBeUndefined();
58
55
  expect(gotten.url).toEqual(previous.url);
59
56
  expect(gotten.actor).toEqual(previous.actor);
60
- expect(gotten.lastModified).toEqual(previous.lastModified);
61
-
62
- // Replace it
63
- const newValue = {
64
- something: "goodbye, world~ :c",
65
- };
66
- const beforeReplaced = await graffiti.put<{}>(
67
- {
68
- url: previous.url,
69
- value: newValue,
70
- channels: [],
71
- },
72
- session,
73
- );
74
- expect(beforeReplaced.value).toEqual(value);
75
- expect(beforeReplaced.url).toEqual(previous.url);
76
- expect(beforeReplaced.actor).toEqual(previous.actor);
77
- expect(beforeReplaced.lastModified).toBeGreaterThanOrEqual(
78
- gotten.lastModified,
79
- );
80
-
81
- // Get it again
82
- const afterReplaced = await graffiti.get(previous, {});
83
- expect(afterReplaced.value).toEqual(newValue);
84
- expect(afterReplaced.lastModified).toEqual(beforeReplaced.lastModified);
85
57
 
86
58
  // Delete it
87
- const beforeDeleted = await graffiti.delete(afterReplaced, session);
88
- expect(beforeDeleted.value).toEqual(newValue);
89
- expect(beforeDeleted.lastModified).toBeGreaterThanOrEqual(
90
- beforeReplaced.lastModified,
91
- );
59
+ await graffiti.delete(gotten, session);
92
60
 
93
61
  // Get is not found
94
- await expect(graffiti.get(afterReplaced, {})).rejects.toBeInstanceOf(
62
+ await expect(graffiti.get(gotten, {})).rejects.toBeInstanceOf(
95
63
  GraffitiErrorNotFound,
96
64
  );
97
65
 
98
66
  // Delete it again
99
- await expect(graffiti.delete(beforeDeleted, session)).rejects.toThrow(
67
+ await expect(graffiti.delete(gotten, session)).rejects.toThrow(
100
68
  GraffitiErrorNotFound,
101
69
  );
102
-
103
- // Try to re-put it
104
- await expect(
105
- graffiti.put(
106
- { url: beforeDeleted.url, value: {}, channels: [] },
107
- session,
108
- ),
109
- ).rejects.toThrow(GraffitiErrorNotFound);
110
70
  });
111
71
 
112
- it("put, delete, patch with wrong actor", async () => {
113
- await expect(
114
- graffiti.put<{}>(
115
- { value: {}, channels: [], actor: session2.actor },
116
- session1,
117
- ),
118
- ).rejects.toThrow(GraffitiErrorForbidden);
119
-
120
- const putted = await graffiti.put<{}>(
72
+ it("post then delete with wrong actor", async () => {
73
+ const posted = await graffiti.post<{}>(
121
74
  { value: {}, channels: [] },
122
75
  session2,
123
76
  );
124
77
 
125
- await expect(
126
- graffiti.put<{}>(
127
- {
128
- url: putted.url,
129
- value: {},
130
- channels: [],
131
- },
132
- session1,
133
- ),
134
- ).rejects.toThrow(GraffitiErrorForbidden);
135
-
136
- await expect(graffiti.delete(putted, session1)).rejects.toThrow(
137
- GraffitiErrorForbidden,
138
- );
139
-
140
- await expect(graffiti.patch({}, putted, session1)).rejects.toThrow(
78
+ await expect(graffiti.delete(posted, session1)).rejects.toThrow(
141
79
  GraffitiErrorForbidden,
142
80
  );
143
81
  });
144
82
 
145
- it("put, patch, delete object that is not allowed", async () => {
146
- const putted = await graffiti.put<{}>(
83
+ it("post then delete object that is not allowed", async () => {
84
+ const posted = await graffiti.post<{}>(
147
85
  {
148
86
  value: {},
149
87
  channels: [],
@@ -152,27 +90,12 @@ export const graffitiCRUDTests = (
152
90
  session1,
153
91
  );
154
92
 
155
- await expect(
156
- graffiti.put(
157
- {
158
- url: putted.url,
159
- value: {},
160
- channels: [],
161
- },
162
- session2,
163
- ),
164
- ).rejects.toThrow(GraffitiErrorNotFound);
165
-
166
- await expect(graffiti.patch({}, putted, session2)).rejects.toThrow(
167
- GraffitiErrorNotFound,
168
- );
169
-
170
- await expect(graffiti.delete(putted, session2)).rejects.toThrow(
93
+ await expect(graffiti.delete(posted, session2)).rejects.toThrow(
171
94
  GraffitiErrorNotFound,
172
95
  );
173
96
  });
174
97
 
175
- it("put and get with schema", async () => {
98
+ it("post and get with schema", async () => {
176
99
  const schema = {
177
100
  properties: {
178
101
  value: {
@@ -209,14 +132,14 @@ export const graffitiCRUDTests = (
209
132
  },
210
133
  };
211
134
 
212
- const putted = await graffiti.put<typeof schema>(
135
+ const posted = await graffiti.post<typeof schema>(
213
136
  {
214
137
  value: goodValue,
215
138
  channels: [],
216
139
  },
217
140
  session,
218
141
  );
219
- const gotten = await graffiti.get(putted, schema);
142
+ const gotten = await graffiti.get(posted, schema);
220
143
 
221
144
  expect(gotten.value.something).toEqual(goodValue.something);
222
145
  expect(gotten.value.another).toEqual(goodValue.another);
@@ -224,13 +147,13 @@ export const graffitiCRUDTests = (
224
147
  expect(gotten.value.deeper.deepProp).toEqual(goodValue.deeper.deepProp);
225
148
  });
226
149
 
227
- it("put and get with invalid schema", async () => {
228
- const putted = await graffiti.put<{}>(
150
+ it("post and get with invalid schema", async () => {
151
+ const posted = await graffiti.post<{}>(
229
152
  { value: {}, channels: [] },
230
153
  session,
231
154
  );
232
155
  await expect(
233
- graffiti.get(putted, {
156
+ graffiti.get(posted, {
234
157
  properties: {
235
158
  value: {
236
159
  //@ts-ignore
@@ -241,8 +164,8 @@ export const graffitiCRUDTests = (
241
164
  ).rejects.toThrow(GraffitiErrorInvalidSchema);
242
165
  });
243
166
 
244
- it("put and get with wrong schema", async () => {
245
- const putted = await graffiti.put<{}>(
167
+ it("post and get with wrong schema", async () => {
168
+ const posted = await graffiti.post<{}>(
246
169
  {
247
170
  value: {
248
171
  hello: "world",
@@ -253,7 +176,7 @@ export const graffitiCRUDTests = (
253
176
  );
254
177
 
255
178
  await expect(
256
- graffiti.get(putted, {
179
+ graffiti.get(posted, {
257
180
  properties: {
258
181
  value: {
259
182
  properties: {
@@ -267,41 +190,43 @@ export const graffitiCRUDTests = (
267
190
  ).rejects.toThrow(GraffitiErrorSchemaMismatch);
268
191
  });
269
192
 
270
- it("put and get with empty access control", async () => {
193
+ it("post and get with empty access control", async () => {
271
194
  const value = {
272
195
  um: "hi",
273
196
  };
274
197
  const allowed = [randomString()];
275
198
  const channels = [randomString()];
276
- const putted = await graffiti.put<{}>(
199
+ const posted = await graffiti.post<{}>(
277
200
  { value, allowed, channels },
278
201
  session1,
279
202
  );
280
203
 
281
204
  // Get it with authenticated session
282
- const gotten = await graffiti.get(putted, {}, session1);
205
+ const gotten = await graffiti.get(posted, {}, session1);
206
+ expect(gotten.url).toEqual(posted.url);
207
+ expect(gotten.actor).toEqual(session1.actor);
283
208
  expect(gotten.value).toEqual(value);
284
209
  expect(gotten.allowed).toEqual(allowed);
285
210
  expect(gotten.channels).toEqual(channels);
286
211
 
287
212
  // But not without session
288
- await expect(graffiti.get(putted, {})).rejects.toBeInstanceOf(
213
+ await expect(graffiti.get(posted, {})).rejects.toBeInstanceOf(
289
214
  GraffitiErrorNotFound,
290
215
  );
291
216
 
292
217
  // Or the wrong session
293
- await expect(graffiti.get(putted, {}, session2)).rejects.toBeInstanceOf(
218
+ await expect(graffiti.get(posted, {}, session2)).rejects.toBeInstanceOf(
294
219
  GraffitiErrorNotFound,
295
220
  );
296
221
  });
297
222
 
298
- it("put and get with specific access control", async () => {
223
+ it("post and get with specific access control", async () => {
299
224
  const value = {
300
225
  um: "hi",
301
226
  };
302
227
  const allowed = [randomString(), session2.actor, randomString()];
303
228
  const channels = [randomString()];
304
- const putted = await graffiti.put<{}>(
229
+ const posted = await graffiti.post<{}>(
305
230
  {
306
231
  value,
307
232
  allowed,
@@ -311,230 +236,27 @@ export const graffitiCRUDTests = (
311
236
  );
312
237
 
313
238
  // Get it with authenticated session
314
- const gotten = await graffiti.get(putted, {}, session1);
239
+ const gotten = await graffiti.get(posted, {}, session1);
240
+ expect(gotten.url).toEqual(posted.url);
241
+ expect(gotten.actor).toEqual(session1.actor);
315
242
  expect(gotten.value).toEqual(value);
316
243
  expect(gotten.allowed).toEqual(allowed);
317
244
  expect(gotten.channels).toEqual(channels);
318
245
 
319
246
  // But not without session
320
- await expect(graffiti.get(putted, {})).rejects.toBeInstanceOf(
247
+ await expect(graffiti.get(posted, {})).rejects.toBeInstanceOf(
321
248
  GraffitiErrorNotFound,
322
249
  );
323
250
 
324
- const gotten2 = await graffiti.get(putted, {}, session2);
251
+ const gotten2 = await graffiti.get(posted, {}, session2);
252
+ expect(gotten.url).toEqual(posted.url);
253
+ expect(gotten.actor).toEqual(session1.actor);
325
254
  expect(gotten2.value).toEqual(value);
326
255
  // They should only see that is is private to them
327
256
  expect(gotten2.allowed).toEqual([session2.actor]);
328
257
  // And not see any channels
329
258
  expect(gotten2.channels).toEqual([]);
330
259
  });
331
-
332
- it("patch value", async () => {
333
- const value = {
334
- something: "hello, world~ c:",
335
- };
336
- const putted = await graffiti.put<{}>({ value, channels: [] }, session);
337
-
338
- // Wait just a bit to make sure the lastModified is different
339
- await new Promise((resolve) => setTimeout(resolve, 10));
340
-
341
- const patch: GraffitiPatch = {
342
- value: [
343
- { op: "replace", path: "/something", value: "goodbye, world~ :c" },
344
- ],
345
- };
346
- const beforePatched = await graffiti.patch(patch, putted, session);
347
- expect(beforePatched.value).toEqual(value);
348
- expect(beforePatched.lastModified).toBeGreaterThan(putted.lastModified);
349
-
350
- const gotten = await graffiti.get(putted, {});
351
- expect(gotten.value).toEqual({
352
- something: "goodbye, world~ :c",
353
- });
354
- expect(beforePatched.lastModified).toBe(gotten.lastModified);
355
-
356
- await graffiti.delete(putted, session);
357
- });
358
-
359
- it("patch deleted object", async () => {
360
- const putted = await graffiti.put<{}>(randomPutObject(), session);
361
- const deleted = await graffiti.delete(putted, session);
362
- await expect(
363
- graffiti.patch({}, putted, session),
364
- ).rejects.toBeInstanceOf(GraffitiErrorNotFound);
365
- });
366
-
367
- it("deep patch", async () => {
368
- const value = {
369
- something: {
370
- another: {
371
- somethingElse: "hello",
372
- },
373
- },
374
- };
375
- const putted = await graffiti.put<{}>(
376
- { value: value, channels: [] },
377
- session,
378
- );
379
-
380
- const beforePatch = await graffiti.patch(
381
- {
382
- value: [
383
- {
384
- op: "replace",
385
- path: "/something/another/somethingElse",
386
- value: "goodbye",
387
- },
388
- ],
389
- },
390
- putted,
391
- session,
392
- );
393
- const gotten = await graffiti.get(putted, {});
394
-
395
- expect(beforePatch.value).toEqual(value);
396
- expect(gotten.value).toEqual({
397
- something: {
398
- another: {
399
- somethingElse: "goodbye",
400
- },
401
- },
402
- });
403
- });
404
-
405
- it("patch channels", async () => {
406
- const channelsBefore = [randomString()];
407
- const channelsAfter = [randomString()];
408
-
409
- const putted = await graffiti.put<{}>(
410
- { value: {}, channels: channelsBefore },
411
- session,
412
- );
413
-
414
- const patch: GraffitiPatch = {
415
- channels: [{ op: "replace", path: "/0", value: channelsAfter[0] }],
416
- };
417
- const patched = await graffiti.patch(patch, putted, session);
418
- expect(patched.channels).toEqual(channelsBefore);
419
- const gotten = await graffiti.get(putted, {}, session);
420
- expect(gotten.channels).toEqual(channelsAfter);
421
- await graffiti.delete(putted, session);
422
- });
423
-
424
- it("patch 'increment' with test", async () => {
425
- const putted = await graffiti.put<{}>(
426
- {
427
- value: {
428
- counter: 1,
429
- },
430
- channels: [],
431
- },
432
- session,
433
- );
434
-
435
- const previous = await graffiti.patch(
436
- {
437
- value: [
438
- { op: "test", path: "/counter", value: 1 },
439
- { op: "replace", path: "/counter", value: 2 },
440
- ],
441
- },
442
- putted,
443
- session,
444
- );
445
- expect(previous.value).toEqual({ counter: 1 });
446
- const result = await graffiti.get(previous, {
447
- properties: {
448
- value: {
449
- properties: {
450
- counter: {
451
- type: "integer",
452
- },
453
- },
454
- },
455
- },
456
- });
457
- expect(result.value.counter).toEqual(2);
458
-
459
- await expect(
460
- graffiti.patch(
461
- {
462
- value: [
463
- { op: "test", path: "/counter", value: 1 },
464
- { op: "replace", path: "/counter", value: 3 },
465
- ],
466
- },
467
- putted,
468
- session,
469
- ),
470
- ).rejects.toThrow(GraffitiErrorPatchTestFailed);
471
- });
472
-
473
- it("invalid patch", async () => {
474
- const object = randomPutObject();
475
- const putted = await graffiti.put<{}>(object, session);
476
-
477
- await expect(
478
- graffiti.patch(
479
- {
480
- value: [
481
- { op: "add", path: "/root", value: [] },
482
- { op: "add", path: "/root/2", value: 2 }, // out of bounds
483
- ],
484
- },
485
- putted,
486
- session,
487
- ),
488
- ).rejects.toThrow(GraffitiErrorPatchError);
489
- });
490
-
491
- it("patch channels to be wrong", async () => {
492
- const object = randomPutObject();
493
- object.allowed = [randomString()];
494
- const putted = await graffiti.put<{}>(object, session);
495
-
496
- const patches: GraffitiPatch[] = [
497
- {
498
- channels: [{ op: "replace", path: "", value: null }],
499
- },
500
- {
501
- channels: [{ op: "replace", path: "", value: {} }],
502
- },
503
- {
504
- channels: [{ op: "replace", path: "", value: ["hello", ["hi"]] }],
505
- },
506
- {
507
- channels: [{ op: "add", path: "/0", value: 1 }],
508
- },
509
- {
510
- value: [{ op: "replace", path: "", value: "not an object" }],
511
- },
512
- {
513
- value: [{ op: "replace", path: "", value: null }],
514
- },
515
- {
516
- value: [{ op: "replace", path: "", value: [] }],
517
- },
518
- {
519
- allowed: [{ op: "replace", path: "", value: {} }],
520
- },
521
- {
522
- allowed: [{ op: "replace", path: "", value: ["hello", ["hi"]] }],
523
- },
524
- ];
525
-
526
- for (const patch of patches) {
527
- await expect(graffiti.patch(patch, putted, session)).rejects.toThrow(
528
- GraffitiErrorPatchError,
529
- );
530
- }
531
-
532
- const gotten = await graffiti.get(putted, {}, session);
533
- expect(gotten.value).toEqual(object.value);
534
- expect(gotten.channels).toEqual(object.channels);
535
- expect(gotten.allowed).toEqual(object.allowed);
536
- expect(gotten.lastModified).toEqual(putted.lastModified);
537
- });
538
260
  },
539
261
  );
540
262
  };