hoppscotch-backend-git/tests/state-secrets.test.ts
tlemesle 0cc7276c23 Auto-generate secrets in per-user state directory
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-24 16:24:27 +02:00

76 lines
3.2 KiB
TypeScript

import { describe, expect, test } from 'bun:test';
import { mkdtemp, rm, readFile, stat } from 'node:fs/promises';
import { tmpdir } from 'node:os';
import { join } from 'node:path';
import { loadConfig } from '../src/config.ts';
import { ensureAppSecrets } from '../src/secrets.ts';
import { resolveStateDir } from '../src/state-dir.ts';
describe('state dir & secrets', () => {
test('resolveStateDir uses HOPP_STATE_DIR override', () => {
expect(resolveStateDir({ HOPP_STATE_DIR: '/tmp/hopp-state' }))
.toBe('/tmp/hopp-state');
});
test('resolveStateDir uses macOS Application Support', () => {
const dir = resolveStateDir({}, 'darwin');
expect(dir.endsWith('Library/Application Support/hoppscotch-backend-git'))
.toBe(true);
});
test('resolveStateDir uses XDG_DATA_HOME on linux', () => {
expect(resolveStateDir(
{ XDG_DATA_HOME: '/var/xdg' },
'linux',
)).toBe('/var/xdg/hoppscotch-backend-git');
});
test('ensureAppSecrets creates and reuses secrets.json', async () => {
const dir = await mkdtemp(join(tmpdir(), 'hbg-secrets-'));
const path = join(dir, 'secrets.json');
try {
const first = await ensureAppSecrets(path);
expect(first.jwtSecret.length).toBeGreaterThanOrEqual(16);
expect(first.webappSigningSecret.length).toBeGreaterThanOrEqual(16);
const mode = (await stat(path)).mode & 0o777;
expect(mode).toBe(0o600);
const second = await ensureAppSecrets(path);
expect(second).toEqual(first);
const overridden = await ensureAppSecrets(path, {
jwtSecret: 'override-jwt-secret-16',
});
expect(overridden.jwtSecret).toBe('override-jwt-secret-16');
expect(overridden.webappSigningSecret).toBe(first.webappSigningSecret);
const stored = JSON.parse(await readFile(path, 'utf8'));
expect(stored.jwtSecret).toBe(first.jwtSecret);
} finally {
await rm(dir, { recursive: true, force: true });
}
});
test('loadConfig defaults meta & secrets under HOPP_STATE_DIR', async () => {
const stateDir = await mkdtemp(join(tmpdir(), 'hbg-cfg-state-'));
const gitRepoPath = await mkdtemp(join(tmpdir(), 'hbg-cfg-git-'));
try {
const config = await loadConfig({
GIT_REPO_PATH: gitRepoPath,
HOPP_STATE_DIR: stateDir,
WEBAPP_FRONTEND_PATH: join(import.meta.dir, '../fixtures/webapp-frontend'),
});
expect(config.stateDir).toBe(stateDir);
expect(config.metaPath).toBe(join(stateDir, 'meta.json'));
expect(config.webappSigningKeyFile).toBe(join(stateDir, 'signing.key'));
expect(config.jwtSecret.length).toBeGreaterThanOrEqual(16);
expect(config.webappSigningSecret?.length).toBeGreaterThanOrEqual(16);
expect(await Bun.file(join(stateDir, 'secrets.json')).exists()).toBe(true);
} finally {
await rm(stateDir, { recursive: true, force: true });
await rm(gitRepoPath, { recursive: true, force: true });
}
});
});