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; json: ReturnType } } 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() }) })