graphql-shield-node23 7.6.5
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/CHANGELOG.md +31 -0
- package/dist/cjs/constructors.js +134 -0
- package/dist/cjs/generator.js +205 -0
- package/dist/cjs/index.js +15 -0
- package/dist/cjs/package.json +1 -0
- package/dist/cjs/rules.js +402 -0
- package/dist/cjs/shield.js +52 -0
- package/dist/cjs/types.js +2 -0
- package/dist/cjs/utils.js +97 -0
- package/dist/cjs/validation.js +84 -0
- package/dist/esm/constructors.js +124 -0
- package/dist/esm/generator.js +201 -0
- package/dist/esm/index.js +2 -0
- package/dist/esm/rules.js +366 -0
- package/dist/esm/shield.js +45 -0
- package/dist/esm/types.js +1 -0
- package/dist/esm/utils.js +88 -0
- package/dist/esm/validation.js +79 -0
- package/dist/package.json +47 -0
- package/dist/typings/constructors.d.cts +91 -0
- package/dist/typings/constructors.d.ts +91 -0
- package/dist/typings/generator.d.cts +11 -0
- package/dist/typings/generator.d.ts +11 -0
- package/dist/typings/index.d.cts +3 -0
- package/dist/typings/index.d.ts +3 -0
- package/dist/typings/rules.d.cts +159 -0
- package/dist/typings/rules.d.ts +159 -0
- package/dist/typings/shield.d.cts +11 -0
- package/dist/typings/shield.d.ts +11 -0
- package/dist/typings/types.d.cts +64 -0
- package/dist/typings/types.d.ts +64 -0
- package/dist/typings/utils.d.cts +52 -0
- package/dist/typings/utils.d.ts +52 -0
- package/dist/typings/validation.d.cts +19 -0
- package/dist/typings/validation.d.ts +19 -0
- package/package.json +67 -0
- package/src/constructors.ts +157 -0
- package/src/generator.ts +294 -0
- package/src/index.ts +13 -0
- package/src/rules.ts +521 -0
- package/src/shield.ts +53 -0
- package/src/types.ts +94 -0
- package/src/utils.ts +101 -0
- package/src/validation.ts +90 -0
- package/tests/__snapshots__/input.test.ts.snap +7 -0
- package/tests/cache.test.ts +545 -0
- package/tests/constructors.test.ts +136 -0
- package/tests/fallback.test.ts +618 -0
- package/tests/fragments.test.ts +113 -0
- package/tests/generator.test.ts +356 -0
- package/tests/input.test.ts +63 -0
- package/tests/integration.test.ts +65 -0
- package/tests/logic.test.ts +530 -0
- package/tests/utils.test.ts +55 -0
- package/tests/validation.test.ts +139 -0
- package/tsconfig.json +10 -0
|
@@ -0,0 +1,545 @@
|
|
|
1
|
+
import { graphql } from 'graphql'
|
|
2
|
+
import { applyMiddleware } from 'graphql-middleware'
|
|
3
|
+
import { makeExecutableSchema } from '@graphql-tools/schema'
|
|
4
|
+
import { shield, rule } from '../src/index'
|
|
5
|
+
import { IHashFunction } from '../src/types'
|
|
6
|
+
|
|
7
|
+
describe('caching:', () => {
|
|
8
|
+
test('Strict cache - Rule is called multiple times, based on different parent.', async () => {
|
|
9
|
+
/* Schema */
|
|
10
|
+
|
|
11
|
+
const typeDefs = `
|
|
12
|
+
type Query {
|
|
13
|
+
test: [Test!]!
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
type Test {
|
|
17
|
+
value: String!
|
|
18
|
+
}
|
|
19
|
+
`
|
|
20
|
+
const resolvers = {
|
|
21
|
+
Query: {
|
|
22
|
+
test: () => [
|
|
23
|
+
{ value: 'pass-A' },
|
|
24
|
+
{ value: 'pass-A' },
|
|
25
|
+
{ value: 'pass-B' },
|
|
26
|
+
],
|
|
27
|
+
},
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const schema = makeExecutableSchema({
|
|
31
|
+
typeDefs,
|
|
32
|
+
resolvers,
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
/* Permissions */
|
|
36
|
+
|
|
37
|
+
const allowMock = jest.fn().mockResolvedValue(true)
|
|
38
|
+
const permissions = shield({
|
|
39
|
+
Test: rule({ cache: 'strict' })(allowMock),
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
const schemaWithPermissions = applyMiddleware(schema, permissions)
|
|
43
|
+
|
|
44
|
+
/* Execution */
|
|
45
|
+
|
|
46
|
+
const query = `
|
|
47
|
+
query {
|
|
48
|
+
test {
|
|
49
|
+
value
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
`
|
|
53
|
+
const res = await graphql({
|
|
54
|
+
schema: schemaWithPermissions,
|
|
55
|
+
source: query,
|
|
56
|
+
contextValue: {},
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
expect(res).toEqual({
|
|
60
|
+
data: {
|
|
61
|
+
test: [{ value: 'pass-A' }, { value: 'pass-A' }, { value: 'pass-B' }],
|
|
62
|
+
},
|
|
63
|
+
})
|
|
64
|
+
expect(allowMock).toBeCalledTimes(2)
|
|
65
|
+
})
|
|
66
|
+
|
|
67
|
+
test('Strict cache - Rule is called multiple times, based on different arguments.', async () => {
|
|
68
|
+
/* Schema */
|
|
69
|
+
|
|
70
|
+
const typeDefs = `
|
|
71
|
+
type Query {
|
|
72
|
+
a: String!
|
|
73
|
+
b: String!
|
|
74
|
+
c(arg: String): String!
|
|
75
|
+
d(arg: String): String!
|
|
76
|
+
e(arg: String): String!
|
|
77
|
+
}
|
|
78
|
+
`
|
|
79
|
+
const resolvers = {
|
|
80
|
+
Query: {
|
|
81
|
+
a: () => 'a',
|
|
82
|
+
b: () => 'b',
|
|
83
|
+
c: () => 'c',
|
|
84
|
+
d: () => 'd',
|
|
85
|
+
e: () => 'e',
|
|
86
|
+
},
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const schema = makeExecutableSchema({
|
|
90
|
+
typeDefs,
|
|
91
|
+
resolvers,
|
|
92
|
+
})
|
|
93
|
+
|
|
94
|
+
/* Tests */
|
|
95
|
+
|
|
96
|
+
const allowMock = jest.fn().mockResolvedValue(true)
|
|
97
|
+
|
|
98
|
+
const permissions = shield({
|
|
99
|
+
Query: rule({ cache: 'strict' })(allowMock),
|
|
100
|
+
})
|
|
101
|
+
|
|
102
|
+
const schemaWithPermissions = applyMiddleware(schema, permissions)
|
|
103
|
+
|
|
104
|
+
/* Execution */
|
|
105
|
+
|
|
106
|
+
const query = `
|
|
107
|
+
query {
|
|
108
|
+
a
|
|
109
|
+
b
|
|
110
|
+
c(arg: "foo")
|
|
111
|
+
d(arg: "bar")
|
|
112
|
+
e
|
|
113
|
+
f: c(arg: "foo")
|
|
114
|
+
}
|
|
115
|
+
`
|
|
116
|
+
const res = await graphql({
|
|
117
|
+
schema: schemaWithPermissions,
|
|
118
|
+
source: query,
|
|
119
|
+
contextValue: {},
|
|
120
|
+
})
|
|
121
|
+
|
|
122
|
+
/* Tests */
|
|
123
|
+
|
|
124
|
+
expect(res).toEqual({
|
|
125
|
+
data: {
|
|
126
|
+
a: 'a',
|
|
127
|
+
b: 'b',
|
|
128
|
+
c: 'c',
|
|
129
|
+
d: 'd',
|
|
130
|
+
e: 'e',
|
|
131
|
+
f: 'c',
|
|
132
|
+
},
|
|
133
|
+
})
|
|
134
|
+
expect(allowMock).toBeCalledTimes(3)
|
|
135
|
+
})
|
|
136
|
+
|
|
137
|
+
test('Contextual Cache - rules get executed only once if reused.', async () => {
|
|
138
|
+
/* Schema */
|
|
139
|
+
|
|
140
|
+
const typeDefs = `
|
|
141
|
+
type Query {
|
|
142
|
+
a: String!
|
|
143
|
+
b: String!
|
|
144
|
+
c(arg: String): String!
|
|
145
|
+
d(arg: String): String!
|
|
146
|
+
e(arg: String): String!
|
|
147
|
+
}
|
|
148
|
+
`
|
|
149
|
+
const resolvers = {
|
|
150
|
+
Query: {
|
|
151
|
+
a: () => 'a',
|
|
152
|
+
b: () => 'b',
|
|
153
|
+
c: () => 'c',
|
|
154
|
+
d: () => 'd',
|
|
155
|
+
e: () => 'e',
|
|
156
|
+
},
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
const schema = makeExecutableSchema({
|
|
160
|
+
typeDefs,
|
|
161
|
+
resolvers,
|
|
162
|
+
})
|
|
163
|
+
|
|
164
|
+
/* Permissions */
|
|
165
|
+
|
|
166
|
+
const ruleOneMock = jest.fn().mockResolvedValue(true)
|
|
167
|
+
const ruleOne = rule({ cache: 'contextual' })(ruleOneMock)
|
|
168
|
+
|
|
169
|
+
const ruleTwoMock = jest.fn().mockResolvedValue(true)
|
|
170
|
+
const ruleTwo = rule({ cache: 'contextual' })(ruleTwoMock)
|
|
171
|
+
|
|
172
|
+
const permissions = shield({
|
|
173
|
+
Query: {
|
|
174
|
+
a: ruleOne,
|
|
175
|
+
b: ruleOne,
|
|
176
|
+
c: ruleOne,
|
|
177
|
+
d: ruleTwo,
|
|
178
|
+
e: ruleTwo,
|
|
179
|
+
},
|
|
180
|
+
})
|
|
181
|
+
|
|
182
|
+
const schemaWithPermissions = applyMiddleware(schema, permissions)
|
|
183
|
+
|
|
184
|
+
// Execution
|
|
185
|
+
const query = `
|
|
186
|
+
query {
|
|
187
|
+
a
|
|
188
|
+
b
|
|
189
|
+
c(arg: "foo")
|
|
190
|
+
d(arg: "bar")
|
|
191
|
+
e
|
|
192
|
+
}
|
|
193
|
+
`
|
|
194
|
+
const res = await graphql({
|
|
195
|
+
schema: schemaWithPermissions,
|
|
196
|
+
source: query,
|
|
197
|
+
contextValue: {},
|
|
198
|
+
})
|
|
199
|
+
|
|
200
|
+
/* Tests */
|
|
201
|
+
|
|
202
|
+
expect(res).toEqual({
|
|
203
|
+
data: {
|
|
204
|
+
a: 'a',
|
|
205
|
+
b: 'b',
|
|
206
|
+
c: 'c',
|
|
207
|
+
d: 'd',
|
|
208
|
+
e: 'e',
|
|
209
|
+
},
|
|
210
|
+
})
|
|
211
|
+
expect(ruleOneMock).toBeCalledTimes(1)
|
|
212
|
+
expect(ruleTwoMock).toBeCalledTimes(1)
|
|
213
|
+
})
|
|
214
|
+
|
|
215
|
+
test('No Cache - rule is reexecuted every time.', async () => {
|
|
216
|
+
/* Schema */
|
|
217
|
+
|
|
218
|
+
const typeDefs = `
|
|
219
|
+
type Query {
|
|
220
|
+
a: String!
|
|
221
|
+
b: String!
|
|
222
|
+
c(arg: String): String!
|
|
223
|
+
d(arg: String): String!
|
|
224
|
+
e(arg: String): String!
|
|
225
|
+
}
|
|
226
|
+
`
|
|
227
|
+
const resolvers = {
|
|
228
|
+
Query: {
|
|
229
|
+
a: () => 'a',
|
|
230
|
+
b: () => 'b',
|
|
231
|
+
c: () => 'c',
|
|
232
|
+
d: () => 'd',
|
|
233
|
+
e: () => 'e',
|
|
234
|
+
},
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
const schema = makeExecutableSchema({
|
|
238
|
+
typeDefs,
|
|
239
|
+
resolvers,
|
|
240
|
+
})
|
|
241
|
+
|
|
242
|
+
/* Permissions */
|
|
243
|
+
|
|
244
|
+
const allowMock = jest.fn().mockResolvedValue(true)
|
|
245
|
+
const allow = rule({ cache: 'no_cache' })(allowMock)
|
|
246
|
+
|
|
247
|
+
const permissions = shield({
|
|
248
|
+
Query: allow,
|
|
249
|
+
})
|
|
250
|
+
|
|
251
|
+
const schemaWithPermissions = applyMiddleware(schema, permissions)
|
|
252
|
+
|
|
253
|
+
/* Execution */
|
|
254
|
+
|
|
255
|
+
const query = `
|
|
256
|
+
query {
|
|
257
|
+
a
|
|
258
|
+
b
|
|
259
|
+
c(arg: "foo")
|
|
260
|
+
d(arg: "bar")
|
|
261
|
+
e
|
|
262
|
+
}
|
|
263
|
+
`
|
|
264
|
+
const res = await graphql({
|
|
265
|
+
schema: schemaWithPermissions,
|
|
266
|
+
source: query,
|
|
267
|
+
contextValue: {},
|
|
268
|
+
})
|
|
269
|
+
|
|
270
|
+
/* Tests */
|
|
271
|
+
|
|
272
|
+
expect(res).toEqual({
|
|
273
|
+
data: {
|
|
274
|
+
a: 'a',
|
|
275
|
+
b: 'b',
|
|
276
|
+
c: 'c',
|
|
277
|
+
d: 'd',
|
|
278
|
+
e: 'e',
|
|
279
|
+
},
|
|
280
|
+
})
|
|
281
|
+
expect(allowMock).toBeCalledTimes(5)
|
|
282
|
+
})
|
|
283
|
+
|
|
284
|
+
test('Custom cache key function - Rule is called based on custom cache key', async () => {
|
|
285
|
+
/* Schema */
|
|
286
|
+
const typeDefs = `
|
|
287
|
+
type Query {
|
|
288
|
+
a(arg: String): String!
|
|
289
|
+
b(arg: String): String!
|
|
290
|
+
}
|
|
291
|
+
`
|
|
292
|
+
const resolvers = {
|
|
293
|
+
Query: {
|
|
294
|
+
a: () => 'a',
|
|
295
|
+
b: () => 'b',
|
|
296
|
+
},
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
const schema = makeExecutableSchema({
|
|
300
|
+
typeDefs,
|
|
301
|
+
resolvers,
|
|
302
|
+
})
|
|
303
|
+
|
|
304
|
+
/* Tests */
|
|
305
|
+
|
|
306
|
+
const allowMock = jest.fn().mockResolvedValue(true)
|
|
307
|
+
|
|
308
|
+
const permissions = shield({
|
|
309
|
+
Query: rule({
|
|
310
|
+
cache: (parent, args, ctx, info) => {
|
|
311
|
+
return JSON.stringify(args)
|
|
312
|
+
},
|
|
313
|
+
})(allowMock),
|
|
314
|
+
})
|
|
315
|
+
|
|
316
|
+
const schemaWithPermissions = applyMiddleware(schema, permissions)
|
|
317
|
+
|
|
318
|
+
/* Execution */
|
|
319
|
+
|
|
320
|
+
const query = `
|
|
321
|
+
query {
|
|
322
|
+
a(arg: "foo")
|
|
323
|
+
b(arg: "bar")
|
|
324
|
+
a2: a(arg: "foo")
|
|
325
|
+
a3: a(arg: "boo")
|
|
326
|
+
}
|
|
327
|
+
`
|
|
328
|
+
const res = await graphql({
|
|
329
|
+
schema: schemaWithPermissions,
|
|
330
|
+
source: query,
|
|
331
|
+
contextValue: {},
|
|
332
|
+
})
|
|
333
|
+
|
|
334
|
+
/* Tests */
|
|
335
|
+
|
|
336
|
+
expect(res).toEqual({
|
|
337
|
+
data: {
|
|
338
|
+
a: 'a',
|
|
339
|
+
b: 'b',
|
|
340
|
+
a2: 'a',
|
|
341
|
+
a3: 'a',
|
|
342
|
+
},
|
|
343
|
+
})
|
|
344
|
+
expect(allowMock).toBeCalledTimes(3)
|
|
345
|
+
})
|
|
346
|
+
})
|
|
347
|
+
|
|
348
|
+
test('Customize hash function', async () => {
|
|
349
|
+
/* Schema */
|
|
350
|
+
const typeDefs = `
|
|
351
|
+
type Query {
|
|
352
|
+
a(arg: String): String!
|
|
353
|
+
b(arg: String): String!
|
|
354
|
+
}
|
|
355
|
+
`
|
|
356
|
+
const resolvers = {
|
|
357
|
+
Query: {
|
|
358
|
+
a: () => 'a',
|
|
359
|
+
b: () => 'b',
|
|
360
|
+
},
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
const schema = makeExecutableSchema({
|
|
364
|
+
typeDefs,
|
|
365
|
+
resolvers,
|
|
366
|
+
})
|
|
367
|
+
|
|
368
|
+
/* Tests */
|
|
369
|
+
|
|
370
|
+
const allowMock = jest.fn().mockResolvedValue(true)
|
|
371
|
+
|
|
372
|
+
const hashFunction: IHashFunction = jest.fn((opts) => JSON.stringify(opts))
|
|
373
|
+
|
|
374
|
+
const permissions = shield(
|
|
375
|
+
{
|
|
376
|
+
Query: rule({ cache: 'strict' })(allowMock),
|
|
377
|
+
},
|
|
378
|
+
{
|
|
379
|
+
hashFunction,
|
|
380
|
+
},
|
|
381
|
+
)
|
|
382
|
+
|
|
383
|
+
const schemaWithPermissions = applyMiddleware(schema, permissions)
|
|
384
|
+
|
|
385
|
+
/* Execution */
|
|
386
|
+
|
|
387
|
+
const query = `
|
|
388
|
+
query {
|
|
389
|
+
a(arg: "foo")
|
|
390
|
+
b(arg: "bar")
|
|
391
|
+
}
|
|
392
|
+
`
|
|
393
|
+
const res = await graphql({
|
|
394
|
+
schema: schemaWithPermissions,
|
|
395
|
+
source: query,
|
|
396
|
+
contextValue: {},
|
|
397
|
+
})
|
|
398
|
+
|
|
399
|
+
/* Tests */
|
|
400
|
+
|
|
401
|
+
expect(res).toEqual({
|
|
402
|
+
data: {
|
|
403
|
+
a: 'a',
|
|
404
|
+
b: 'b',
|
|
405
|
+
},
|
|
406
|
+
})
|
|
407
|
+
expect(allowMock).toBeCalledTimes(2)
|
|
408
|
+
expect(hashFunction).toHaveBeenCalledTimes(2)
|
|
409
|
+
expect(hashFunction).toHaveBeenCalledWith({
|
|
410
|
+
parent: undefined,
|
|
411
|
+
args: { arg: 'foo' },
|
|
412
|
+
})
|
|
413
|
+
expect(hashFunction).toHaveBeenCalledWith({
|
|
414
|
+
parent: undefined,
|
|
415
|
+
args: { arg: 'bar' },
|
|
416
|
+
})
|
|
417
|
+
})
|
|
418
|
+
|
|
419
|
+
describe('legacy cache:', () => {
|
|
420
|
+
test('Strict cache - Rule is called multiple times, based on different parent.', async () => {
|
|
421
|
+
/* Schema */
|
|
422
|
+
|
|
423
|
+
const typeDefs = `
|
|
424
|
+
type Query {
|
|
425
|
+
test: [Test!]!
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
type Test {
|
|
429
|
+
value: String!
|
|
430
|
+
}
|
|
431
|
+
`
|
|
432
|
+
const resolvers = {
|
|
433
|
+
Query: {
|
|
434
|
+
test: () => [
|
|
435
|
+
{ value: 'pass-A' },
|
|
436
|
+
{ value: 'pass-A' },
|
|
437
|
+
{ value: 'pass-B' },
|
|
438
|
+
],
|
|
439
|
+
},
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
const schema = makeExecutableSchema({
|
|
443
|
+
typeDefs,
|
|
444
|
+
resolvers,
|
|
445
|
+
})
|
|
446
|
+
|
|
447
|
+
/* Permissions */
|
|
448
|
+
|
|
449
|
+
const allowMock = jest.fn().mockResolvedValue(true)
|
|
450
|
+
const permissions = shield({
|
|
451
|
+
Test: rule({ cache: true })(allowMock),
|
|
452
|
+
})
|
|
453
|
+
|
|
454
|
+
const schemaWithPermissions = applyMiddleware(schema, permissions)
|
|
455
|
+
|
|
456
|
+
/* Execution */
|
|
457
|
+
|
|
458
|
+
const query = `
|
|
459
|
+
query {
|
|
460
|
+
test {
|
|
461
|
+
value
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
`
|
|
465
|
+
const res = await graphql({
|
|
466
|
+
schema: schemaWithPermissions,
|
|
467
|
+
source: query,
|
|
468
|
+
contextValue: {},
|
|
469
|
+
})
|
|
470
|
+
|
|
471
|
+
/* Tests */
|
|
472
|
+
|
|
473
|
+
expect(res).toEqual({
|
|
474
|
+
data: {
|
|
475
|
+
test: [{ value: 'pass-A' }, { value: 'pass-A' }, { value: 'pass-B' }],
|
|
476
|
+
},
|
|
477
|
+
})
|
|
478
|
+
expect(allowMock).toBeCalledTimes(2)
|
|
479
|
+
})
|
|
480
|
+
|
|
481
|
+
test('No Cache - rule is reexecuted every time.', async () => {
|
|
482
|
+
/* Schema */
|
|
483
|
+
|
|
484
|
+
const typeDefs = `
|
|
485
|
+
type Query {
|
|
486
|
+
a: String!
|
|
487
|
+
b: String!
|
|
488
|
+
c(arg: String): String!
|
|
489
|
+
d(arg: String): String!
|
|
490
|
+
e(arg: String): String!
|
|
491
|
+
}
|
|
492
|
+
`
|
|
493
|
+
const resolvers = {
|
|
494
|
+
Query: {
|
|
495
|
+
a: () => 'a',
|
|
496
|
+
b: () => 'b',
|
|
497
|
+
c: () => 'c',
|
|
498
|
+
d: () => 'd',
|
|
499
|
+
e: () => 'e',
|
|
500
|
+
},
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
const schema = makeExecutableSchema({
|
|
504
|
+
typeDefs,
|
|
505
|
+
resolvers,
|
|
506
|
+
})
|
|
507
|
+
|
|
508
|
+
/* Permissions */
|
|
509
|
+
const allowMock = jest.fn().mockResolvedValue(true)
|
|
510
|
+
const allow = rule({ cache: false })(allowMock)
|
|
511
|
+
|
|
512
|
+
const permissions = shield({
|
|
513
|
+
Query: allow,
|
|
514
|
+
})
|
|
515
|
+
|
|
516
|
+
const schemaWithPermissions = applyMiddleware(schema, permissions)
|
|
517
|
+
|
|
518
|
+
// Execution
|
|
519
|
+
const query = `
|
|
520
|
+
query {
|
|
521
|
+
a
|
|
522
|
+
b
|
|
523
|
+
c(arg: "foo")
|
|
524
|
+
d(arg: "bar")
|
|
525
|
+
e
|
|
526
|
+
}
|
|
527
|
+
`
|
|
528
|
+
const res = await graphql({
|
|
529
|
+
schema: schemaWithPermissions,
|
|
530
|
+
source: query,
|
|
531
|
+
contextValue: {},
|
|
532
|
+
})
|
|
533
|
+
|
|
534
|
+
expect(res).toEqual({
|
|
535
|
+
data: {
|
|
536
|
+
a: 'a',
|
|
537
|
+
b: 'b',
|
|
538
|
+
c: 'c',
|
|
539
|
+
d: 'd',
|
|
540
|
+
e: 'e',
|
|
541
|
+
},
|
|
542
|
+
})
|
|
543
|
+
expect(allowMock).toBeCalledTimes(5)
|
|
544
|
+
})
|
|
545
|
+
})
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import * as Yup from 'yup'
|
|
2
|
+
import { rule, and, or, not, allow, deny, inputRule, chain } from '../src/constructors'
|
|
3
|
+
import { RuleAnd, RuleOr, RuleNot, RuleTrue, RuleFalse, Rule, InputRule, RuleChain } from '../src/rules'
|
|
4
|
+
|
|
5
|
+
describe('rule constructor', () => {
|
|
6
|
+
beforeEach(() => {
|
|
7
|
+
jest.restoreAllMocks()
|
|
8
|
+
})
|
|
9
|
+
|
|
10
|
+
test('correctly constructs from no arguments', async () => {
|
|
11
|
+
/* Mocks */
|
|
12
|
+
|
|
13
|
+
const n = Math.random()
|
|
14
|
+
jest.spyOn(Math, 'random').mockReturnValue(n)
|
|
15
|
+
|
|
16
|
+
/* Tests */
|
|
17
|
+
|
|
18
|
+
const func = () => true
|
|
19
|
+
|
|
20
|
+
expect(rule()(func)).toEqual(new Rule(n.toString(), func, {}))
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
test('correctly constructs with name and options', async () => {
|
|
24
|
+
const func = () => true
|
|
25
|
+
|
|
26
|
+
expect(
|
|
27
|
+
rule('name', {
|
|
28
|
+
cache: 'contextual',
|
|
29
|
+
fragment: 'fragment',
|
|
30
|
+
})(func),
|
|
31
|
+
).toEqual(new Rule('name', func, { cache: 'contextual', fragment: 'fragment' }))
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
test('correctly constructs with name but no options', async () => {
|
|
35
|
+
const func = () => true
|
|
36
|
+
|
|
37
|
+
expect(rule('name')(func)).toEqual(new Rule('name', func, {}))
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
test('correctly constructs with options', async () => {
|
|
41
|
+
/* Mocks */
|
|
42
|
+
const n = Math.random()
|
|
43
|
+
jest.spyOn(Math, 'random').mockReturnValue(n)
|
|
44
|
+
|
|
45
|
+
/* Tests */
|
|
46
|
+
|
|
47
|
+
const func = () => true
|
|
48
|
+
|
|
49
|
+
expect(
|
|
50
|
+
rule({
|
|
51
|
+
cache: 'contextual',
|
|
52
|
+
fragment: 'fragment',
|
|
53
|
+
})(func),
|
|
54
|
+
).toEqual(
|
|
55
|
+
new Rule(n.toString(), func, {
|
|
56
|
+
cache: 'contextual',
|
|
57
|
+
fragment: 'fragment',
|
|
58
|
+
}),
|
|
59
|
+
)
|
|
60
|
+
})
|
|
61
|
+
})
|
|
62
|
+
|
|
63
|
+
describe('input rules constructor', () => {
|
|
64
|
+
test('correnctly constructs an input rule with name', async () => {
|
|
65
|
+
const name = Math.random().toString()
|
|
66
|
+
let schema: Yup.ObjectSchema<{}>
|
|
67
|
+
|
|
68
|
+
const rule = inputRule(name)((yup) => {
|
|
69
|
+
schema = yup.object().shape({}).required()
|
|
70
|
+
return schema
|
|
71
|
+
})
|
|
72
|
+
expect(JSON.stringify(rule)).toEqual(JSON.stringify(new InputRule(name, () => schema)))
|
|
73
|
+
})
|
|
74
|
+
|
|
75
|
+
test('correnctly constructs an input rule', async () => {
|
|
76
|
+
const n = Math.random()
|
|
77
|
+
jest.spyOn(Math, 'random').mockReturnValue(n)
|
|
78
|
+
|
|
79
|
+
let schema: Yup.ObjectSchema<{}>
|
|
80
|
+
|
|
81
|
+
const rule = inputRule()((yup) => {
|
|
82
|
+
schema = yup.object().shape({}).required()
|
|
83
|
+
return schema
|
|
84
|
+
})
|
|
85
|
+
expect(JSON.stringify(rule)).toEqual(JSON.stringify(new InputRule(n.toString(), () => schema)))
|
|
86
|
+
})
|
|
87
|
+
|
|
88
|
+
test('correctly contructs an input rule with validation options', async () => {
|
|
89
|
+
const n = Math.random()
|
|
90
|
+
jest.spyOn(Math, 'random').mockReturnValue(n)
|
|
91
|
+
|
|
92
|
+
let schema: Yup.ObjectSchema<{}>
|
|
93
|
+
let options = { abortEarly: false }
|
|
94
|
+
|
|
95
|
+
const rule = inputRule()((yup) => {
|
|
96
|
+
schema = yup.object().shape({}).required()
|
|
97
|
+
return schema
|
|
98
|
+
}, options)
|
|
99
|
+
expect(JSON.stringify(rule)).toEqual(JSON.stringify(new InputRule(n.toString(), () => schema, options)))
|
|
100
|
+
})
|
|
101
|
+
})
|
|
102
|
+
|
|
103
|
+
describe('logic rules constructors', () => {
|
|
104
|
+
test('and correctly constructs rule and', async () => {
|
|
105
|
+
const ruleA = rule()(() => true)
|
|
106
|
+
const ruleB = rule()(() => true)
|
|
107
|
+
expect(and(ruleA, ruleB)).toEqual(new RuleAnd([ruleA, ruleB]))
|
|
108
|
+
})
|
|
109
|
+
|
|
110
|
+
test('chain correctly constructs rule chain', async () => {
|
|
111
|
+
const ruleA = rule()(() => true)
|
|
112
|
+
const ruleB = rule()(() => true)
|
|
113
|
+
expect(chain(ruleA, ruleB)).toEqual(new RuleChain([ruleA, ruleB]))
|
|
114
|
+
})
|
|
115
|
+
|
|
116
|
+
test('or correctly constructs rule or', async () => {
|
|
117
|
+
const ruleA = rule()(() => true)
|
|
118
|
+
const ruleB = rule()(() => true)
|
|
119
|
+
expect(or(ruleA, ruleB)).toEqual(new RuleOr([ruleA, ruleB]))
|
|
120
|
+
})
|
|
121
|
+
|
|
122
|
+
test('not correctly constructs rule not', async () => {
|
|
123
|
+
const ruleA = rule()(() => true)
|
|
124
|
+
expect(not(ruleA)).toEqual(new RuleNot(ruleA))
|
|
125
|
+
})
|
|
126
|
+
})
|
|
127
|
+
|
|
128
|
+
describe('basic rules', () => {
|
|
129
|
+
test('rule allow', async () => {
|
|
130
|
+
expect(allow).toEqual(new RuleTrue())
|
|
131
|
+
})
|
|
132
|
+
|
|
133
|
+
test('rule deny', async () => {
|
|
134
|
+
expect(deny).toEqual(new RuleFalse())
|
|
135
|
+
})
|
|
136
|
+
})
|