Skip to content

test: add unit tests for TechStackDetector module#503

Open
nikolasdehor wants to merge 3 commits intoSynkraAI:mainfrom
nikolasdehor:test/tech-stack-detector-coverage
Open

test: add unit tests for TechStackDetector module#503
nikolasdehor wants to merge 3 commits intoSynkraAI:mainfrom
nikolasdehor:test/tech-stack-detector-coverage

Conversation

@nikolasdehor
Copy link
Contributor

@nikolasdehor nikolasdehor commented Feb 24, 2026

Resumo

  • 84 testes unitários para .aios-core/core/orchestration/tech-stack-detector.js
  • Módulo com 599 linhas e ZERO cobertura anterior
  • Mock completo do fs-extra para testes determinísticos

Áreas testadas

  • Constructor: Armazenamento de projectRoot, cache de package.json
  • Profile vazio: Validação de todos os campos iniciais
  • Detecção de banco de dados: Supabase (diretório + npm), Prisma, PostgreSQL (pg, @prisma/client), MongoDB (mongoose), MySQL (mysql2), SQLite (better-sqlite3)
  • RLS: Detecção de ENABLE ROW LEVEL SECURITY e CREATE POLICY em migrações SQL
  • Variáveis de ambiente: Detecção em .env, .env.local, .env.example
  • Frontend: React, Vue, Angular, Svelte, Next.js (→ React), Nuxt (→ Vue), fallback por .tsx/.jsx em src/
  • Build tools: Vite, Webpack, esbuild, Parcel
  • Styling: Tailwind, styled-components, Emotion, SCSS
  • Bibliotecas de componentes: shadcn (diretório), MUI, Chakra, Ant Design
  • Backend: Express, Fastify, NestJS, Hono, Edge Functions (supabase/functions)
  • Rotas API: api/, src/api/, pages/api/ (Next.js), app/api/ (App Router)
  • TypeScript e testes: Detecção por dependência e por tsconfig.json/diretórios
  • Fases aplicáveis: Fase 1 sempre, fase 2 com DB, fase 3 com frontend
  • Cálculo de confiança: Pontuação incremental, cap em 100
  • getSummary: Todas as combinações, "unknown" para tipos nulos, pipe separator
  • Integração: Projeto vazio vs full-stack completo

Plano de teste

  • Todos os 84 testes passam localmente
  • fs-extra totalmente mockado (sem I/O real)
  • Nomes dos testes em pt-BR

Summary by CodeRabbit

  • Tests
    • Expanded test coverage for tech-stack detection: extensive unit and integration scenarios covering database, frontend, backend, TypeScript, and test framework identification; detection confidence and summary formatting; caching and error-tolerance behaviors; detection of migrations, edge functions, build tools, and styling/libs; src-structure and config-file signals; end-to-end empty and full-stack scenarios with timestamp validation; heavy filesystem mocking to exercise positive and failure paths.

84 tests covering:
- Constructor and package.json caching
- Empty profile structure validation
- Database detection (Supabase, Prisma, pg, MongoDB, MySQL, SQLite)
- RLS detection in SQL migrations
- Environment variable detection
- Frontend detection (React, Vue, Angular, Svelte, Next, Nuxt)
- Build tool detection (Vite, Webpack, esbuild, Parcel)
- Styling detection (Tailwind, styled-components, Emotion, SCSS)
- Component library detection (shadcn, MUI, Chakra, Ant Design)
- Backend detection (Express, Fastify, NestJS, Hono, Edge Functions)
- API route detection (api/, pages/api/, app/api/)
- TypeScript and test framework detection
- Applicable phase computation
- Confidence score calculation with cap at 100
- Static getSummary with all combinations
- Full integration test (empty project + full-stack project)
Copilot AI review requested due to automatic review settings February 24, 2026 23:40
@vercel
Copy link

vercel bot commented Feb 24, 2026

@nikolasdehor is attempting to deploy a commit to the Pedro Valério Lopez's projects Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai
Copy link

coderabbitai bot commented Feb 24, 2026

Walkthrough

Adds a comprehensive unit test suite for the TechStackDetector module, covering constructor/state, package.json loading/caching, dependency- and filesystem-based detection for database/frontend/backend, TypeScript/tests detection, phase computation, confidence scoring, and end-to-end detection flows (including timestamp validation).

Changes

Cohort / File(s) Summary
Test Suite — TechStackDetector
tests/core/orchestration/tech-stack-detector.test.js
Adds ~900 lines of unit tests validating: constructor and internal state, _createEmptyProfile, _loadPackageJson caching/error cases, _getAllDependencies merging, _detectDatabase (dirs, deps, migrations, env), _detectFrontend (deps, build tools, styling, component libs, src structure), _detectBackend (frameworks, edge/functions, API routes), _detectTypeScript (devDeps, tsconfig), _detectTests (deps, test dirs), _computeApplicablePhases, _calculateConfidence, getSummary formatting, and integration detect scenarios. Uses extensive fs-extra mocking to simulate project layouts.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Suggested labels

core, tests

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'test: add unit tests for TechStackDetector module' is clear, concise, and directly describes the main change—addition of comprehensive unit tests for a specific module.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

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 a comprehensive Jest unit test suite for the TechStackDetector orchestration module, aiming to validate deterministic stack detection behavior via fully mocked filesystem operations.

Changes:

  • Adds 84 unit tests covering database/frontend/backend/TypeScript/tests detection, applicable phases, confidence scoring, summary formatting, and end-to-end detect() behavior.
  • Introduces a full fs-extra mock strategy to keep tests deterministic (no real I/O).

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

Comment on lines +9 to +14
const fs = require('fs-extra');
const TechStackDetector = require('../../../.aios-core/core/orchestration/tech-stack-detector');

// Mock fs-extra
jest.mock('fs-extra');

Copy link

Copilot AI Feb 24, 2026

Choose a reason for hiding this comment

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

jest.mock('fs-extra') is declared after require('fs-extra') and after importing TechStackDetector. With this repo’s Jest setup (no transform/hoisting configured in jest.config.js), the module under test will likely keep a reference to the real fs-extra, and fs.pathExists.mockResolvedValue(...) will throw because pathExists won’t be a Jest mock. Move the jest.mock('fs-extra') call above all require(...) statements that import fs-extra directly or indirectly (i.e., before requiring TechStackDetector).

Suggested change
const fs = require('fs-extra');
const TechStackDetector = require('../../../.aios-core/core/orchestration/tech-stack-detector');
// Mock fs-extra
jest.mock('fs-extra');
// Mock fs-extra
jest.mock('fs-extra');
const fs = require('fs-extra');
const TechStackDetector = require('../../../.aios-core/core/orchestration/tech-stack-detector');

Copilot uses AI. Check for mistakes.
Comment on lines +1 to +6
/**
* Testes unitários para o módulo tech-stack-detector
*
* Testa a classe TechStackDetector que detecta a stack tecnológica
* do projeto de forma determinística usando operações de filesystem.
*/
Copy link

Copilot AI Feb 24, 2026

Choose a reason for hiding this comment

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

PR description mentions improving coverage for .aios-core/core/orchestration/tech-stack-detector.js, but Jest coverage collection currently excludes .aios-core/core/orchestration/** (jest.config.js collectCoverageFrom). These tests will run, but they won’t change the reported coverage numbers unless that exclusion is adjusted.

Copilot uses AI. Check for mistakes.
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
tests/core/orchestration/tech-stack-detector.test.js (1)

166-172: Consolidate repeated dependency mock setup helper

setupDeps is duplicated across three describe blocks. Consider extracting a single helper (or factory) to reduce drift and make future test updates safer.

Also applies to: 343-349, 503-509

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/core/orchestration/tech-stack-detector.test.js` around lines 166 - 172,
The test file repeats the setupDeps helper in multiple describe blocks; extract
a single shared helper (e.g., a top-level setupDepsFactory or setupDeps
function) and replace the duplicated implementations in the three describe
blocks with calls to that single helper. Move the helper near the top of the
test file (before any describe blocks) and have it encapsulate the
fs.pathExists.mockImplementation and fs.readJson.mockResolvedValue logic
(checking path.join(PROJECT_ROOT, 'package.json') and returning the provided
deps), then update each test block to call the shared setupDeps instead of
redefining it.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@tests/core/orchestration/tech-stack-detector.test.js`:
- Line 335: The test is using an invalid Jest matcher chain on
detector._detectDatabase(profile): `.resolves.not.toThrow()` is wrong because
`.resolves` unwraps the fulfilled value (undefined) and `.toThrow()` expects a
function; change the assertion to assert the resolved value instead — replace
the matcher with `.resolves.toBeUndefined()` (or alternatively assert the
promise resolves without rejecting via `.resolves.not.toBeDefined()` if you
prefer) to correctly verify the promise fulfills without throwing.

---

Nitpick comments:
In `@tests/core/orchestration/tech-stack-detector.test.js`:
- Around line 166-172: The test file repeats the setupDeps helper in multiple
describe blocks; extract a single shared helper (e.g., a top-level
setupDepsFactory or setupDeps function) and replace the duplicated
implementations in the three describe blocks with calls to that single helper.
Move the helper near the top of the test file (before any describe blocks) and
have it encapsulate the fs.pathExists.mockImplementation and
fs.readJson.mockResolvedValue logic (checking path.join(PROJECT_ROOT,
'package.json') and returning the provided deps), then update each test block to
call the shared setupDeps instead of redefining it.

ℹ️ Review info

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9425a35 and b80faaa.

📒 Files selected for processing (1)
  • tests/core/orchestration/tech-stack-detector.test.js

- Extrai setupDeps para nível superior do describe (evita duplicação)
- Move jest.mock('fs-extra') antes dos requires por clareza
- Troca .resolves.not.toThrow() por .resolves.toBeUndefined()
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (1)
tests/core/orchestration/tech-stack-detector.test.js (1)

345-566: Add explicit failure-path tests for frontend/backend filesystem calls.

Happy path coverage is strong, but there is no explicit assertion that _detectFrontend and _detectBackend tolerate fs errors (similar to the DB migration error-path test). Adding those tests will harden reliability expectations.

As per coding guidelines, "Verify error handling is comprehensive."

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/core/orchestration/tech-stack-detector.test.js` around lines 345 - 566,
Add negative-path unit tests that simulate filesystem errors for
detector._detectFrontend and detector._detectBackend: mock
fs.pathExists/fs.readJson/fs.readdir to throw (or reject) and call
detector._detectFrontend(profile) / detector._detectBackend(profile) using
detector._createEmptyProfile(), then assert the call does not throw and that
profile.hasFrontend/profile.hasBackend remain false (or unchanged) and any
related flags (frontend.buildTool/backend.hasAPI) are not set; follow the
existing DB migration error-path test pattern and reuse setupDeps when
appropriate to keep test structure consistent.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@tests/core/orchestration/tech-stack-detector.test.js`:
- Around line 312-325: Update the "detecta env vars de banco de dados" test to
cover the other env-file variants the detector supports: adjust the
fs.pathExists mock in tests/core/orchestration/tech-stack-detector.test.js so it
returns true for paths ending with '.env', '.env.local', and '.env.example' (or
add separate test cases for each filename), and ensure
fs.readFile.mockResolvedValue returns content containing the DB env var for
those files (or mock multiple readFile calls accordingly) so
detector._detectDatabase and the test for profile.database.envVarsConfigured
exercise all supported env-file branches.
- Around line 541-565: Add coverage for src/api and app/api by adding tests
analogous to the existing 'detecta rotas API em api/' and 'detecta rotas API em
pages/api/': for each new test mock fs.pathExists to return true for
path.join(PROJECT_ROOT, 'src/api') and path.join(PROJECT_ROOT, 'app/api')
respectively, keep fs.readJson.mockResolvedValue({ dependencies: {} }), call
detector._createEmptyProfile() and await detector._detectBackend(profile), and
assert expect(profile.backend.hasAPI).toBe(true); this ensures
detector._detectBackend and profile.backend.hasAPI behavior is exercised for
src/api and app/api paths.

---

Nitpick comments:
In `@tests/core/orchestration/tech-stack-detector.test.js`:
- Around line 345-566: Add negative-path unit tests that simulate filesystem
errors for detector._detectFrontend and detector._detectBackend: mock
fs.pathExists/fs.readJson/fs.readdir to throw (or reject) and call
detector._detectFrontend(profile) / detector._detectBackend(profile) using
detector._createEmptyProfile(), then assert the call does not throw and that
profile.hasFrontend/profile.hasBackend remain false (or unchanged) and any
related flags (frontend.buildTool/backend.hasAPI) are not set; follow the
existing DB migration error-path test pattern and reuse setupDeps when
appropriate to keep test structure consistent.

ℹ️ Review info

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b80faaa and 79eef9e.

📒 Files selected for processing (1)
  • tests/core/orchestration/tech-stack-detector.test.js

@nikolasdehor
Copy link
Contributor Author

@coderabbitai review

Issues resolvidas no commit anterior:

  1. jest.mock('fs-extra') movido para antes dos requires
  2. setupDeps consolidado no top-level describe
  3. .resolves.not.toThrow() trocado por .resolves.toBeUndefined()

@coderabbitai
Copy link

coderabbitai bot commented Feb 25, 2026

🧩 Analysis chain

@nikolasdehor: I'll review the changes now. Let me first verify the fixes you mentioned, then trigger a comprehensive review of the PR.


🏁 Script executed:

#!/bin/bash
# Read the test file to verify the fixes
cat tests/core/orchestration/tech-stack-detector.test.js | head -100

Length of output: 3199


🏁 Script executed:

#!/bin/bash
# Check if jest.mock is properly placed before requires and look for setupDeps usage
grep -n "jest.mock\|require\|setupDeps" tests/core/orchestration/tech-stack-detector.test.js | head -20

Length of output: 894


🏁 Script executed:

#!/bin/bash
# Check for any remaining .resolves.not.toThrow() patterns
rg "\.resolves\.not\.toThrow\(\)" tests/core/orchestration/tech-stack-detector.test.js

Length of output: 0


🏁 Script executed:

#!/bin/bash
# Count test cases to verify the 84 tests claim
grep -c "^\s*it\(" tests/core/orchestration/tech-stack-detector.test.js

Length of output: 23


🏁 Script executed:

#!/bin/bash
# Count test cases properly (fix the regex)
grep -c "^\s*test(" tests/core/orchestration/tech-stack-detector.test.js

Length of output: 2


🏁 Script executed:

#!/bin/bash
# Also check for 'it(' patterns with better regex
rg "^\s+(test|it)\(" tests/core/orchestration/tech-stack-detector.test.js | wc -l

Length of output: 2


🏁 Script executed:

#!/bin/bash
# Verify .resolves.toBeUndefined() is being used instead
rg "\.resolves\.toBeUndefined\(\)" tests/core/orchestration/tech-stack-detector.test.js | head -5

Length of output: 79


@nikolasdehor: Perfect! I've verified all three fixes:

jest.mock('fs-extra') - Now correctly placed on line 10, before the require statements
setupDeps consolidation - Defined once in the top-level describe block (line 22) and reused throughout all test suites
.resolves.toBeUndefined() - Replaced .resolves.not.toThrow() successfully

Also confirmed 84 test cases as described in the PR summary. The test structure looks clean and well-organized. I'll now perform a comprehensive review of the entire PR.

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

- Env vars de banco: cobre .env, .env.local e .env.example
- Rotas API: cobre api/, src/api/, pages/api/ e app/api/
@codecov
Copy link

codecov bot commented Feb 28, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
tests/core/orchestration/tech-stack-detector.test.js (1)

349-467: Consider table-driving more dependency-detection tests to reduce repetition.

The repeated “setup deps → detect → assert type” pattern can be condensed, making additions easier and reducing maintenance overhead.

Example refactor pattern
+    test.each([
+      [{ react: '^18' }, 'react'],
+      [{ vue: '^3' }, 'vue'],
+      [{ '@angular/core': '^17' }, 'angular'],
+      [{ svelte: '^4' }, 'svelte'],
+    ])('detecta framework %p => %s', async (deps, expected) => {
+      setupDeps(deps);
+      const profile = detector._createEmptyProfile();
+      await detector._detectFrontend(profile);
+      expect(profile.frontend.framework).toBe(expected);
+    });

Also applies to: 501-529

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/core/orchestration/tech-stack-detector.test.js` around lines 349 - 467,
The tests repeat the same "setupDeps → detector._createEmptyProfile →
detector._detectFrontend → expect" flow; refactor by table-driving cases: create
an array of {name, deps, expectedPath, expectedValue} and iterate (use test.each
or forEach) to call setupDeps(deps), build profile via
detector._createEmptyProfile(), await detector._detectFrontend(profile), and
assert the expected field (e.g., profile.frontend.framework, buildTool, styling,
componentLibrary) matches expectedValue; reference functions setupDeps,
detector._createEmptyProfile and detector._detectFrontend and the profile
assertions to replace the many near-duplicate test blocks with a single
parametrized loop for each assertion category.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@tests/core/orchestration/tech-stack-detector.test.js`:
- Around line 349-467: The tests repeat the same "setupDeps →
detector._createEmptyProfile → detector._detectFrontend → expect" flow; refactor
by table-driving cases: create an array of {name, deps, expectedPath,
expectedValue} and iterate (use test.each or forEach) to call setupDeps(deps),
build profile via detector._createEmptyProfile(), await
detector._detectFrontend(profile), and assert the expected field (e.g.,
profile.frontend.framework, buildTool, styling, componentLibrary) matches
expectedValue; reference functions setupDeps, detector._createEmptyProfile and
detector._detectFrontend and the profile assertions to replace the many
near-duplicate test blocks with a single parametrized loop for each assertion
category.

ℹ️ Review info

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 79eef9e and c344b15.

📒 Files selected for processing (1)
  • tests/core/orchestration/tech-stack-detector.test.js

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.

2 participants