useTestQueryRLS.utils.test.ts147 lines · main
1import { describe, expect, it } from 'vitest'
2
3import type { Policy } from '@/components/interfaces/Auth/Policies/PolicyTableRow/PolicyTableRow.utils'
4import { filterTablePolicies } from '@/components/interfaces/Auth/RLSTester/useTestQueryRLS.utils'
5
6const makePolicy = (overrides: Partial<Policy>): Policy =>
7 ({
8 schema: 'public',
9 table: 'items',
10 roles: ['anon'],
11 command: 'SELECT',
12 ...overrides,
13 }) as Policy
14
15const base = {
16 policies: [] as Policy[],
17 schema: 'public',
18 table: 'items',
19 role: 'anon',
20 operation: 'SELECT' as const,
21}
22
23describe('filterTablePolicies', () => {
24 describe('schema / table matching', () => {
25 it('excludes policies from a different schema', () => {
26 const policy = makePolicy({ schema: 'private', table: 'items' })
27 expect(filterTablePolicies({ ...base, policies: [policy] })).toHaveLength(0)
28 })
29
30 it('excludes policies from a different table', () => {
31 const policy = makePolicy({ schema: 'public', table: 'other' })
32 expect(filterTablePolicies({ ...base, policies: [policy] })).toHaveLength(0)
33 })
34
35 it('includes a policy matching schema and table', () => {
36 const policy = makePolicy({ schema: 'public', table: 'items' })
37 expect(filterTablePolicies({ ...base, policies: [policy] })).toHaveLength(1)
38 })
39 })
40
41 describe('role matching', () => {
42 it('includes policy when role is in the policy roles array', () => {
43 const policy = makePolicy({ roles: ['anon', 'authenticated'] })
44 expect(filterTablePolicies({ ...base, role: 'anon', policies: [policy] })).toHaveLength(1)
45 })
46
47 it('excludes policy when role is not in the policy roles array', () => {
48 const policy = makePolicy({ roles: ['authenticated'] })
49 expect(filterTablePolicies({ ...base, role: 'anon', policies: [policy] })).toHaveLength(0)
50 })
51
52 it('includes policy when the only role is "public" (applies to all roles)', () => {
53 const policy = makePolicy({ roles: ['public'] })
54 expect(filterTablePolicies({ ...base, role: 'anon', policies: [policy] })).toHaveLength(1)
55 })
56
57 it('excludes "public" role shortcut when policy has multiple roles including public', () => {
58 const policy = makePolicy({ roles: ['public', 'authenticated'] })
59 expect(filterTablePolicies({ ...base, role: 'anon', policies: [policy] })).toHaveLength(0)
60 })
61
62 it('handles undefined role (service role) — matches nothing unless public', () => {
63 const rolePolicy = makePolicy({ roles: ['anon'] })
64 const publicPolicy = makePolicy({ roles: ['public'] })
65 const result = filterTablePolicies({
66 ...base,
67 role: undefined,
68 policies: [rolePolicy, publicPolicy],
69 })
70 expect(result).toHaveLength(1)
71 expect(result[0]).toBe(publicPolicy)
72 })
73 })
74
75 describe('command matching', () => {
76 it('includes policy when command matches the operation', () => {
77 const policy = makePolicy({ command: 'SELECT' })
78 expect(
79 filterTablePolicies({ ...base, operation: 'SELECT', policies: [policy] })
80 ).toHaveLength(1)
81 })
82
83 it('excludes policy when command does not match the operation', () => {
84 const policy = makePolicy({ command: 'INSERT' })
85 expect(
86 filterTablePolicies({ ...base, operation: 'SELECT', policies: [policy] })
87 ).toHaveLength(0)
88 })
89
90 it('includes policy with command ALL regardless of operation', () => {
91 const policy = makePolicy({ command: 'ALL' })
92 expect(
93 filterTablePolicies({ ...base, operation: 'SELECT', policies: [policy] })
94 ).toHaveLength(1)
95 })
96
97 it('includes ALL command policy for non-SELECT operations too', () => {
98 const policy = makePolicy({ command: 'ALL' })
99 expect(
100 filterTablePolicies({ ...base, operation: 'INSERT', policies: [policy] })
101 ).toHaveLength(1)
102 })
103
104 it('does not include a SELECT-only policy when operation is INSERT', () => {
105 const policy = makePolicy({ command: 'SELECT' })
106 expect(
107 filterTablePolicies({ ...base, operation: 'INSERT', policies: [policy] })
108 ).toHaveLength(0)
109 })
110 })
111
112 describe('combined filters', () => {
113 it('returns only policies that satisfy all conditions', () => {
114 const match = makePolicy({
115 schema: 'public',
116 table: 'items',
117 roles: ['anon'],
118 command: 'ALL',
119 })
120 const wrongSchema = makePolicy({
121 schema: 'private',
122 table: 'items',
123 roles: ['anon'],
124 command: 'ALL',
125 })
126 const wrongRole = makePolicy({
127 schema: 'public',
128 table: 'items',
129 roles: ['authenticated'],
130 command: 'ALL',
131 })
132 const wrongCommand = makePolicy({
133 schema: 'public',
134 table: 'items',
135 roles: ['anon'],
136 command: 'INSERT',
137 })
138
139 const result = filterTablePolicies({
140 ...base,
141 policies: [match, wrongSchema, wrongRole, wrongCommand],
142 })
143 expect(result).toHaveLength(1)
144 expect(result[0]).toBe(match)
145 })
146 })
147})