mirror of
https://github.com/garrytan/gstack.git
synced 2026-05-07 05:56:41 +02:00
2468a25aa1
safeUnlink (ignores ENOENT), safeKill (ignores ESRCH), isProcessAlive (extracted from cli.ts with Windows support), and json() Response helper. All catches check err.code and rethrow unexpected errors instead of swallowing silently. Unit tests cover happy path + error code paths. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
65 lines
2.0 KiB
TypeScript
65 lines
2.0 KiB
TypeScript
import { describe, test, expect } from 'bun:test';
|
|
import * as fs from 'fs';
|
|
import * as os from 'os';
|
|
import * as path from 'path';
|
|
import { safeUnlink, safeKill, isProcessAlive, json } from '../src/error-handling';
|
|
|
|
describe('safeUnlink', () => {
|
|
test('removes an existing file', () => {
|
|
const tmp = path.join(os.tmpdir(), `test-safeUnlink-${Date.now()}`);
|
|
fs.writeFileSync(tmp, 'hello');
|
|
safeUnlink(tmp);
|
|
expect(fs.existsSync(tmp)).toBe(false);
|
|
});
|
|
|
|
test('ignores ENOENT (file does not exist)', () => {
|
|
expect(() => safeUnlink('/tmp/nonexistent-file-' + Date.now())).not.toThrow();
|
|
});
|
|
|
|
test('rethrows non-ENOENT errors', () => {
|
|
// Attempt to unlink a directory — throws EPERM/EISDIR
|
|
const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'test-safeUnlink-'));
|
|
expect(() => safeUnlink(dir)).toThrow();
|
|
fs.rmdirSync(dir);
|
|
});
|
|
});
|
|
|
|
describe('safeKill', () => {
|
|
test('sends signal to a running process', () => {
|
|
// signal 0 is a no-op existence check — safe to send to self
|
|
expect(() => safeKill(process.pid, 0)).not.toThrow();
|
|
});
|
|
|
|
test('ignores ESRCH (process does not exist)', () => {
|
|
// PID 99999999 is extremely unlikely to exist
|
|
expect(() => safeKill(99999999, 0)).not.toThrow();
|
|
});
|
|
});
|
|
|
|
describe('isProcessAlive', () => {
|
|
test('returns true for current process', () => {
|
|
expect(isProcessAlive(process.pid)).toBe(true);
|
|
});
|
|
|
|
test('returns false for non-existent process', () => {
|
|
expect(isProcessAlive(99999999)).toBe(false);
|
|
});
|
|
});
|
|
|
|
describe('json', () => {
|
|
test('returns Response with JSON body and correct Content-Type', async () => {
|
|
const resp = json({ ok: true });
|
|
expect(resp.status).toBe(200);
|
|
expect(resp.headers.get('Content-Type')).toBe('application/json');
|
|
const body = await resp.json();
|
|
expect(body).toEqual({ ok: true });
|
|
});
|
|
|
|
test('uses custom status code', async () => {
|
|
const resp = json({ error: 'not found' }, 404);
|
|
expect(resp.status).toBe(404);
|
|
const body = await resp.json();
|
|
expect(body).toEqual({ error: 'not found' });
|
|
});
|
|
});
|