fix architecture and write new tests
This commit is contained in:
@@ -0,0 +1,101 @@
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
import type { NextFunction, Request, Response } from 'express'
|
||||
|
||||
vi.mock('../../lib/prisma', () => ({
|
||||
prisma: {
|
||||
subscription: {
|
||||
findUnique: vi.fn(),
|
||||
},
|
||||
},
|
||||
}))
|
||||
|
||||
import { prisma } from '../../lib/prisma'
|
||||
import { requireActiveSubscription, requireFullAccess } from './subscription.entitlement'
|
||||
|
||||
function createRes() {
|
||||
const res = {
|
||||
status: vi.fn().mockReturnThis(),
|
||||
json: vi.fn().mockReturnThis(),
|
||||
}
|
||||
return res as unknown as Response & { status: ReturnType<typeof vi.fn>; json: ReturnType<typeof vi.fn> }
|
||||
}
|
||||
|
||||
describe('subscription.entitlement middleware', () => {
|
||||
beforeEach(() => vi.clearAllMocks())
|
||||
|
||||
it('rejects unauthenticated requests before touching subscription storage', async () => {
|
||||
const req = {} as Request
|
||||
const res = createRes()
|
||||
const next = vi.fn() as NextFunction
|
||||
|
||||
await requireActiveSubscription(req, res, next)
|
||||
|
||||
expect(res.status).toHaveBeenCalledWith(401)
|
||||
expect(res.json).toHaveBeenCalledWith({ error: 'unauthenticated' })
|
||||
expect(prisma.subscription.findUnique).not.toHaveBeenCalled()
|
||||
expect(next).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('rejects missing or expired subscriptions with a precise entitlement payload', async () => {
|
||||
vi.mocked(prisma.subscription.findUnique).mockResolvedValue(null as never)
|
||||
const req = { companyId: 'company_1' } as Request
|
||||
const res = createRes()
|
||||
const next = vi.fn() as NextFunction
|
||||
|
||||
await requireActiveSubscription(req, res, next)
|
||||
|
||||
expect(prisma.subscription.findUnique).toHaveBeenCalledWith({ where: { companyId: 'company_1' } })
|
||||
expect(res.status).toHaveBeenCalledWith(403)
|
||||
expect(res.json).toHaveBeenCalledWith(expect.objectContaining({
|
||||
error: 'subscription_required',
|
||||
subscriptionStatus: 'EXPIRED',
|
||||
accessLevel: 'none',
|
||||
}))
|
||||
expect(next).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('allows limited subscriptions through requireActiveSubscription but annotates the request', async () => {
|
||||
vi.mocked(prisma.subscription.findUnique).mockResolvedValue({ status: 'PAST_DUE' } as never)
|
||||
const req = { companyId: 'company_1' } as Request & { subscriptionStatus?: string; accessLevel?: string }
|
||||
const res = createRes()
|
||||
const next = vi.fn() as NextFunction
|
||||
|
||||
await requireActiveSubscription(req, res, next)
|
||||
|
||||
expect(req.subscriptionStatus).toBe('PAST_DUE')
|
||||
expect(req.accessLevel).toBe('limited')
|
||||
expect(next).toHaveBeenCalledOnce()
|
||||
expect(res.status).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('requires full access for write-protected actions', async () => {
|
||||
vi.mocked(prisma.subscription.findUnique).mockResolvedValue({ status: 'SUSPENDED' } as never)
|
||||
const req = { companyId: 'company_1' } as Request
|
||||
const res = createRes()
|
||||
const next = vi.fn() as NextFunction
|
||||
|
||||
await requireFullAccess(req, res, next)
|
||||
|
||||
expect(res.status).toHaveBeenCalledWith(403)
|
||||
expect(res.json).toHaveBeenCalledWith(expect.objectContaining({
|
||||
error: 'insufficient_access',
|
||||
subscriptionStatus: 'SUSPENDED',
|
||||
accessLevel: 'read_only',
|
||||
}))
|
||||
expect(next).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('passes active subscriptions through requireFullAccess', async () => {
|
||||
vi.mocked(prisma.subscription.findUnique).mockResolvedValue({ status: 'ACTIVE' } as never)
|
||||
const req = { companyId: 'company_1' } as Request & { subscriptionStatus?: string; accessLevel?: string }
|
||||
const res = createRes()
|
||||
const next = vi.fn() as NextFunction
|
||||
|
||||
await requireFullAccess(req, res, next)
|
||||
|
||||
expect(req.subscriptionStatus).toBe('ACTIVE')
|
||||
expect(req.accessLevel).toBe('full')
|
||||
expect(next).toHaveBeenCalledOnce()
|
||||
expect(res.status).not.toHaveBeenCalled()
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user