// Mock du module 'jose' (ESM) pour utilisation avec Jest CJS jest.mock('jose', () => { type Payload = { origin: string; type: 'access' | 'refresh' }; const makeToken = (p: Payload) => `${p.type}:${p.origin}`; return { SignJWT: class { private payload: Payload; constructor(payload: Payload) { this.payload = payload; } setProtectedHeader() { return this; } setIssuedAt() { return this; } setExpirationTime() { return this; } async sign() { return makeToken(this.payload); } }, jwtVerify: async (token: string) => { const [type, origin] = (token || '').split(':'); return { payload: { type, origin } } as any; } } as any; }); const TokenService = require('../../src/services/token').default as typeof import('../../src/services/token').default; describe('TokenService', () => { const ORIGIN = 'http://localhost'; beforeAll(() => { process.env.VITE_JWT_SECRET_KEY = 'test-secret-key'; }); it('génère un pair de tokens de type chaîne', async () => { const service = await TokenService.getInstance(); const { accessToken, refreshToken } = await service.generateSessionToken(ORIGIN); expect(typeof accessToken).toBe('string'); expect(typeof refreshToken).toBe('string'); }); it('rafraîchit un access token (retourne une chaîne ou null)', async () => { const service = await TokenService.getInstance(); const { refreshToken } = await service.generateSessionToken(ORIGIN); const newAccess = await service.refreshAccessToken(refreshToken, ORIGIN); expect(typeof newAccess === 'string' || newAccess === null).toBe(true); }); it("retourne false si l'origine ne correspond pas", async () => { const service = await TokenService.getInstance(); const { accessToken } = await service.generateSessionToken(ORIGIN); const isValid = await service.validateToken(accessToken, 'https://example.com'); expect(isValid).toBe(false); }); });