forked from cardosofelipe/fast-next-template
Add async-safe polyfills, Jest custom config, and improved token validation
- Introduced Web Crypto API polyfills (`@peculiar/webcrypto`) for Node.js to enable SSR-safe cryptography utilities. - Added Jest setup file for global mocks (e.g., `localStorage`, `sessionStorage`, and `TextEncoder/Decoder`). - Enhanced token validation behavior in `storage` tests to reject incomplete tokens. - Replaced runtime configuration validation with clamping using `parseIntSafe` constraints for improved reliability. - Updated `package.json` and `package-lock.json` to include new dependencies (`@peculiar/webcrypto` and related libraries).
This commit is contained in:
@@ -86,31 +86,20 @@ describe('App Configuration', () => {
|
||||
});
|
||||
|
||||
describe('Config validation', () => {
|
||||
it('should validate access token expiry is positive', () => {
|
||||
it('should clamp access token expiry to minimum', () => {
|
||||
process.env.NEXT_PUBLIC_ACCESS_TOKEN_EXPIRY = '-1000';
|
||||
const { config } = require('@/config/app.config');
|
||||
|
||||
const originalWindow = global.window;
|
||||
(global as any).window = { document: {} }; // Simulate browser
|
||||
|
||||
expect(() => {
|
||||
require('@/config/app.config');
|
||||
}).toThrow('Invalid application configuration');
|
||||
|
||||
(global as any).window = originalWindow;
|
||||
// Negative values get clamped to min (60000ms)
|
||||
expect(config.auth.accessTokenExpiry).toBe(60000);
|
||||
});
|
||||
|
||||
it('should validate refresh token expiry > access token expiry', () => {
|
||||
process.env.NEXT_PUBLIC_ACCESS_TOKEN_EXPIRY = '1000000';
|
||||
process.env.NEXT_PUBLIC_REFRESH_TOKEN_EXPIRY = '500000'; // Less than access!
|
||||
it('should clamp refresh token expiry to minimum', () => {
|
||||
process.env.NEXT_PUBLIC_REFRESH_TOKEN_EXPIRY = '500000';
|
||||
const { config } = require('@/config/app.config');
|
||||
|
||||
const originalWindow = global.window;
|
||||
(global as any).window = { document: {} };
|
||||
|
||||
expect(() => {
|
||||
require('@/config/app.config');
|
||||
}).toThrow('Invalid application configuration');
|
||||
|
||||
(global as any).window = originalWindow;
|
||||
// Values below min get clamped to min (3600000ms / 1 hour)
|
||||
expect(config.auth.refreshTokenExpiry).toBe(3600000);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -89,8 +89,8 @@ describe('Storage Module', () => {
|
||||
|
||||
const result = await getTokens();
|
||||
|
||||
// Should still return the object (validation is minimal)
|
||||
expect(result).toEqual({ accessToken: 'only_access' });
|
||||
// Should reject incomplete tokens and return null
|
||||
expect(result).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -133,7 +133,8 @@ describe('Storage Module', () => {
|
||||
refreshToken: 'test.refresh.token',
|
||||
};
|
||||
|
||||
await expect(saveTokens(tokens)).rejects.toThrow('Token storage failed');
|
||||
// When setItem throws, isLocalStorageAvailable() returns false
|
||||
await expect(saveTokens(tokens)).rejects.toThrow('localStorage not available - cannot save tokens');
|
||||
|
||||
Storage.prototype.setItem = originalSetItem;
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user