@pyreon/permissions 0.11.4 → 0.11.6
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/README.md +22 -18
- package/lib/analysis/index.js.html +1 -1
- package/lib/index.js +11 -7
- package/lib/index.js.map +1 -1
- package/package.json +16 -16
- package/src/context.ts +4 -4
- package/src/index.ts +3 -8
- package/src/permissions.ts +18 -14
- package/src/tests/api.test.ts +156 -156
- package/src/tests/context.test.ts +25 -25
- package/src/tests/permissions.test.ts +284 -284
- package/src/tests/predicates.test.ts +74 -74
- package/src/tests/wildcards.test.ts +80 -80
- package/src/types.ts +1 -1
package/src/tests/api.test.ts
CHANGED
|
@@ -1,344 +1,344 @@
|
|
|
1
|
-
import { computed, effect } from
|
|
2
|
-
import { describe, expect, it } from
|
|
3
|
-
import { createPermissions } from
|
|
1
|
+
import { computed, effect } from '@pyreon/reactivity'
|
|
2
|
+
import { describe, expect, it } from 'vitest'
|
|
3
|
+
import { createPermissions } from '../index'
|
|
4
4
|
|
|
5
|
-
describe(
|
|
6
|
-
it(
|
|
5
|
+
describe('createPermissions — can.all()', () => {
|
|
6
|
+
it('returns true when all permissions are granted', () => {
|
|
7
7
|
const can = createPermissions({
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
'posts.read': true,
|
|
9
|
+
'posts.create': true,
|
|
10
|
+
'posts.update': true,
|
|
11
11
|
})
|
|
12
|
-
expect(can.all(
|
|
12
|
+
expect(can.all('posts.read', 'posts.create', 'posts.update')).toBe(true)
|
|
13
13
|
})
|
|
14
14
|
|
|
15
|
-
it(
|
|
15
|
+
it('returns false when any permission is denied', () => {
|
|
16
16
|
const can = createPermissions({
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
17
|
+
'posts.read': true,
|
|
18
|
+
'posts.create': true,
|
|
19
|
+
'posts.delete': false,
|
|
20
20
|
})
|
|
21
|
-
expect(can.all(
|
|
21
|
+
expect(can.all('posts.read', 'posts.create', 'posts.delete')).toBe(false)
|
|
22
22
|
})
|
|
23
23
|
|
|
24
|
-
it(
|
|
25
|
-
const can = createPermissions({
|
|
26
|
-
expect(can.all(
|
|
24
|
+
it('returns false when any permission is undefined', () => {
|
|
25
|
+
const can = createPermissions({ 'posts.read': true })
|
|
26
|
+
expect(can.all('posts.read', 'posts.create')).toBe(false) // posts.create undefined
|
|
27
27
|
})
|
|
28
28
|
|
|
29
|
-
it(
|
|
29
|
+
it('returns true for empty args (vacuous truth)', () => {
|
|
30
30
|
const can = createPermissions()
|
|
31
31
|
expect(can.all()).toBe(true)
|
|
32
32
|
})
|
|
33
33
|
|
|
34
|
-
it(
|
|
35
|
-
const can = createPermissions({
|
|
36
|
-
expect(can.all(
|
|
37
|
-
expect(can.all(
|
|
34
|
+
it('works with wildcards', () => {
|
|
35
|
+
const can = createPermissions({ 'posts.*': true })
|
|
36
|
+
expect(can.all('posts.read', 'posts.create')).toBe(true)
|
|
37
|
+
expect(can.all('posts.read', 'users.manage')).toBe(false)
|
|
38
38
|
})
|
|
39
39
|
|
|
40
|
-
it(
|
|
40
|
+
it('is reactive in effects', () => {
|
|
41
41
|
const can = createPermissions({
|
|
42
|
-
|
|
43
|
-
|
|
42
|
+
'posts.read': true,
|
|
43
|
+
'posts.create': true,
|
|
44
44
|
})
|
|
45
45
|
const results: boolean[] = []
|
|
46
46
|
|
|
47
47
|
effect(() => {
|
|
48
|
-
results.push(can.all(
|
|
48
|
+
results.push(can.all('posts.read', 'posts.create'))
|
|
49
49
|
})
|
|
50
50
|
|
|
51
|
-
can.patch({
|
|
51
|
+
can.patch({ 'posts.create': false })
|
|
52
52
|
expect(results).toEqual([true, false])
|
|
53
53
|
})
|
|
54
54
|
|
|
55
|
-
it(
|
|
55
|
+
it('is reactive in computed', () => {
|
|
56
56
|
const can = createPermissions({
|
|
57
|
-
|
|
58
|
-
|
|
57
|
+
'posts.read': true,
|
|
58
|
+
'posts.create': true,
|
|
59
59
|
})
|
|
60
|
-
const allGranted = computed(() => can.all(
|
|
60
|
+
const allGranted = computed(() => can.all('posts.read', 'posts.create'))
|
|
61
61
|
expect(allGranted()).toBe(true)
|
|
62
62
|
|
|
63
|
-
can.patch({
|
|
63
|
+
can.patch({ 'posts.create': false })
|
|
64
64
|
expect(allGranted()).toBe(false)
|
|
65
65
|
})
|
|
66
66
|
})
|
|
67
67
|
|
|
68
|
-
describe(
|
|
69
|
-
it(
|
|
68
|
+
describe('createPermissions — can.any()', () => {
|
|
69
|
+
it('returns true when at least one permission is granted', () => {
|
|
70
70
|
const can = createPermissions({
|
|
71
|
-
|
|
72
|
-
|
|
71
|
+
'posts.read': false,
|
|
72
|
+
'posts.create': true,
|
|
73
73
|
})
|
|
74
|
-
expect(can.any(
|
|
74
|
+
expect(can.any('posts.read', 'posts.create')).toBe(true)
|
|
75
75
|
})
|
|
76
76
|
|
|
77
|
-
it(
|
|
77
|
+
it('returns false when no permissions are granted', () => {
|
|
78
78
|
const can = createPermissions({
|
|
79
|
-
|
|
80
|
-
|
|
79
|
+
'posts.read': false,
|
|
80
|
+
'posts.create': false,
|
|
81
81
|
})
|
|
82
|
-
expect(can.any(
|
|
82
|
+
expect(can.any('posts.read', 'posts.create')).toBe(false)
|
|
83
83
|
})
|
|
84
84
|
|
|
85
|
-
it(
|
|
85
|
+
it('returns true when all are granted', () => {
|
|
86
86
|
const can = createPermissions({
|
|
87
|
-
|
|
88
|
-
|
|
87
|
+
'posts.read': true,
|
|
88
|
+
'posts.create': true,
|
|
89
89
|
})
|
|
90
|
-
expect(can.any(
|
|
90
|
+
expect(can.any('posts.read', 'posts.create')).toBe(true)
|
|
91
91
|
})
|
|
92
92
|
|
|
93
|
-
it(
|
|
94
|
-
const can = createPermissions({
|
|
93
|
+
it('returns false for empty args', () => {
|
|
94
|
+
const can = createPermissions({ 'posts.read': true })
|
|
95
95
|
expect(can.any()).toBe(false)
|
|
96
96
|
})
|
|
97
97
|
|
|
98
|
-
it(
|
|
99
|
-
const can = createPermissions({
|
|
100
|
-
expect(can.any(
|
|
101
|
-
expect(can.any(
|
|
98
|
+
it('works with undefined permissions', () => {
|
|
99
|
+
const can = createPermissions({ 'posts.read': true })
|
|
100
|
+
expect(can.any('posts.read', 'nonexistent')).toBe(true)
|
|
101
|
+
expect(can.any('nonexistent', 'also-nonexistent')).toBe(false)
|
|
102
102
|
})
|
|
103
103
|
|
|
104
|
-
it(
|
|
105
|
-
const can = createPermissions({
|
|
106
|
-
expect(can.any(
|
|
107
|
-
expect(can.any(
|
|
104
|
+
it('works with wildcards', () => {
|
|
105
|
+
const can = createPermissions({ 'posts.*': true })
|
|
106
|
+
expect(can.any('posts.read', 'users.manage')).toBe(true)
|
|
107
|
+
expect(can.any('users.read', 'users.manage')).toBe(false)
|
|
108
108
|
})
|
|
109
109
|
|
|
110
|
-
it(
|
|
110
|
+
it('is reactive in effects', () => {
|
|
111
111
|
const can = createPermissions({
|
|
112
|
-
|
|
113
|
-
|
|
112
|
+
'posts.read': false,
|
|
113
|
+
'posts.create': true,
|
|
114
114
|
})
|
|
115
115
|
const results: boolean[] = []
|
|
116
116
|
|
|
117
117
|
effect(() => {
|
|
118
|
-
results.push(can.any(
|
|
118
|
+
results.push(can.any('posts.read', 'posts.create'))
|
|
119
119
|
})
|
|
120
120
|
|
|
121
|
-
can.patch({
|
|
121
|
+
can.patch({ 'posts.create': false })
|
|
122
122
|
expect(results).toEqual([true, false])
|
|
123
123
|
})
|
|
124
124
|
})
|
|
125
125
|
|
|
126
|
-
describe(
|
|
127
|
-
it(
|
|
126
|
+
describe('createPermissions — can.not()', () => {
|
|
127
|
+
it('returns inverse of can()', () => {
|
|
128
128
|
const can = createPermissions({
|
|
129
|
-
|
|
130
|
-
|
|
129
|
+
'posts.read': true,
|
|
130
|
+
'posts.delete': false,
|
|
131
131
|
})
|
|
132
|
-
expect(can.not(
|
|
133
|
-
expect(can.not(
|
|
132
|
+
expect(can.not('posts.read')).toBe(false)
|
|
133
|
+
expect(can.not('posts.delete')).toBe(true)
|
|
134
134
|
})
|
|
135
135
|
|
|
136
|
-
it(
|
|
136
|
+
it('returns true for undefined permissions', () => {
|
|
137
137
|
const can = createPermissions()
|
|
138
|
-
expect(can.not(
|
|
138
|
+
expect(can.not('anything')).toBe(true)
|
|
139
139
|
})
|
|
140
140
|
|
|
141
|
-
it(
|
|
141
|
+
it('works with context for predicate permissions', () => {
|
|
142
142
|
const can = createPermissions({
|
|
143
|
-
|
|
143
|
+
'posts.update': (post: any) => post?.authorId === 'me',
|
|
144
144
|
})
|
|
145
|
-
expect(can.not(
|
|
146
|
-
expect(can.not(
|
|
145
|
+
expect(can.not('posts.update', { authorId: 'me' })).toBe(false)
|
|
146
|
+
expect(can.not('posts.update', { authorId: 'other' })).toBe(true)
|
|
147
147
|
})
|
|
148
148
|
|
|
149
|
-
it(
|
|
150
|
-
const can = createPermissions({
|
|
149
|
+
it('is reactive', () => {
|
|
150
|
+
const can = createPermissions({ 'posts.read': true })
|
|
151
151
|
const results: boolean[] = []
|
|
152
152
|
|
|
153
153
|
effect(() => {
|
|
154
|
-
results.push(can.not(
|
|
154
|
+
results.push(can.not('posts.read'))
|
|
155
155
|
})
|
|
156
156
|
|
|
157
|
-
can.set({
|
|
157
|
+
can.set({ 'posts.read': false })
|
|
158
158
|
expect(results).toEqual([false, true])
|
|
159
159
|
})
|
|
160
160
|
})
|
|
161
161
|
|
|
162
|
-
describe(
|
|
163
|
-
it(
|
|
162
|
+
describe('createPermissions — can.set()', () => {
|
|
163
|
+
it('replaces all permissions entirely', () => {
|
|
164
164
|
const can = createPermissions({
|
|
165
|
-
|
|
166
|
-
|
|
165
|
+
'posts.read': true,
|
|
166
|
+
'users.manage': true,
|
|
167
167
|
})
|
|
168
168
|
|
|
169
|
-
can.set({
|
|
170
|
-
expect(can(
|
|
171
|
-
expect(can(
|
|
169
|
+
can.set({ 'posts.read': false })
|
|
170
|
+
expect(can('posts.read')).toBe(false)
|
|
171
|
+
expect(can('users.manage')).toBe(false) // was not in new set
|
|
172
172
|
})
|
|
173
173
|
|
|
174
|
-
it(
|
|
175
|
-
const can = createPermissions({
|
|
174
|
+
it('triggers reactive updates', () => {
|
|
175
|
+
const can = createPermissions({ 'posts.read': true })
|
|
176
176
|
const results: boolean[] = []
|
|
177
177
|
|
|
178
178
|
effect(() => {
|
|
179
|
-
results.push(can(
|
|
179
|
+
results.push(can('posts.read'))
|
|
180
180
|
})
|
|
181
181
|
|
|
182
|
-
can.set({
|
|
183
|
-
can.set({
|
|
182
|
+
can.set({ 'posts.read': false })
|
|
183
|
+
can.set({ 'posts.read': true })
|
|
184
184
|
expect(results).toEqual([true, false, true])
|
|
185
185
|
})
|
|
186
186
|
|
|
187
|
-
it(
|
|
188
|
-
const can = createPermissions({
|
|
187
|
+
it('set with empty object removes all permissions', () => {
|
|
188
|
+
const can = createPermissions({ 'posts.read': true, 'users.manage': true })
|
|
189
189
|
can.set({})
|
|
190
|
-
expect(can(
|
|
191
|
-
expect(can(
|
|
190
|
+
expect(can('posts.read')).toBe(false)
|
|
191
|
+
expect(can('users.manage')).toBe(false)
|
|
192
192
|
})
|
|
193
193
|
|
|
194
|
-
it(
|
|
194
|
+
it('set with predicates', () => {
|
|
195
195
|
const can = createPermissions({})
|
|
196
196
|
can.set({
|
|
197
|
-
|
|
197
|
+
'posts.update': (post: any) => post?.authorId === 'me',
|
|
198
198
|
})
|
|
199
|
-
expect(can(
|
|
200
|
-
expect(can(
|
|
199
|
+
expect(can('posts.update', { authorId: 'me' })).toBe(true)
|
|
200
|
+
expect(can('posts.update', { authorId: 'other' })).toBe(false)
|
|
201
201
|
})
|
|
202
202
|
})
|
|
203
203
|
|
|
204
|
-
describe(
|
|
205
|
-
it(
|
|
204
|
+
describe('createPermissions — can.patch()', () => {
|
|
205
|
+
it('merges with existing permissions', () => {
|
|
206
206
|
const can = createPermissions({
|
|
207
|
-
|
|
208
|
-
|
|
207
|
+
'posts.read': true,
|
|
208
|
+
'users.manage': false,
|
|
209
209
|
})
|
|
210
210
|
|
|
211
|
-
can.patch({
|
|
212
|
-
expect(can(
|
|
213
|
-
expect(can(
|
|
214
|
-
expect(can(
|
|
211
|
+
can.patch({ 'users.manage': true, 'billing.view': true })
|
|
212
|
+
expect(can('posts.read')).toBe(true) // unchanged
|
|
213
|
+
expect(can('users.manage')).toBe(true) // updated
|
|
214
|
+
expect(can('billing.view')).toBe(true) // added
|
|
215
215
|
})
|
|
216
216
|
|
|
217
|
-
it(
|
|
218
|
-
const can = createPermissions({
|
|
219
|
-
can.patch({
|
|
220
|
-
expect(can(
|
|
217
|
+
it('overwrites existing keys', () => {
|
|
218
|
+
const can = createPermissions({ 'posts.read': true })
|
|
219
|
+
can.patch({ 'posts.read': false })
|
|
220
|
+
expect(can('posts.read')).toBe(false)
|
|
221
221
|
})
|
|
222
222
|
|
|
223
|
-
it(
|
|
223
|
+
it('adds new keys without removing existing', () => {
|
|
224
224
|
const can = createPermissions({ a: true })
|
|
225
225
|
can.patch({ b: true })
|
|
226
|
-
expect(can(
|
|
227
|
-
expect(can(
|
|
226
|
+
expect(can('a')).toBe(true)
|
|
227
|
+
expect(can('b')).toBe(true)
|
|
228
228
|
})
|
|
229
229
|
|
|
230
|
-
it(
|
|
231
|
-
const can = createPermissions({
|
|
230
|
+
it('triggers reactive updates', () => {
|
|
231
|
+
const can = createPermissions({ 'posts.read': false })
|
|
232
232
|
const results: boolean[] = []
|
|
233
233
|
|
|
234
234
|
effect(() => {
|
|
235
|
-
results.push(can(
|
|
235
|
+
results.push(can('posts.read'))
|
|
236
236
|
})
|
|
237
237
|
|
|
238
|
-
can.patch({
|
|
238
|
+
can.patch({ 'posts.read': true })
|
|
239
239
|
expect(results).toEqual([false, true])
|
|
240
240
|
})
|
|
241
241
|
|
|
242
|
-
it(
|
|
243
|
-
const can = createPermissions({
|
|
242
|
+
it('patch with predicates', () => {
|
|
243
|
+
const can = createPermissions({ 'posts.read': true })
|
|
244
244
|
can.patch({
|
|
245
|
-
|
|
245
|
+
'posts.update': (post: any) => post?.draft === true,
|
|
246
246
|
})
|
|
247
|
-
expect(can(
|
|
248
|
-
expect(can(
|
|
249
|
-
expect(can(
|
|
247
|
+
expect(can('posts.read')).toBe(true)
|
|
248
|
+
expect(can('posts.update', { draft: true })).toBe(true)
|
|
249
|
+
expect(can('posts.update', { draft: false })).toBe(false)
|
|
250
250
|
})
|
|
251
251
|
})
|
|
252
252
|
|
|
253
|
-
describe(
|
|
254
|
-
it(
|
|
253
|
+
describe('createPermissions — can.granted()', () => {
|
|
254
|
+
it('returns keys with true values', () => {
|
|
255
255
|
const can = createPermissions({
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
256
|
+
'posts.read': true,
|
|
257
|
+
'posts.delete': false,
|
|
258
|
+
'users.manage': true,
|
|
259
259
|
})
|
|
260
260
|
const granted = can.granted()
|
|
261
|
-
expect(granted).toContain(
|
|
262
|
-
expect(granted).toContain(
|
|
263
|
-
expect(granted).not.toContain(
|
|
261
|
+
expect(granted).toContain('posts.read')
|
|
262
|
+
expect(granted).toContain('users.manage')
|
|
263
|
+
expect(granted).not.toContain('posts.delete')
|
|
264
264
|
})
|
|
265
265
|
|
|
266
|
-
it(
|
|
266
|
+
it('includes predicate keys (capabilities exist)', () => {
|
|
267
267
|
const can = createPermissions({
|
|
268
|
-
|
|
268
|
+
'posts.update': (post: any) => post?.authorId === 'me',
|
|
269
269
|
})
|
|
270
|
-
expect(can.granted()).toContain(
|
|
270
|
+
expect(can.granted()).toContain('posts.update')
|
|
271
271
|
})
|
|
272
272
|
|
|
273
|
-
it(
|
|
273
|
+
it('returns empty array for no permissions', () => {
|
|
274
274
|
const can = createPermissions()
|
|
275
275
|
expect(can.granted()).toEqual([])
|
|
276
276
|
})
|
|
277
277
|
|
|
278
|
-
it(
|
|
278
|
+
it('returns empty array when all denied', () => {
|
|
279
279
|
const can = createPermissions({ a: false, b: false })
|
|
280
280
|
expect(can.granted()).toEqual([])
|
|
281
281
|
})
|
|
282
282
|
|
|
283
|
-
it(
|
|
284
|
-
const can = createPermissions({
|
|
283
|
+
it('is reactive — updates on set()', () => {
|
|
284
|
+
const can = createPermissions({ 'posts.read': true })
|
|
285
285
|
const results: string[][] = []
|
|
286
286
|
|
|
287
287
|
effect(() => {
|
|
288
288
|
results.push([...can.granted()])
|
|
289
289
|
})
|
|
290
290
|
|
|
291
|
-
can.set({
|
|
291
|
+
can.set({ 'posts.read': true, 'users.manage': true })
|
|
292
292
|
expect(results).toHaveLength(2)
|
|
293
|
-
expect(results[1]).toEqual(expect.arrayContaining([
|
|
293
|
+
expect(results[1]).toEqual(expect.arrayContaining(['posts.read', 'users.manage']))
|
|
294
294
|
})
|
|
295
295
|
|
|
296
|
-
it(
|
|
297
|
-
const can = createPermissions({
|
|
296
|
+
it('is reactive — updates on patch()', () => {
|
|
297
|
+
const can = createPermissions({ 'posts.read': true })
|
|
298
298
|
const results: string[][] = []
|
|
299
299
|
|
|
300
300
|
effect(() => {
|
|
301
301
|
results.push([...can.granted()])
|
|
302
302
|
})
|
|
303
303
|
|
|
304
|
-
can.patch({
|
|
305
|
-
expect(results).toEqual([[
|
|
304
|
+
can.patch({ 'users.manage': true })
|
|
305
|
+
expect(results).toEqual([['posts.read'], ['posts.read', 'users.manage']])
|
|
306
306
|
})
|
|
307
307
|
})
|
|
308
308
|
|
|
309
|
-
describe(
|
|
310
|
-
it(
|
|
309
|
+
describe('createPermissions — can.entries()', () => {
|
|
310
|
+
it('returns all entries as [key, value] pairs', () => {
|
|
311
311
|
const can = createPermissions({
|
|
312
|
-
|
|
313
|
-
|
|
312
|
+
'posts.read': true,
|
|
313
|
+
'posts.delete': false,
|
|
314
314
|
})
|
|
315
315
|
const entries = can.entries()
|
|
316
316
|
expect(entries).toHaveLength(2)
|
|
317
317
|
expect(entries).toEqual(
|
|
318
318
|
expect.arrayContaining([
|
|
319
|
-
[
|
|
320
|
-
[
|
|
319
|
+
['posts.read', true],
|
|
320
|
+
['posts.delete', false],
|
|
321
321
|
]),
|
|
322
322
|
)
|
|
323
323
|
})
|
|
324
324
|
|
|
325
|
-
it(
|
|
325
|
+
it('returns empty array for no permissions', () => {
|
|
326
326
|
const can = createPermissions()
|
|
327
327
|
expect(can.entries()).toEqual([])
|
|
328
328
|
})
|
|
329
329
|
|
|
330
|
-
it(
|
|
331
|
-
const pred = (post: any) => post?.authorId ===
|
|
330
|
+
it('includes predicate entries', () => {
|
|
331
|
+
const pred = (post: any) => post?.authorId === 'me'
|
|
332
332
|
const can = createPermissions({
|
|
333
|
-
|
|
333
|
+
'posts.update': pred,
|
|
334
334
|
})
|
|
335
335
|
const entries = can.entries()
|
|
336
336
|
expect(entries).toHaveLength(1)
|
|
337
|
-
expect(entries[0]?.[0]).toBe(
|
|
337
|
+
expect(entries[0]?.[0]).toBe('posts.update')
|
|
338
338
|
expect(entries[0]?.[1]).toBe(pred)
|
|
339
339
|
})
|
|
340
340
|
|
|
341
|
-
it(
|
|
341
|
+
it('is reactive — updates on mutations', () => {
|
|
342
342
|
const can = createPermissions({ a: true })
|
|
343
343
|
const counts: number[] = []
|
|
344
344
|
|
|
@@ -351,12 +351,12 @@ describe("createPermissions — can.entries()", () => {
|
|
|
351
351
|
expect(counts).toEqual([1, 2, 3])
|
|
352
352
|
})
|
|
353
353
|
|
|
354
|
-
it(
|
|
354
|
+
it('reflects set() replacement', () => {
|
|
355
355
|
const can = createPermissions({ a: true, b: true, c: true })
|
|
356
356
|
expect(can.entries()).toHaveLength(3)
|
|
357
357
|
|
|
358
358
|
can.set({ x: true })
|
|
359
359
|
expect(can.entries()).toHaveLength(1)
|
|
360
|
-
expect(can.entries()[0]?.[0]).toBe(
|
|
360
|
+
expect(can.entries()[0]?.[0]).toBe('x')
|
|
361
361
|
})
|
|
362
362
|
})
|
|
@@ -1,50 +1,50 @@
|
|
|
1
|
-
import { describe, expect, it } from
|
|
2
|
-
import { createPermissions, usePermissions } from
|
|
1
|
+
import { describe, expect, it } from 'vitest'
|
|
2
|
+
import { createPermissions, usePermissions } from '../index'
|
|
3
3
|
|
|
4
|
-
describe(
|
|
5
|
-
it(
|
|
4
|
+
describe('usePermissions', () => {
|
|
5
|
+
it('throws when called outside PermissionsProvider', () => {
|
|
6
6
|
expect(() => usePermissions()).toThrow(
|
|
7
|
-
|
|
7
|
+
'[@pyreon/permissions] usePermissions() must be used within <PermissionsProvider>.',
|
|
8
8
|
)
|
|
9
9
|
})
|
|
10
10
|
})
|
|
11
11
|
|
|
12
|
-
describe(
|
|
13
|
-
it(
|
|
14
|
-
const can = createPermissions({
|
|
15
|
-
expect(can(
|
|
12
|
+
describe('createPermissions used directly (no context)', () => {
|
|
13
|
+
it('works standalone without any provider', () => {
|
|
14
|
+
const can = createPermissions({ 'posts.read': true })
|
|
15
|
+
expect(can('posts.read')).toBe(true)
|
|
16
16
|
})
|
|
17
17
|
|
|
18
|
-
it(
|
|
19
|
-
const canA = createPermissions({
|
|
20
|
-
const canB = createPermissions({
|
|
18
|
+
it('multiple independent instances do not interfere', () => {
|
|
19
|
+
const canA = createPermissions({ 'posts.read': true })
|
|
20
|
+
const canB = createPermissions({ 'posts.read': false })
|
|
21
21
|
|
|
22
|
-
expect(canA(
|
|
23
|
-
expect(canB(
|
|
22
|
+
expect(canA('posts.read')).toBe(true)
|
|
23
|
+
expect(canB('posts.read')).toBe(false)
|
|
24
24
|
|
|
25
|
-
canA.set({
|
|
26
|
-
expect(canA(
|
|
27
|
-
expect(canB(
|
|
25
|
+
canA.set({ 'posts.read': false })
|
|
26
|
+
expect(canA('posts.read')).toBe(false)
|
|
27
|
+
expect(canB('posts.read')).toBe(false) // unchanged, already false
|
|
28
28
|
})
|
|
29
29
|
|
|
30
|
-
it(
|
|
30
|
+
it('set() on one instance does not affect another', () => {
|
|
31
31
|
const canA = createPermissions({ a: true, b: true })
|
|
32
32
|
const canB = createPermissions({ a: true, b: true })
|
|
33
33
|
|
|
34
34
|
canA.set({ a: false })
|
|
35
|
-
expect(canA(
|
|
36
|
-
expect(canA(
|
|
35
|
+
expect(canA('a')).toBe(false)
|
|
36
|
+
expect(canA('b')).toBe(false) // cleared by set
|
|
37
37
|
|
|
38
|
-
expect(canB(
|
|
39
|
-
expect(canB(
|
|
38
|
+
expect(canB('a')).toBe(true) // unaffected
|
|
39
|
+
expect(canB('b')).toBe(true)
|
|
40
40
|
})
|
|
41
41
|
|
|
42
|
-
it(
|
|
42
|
+
it('patch() on one instance does not affect another', () => {
|
|
43
43
|
const canA = createPermissions({ shared: true })
|
|
44
44
|
const canB = createPermissions({ shared: true })
|
|
45
45
|
|
|
46
46
|
canA.patch({ shared: false })
|
|
47
|
-
expect(canA(
|
|
48
|
-
expect(canB(
|
|
47
|
+
expect(canA('shared')).toBe(false)
|
|
48
|
+
expect(canB('shared')).toBe(true) // unaffected
|
|
49
49
|
})
|
|
50
50
|
})
|