mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-11-13 18:29:32 +01:00
safeRmHomeTree and isUnderTestHome answered "is this path under process.env.HOME?". With test/setup.ts skipped (a bare vitest) HOME is the developer's real home, so every real file passed, which is how the real linked-cases registry was deleted on 2026-10-10. They now also require HOME to be the throwaway codeman-vitest-* directory setup.ts creates, and the shared route harness throws when it is not, so every route test refuses to start against a real ~/.codeman rather than just the one file that checked.
79 lines
3.0 KiB
TypeScript
79 lines
3.0 KiB
TypeScript
/**
|
|
* @fileoverview The test-only deletion guards must treat a REAL home as "not the test HOME".
|
|
*
|
|
* `safeRmHomeTree` and `isUnderTestHome` were written so a test could never delete production
|
|
* state, and they asked "is this path under `process.env.HOME`?". With `test/setup.ts` skipped
|
|
* (a bare `vitest`), HOME is the developer's real home, so that answer is "yes" for every real
|
|
* file, and on 2026-10-10 they approved wiping the real linked-cases registry. They now also
|
|
* require HOME to be the throwaway directory setup.ts made.
|
|
*
|
|
* Port: none. Everything happens in a temp tree; HOME is stubbed for the duration of a test.
|
|
*/
|
|
import { afterEach, describe, expect, it, vi } from 'vitest';
|
|
import { existsSync, mkdirSync, mkdtempSync, rmSync, writeFileSync } from 'node:fs';
|
|
import { tmpdir } from 'node:os';
|
|
import { join } from 'node:path';
|
|
import {
|
|
TEST_HOME_PREFIX,
|
|
assertSandboxedHome,
|
|
isSandboxedHome,
|
|
isUnderTestHome,
|
|
safeRmHomeTree,
|
|
} from './mocks/index.js';
|
|
import { createRouteTestHarness } from './routes/_route-test-utils.js';
|
|
|
|
const made: string[] = [];
|
|
/** A stand-in for a developer's REAL home: a real directory with real files, not a sandbox name. */
|
|
function fakeRealHome(): string {
|
|
const dir = mkdtempSync(join(tmpdir(), 'not-the-sandbox-'));
|
|
made.push(dir);
|
|
mkdirSync(join(dir, '.codeman'));
|
|
writeFileSync(join(dir, '.codeman', 'linked-cases.json'), '{"keep":"/me"}');
|
|
return dir;
|
|
}
|
|
|
|
afterEach(() => {
|
|
vi.unstubAllEnvs();
|
|
for (const d of made.splice(0)) rmSync(d, { recursive: true, force: true });
|
|
});
|
|
|
|
describe('test HOME guards', () => {
|
|
it('this suite really runs under the sandboxed HOME', () => {
|
|
expect(isSandboxedHome()).toBe(true);
|
|
expect(() => assertSandboxedHome()).not.toThrow();
|
|
});
|
|
|
|
it('pins the prefix test/setup.ts creates', () => {
|
|
expect(TEST_HOME_PREFIX).toBe('codeman-vitest-');
|
|
});
|
|
|
|
it('safeRmHomeTree does not delete anything under a real home', () => {
|
|
const home = fakeRealHome();
|
|
vi.stubEnv('HOME', home);
|
|
safeRmHomeTree(join(home, '.codeman'));
|
|
expect(existsSync(join(home, '.codeman', 'linked-cases.json'))).toBe(true);
|
|
});
|
|
|
|
it('isUnderTestHome is false for a real home, even for a file inside it', () => {
|
|
const home = fakeRealHome();
|
|
vi.stubEnv('HOME', home);
|
|
expect(isSandboxedHome()).toBe(false);
|
|
expect(isUnderTestHome(join(home, '.codeman', 'linked-cases.json'))).toBe(false);
|
|
});
|
|
|
|
it('still deletes inside the real sandbox', () => {
|
|
const inside = mkdtempSync(join(process.env.HOME as string, 'guard-'));
|
|
writeFileSync(join(inside, 'f'), 'x');
|
|
expect(isUnderTestHome(inside)).toBe(true);
|
|
safeRmHomeTree(inside);
|
|
expect(existsSync(inside)).toBe(false);
|
|
});
|
|
|
|
it('the route harness refuses to start against a real home', async () => {
|
|
const home = fakeRealHome();
|
|
vi.stubEnv('HOME', home);
|
|
await expect(createRouteTestHarness(() => undefined)).rejects.toThrow(/temp HOME/);
|
|
expect(existsSync(join(home, '.codeman', 'linked-cases.json'))).toBe(true);
|
|
});
|
|
});
|