Files
basic-erp/apps/api/src/config/env.schema.spec.ts
T
GeorgeandClaude Sonnet 5.5 73fffee2f7 feat(api): permisos de menú en SQLite con API de administración
- SQLite (better-sqlite3 + TypeORM, WAL) con tabla menu_permissions
  (usuario web, patrón de ruta); archivo fuera del repo.
- GET /api/user/menu para el frontend; GET/PUT/DELETE /api/permissions
  solo para administradores (acceso "*").
- ADMIN_WEB_USERS garantiza el acceso total al arrancar; no se puede
  quitar el "*" al último administrador (409, dentro de una transacción).
- Patrones validados (`*`, `/modulo/ruta`, `/modulo/*`). A diferencia del
  frontend anterior, `/inventario/*` ya no habilita `/inventario-x`.
- Helper de e2e compartido (SAP simulado, SQLite en memoria).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-13 18:47:51 -05:00

60 lines
2.1 KiB
TypeScript

import { validateEnv } from './env.schema.js';
const sap = {
SAPB1_SL_URL: 'https://sap.local:50000/b1s/v1/',
SAPB1_SL_COMPANYDB: 'DB',
SAPB1_SL_USER: 'u',
SAPB1_SL_PASSWORD: 'p',
};
describe('validateEnv', () => {
it('aplica valores por defecto', () => {
const env = validateEnv(sap);
expect(env.PORT).toBe(3000);
expect(env.CORS_ORIGINS).toEqual([]);
expect(env.LOG_LEVEL).toBe('log');
expect(env.SAPB1_SL_VERIFY_SSL).toBe(true);
expect(env.SAPB1_SL_CA_FILE).toBeUndefined();
expect(env.SAPB1_SL_MAX_CONCURRENCY).toBe(1);
expect(env.SQLITE_PATH).toBe('./data/app.sqlite');
expect(env.ADMIN_WEB_USERS).toEqual([]);
});
it('separa ADMIN_WEB_USERS', () => {
expect(validateEnv({ ...sap, ADMIN_WEB_USERS: 'george, ana ,' }).ADMIN_WEB_USERS).toEqual(['george', 'ana']);
});
it('quita la barra final de la URL de SAP', () => {
expect(validateEnv(sap).SAPB1_SL_URL).toBe('https://sap.local:50000/b1s/v1');
});
it('convierte PORT y separa CORS_ORIGINS', () => {
const env = validateEnv({ ...sap, PORT: '8080', CORS_ORIGINS: 'https://a.local, https://b.local' });
expect(env.PORT).toBe(8080);
expect(env.CORS_ORIGINS).toEqual(['https://a.local', 'https://b.local']);
});
it('rechaza valores inválidos con un mensaje claro', () => {
expect(() => validateEnv({ ...sap, PORT: 'abc' })).toThrow(/PORT/);
});
it('exige las credenciales de SAP', () => {
expect(() => validateEnv({})).toThrow(/SAPB1_SL_URL/);
});
it('trata SAPB1_SL_CA_FILE vacío como no configurado', () => {
expect(validateEnv({ ...sap, SAPB1_SL_CA_FILE: '' }).SAPB1_SL_CA_FILE).toBeUndefined();
});
it('rechaza un SAPB1_SL_CA_FILE que no existe', () => {
expect(() => validateEnv({ ...sap, SAPB1_SL_CA_FILE: './no-existe.pem' })).toThrow(/CA_FILE/);
});
it('no permite desactivar la validación SSL en producción', () => {
expect(() =>
validateEnv({ ...sap, NODE_ENV: 'production', SAPB1_SL_VERIFY_SSL: 'false' }),
).toThrow(/producción/);
expect(validateEnv({ ...sap, SAPB1_SL_VERIFY_SSL: 'false' }).SAPB1_SL_VERIFY_SSL).toBe(false);
});
});