🛠️ Add default header management methods to API client
This commit is contained in:
154
code/websites/pokedex.online/tests/unit/auth/jwt-utils.test.js
Normal file
154
code/websites/pokedex.online/tests/unit/auth/jwt-utils.test.js
Normal file
@@ -0,0 +1,154 @@
|
||||
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
|
||||
import {
|
||||
createToken,
|
||||
verifyToken,
|
||||
decodeToken,
|
||||
isTokenExpired,
|
||||
getTokenExpiresIn
|
||||
} from '../../server/utils/jwt-utils.js';
|
||||
|
||||
describe('JWT Utilities', () => {
|
||||
const testSecret = 'test-secret-key';
|
||||
let token;
|
||||
|
||||
beforeEach(() => {
|
||||
// Create a test token
|
||||
token = createToken(
|
||||
{
|
||||
userId: '123',
|
||||
isAdmin: true,
|
||||
permissions: ['admin']
|
||||
},
|
||||
testSecret,
|
||||
3600 // 1 hour
|
||||
);
|
||||
});
|
||||
|
||||
describe('createToken', () => {
|
||||
it('creates a valid token', () => {
|
||||
expect(token).toBeDefined();
|
||||
expect(typeof token).toBe('string');
|
||||
expect(token.split('.')).toHaveLength(3);
|
||||
});
|
||||
|
||||
it('includes payload data', () => {
|
||||
const decoded = decodeToken(token);
|
||||
expect(decoded.userId).toBe('123');
|
||||
expect(decoded.isAdmin).toBe(true);
|
||||
expect(decoded.permissions).toContain('admin');
|
||||
});
|
||||
|
||||
it('includes timestamps', () => {
|
||||
const decoded = decodeToken(token);
|
||||
expect(decoded.iat).toBeDefined();
|
||||
expect(decoded.exp).toBeDefined();
|
||||
expect(decoded.exp).toBeGreaterThan(decoded.iat);
|
||||
});
|
||||
|
||||
it('respects custom expiration time', () => {
|
||||
const shortToken = createToken(
|
||||
{ userId: '123' },
|
||||
testSecret,
|
||||
60 // 1 minute
|
||||
);
|
||||
const longToken = createToken(
|
||||
{ userId: '123' },
|
||||
testSecret,
|
||||
7200 // 2 hours
|
||||
);
|
||||
|
||||
const shortDecoded = decodeToken(shortToken);
|
||||
const longDecoded = decodeToken(longToken);
|
||||
|
||||
expect(longDecoded.exp - longDecoded.iat).toBeGreaterThan(
|
||||
shortDecoded.exp - shortDecoded.iat
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('verifyToken', () => {
|
||||
it('verifies a valid token', () => {
|
||||
const decoded = verifyToken(token, testSecret);
|
||||
expect(decoded.userId).toBe('123');
|
||||
expect(decoded.isAdmin).toBe(true);
|
||||
});
|
||||
|
||||
it('throws on invalid secret', () => {
|
||||
expect(() => {
|
||||
verifyToken(token, 'wrong-secret');
|
||||
}).toThrow();
|
||||
});
|
||||
|
||||
it('throws on malformed token', () => {
|
||||
expect(() => {
|
||||
verifyToken('not.a.token', testSecret);
|
||||
}).toThrow();
|
||||
});
|
||||
|
||||
it('throws on expired token', () => {
|
||||
// Create an already expired token
|
||||
const expiredToken = createToken(
|
||||
{ userId: '123' },
|
||||
testSecret,
|
||||
-1 // Already expired
|
||||
);
|
||||
|
||||
expect(() => {
|
||||
verifyToken(expiredToken, testSecret);
|
||||
}).toThrow();
|
||||
});
|
||||
});
|
||||
|
||||
describe('decodeToken', () => {
|
||||
it('decodes token without verification', () => {
|
||||
const decoded = decodeToken(token);
|
||||
expect(decoded.userId).toBe('123');
|
||||
expect(decoded.isAdmin).toBe(true);
|
||||
});
|
||||
|
||||
it('returns null for invalid token', () => {
|
||||
const result = decodeToken('invalid');
|
||||
expect(result).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
describe('isTokenExpired', () => {
|
||||
it('returns false for valid token', () => {
|
||||
expect(isTokenExpired(token)).toBe(false);
|
||||
});
|
||||
|
||||
it('returns true for expired token', () => {
|
||||
const expiredToken = createToken(
|
||||
{ userId: '123' },
|
||||
testSecret,
|
||||
-1
|
||||
);
|
||||
expect(isTokenExpired(expiredToken)).toBe(true);
|
||||
});
|
||||
|
||||
it('returns true for invalid token', () => {
|
||||
expect(isTokenExpired('invalid')).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getTokenExpiresIn', () => {
|
||||
it('returns remaining time in milliseconds', () => {
|
||||
const remaining = getTokenExpiresIn(token);
|
||||
expect(remaining).toBeGreaterThan(0);
|
||||
expect(remaining).toBeLessThanOrEqual(3600000); // 1 hour in ms
|
||||
});
|
||||
|
||||
it('returns 0 for expired token', () => {
|
||||
const expiredToken = createToken(
|
||||
{ userId: '123' },
|
||||
testSecret,
|
||||
-1
|
||||
);
|
||||
expect(getTokenExpiresIn(expiredToken)).toBe(0);
|
||||
});
|
||||
|
||||
it('returns 0 for invalid token', () => {
|
||||
expect(getTokenExpiresIn('invalid')).toBe(0);
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user