Skip to content

feat(parser): add Vitest/Jest test detection for describe/it/test blocks#54

Closed
JF10R wants to merge 3 commits intotirth8205:mainfrom
JF10R:feat/vitest-test-detection
Closed

feat(parser): add Vitest/Jest test detection for describe/it/test blocks#54
JF10R wants to merge 3 commits intotirth8205:mainfrom
JF10R:feat/vitest-test-detection

Conversation

@JF10R
Copy link

@JF10R JF10R commented Mar 22, 2026

Summary

  • Detect Vitest/Jest test runner calls (describe, it, test, beforeEach, etc.) in test files and create proper Test nodes
  • Recurse into callback bodies with correct enclosing_func context so CALLS edges inside tests are properly attributed
  • Enables automatic TESTED_BY edge generation via the existing reverse-edge logic

Before: 1 Test node, 2 TESTED_BY edges across 69 test files
After: 3,205 Test nodes, 18,331 TESTED_BY edges

Root cause

Tree-sitter parses describe("suite", () => { ... }) as a call_expression containing an anonymous arrow_function. The parser found the arrow function but skipped it because _get_name() returns None for anonymous functions. No Test node was ever created.

Changes

  • Modified: code_review_graph/parser.py
    • Added _TEST_RUNNER_NAMES constant
    • Added _get_test_description() method to extract the description string from test calls
    • New branch in _extract_from_tree() that intercepts test runner call_expression nodes in test files, creates Test nodes with synthetic names (e.g., describe:UserService), and recurses with proper enclosing_func
    • Deduplicated _is_test_function() to reuse _TEST_RUNNER_NAMES
  • New fixture: tests/fixtures/sample_vitest.test.ts
  • New tests: 5 test methods covering detection, CONTAINS edges, CALLS edges, TESTED_BY edges, and non-test-file guard

Design decisions

  • Test runner calls are intercepted at the call_expression level (not by modifying arrow function naming), keeping the change localized
  • Synthetic node names use call_name:description format (e.g., it:should create a user)
  • Only applies to JS/TS/TSX files that match test file patterns — describe() in production code is not affected
  • Nesting is handled naturally by recursion: describeit → function calls

Test plan

  • All 33 parser tests pass (pytest tests/test_parser.py -v)
  • Full test suite: 196 passed, 26 pre-existing Windows-only SQLite teardown errors
  • Validated on a real-world TypeScript project (357 files, 69 test files): 3,205 Test nodes and 18,331 TESTED_BY edges detected

🤖 Generated with Claude Code

JF10R added 2 commits March 22, 2026 11:10
Intercept call_expression nodes with test runner names (describe, it,
test, beforeEach, etc.) in test files and create Test nodes with
synthetic names from the description string. Recurse into callbacks
with enclosing_func set so CALLS edges inside tests are properly
attributed, enabling automatic TESTED_BY edge generation.

New constant: _TEST_RUNNER_NAMES
New method: _get_test_description()
New fixture: sample_vitest.test.ts
5 new test methods
- _is_test_function: réutilise _TEST_RUNNER_NAMES au lieu du tuple dupliqué
- _get_test_description: docstring condensée, variable intermédiaire retirée
- test_vitest_contains_edges: ajout assertion sur les edges CONTAINS
- test_vitest_calls_edges: correction message assertion
- test_non_test_file_describe_not_special: pattern cohérent avec le repo
Copilot AI review requested due to automatic review settings March 22, 2026 15:20
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds Vitest/Jest-style test block detection to the Tree-sitter parser so describe/it/test (and hooks) in JS/TS test files produce Test nodes and proper containment/call attribution, enabling much broader automatic TESTED_BY edge generation.

Changes:

  • Extend code_review_graph/parser.py to detect test-runner call_expression nodes in JS/TS test files, create synthetic Test nodes, and recurse into callback bodies with the correct enclosing_func.
  • Add a Vitest fixture (sample_vitest.test.ts) that exercises nested describe + it/test blocks and calls into imported production symbols.
  • Add parser tests validating Test node creation plus CONTAINS, CALLS, and TESTED_BY edge generation, and ensure non-test files don’t get special handling.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 5 comments.

File Description
code_review_graph/parser.py Adds test-runner call interception and description extraction to build Test nodes and attribute internal calls to those tests.
tests/fixtures/sample_vitest.test.ts New TS fixture containing describe/it/test blocks and calls into imported code.
tests/test_parser.py New pytest cases covering test detection and edge generation for Vitest/Jest-style tests.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

…ertions

- Add _MAX_TEST_DESCRIPTION_LEN = 200 constant; _get_test_description now
  strips surrounding quotes/backticks, collapses internal whitespace via
  re.sub, and truncates to the cap to prevent bloated node names
- Append @l{line_no} to synthetic test names so identical descriptions
  under different describe blocks produce unique node names
- Add _get_base_call_name() + _TEST_MODIFIER_SUFFIXES to detect
  describe.only(), it.skip(), test.each(), etc. as proper test runner calls
- Replace "describe" in n / "it:" in n substring checks with startswith()
  in test_vitest_test_detection and test_vitest_contains_edges

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@JF10R
Copy link
Author

JF10R commented Mar 22, 2026

All 5 review comments addressed in 460f516:

parser.py:

  • _get_test_description() now normalizes whitespace and truncates to 200 chars
  • Synthetic test names include @l{line} suffix for uniqueness (e.g., it:should work@L42)
  • Added _get_base_call_name() to detect describe.only(), it.skip(), test.each() and other modifier patterns

Tests:

  • All assertions use startswith() instead of substring in checks to avoid false positives

tirth8205 added a commit that referenced this pull request Mar 26, 2026
Adds describe/it/test block parsing for JS/TS test files, producing
synthetic Test nodes with description labels. Supports modifier suffixes
(describe.only, it.skip, test.each) and nested describe/it containment.

Co-Authored-By: JF10R <noreply@github.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
tirth8205 added a commit that referenced this pull request Mar 26, 2026
…nfigurable embeddings, MiniMax, Perl)

* feat: integrate PR #43 — R language support

Adds R language parsing with function extraction (both <- and = assignment),
S4/R5 class detection via setClass/setRefClass, library/require/source
imports, namespace-qualified calls (dplyr::filter), and testthat test detection.

Co-Authored-By: michael-denyer <noreply@github.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: integrate PR #54 — Vitest/Jest test detection

Adds describe/it/test block parsing for JS/TS test files, producing
synthetic Test nodes with description labels. Supports modifier suffixes
(describe.only, it.skip, test.each) and nested describe/it containment.

Co-Authored-By: JF10R <noreply@github.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: integrate PR #53 — tsconfig path alias resolution

Adds TsconfigResolver module that resolves TypeScript path aliases
(e.g., @/ -> src/) from tsconfig.json compilerOptions.paths. Also
resolves import targets to absolute file paths in IMPORTS_FROM edges.

Co-Authored-By: JF10R <noreply@github.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: integrate PR #58 — .mjs/.astro support

Adds .mjs extension mapping to JavaScript and .astro extension mapping
to TypeScript for import path resolution.

Co-Authored-By: zoneghost7 <noreply@github.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: integrate PR #55 — configurable embedding model

Adds CRG_EMBEDDING_MODEL env var and model parameter to embedding
functions, allowing users to specify any sentence-transformers compatible
model. Changing the model re-embeds all nodes automatically.

Co-Authored-By: eugenepro2 <noreply@github.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: integrate PR #45 — MiniMax embedding provider

Adds MiniMaxEmbeddingProvider using the embo-01 model (1536 dimensions)
with support for distinct task types (db/query), batching, and retry logic.

Co-Authored-By: octo-patch <noreply@github.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: integrate PR #62 — Perl support

Adds Perl language parsing with package detection, subroutine extraction,
use/require imports, and function call tracking. Includes test fixture
and comprehensive test class.

Co-Authored-By: potatogim <noreply@github.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: michael-denyer <noreply@github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@tirth8205
Copy link
Owner

Integrated into main via PR #68. Thank you for the contribution! 🎉

@tirth8205 tirth8205 closed this Mar 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants