- Introduced SKIP_GPS_VALIDATION environment variable to control GPS validation during check-ins and check-outs. - Updated loadEnv function to parse SKIP_GPS_VALIDATION and enforce its rules based on NODE_ENV. - Enhanced attendance and visit services to utilize the new configuration, allowing GPS validation to be skipped in development environments. - Added unit tests to verify the behavior of SKIP_GPS_VALIDATION in various scenarios, ensuring proper handling in both production and development contexts. - Updated check-in verification logic to respect the SKIP_GPS_VALIDATION option, improving flexibility in location checks.
109 lines
3.0 KiB
TypeScript
109 lines
3.0 KiB
TypeScript
import { loadEnv } from './env';
|
|
|
|
describe('loadEnv', () => {
|
|
const valid = {
|
|
DATABASE_URL: 'postgresql://user:pass@localhost:5432/tracking',
|
|
JWT_ACCESS_SECRET: 'test-secret-at-least-32-chars-long!!',
|
|
};
|
|
|
|
it('loads required values with defaults', () => {
|
|
const env = loadEnv(valid);
|
|
|
|
expect(env.DATABASE_URL).toBe(valid.DATABASE_URL);
|
|
expect(env.JWT_ACCESS_SECRET).toBe(valid.JWT_ACCESS_SECRET);
|
|
expect(env.PORT).toBe(3000);
|
|
expect(env.JWT_ACCESS_EXPIRES_IN).toBe('15m');
|
|
expect(env.JWT_ACCESS_EXPIRES_IN_MS).toBe(15 * 60 * 1000);
|
|
expect(env.REFRESH_TOKEN_EXPIRES_IN_MS).toBe(7 * 24 * 60 * 60 * 1000);
|
|
expect(env.BCRYPT_SALT_ROUNDS).toBe(10);
|
|
expect(env.DEFAULT_TIMEZONE).toBe('GMT+7');
|
|
expect(env.SKIP_GPS_VALIDATION).toBe(false);
|
|
});
|
|
|
|
it('throws when DATABASE_URL is missing', () => {
|
|
expect(() =>
|
|
loadEnv({ JWT_ACCESS_SECRET: valid.JWT_ACCESS_SECRET }),
|
|
).toThrow('DATABASE_URL is not configured');
|
|
});
|
|
|
|
it('throws when JWT_ACCESS_SECRET is missing', () => {
|
|
expect(() => loadEnv({ DATABASE_URL: valid.DATABASE_URL })).toThrow(
|
|
'JWT_ACCESS_SECRET is not configured',
|
|
);
|
|
});
|
|
|
|
it('throws when JWT_ACCESS_SECRET is a placeholder', () => {
|
|
expect(() =>
|
|
loadEnv({
|
|
DATABASE_URL: valid.DATABASE_URL,
|
|
JWT_ACCESS_SECRET: 'change-me-to-a-long-random-secret',
|
|
}),
|
|
).toThrow('known placeholder');
|
|
});
|
|
|
|
it('throws when JWT_ACCESS_SECRET is too short', () => {
|
|
expect(() =>
|
|
loadEnv({
|
|
DATABASE_URL: valid.DATABASE_URL,
|
|
JWT_ACCESS_SECRET: 'short-secret',
|
|
}),
|
|
).toThrow('at least 32 characters');
|
|
});
|
|
|
|
it('parses optional numeric overrides', () => {
|
|
const env = loadEnv({
|
|
...valid,
|
|
PORT: '4000',
|
|
BCRYPT_SALT_ROUNDS: '12',
|
|
REFRESH_TOKEN_EXPIRES_IN_MS: '3600000',
|
|
JWT_ACCESS_EXPIRES_IN: '5m',
|
|
DEFAULT_TIMEZONE: 'GMT+0',
|
|
});
|
|
|
|
expect(env.PORT).toBe(4000);
|
|
expect(env.BCRYPT_SALT_ROUNDS).toBe(12);
|
|
expect(env.REFRESH_TOKEN_EXPIRES_IN_MS).toBe(3_600_000);
|
|
expect(env.JWT_ACCESS_EXPIRES_IN).toBe('5m');
|
|
expect(env.JWT_ACCESS_EXPIRES_IN_MS).toBe(5 * 60 * 1000);
|
|
expect(env.DEFAULT_TIMEZONE).toBe('GMT+0');
|
|
});
|
|
|
|
it('rejects invalid JWT_ACCESS_EXPIRES_IN format', () => {
|
|
expect(() =>
|
|
loadEnv({
|
|
...valid,
|
|
JWT_ACCESS_EXPIRES_IN: '900',
|
|
}),
|
|
).toThrow('must match');
|
|
});
|
|
|
|
it('enables SKIP_GPS_VALIDATION outside production', () => {
|
|
const env = loadEnv({
|
|
...valid,
|
|
SKIP_GPS_VALIDATION: 'true',
|
|
NODE_ENV: 'development',
|
|
});
|
|
|
|
expect(env.SKIP_GPS_VALIDATION).toBe(true);
|
|
});
|
|
|
|
it('rejects SKIP_GPS_VALIDATION in production', () => {
|
|
expect(() =>
|
|
loadEnv({
|
|
...valid,
|
|
SKIP_GPS_VALIDATION: 'true',
|
|
NODE_ENV: 'production',
|
|
}),
|
|
).toThrow('cannot be enabled in production');
|
|
});
|
|
|
|
it('rejects invalid SKIP_GPS_VALIDATION values', () => {
|
|
expect(() =>
|
|
loadEnv({
|
|
...valid,
|
|
SKIP_GPS_VALIDATION: 'yes',
|
|
}),
|
|
).toThrow('must be true or false');
|
|
});
|
|
});
|