import { UnauthorizedException } from '@nestjs/common'; import { JwtStrategy } from './jwt.strategy'; describe('JwtStrategy', () => { const config = { get: jest.fn().mockReturnValue('secret') }; it('refreshes permissions from the database instead of trusting stale JWT permissions', async () => { const userRepo = { findOne: jest.fn().mockResolvedValue({ id: 7, username: 'teacher', isActive: true, isArchived: false, roles: [ { name: '老师', status: 1, permissions: [{ code: 'class:view' }, { code: 'attendance:view' }], }, ], }), }; const strategy = new JwtStrategy(config as never, userRepo as never); await expect( strategy.validate({ sub: 7, username: 'teacher', permissions: ['user:delete'] }), ).resolves.toEqual({ id: 7, username: 'teacher', permissions: ['class:view', 'attendance:view'], isSuperAdmin: false, roles: ['老师'], }); }); it('recognizes the canonical super_admin role code even when the display name changes', async () => { const userRepo = { findOne: jest.fn().mockResolvedValue({ id: 1, username: 'admin', isActive: true, isArchived: false, roles: [{ name: '系统管理员', code: 'super_admin', status: 1, permissions: [] }], }), }; const strategy = new JwtStrategy(config as never, userRepo as never); await expect(strategy.validate({ sub: 1 })).resolves.toEqual( expect.objectContaining({ isSuperAdmin: true }), ); }); it.each([ [{ id: 7, isActive: false, isArchived: false, roles: [] }], [{ id: 7, isActive: true, isArchived: true, roles: [] }], [null], ])('rejects disabled, archived, or deleted users', async (user) => { const userRepo = { findOne: jest.fn().mockResolvedValue(user) }; const strategy = new JwtStrategy(config as never, userRepo as never); await expect(strategy.validate({ sub: 7, username: 'teacher' })).rejects.toBeInstanceOf( UnauthorizedException, ); }); });