From 640ab439985875f9f983119b0814a6affa9956f7 Mon Sep 17 00:00:00 2001 From: Gergo Magyar Date: Thu, 18 Jun 2026 15:57:11 +0000 Subject: [PATCH] test(server): scope customHome temp dir to the GITNEXUS_HOME-set cases beforeEach created a customHome temp dir for all five tests, but the two fallback cases never use it (one manages its own fakeHome, the other needs none). Moved the mkdtemp/rm into a nested describe('with GITNEXUS_HOME set') wrapping the three set-cases; the shared outer afterEach still restores GITNEXUS_HOME and resets modules for all five. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../test/unit/gitnexus-home-roots.test.ts | 75 +++++++++++-------- 1 file changed, 42 insertions(+), 33 deletions(-) diff --git a/gitnexus/test/unit/gitnexus-home-roots.test.ts b/gitnexus/test/unit/gitnexus-home-roots.test.ts index a01ddf309..f50f2a7a6 100644 --- a/gitnexus/test/unit/gitnexus-home-roots.test.ts +++ b/gitnexus/test/unit/gitnexus-home-roots.test.ts @@ -20,47 +20,56 @@ import fs from 'node:fs/promises'; */ describe('GITNEXUS_HOME path roots', () => { const savedHome = process.env.GITNEXUS_HOME; - // mkdtemp (not a fixed os.tmpdir() name) so a co-located process cannot - // pre-create or symlink the path before our writes land - // (CodeQL js/insecure-temporary-file). - let customHome: string; - beforeEach(async () => { - customHome = await fs.mkdtemp(path.join(os.tmpdir(), 'gitnexus-home-roots-')); - }); - - afterEach(async () => { + afterEach(() => { if (savedHome === undefined) delete process.env.GITNEXUS_HOME; else process.env.GITNEXUS_HOME = savedHome; vi.resetModules(); - await fs.rm(customHome, { recursive: true, force: true }); }); - it('clone root follows GITNEXUS_HOME', async () => { - process.env.GITNEXUS_HOME = customHome; - vi.resetModules(); - const { getCloneDir } = await import('../../src/server/git-clone.js'); - expect(getCloneDir('my-repo')).toBe(path.resolve(customHome, 'repos', 'my-repo')); - }); + // customHome is only needed by the GITNEXUS_HOME-set cases below; the two + // fallback cases manage their own (or no) temp dir, so its lifecycle lives in + // this nested block rather than a shared beforeEach. + describe('with GITNEXUS_HOME set', () => { + // mkdtemp (not a fixed os.tmpdir() name) so a co-located process cannot + // pre-create or symlink the path before our writes land + // (CodeQL js/insecure-temporary-file). + let customHome: string; - it('upload root follows GITNEXUS_HOME', async () => { - process.env.GITNEXUS_HOME = customHome; - vi.resetModules(); - const { UPLOAD_ROOT, getUploadDir } = await import('../../src/server/upload-paths.js'); - expect(UPLOAD_ROOT).toBe(path.resolve(customHome, 'uploads')); - expect(getUploadDir('my-repo')).toBe(path.resolve(customHome, 'uploads', 'my-repo')); - }); + beforeEach(async () => { + customHome = await fs.mkdtemp(path.join(os.tmpdir(), 'gitnexus-home-roots-')); + }); - it('server-mapping file is read from GITNEXUS_HOME', async () => { - process.env.GITNEXUS_HOME = customHome; - await fs.writeFile( - path.join(customHome, 'server-mapping.json'), - JSON.stringify({ 'my-repo': 'payments-service' }), - 'utf-8', - ); - vi.resetModules(); - const { readServerMapping } = await import('../../src/core/embeddings/server-mapping.js'); - expect(await readServerMapping('my-repo')).toBe('payments-service'); + afterEach(async () => { + await fs.rm(customHome, { recursive: true, force: true }); + }); + + it('clone root follows GITNEXUS_HOME', async () => { + process.env.GITNEXUS_HOME = customHome; + vi.resetModules(); + const { getCloneDir } = await import('../../src/server/git-clone.js'); + expect(getCloneDir('my-repo')).toBe(path.resolve(customHome, 'repos', 'my-repo')); + }); + + it('upload root follows GITNEXUS_HOME', async () => { + process.env.GITNEXUS_HOME = customHome; + vi.resetModules(); + const { UPLOAD_ROOT, getUploadDir } = await import('../../src/server/upload-paths.js'); + expect(UPLOAD_ROOT).toBe(path.resolve(customHome, 'uploads')); + expect(getUploadDir('my-repo')).toBe(path.resolve(customHome, 'uploads', 'my-repo')); + }); + + it('server-mapping file is read from GITNEXUS_HOME', async () => { + process.env.GITNEXUS_HOME = customHome; + await fs.writeFile( + path.join(customHome, 'server-mapping.json'), + JSON.stringify({ 'my-repo': 'payments-service' }), + 'utf-8', + ); + vi.resetModules(); + const { readServerMapping } = await import('../../src/core/embeddings/server-mapping.js'); + expect(await readServerMapping('my-repo')).toBe('payments-service'); + }); }); it('falls back to ~/.gitnexus when GITNEXUS_HOME is unset', async () => {