mirror of
https://github.com/fsolla/teqo.git
synced 2026-11-13 15:05:19 +00:00
Fold duplicated campanha access, loaders, list/filter/form shells, and scripts into shared modules; reorganize utilities by domain; stabilize e2e; and document prevention-first audit workflow so the same smells cannot creep back in.
84 lines
3.2 KiB
TypeScript
84 lines
3.2 KiB
TypeScript
// @vitest-environment node
|
|
|
|
import type { Payload, PayloadRequest } from 'payload'
|
|
import { describe, expect, it, vi } from 'vitest'
|
|
|
|
import type { CampaignUser, User } from '@/payload-types'
|
|
import {
|
|
advisorMunicipalityScopeWhere,
|
|
resolveAccessibleIds,
|
|
resolveActorScopedRead,
|
|
} from '@/utilities/access/shared'
|
|
|
|
import { stub } from '../helpers/stub'
|
|
|
|
const advisorUser = stub<CampaignUser>({
|
|
collection: 'campaignUser',
|
|
id: 7,
|
|
role: 'advisor',
|
|
})
|
|
|
|
/**
|
|
* P3-D pin: one spec per consolidated predicate form — the scope fragment, the
|
|
* scoped-read prologue, and the memoized accessible-ids engine. The int access
|
|
* matrix pins behavior end-to-end; these pin the single spellings the guard in
|
|
* `codebaseConventions.unit.spec.ts` makes the only writable ones.
|
|
*/
|
|
describe('access shared policies (P3-D)', () => {
|
|
it('spells the advisor scope fragment exactly once per field', () => {
|
|
expect(advisorMunicipalityScopeWhere('municipality', [1, 2])).toEqual({
|
|
municipality: { in: [1, 2] },
|
|
})
|
|
expect(advisorMunicipalityScopeWhere('municipalities', null)).toEqual({
|
|
municipalities: { in: [] },
|
|
})
|
|
})
|
|
|
|
it('resolveActorScopedRead: admin → all, anon → nothing, advisor → scope', async () => {
|
|
const adminReq = stub<PayloadRequest>({
|
|
user: stub<User>({ collection: 'users', roles: ['admin'] }),
|
|
})
|
|
await expect(resolveActorScopedRead(adminReq, 'municipality', vi.fn())).resolves.toBe(true)
|
|
|
|
const anonReq = stub<PayloadRequest>({ user: null })
|
|
await expect(resolveActorScopedRead(anonReq, 'municipality', vi.fn())).resolves.toBe(false)
|
|
|
|
const loadAccessibleIds = vi.fn().mockResolvedValue([42])
|
|
// The prologue reloads the actor fresh (getFreshCampaignUser), so the stub
|
|
// request needs a payload answering findByID with the same advisor.
|
|
const advisorReq = stub<PayloadRequest>({
|
|
user: advisorUser,
|
|
payload: stub<Payload>({ findByID: vi.fn().mockResolvedValue(advisorUser) }),
|
|
})
|
|
await expect(
|
|
resolveActorScopedRead(advisorReq, 'municipality', loadAccessibleIds),
|
|
).resolves.toEqual({ municipality: { in: [42] } })
|
|
})
|
|
|
|
it('resolveAccessibleIds: unrestricted → null, non-campaign → [], memoizes per request', async () => {
|
|
const coordinator = stub<CampaignUser>({
|
|
collection: 'campaignUser',
|
|
id: 1,
|
|
role: 'coordinator',
|
|
})
|
|
const unrestrictedReq = stub<PayloadRequest>({
|
|
user: coordinator,
|
|
payload: stub<Payload>({ findByID: vi.fn().mockResolvedValue(coordinator) }),
|
|
})
|
|
await expect(resolveAccessibleIds(unrestrictedReq, undefined, 'k', vi.fn())).resolves.toBeNull()
|
|
|
|
const foreignReq = stub<PayloadRequest>({
|
|
user: stub<User>({ collection: 'users', roles: ['editor'] }),
|
|
})
|
|
await expect(resolveAccessibleIds(foreignReq, undefined, 'k', vi.fn())).resolves.toEqual([])
|
|
|
|
const compute = vi.fn().mockResolvedValue([5])
|
|
const req = stub<PayloadRequest>({
|
|
user: advisorUser,
|
|
payload: stub<Payload>({ findByID: vi.fn().mockResolvedValue(advisorUser) }),
|
|
})
|
|
await expect(resolveAccessibleIds(req, undefined, 'k', compute)).resolves.toEqual([5])
|
|
await expect(resolveAccessibleIds(req, undefined, 'k', compute)).resolves.toEqual([5])
|
|
expect(compute).toHaveBeenCalledTimes(1)
|
|
})
|
|
})
|