Skip to content

Commit 2c96d78

Browse files
committed
test(embed): cover resolveNpmInstallCwd happy path
Mock createRequire so resolve returns a synthetic scoped package.json path, then assert the 4 dirname hops land at the host directory. Without this, only the catch-to-undefined branch was exercised and a miscounted dirname would pass CI silently. Closes follow-up suggestion from #1178 review.
1 parent 15f11ed commit 2c96d78

2 files changed

Lines changed: 49 additions & 1 deletion

File tree

src/domain/search/models.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,10 @@ const _require = createRequire(import.meta.url);
1919
*
2020
* Pin cwd to the directory that contains @optave/codegraph's `node_modules`
2121
* so the install lands where Node's resolution algorithm will find it.
22+
*
23+
* @internal Exported for unit tests; not part of the public barrel.
2224
*/
23-
function resolveNpmInstallCwd(): string | undefined {
25+
export function resolveNpmInstallCwd(): string | undefined {
2426
try {
2527
const pkgJsonPath = _require.resolve('@optave/codegraph/package.json');
2628
// pkgJsonPath = <host>/node_modules/@optave/codegraph/package.json

tests/unit/prompt-install.test.ts

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
* so every test gets a fresh embedder module with its own mocks.
99
*/
1010

11+
import path from 'node:path';
1112
import { afterEach, beforeEach, describe, expect, test, vi } from 'vitest';
1213

1314
const expectedNpmBin = process.platform === 'win32' ? 'npm.cmd' : 'npm';
@@ -186,3 +187,48 @@ describe('loadTransformers install prompt', () => {
186187
expect(exitSpy).not.toHaveBeenCalled();
187188
});
188189
});
190+
191+
describe('resolveNpmInstallCwd', () => {
192+
beforeEach(() => {
193+
vi.resetModules();
194+
});
195+
196+
afterEach(() => {
197+
vi.restoreAllMocks();
198+
});
199+
200+
test('returns host directory (4 dirname hops from scoped package.json)', async () => {
201+
const fakePkg = path.join(
202+
path.sep,
203+
'host',
204+
'node_modules',
205+
'@optave',
206+
'codegraph',
207+
'package.json',
208+
);
209+
vi.doMock('node:module', () => ({
210+
createRequire: () => ({
211+
resolve: (req: string) => {
212+
if (req === '@optave/codegraph/package.json') return fakePkg;
213+
throw new Error(`Cannot find: ${req}`);
214+
},
215+
}),
216+
}));
217+
218+
const { resolveNpmInstallCwd } = await import('../../src/domain/search/models.js');
219+
expect(resolveNpmInstallCwd()).toBe(path.join(path.sep, 'host'));
220+
});
221+
222+
test('returns undefined when @optave/codegraph cannot be resolved', async () => {
223+
vi.doMock('node:module', () => ({
224+
createRequire: () => ({
225+
resolve: () => {
226+
throw new Error('Cannot find module @optave/codegraph');
227+
},
228+
}),
229+
}));
230+
231+
const { resolveNpmInstallCwd } = await import('../../src/domain/search/models.js');
232+
expect(resolveNpmInstallCwd()).toBeUndefined();
233+
});
234+
});

0 commit comments

Comments
 (0)