hoppscotch-backend-git/tests/cli.hopp.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

125 lines
3.9 KiB
TypeScript

import { afterAll, beforeAll, describe, expect, test } from 'bun:test';
import { mkdtemp, rm } from 'node:fs/promises';
import { tmpdir } from 'node:os';
import { join } from 'node:path';
import axios from 'axios';
import { createApp } from '../src/app.ts';
import { loadConfig } from '../src/config.ts';
import { createSampleCollection } from '../fixtures/sample.ts';
import { userFromOsIdentity } from '../src/os-user.ts';
const jwtSecret = 'test-jwt-secret-16chars';
const testUser = await userFromOsIdentity({
recordName: 'cli-test',
email: 'cli-test@example.com',
displayName: 'CLI Test',
});
const findHoppBin = async () => {
const candidates = [
join(import.meta.dir, '../node_modules/@hoppscotch/cli/bin/hopp.js'),
join(import.meta.dir, '../hoppscotch-upstream/packages/hoppscotch-cli/bin/hopp.js'),
];
for(const candidate of candidates) {
if(await Bun.file(candidate).exists())
return candidate;
}
return null;
};
describe('Hoppscotch CLI integration', () => {
let gitRepoPath = '';
let metaPath = '';
let baseURL = '';
let server: ReturnType<typeof Bun.serve> | null = null;
let echoServer: ReturnType<typeof Bun.serve> | null = null;
let echoUrl = '';
let pat = '';
let hoppBin: string | null = null;
beforeAll(async () => {
hoppBin = await findHoppBin();
gitRepoPath = await mkdtemp(join(tmpdir(), 'hbg-cli-git-'));
metaPath = join(await mkdtemp(join(tmpdir(), 'hbg-cli-meta-')), 'meta.json');
echoServer = Bun.serve({
port: 0,
fetch: () => Response.json({ ok: true, method: 'GET', headers: {} }),
});
echoUrl = `http://127.0.0.1:${echoServer.port}/`;
const config = await loadConfig({
PORT: '0',
GIT_REPO_PATH: gitRepoPath,
META_PATH: metaPath,
JWT_SECRET: jwtSecret,
WEBAPP_FRONTEND_PATH: join(import.meta.dir, '../fixtures/webapp-frontend'),
WEBAPP_SERVER_SIGNING_SECRET: 'test-webapp-signing-secret',
HOPP_STATE_DIR: await mkdtemp(join(tmpdir(), 'hbg-cli-state-')),
});
const app = await createApp(config, { localUser: testUser });
server = Bun.serve({
port: 0,
fetch: app.fetch,
});
baseURL = `http://127.0.0.1:${server.port}`;
const collection = createSampleCollection(echoUrl);
await axios.post(`${baseURL}/v1/collections`, {
id: collection.id,
collection,
});
const patRes = await axios.post(
`${baseURL}/v1/access-tokens/create`,
{ label: 'hopp-cli', expiryInDays: null },
);
pat = patRes.data.token;
});
afterAll(async () => {
server?.stop(true);
echoServer?.stop(true);
await rm(gitRepoPath, { recursive: true, force: true });
await rm(join(metaPath, '..'), { recursive: true, force: true });
});
test('hopp test fetches collection via access-token API', async () => {
if(!hoppBin) {
console.warn('Skipping hopp CLI test: binary not found (install @hoppscotch/cli)');
return;
}
const proc = Bun.spawn([
'node',
hoppBin,
'test',
'sample-echo',
'--token',
pat,
'--server',
baseURL,
], {
stdout: 'pipe',
stderr: 'pipe',
env: {
...process.env,
NODE_OPTIONS: '--no-node-snapshot',
},
});
const [stdout, stderr, code] = await Promise.all([
new Response(proc.stdout).text(),
new Response(proc.stderr).text(),
proc.exited,
]);
if(code !== 0) {
console.error(stdout);
console.error(stderr);
}
expect(code).toBe(0);
}, 120_000);
});