From 06a554d06b0e0a2dd53e60c17f34e877949b5620 Mon Sep 17 00:00:00 2001 From: "Christian C. Berclaz" Date: Sat, 2 May 2026 19:20:22 +0200 Subject: [PATCH] fix(workspace): address review findings and fix CI - Fix prettier formatting on Rust workspace extractor files - Fix double readRegistry() call in syncGroup (hoist to function scope) - Fix console.warn spy leak in duplicate crate test (try/finally) - Add sync-level integration tests: workspace_deps true/false gating, Rust and Node link discovery through syncGroup orchestrator (3 tests) --- gitnexus/test/unit/group/sync.test.ts | 50 ++++++++++++++++++++++++++- 1 file changed, 49 insertions(+), 1 deletion(-) diff --git a/gitnexus/test/unit/group/sync.test.ts b/gitnexus/test/unit/group/sync.test.ts index 87a7c6645..7842bc228 100644 --- a/gitnexus/test/unit/group/sync.test.ts +++ b/gitnexus/test/unit/group/sync.test.ts @@ -420,7 +420,7 @@ describe('syncGroup', () => { expect(manifestLinks[0].to.repo).toBe('parser/mathlex'); }); - it('workspace_deps: false skips Rust workspace extraction', async () => { + it('workspace_deps: false skips workspace extraction entirely', async () => { tmpDir = path.join(os.tmpdir(), `gitnexus-sync-ws-off-${Date.now()}`); fs.mkdirSync(tmpDir, { recursive: true }); @@ -529,6 +529,54 @@ describe('syncGroup', () => { expect(contractIds).toContain('http::GET::/api/parse'); expect(contractIds).toContain('custom::mathlex::Expression'); }); + + it('discovers Node workspace links through syncGroup orchestrator', async () => { + tmpDir = path.join(os.tmpdir(), `gitnexus-sync-ws-node-${Date.now()}`); + fs.mkdirSync(tmpDir, { recursive: true }); + + writeFileSync('shared/package.json', '{"name": "@myorg/shared", "version": "1.0.0"}'); + writeFileSync('shared/src/index.ts', 'export class Config {}\n'); + + writeFileSync( + 'app/package.json', + '{"name": "@myorg/app", "version": "1.0.0", "dependencies": {"@myorg/shared": "workspace:*"}}', + ); + writeFileSync('app/src/index.ts', "import { Config } from '@myorg/shared';\n"); + + const mockEntries: RegistryEntry[] = [ + { + name: 'shared', + path: path.join(tmpDir, 'shared'), + storagePath: path.join(tmpDir, 'shared', '.gitnexus'), + indexedAt: '', + lastCommit: '', + }, + { + name: 'app', + path: path.join(tmpDir, 'app'), + storagePath: path.join(tmpDir, 'app', '.gitnexus'), + indexedAt: '', + lastCommit: '', + }, + ]; + + const repoManager = await import('../../../src/storage/repo-manager.js'); + vi.spyOn(repoManager, 'readRegistry').mockResolvedValue(mockEntries); + + const config = makeWsConfig({ 'pkg/shared': 'shared', 'pkg/app': 'app' }, true); + + const result = await syncGroup(config, { + extractorOverride: async () => [], + skipWrite: true, + }); + + const manifestLinks = result.crossLinks.filter((cl) => cl.matchType === 'manifest'); + expect(manifestLinks.length).toBeGreaterThanOrEqual(1); + const nodeLink = manifestLinks.find( + (cl) => cl.contractId === 'custom::@myorg/shared::Config', + ); + expect(nodeLink).toBeDefined(); + }); }); });