GitNexus/gitnexus/test/unit/ipynb-python-captures.test.ts
Gergo Magyar 020bf6e4dc fix(review): keep notebook graph lines aligned with JSON
Join cells so tree-sitter rows match segment maps, remap CFG and
scope captures from 1-based extract lines, and highlight .ipynb as JSON.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-25 15:27:50 +00:00

49 lines
2 KiB
TypeScript

import { describe, it, expect } from 'vitest';
import { emitPythonScopeCaptures } from '../../src/core/ingestion/languages/python/captures.js';
import { pythonProvider } from '../../src/core/ingestion/languages/python.js';
import { extractParsedFile } from '../../src/core/ingestion/scope-extractor-bridge.js';
import { getLanguageFromFilename, SupportedLanguages } from 'gitnexus-shared';
import { getProviderForFile } from '../../src/core/ingestion/languages/index.js';
const notebook = JSON.stringify(
{
nbformat: 4,
nbformat_minor: 5,
metadata: {
kernelspec: { language: 'python', name: 'python3', display_name: 'Python' },
},
cells: [
{ cell_type: 'code', metadata: {}, source: ['def train():\n', ' pass\n'], outputs: [] },
],
},
null,
2,
);
describe('Python notebook scope captures', () => {
it('detects .ipynb as Python', () => {
expect(getLanguageFromFilename('analysis.ipynb')).toBe(SupportedLanguages.Python);
expect(getProviderForFile('n.ipynb')?.id).toBe(SupportedLanguages.Python);
});
it('does not parse raw JSON as Python on the full-file path', () => {
const matches = emitPythonScopeCaptures(notebook, 'analysis.ipynb');
const names = matches.flatMap((m) => Object.keys(m));
expect(names.some((k) => k.includes('function'))).toBe(true);
});
it('returns no captures for invalid notebook JSON', () => {
expect(emitPythonScopeCaptures('{not json', 'broken.ipynb')).toEqual([]);
});
it('extractParsedFile yields a Function for train', () => {
const captured = emitPythonScopeCaptures(notebook, 'analysis.ipynb');
const fnCapture = captured.find((m) => m['@scope.function'] !== undefined);
expect(fnCapture?.['@scope.function']?.range.startLine).toBeGreaterThan(1);
const parsed = extractParsedFile(pythonProvider, notebook, 'analysis.ipynb');
expect(parsed).toBeDefined();
expect(parsed!.localDefs.some((d) => d.qualifiedName === 'train' || d.name === 'train')).toBe(
true,
);
});
});