@crownpeak/dqm-react-component-dev-mcp 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +138 -0
- package/data/.env.example +22 -0
- package/data/.gitattributes +47 -0
- package/data/.glfrc.json +7 -0
- package/data/.husky/pre-commit +5 -0
- package/data/.nvmrc +1 -0
- package/data/CHANGELOG.md +75 -0
- package/data/CODE_OF_CONDUCT.md +129 -0
- package/data/CONTRIBUTING.md +203 -0
- package/data/DOCS-STRUCTURE.md +307 -0
- package/data/I18N.md +292 -0
- package/data/LICENSE +22 -0
- package/data/README.md +315 -0
- package/data/SECURITY.md +125 -0
- package/data/WIKI-DEPLOYMENT.md +348 -0
- package/data/docs/AI-FEATURES.md +610 -0
- package/data/docs/API-REFERENCE.md +1022 -0
- package/data/docs/AUTHENTICATION.md +301 -0
- package/data/docs/BACKEND-API.md +468 -0
- package/data/docs/DEVELOPMENT.md +375 -0
- package/data/docs/EXAMPLES.md +622 -0
- package/data/docs/MCP-SERVER.md +307 -0
- package/data/docs/MIGRATION-GUIDE.md +367 -0
- package/data/docs/NPM-PUBLISH.md +193 -0
- package/data/docs/QUICKSTART.md +206 -0
- package/data/docs/REDIS-SETUP.md +162 -0
- package/data/docs/SERVER.md +228 -0
- package/data/docs/TROUBLESHOOTING.md +657 -0
- package/data/docs/WIDGET-GUIDE.md +638 -0
- package/data/docs/WIKI-HOME.md +58 -0
- package/data/docs/WIKI-SIDEBAR.md +39 -0
- package/data/package.json +171 -0
- package/data/playwright.config.ts +64 -0
- package/data/probe/.cargo/config.toml +10 -0
- package/data/probe/.claude/commands/performance-review.md +15 -0
- package/data/probe/.clinerules +288 -0
- package/data/probe/.dockerignore +57 -0
- package/data/probe/.githooks/post-commit +11 -0
- package/data/probe/.githooks/pre-commit +99 -0
- package/data/probe/.githooks/pre-commit-vow +9 -0
- package/data/probe/.prompts/engineer.md +41 -0
- package/data/probe/.roomodes +28 -0
- package/data/probe/.windsurfrules +0 -0
- package/data/probe/BASH_TOOL_SUMMARY.md +148 -0
- package/data/probe/BENCHMARKING.md +256 -0
- package/data/probe/CLAUDE.md +226 -0
- package/data/probe/CODE_OF_CONDUCT.md +128 -0
- package/data/probe/CONTRIBUTING.md +193 -0
- package/data/probe/Cargo.toml +120 -0
- package/data/probe/Cross.toml +10 -0
- package/data/probe/DOCKER-README.md +224 -0
- package/data/probe/Dockerfile +32 -0
- package/data/probe/ENHANCED_DEBUG_TELEMETRY.md +188 -0
- package/data/probe/LICENSE +201 -0
- package/data/probe/Makefile +210 -0
- package/data/probe/README.md +824 -0
- package/data/probe/SECURITY.md +67 -0
- package/data/probe/WINDOWS-GUIDE.md +294 -0
- package/data/probe/benches/parsing_benchmarks.rs +370 -0
- package/data/probe/benches/search_benchmarks.rs +599 -0
- package/data/probe/benches/simd_benchmarks.rs +372 -0
- package/data/probe/benches/timing_benchmarks.rs +287 -0
- package/data/probe/build-windows.bat +229 -0
- package/data/probe/codex-config/config.toml +6 -0
- package/data/probe/docs/PERFORMANCE_OPTIMIZATION.md +161 -0
- package/data/probe/examples/cache_demo.rs +46 -0
- package/data/probe/examples/chat/.dockerignore +37 -0
- package/data/probe/examples/chat/ChatSessionManager.js +295 -0
- package/data/probe/examples/chat/Dockerfile +98 -0
- package/data/probe/examples/chat/LICENSE +201 -0
- package/data/probe/examples/chat/LOCAL_IMAGE_SUPPORT.md +195 -0
- package/data/probe/examples/chat/MCP_INTEGRATION.md +400 -0
- package/data/probe/examples/chat/README.md +338 -0
- package/data/probe/examples/chat/TRACING.md +226 -0
- package/data/probe/examples/chat/appTracer.js +968 -0
- package/data/probe/examples/chat/auth.js +76 -0
- package/data/probe/examples/chat/bin/probe-chat.js +13 -0
- package/data/probe/examples/chat/build.js +104 -0
- package/data/probe/examples/chat/cancelRequest.js +84 -0
- package/data/probe/examples/chat/demo-agentic-image-flow.js +88 -0
- package/data/probe/examples/chat/demo-local-images.js +128 -0
- package/data/probe/examples/chat/fileSpanExporter.js +181 -0
- package/data/probe/examples/chat/implement/README.md +228 -0
- package/data/probe/examples/chat/implement/backends/AiderBackend.js +750 -0
- package/data/probe/examples/chat/implement/backends/BaseBackend.js +276 -0
- package/data/probe/examples/chat/implement/backends/ClaudeCodeBackend.js +767 -0
- package/data/probe/examples/chat/implement/backends/MockBackend.js +237 -0
- package/data/probe/examples/chat/implement/backends/registry.js +85 -0
- package/data/probe/examples/chat/implement/core/BackendManager.js +567 -0
- package/data/probe/examples/chat/implement/core/ImplementTool.js +354 -0
- package/data/probe/examples/chat/implement/core/config.js +428 -0
- package/data/probe/examples/chat/implement/core/timeouts.js +58 -0
- package/data/probe/examples/chat/implement/core/utils.js +496 -0
- package/data/probe/examples/chat/implement/types/BackendTypes.js +126 -0
- package/data/probe/examples/chat/index.js +669 -0
- package/data/probe/examples/chat/mcpServer.js +341 -0
- package/data/probe/examples/chat/npm/LICENSE +15 -0
- package/data/probe/examples/chat/npm/README.md +168 -0
- package/data/probe/examples/chat/npm/bin/probe-chat.js +156 -0
- package/data/probe/examples/chat/npm/index.js +259 -0
- package/data/probe/examples/chat/npm/package.json +54 -0
- package/data/probe/examples/chat/package.json +102 -0
- package/data/probe/examples/chat/probeChat.js +456 -0
- package/data/probe/examples/chat/probeTool.js +491 -0
- package/data/probe/examples/chat/storage/JsonChatStorage.js +476 -0
- package/data/probe/examples/chat/telemetry.js +281 -0
- package/data/probe/examples/chat/test/integration/chatFlows.test.js +320 -0
- package/data/probe/examples/chat/test/integration/toolCalling.test.js +471 -0
- package/data/probe/examples/chat/test/mocks/mockLLMProvider.js +269 -0
- package/data/probe/examples/chat/test/test-backends.js +90 -0
- package/data/probe/examples/chat/test/testUtils.js +530 -0
- package/data/probe/examples/chat/test/unit/backendTimeout.test.js +161 -0
- package/data/probe/examples/chat/test/unit/packageFiles.test.js +120 -0
- package/data/probe/examples/chat/test/verify-tests.js +118 -0
- package/data/probe/examples/chat/test-agentic-image-loading.js +294 -0
- package/data/probe/examples/chat/test-ai-sdk-telemetry.js +204 -0
- package/data/probe/examples/chat/test-chat-tracing.js +38 -0
- package/data/probe/examples/chat/test-direct-function.js +49 -0
- package/data/probe/examples/chat/test-file-size-validation.js +103 -0
- package/data/probe/examples/chat/test-full-mcp-integration.js +258 -0
- package/data/probe/examples/chat/test-github-context.txt +12 -0
- package/data/probe/examples/chat/test-hierarchy.js +203 -0
- package/data/probe/examples/chat/test-image-spans.js +37 -0
- package/data/probe/examples/chat/test-local-image-reading.js +176 -0
- package/data/probe/examples/chat/test-mcp-integration.js +136 -0
- package/data/probe/examples/chat/test-mcp-probe-server.js +161 -0
- package/data/probe/examples/chat/test-mcp-with-ai.js +279 -0
- package/data/probe/examples/chat/test-multiple-allowed-dirs.js +111 -0
- package/data/probe/examples/chat/test-probe-mcp-server.js +110 -0
- package/data/probe/examples/chat/test-security-validation.js +145 -0
- package/data/probe/examples/chat/test-simple-tracing.js +32 -0
- package/data/probe/examples/chat/test-trace-verification.js +235 -0
- package/data/probe/examples/chat/test-tracing.js +114 -0
- package/data/probe/examples/chat/tokenCounter.js +419 -0
- package/data/probe/examples/chat/tokenUsageDisplay.js +134 -0
- package/data/probe/examples/chat/webServer.js +1103 -0
- package/data/probe/examples/reranker/Cargo.toml +33 -0
- package/data/probe/examples/reranker/DEBUG_OUTPUT_ANALYSIS.md +71 -0
- package/data/probe/examples/reranker/MODELS.md +66 -0
- package/data/probe/examples/reranker/MODEL_COMPARISON.md +60 -0
- package/data/probe/examples/reranker/MULTI_MODEL_ANALYSIS.md +176 -0
- package/data/probe/examples/reranker/PERFORMANCE_SUMMARY.md +156 -0
- package/data/probe/examples/reranker/README.md +347 -0
- package/data/probe/examples/reranker/RUST_BERT_COMPARISON.md +82 -0
- package/data/probe/examples/reranker/TOKENIZATION_GUIDE.md +120 -0
- package/data/probe/examples/reranker/check_rust_tokenizer.py +108 -0
- package/data/probe/examples/reranker/convert_to_torchscript.py +109 -0
- package/data/probe/examples/reranker/debug_scoring.py +189 -0
- package/data/probe/examples/reranker/debug_tokenization.py +154 -0
- package/data/probe/examples/reranker/download_models.sh +73 -0
- package/data/probe/examples/reranker/requirements.txt +13 -0
- package/data/probe/examples/reranker/run_comprehensive_benchmark.sh +83 -0
- package/data/probe/examples/reranker/rust_bert_test/Cargo.toml +12 -0
- package/data/probe/examples/reranker/rust_bert_test/README.md +54 -0
- package/data/probe/examples/reranker/simple_test.py +50 -0
- package/data/probe/examples/reranker/test_all_models.sh +63 -0
- package/data/probe/examples/reranker/test_bert_results.sh +44 -0
- package/data/probe/examples/reranker/test_cross_encoder.py +334 -0
- package/data/probe/examples/reranker/test_cross_encoder.sh +80 -0
- package/data/probe/examples/reranker/test_exact_comparison.py +151 -0
- package/data/probe/examples/reranker/test_parallel_performance.sh +56 -0
- package/data/probe/examples/reranker/test_scores.py +132 -0
- package/data/probe/install.ps1 +508 -0
- package/data/probe/install.sh +460 -0
- package/data/probe/npm/CLONE_METHOD_EXAMPLES.md +596 -0
- package/data/probe/npm/CONTEXT_COMPACTION.md +303 -0
- package/data/probe/npm/DELEGATE_TOOL_README.md +166 -0
- package/data/probe/npm/MAID_INTEGRATION.md +313 -0
- package/data/probe/npm/MCP_INTEGRATION_SUMMARY.md +241 -0
- package/data/probe/npm/README.md +824 -0
- package/data/probe/npm/bin/.gitignore +7 -0
- package/data/probe/npm/bin/.gitkeep +0 -0
- package/data/probe/npm/bin/README.md +12 -0
- package/data/probe/npm/bin/probe +167 -0
- package/data/probe/npm/docs/CLAUDE_CODE_INTEGRATION.md +414 -0
- package/data/probe/npm/docs/CODEX_INTEGRATION.md +502 -0
- package/data/probe/npm/docs/EDIT_CREATE_TOOLS.md +233 -0
- package/data/probe/npm/docs/RETRY_AND_FALLBACK.md +674 -0
- package/data/probe/npm/example-usage.js +335 -0
- package/data/probe/npm/examples/multi-engine-demo.js +117 -0
- package/data/probe/npm/examples/probe-agent-cli.js +113 -0
- package/data/probe/npm/examples/test-agent-edit.js +114 -0
- package/data/probe/npm/examples/test-edit-create.js +120 -0
- package/data/probe/npm/examples/test-edit-direct.js +114 -0
- package/data/probe/npm/index.d.ts +744 -0
- package/data/probe/npm/jest.config.js +52 -0
- package/data/probe/npm/package.json +117 -0
- package/data/probe/npm/scripts/build-agent.cjs +75 -0
- package/data/probe/npm/scripts/build-cjs.js +124 -0
- package/data/probe/npm/scripts/build-mcp.cjs +36 -0
- package/data/probe/npm/scripts/postinstall.js +216 -0
- package/data/probe/npm/test-codex-e2e.js +78 -0
- package/data/probe/npm/test-download-lock.js +109 -0
- package/data/probe/npm/test-grep-security.js +94 -0
- package/data/probe/npm/test-grep-simplified.js +63 -0
- package/data/probe/npm/test-grep.js +51 -0
- package/data/probe/npm/tests/README.md +96 -0
- package/data/probe/npm/tests/agent-compact-history.test.js +174 -0
- package/data/probe/npm/tests/allow-tests-default.test.js +151 -0
- package/data/probe/npm/tests/contextCompactor.test.js +498 -0
- package/data/probe/npm/tests/delegate-config.test.js +353 -0
- package/data/probe/npm/tests/delegate-integration.test.js +348 -0
- package/data/probe/npm/tests/extractor-integration.test.js +162 -0
- package/data/probe/npm/tests/extractor.test.js +317 -0
- package/data/probe/npm/tests/fixtures/sampleDiagrams.js +267 -0
- package/data/probe/npm/tests/integration/claude-code-auto-fallback.spec.js +148 -0
- package/data/probe/npm/tests/integration/claude-code-multi-step.spec.js +127 -0
- package/data/probe/npm/tests/integration/claude-code-tool-events.spec.js +163 -0
- package/data/probe/npm/tests/integration/codex-auto-fallback.spec.js +191 -0
- package/data/probe/npm/tests/integration/codex-tool-events.spec.js +147 -0
- package/data/probe/npm/tests/integration/examplesChatMcp.test.js +402 -0
- package/data/probe/npm/tests/integration/mcpDotenvSupport.test.js +174 -0
- package/data/probe/npm/tests/integration/mcpErrorHandling.test.js +566 -0
- package/data/probe/npm/tests/integration/mcpRobustness.test.js +564 -0
- package/data/probe/npm/tests/integration/mcpStdoutPurity.test.js +355 -0
- package/data/probe/npm/tests/integration/probeAgentMcp.test.js +398 -0
- package/data/probe/npm/tests/integration/retryFallback.test.js +368 -0
- package/data/probe/npm/tests/integration/schema-in-initial-message.test.js +318 -0
- package/data/probe/npm/tests/integration/schema-validation-loop-prevention.test.js +244 -0
- package/data/probe/npm/tests/integration/schemaRetryLogic.test.js +94 -0
- package/data/probe/npm/tests/integration/validationFlow.test.js +329 -0
- package/data/probe/npm/tests/manual/test-codex-basic.js +110 -0
- package/data/probe/npm/tests/mcp/mcpClientManager.test.js +614 -0
- package/data/probe/npm/tests/mcp/mcpConfig.test.js +359 -0
- package/data/probe/npm/tests/mcp/mcpXmlBridge.test.js +436 -0
- package/data/probe/npm/tests/mcp/mockMcpServer.js +510 -0
- package/data/probe/npm/tests/mcp-strict-syntax.test.js +319 -0
- package/data/probe/npm/tests/mermaidQuoteEscaping.test.js +214 -0
- package/data/probe/npm/tests/nestedQuoteFix.test.js +40 -0
- package/data/probe/npm/tests/setup.js +46 -0
- package/data/probe/npm/tests/unit/allowed-tools.test.js +513 -0
- package/data/probe/npm/tests/unit/attempt-completion-closing-tag-in-content.test.js +188 -0
- package/data/probe/npm/tests/unit/attemptCompletionJsonFix.test.js +238 -0
- package/data/probe/npm/tests/unit/attemptCompletionJsonIssue.test.js +128 -0
- package/data/probe/npm/tests/unit/backtickAutoFix.test.js +35 -0
- package/data/probe/npm/tests/unit/bash-probe-agent-integration.test.js +389 -0
- package/data/probe/npm/tests/unit/bash-simple-commands.test.js +324 -0
- package/data/probe/npm/tests/unit/bash-tool-comprehensive.test.js +371 -0
- package/data/probe/npm/tests/unit/bash-tool-integration.test.js +310 -0
- package/data/probe/npm/tests/unit/bash-tool.test.js +341 -0
- package/data/probe/npm/tests/unit/completion-prompt.test.js +379 -0
- package/data/probe/npm/tests/unit/cwd-path-options.test.js +287 -0
- package/data/probe/npm/tests/unit/delegate-limits.test.js +422 -0
- package/data/probe/npm/tests/unit/direct-content-attempt-completion.test.js +235 -0
- package/data/probe/npm/tests/unit/edit-create-tools.test.js +609 -0
- package/data/probe/npm/tests/unit/enhancedMermaidValidation.test.js +577 -0
- package/data/probe/npm/tests/unit/extract-content.test.js +83 -0
- package/data/probe/npm/tests/unit/extract-multiple-targets.test.js +89 -0
- package/data/probe/npm/tests/unit/fallbackManager.test.js +442 -0
- package/data/probe/npm/tests/unit/githubCompatibilityValidation.test.js +258 -0
- package/data/probe/npm/tests/unit/imageConfig.test.js +149 -0
- package/data/probe/npm/tests/unit/imagePathResolution.test.js +345 -0
- package/data/probe/npm/tests/unit/json-fixing-agent.test.js +238 -0
- package/data/probe/npm/tests/unit/json-validation-enhanced-errors.test.js +199 -0
- package/data/probe/npm/tests/unit/jsonValidationInfiniteLoopFix.test.js +228 -0
- package/data/probe/npm/tests/unit/maidIntegration.test.js +139 -0
- package/data/probe/npm/tests/unit/maxIterationsWarning.test.js +195 -0
- package/data/probe/npm/tests/unit/mermaidEdgeLabelFix.test.js +161 -0
- package/data/probe/npm/tests/unit/mermaidHtmlEntities.test.js +76 -0
- package/data/probe/npm/tests/unit/mermaidInfiniteLoopFix.test.js +64 -0
- package/data/probe/npm/tests/unit/mermaidValidation.test.js +723 -0
- package/data/probe/npm/tests/unit/mermaidValidationVisorExample.test.js +309 -0
- package/data/probe/npm/tests/unit/probe-agent-clone-realistic.test.js +643 -0
- package/data/probe/npm/tests/unit/probe-agent-clone.test.js +476 -0
- package/data/probe/npm/tests/unit/probe-agent-delegate.test.js +400 -0
- package/data/probe/npm/tests/unit/probe-agent-model-option.test.js +118 -0
- package/data/probe/npm/tests/unit/probeTool-security.test.js +283 -0
- package/data/probe/npm/tests/unit/readImageTool.test.js +418 -0
- package/data/probe/npm/tests/unit/retryManager.test.js +317 -0
- package/data/probe/npm/tests/unit/schema-aware-reminders.test.js +288 -0
- package/data/probe/npm/tests/unit/schemaDefinitionDetection.test.js +115 -0
- package/data/probe/npm/tests/unit/schemaUtils.test.js +1268 -0
- package/data/probe/npm/tests/unit/simpleTelemetry.test.js +282 -0
- package/data/probe/npm/tests/unit/simplified-attempt-completion.test.js +274 -0
- package/data/probe/npm/tests/unit/single-quote-json-bug.test.js +231 -0
- package/data/probe/npm/tests/unit/subgraphAutoFix.test.js +110 -0
- package/data/probe/npm/tests/unit/system-prompt.test.js +32 -0
- package/data/probe/npm/tests/unit/types-probe-agent-options.test.js +42 -0
- package/data/probe/npm/tests/unit/xmlParsing.test.js +720 -0
- package/data/probe/npm/tsconfig.json +21 -0
- package/data/probe/result1.txt +19 -0
- package/data/probe/result2.txt +26 -0
- package/data/probe/scripts/benchmark.sh +270 -0
- package/data/probe/scripts/cache_memory_analysis.rs +844 -0
- package/data/probe/scripts/claude-hook-wrapper.sh +56 -0
- package/data/probe/site/.env.example +10 -0
- package/data/probe/site/DEPLOYMENT.md +86 -0
- package/data/probe/site/README.md +183 -0
- package/data/probe/site/adding-languages.md +135 -0
- package/data/probe/site/ai-chat.md +427 -0
- package/data/probe/site/ai-integration.md +1488 -0
- package/data/probe/site/blog/agentic-flow-custom-xml-protocol.md +407 -0
- package/data/probe/site/blog/index.md +118 -0
- package/data/probe/site/blog/v0.6.0-release.md +426 -0
- package/data/probe/site/blog.md +8 -0
- package/data/probe/site/changelog.md +200 -0
- package/data/probe/site/cli-mode.md +437 -0
- package/data/probe/site/code-extraction.md +436 -0
- package/data/probe/site/contributing/README.md +9 -0
- package/data/probe/site/contributing/documentation-cross-references.md +215 -0
- package/data/probe/site/contributing/documentation-maintenance.md +275 -0
- package/data/probe/site/contributing/documentation-structure.md +75 -0
- package/data/probe/site/documentation-cross-references.md +215 -0
- package/data/probe/site/documentation-guide.md +132 -0
- package/data/probe/site/documentation-maintenance.md +275 -0
- package/data/probe/site/features.md +147 -0
- package/data/probe/site/how-it-works.md +118 -0
- package/data/probe/site/index.md +175 -0
- package/data/probe/site/index.md.bak +133 -0
- package/data/probe/site/installation.md +235 -0
- package/data/probe/site/integrations/docker.md +248 -0
- package/data/probe/site/integrations/github-actions.md +413 -0
- package/data/probe/site/language-support-overview.md +168 -0
- package/data/probe/site/mcp-integration.md +587 -0
- package/data/probe/site/mcp-server.md +304 -0
- package/data/probe/site/navigation-structure.md +76 -0
- package/data/probe/site/nodejs-sdk.md +798 -0
- package/data/probe/site/output-formats.md +625 -0
- package/data/probe/site/package.json +21 -0
- package/data/probe/site/public/_headers +28 -0
- package/data/probe/site/public/_redirects +11 -0
- package/data/probe/site/quick-start.md +289 -0
- package/data/probe/site/search-functionality.md +291 -0
- package/data/probe/site/search-reference.md +291 -0
- package/data/probe/site/supported-languages.md +215 -0
- package/data/probe/site/use-cases/README.md +8 -0
- package/data/probe/site/use-cases/advanced-cli.md +253 -0
- package/data/probe/site/use-cases/ai-code-editors.md +239 -0
- package/data/probe/site/use-cases/building-ai-tools.md +529 -0
- package/data/probe/site/use-cases/cli-ai-workflows.md +285 -0
- package/data/probe/site/use-cases/deploying-probe-web-interface.md +255 -0
- package/data/probe/site/use-cases/integrating-probe-into-ai-code-editors.md +161 -0
- package/data/probe/site/use-cases/nodejs-sdk.md +596 -0
- package/data/probe/site/use-cases/team-chat.md +350 -0
- package/data/probe/site/web-interface.md +434 -0
- package/data/probe/site/wrangler.toml +9 -0
- package/data/probe/test-api-key.sh +1 -0
- package/data/probe/test-probe-implementation/hello.js +7 -0
- package/data/probe/test_cases/demonstrate_early_termination_issues.sh +176 -0
- package/data/probe/test_cases/early_termination_issues.rs +533 -0
- package/data/probe/test_data/test_nested_struct.go +26 -0
- package/data/probe/tests/README.md +286 -0
- package/data/probe/tests/README_search_determinism_tests.md +116 -0
- package/data/probe/tests/adjacent_comment_test.rs +152 -0
- package/data/probe/tests/apostrophe_handling_tests.rs +132 -0
- package/data/probe/tests/block_filtering_with_ast_tests.rs +669 -0
- package/data/probe/tests/block_merging_tests.rs +396 -0
- package/data/probe/tests/c_outline_format_tests.rs +2179 -0
- package/data/probe/tests/cache_invalidation_issues.rs.disabled +682 -0
- package/data/probe/tests/cache_order_tests.rs +147 -0
- package/data/probe/tests/cache_query_scoping_tests.rs +221 -0
- package/data/probe/tests/cli_tests.rs +680 -0
- package/data/probe/tests/comment_context_integration_test.rs +240 -0
- package/data/probe/tests/common.rs +33 -0
- package/data/probe/tests/complex_block_merging_tests.rs +599 -0
- package/data/probe/tests/complex_query_block_filtering_tests.rs +422 -0
- package/data/probe/tests/control_flow_closing_braces_test.rs +91 -0
- package/data/probe/tests/cpp_outline_format_tests.rs +1507 -0
- package/data/probe/tests/csharp_outline_format_tests.rs +941 -0
- package/data/probe/tests/elastic_query_integration_tests.rs +922 -0
- package/data/probe/tests/extract_command_tests.rs +1848 -0
- package/data/probe/tests/extract_deduplication_tests.rs +146 -0
- package/data/probe/tests/extract_input_file_tests.rs +84 -0
- package/data/probe/tests/extract_prompt_tests.rs +102 -0
- package/data/probe/tests/filename_search_tests.rs +96 -0
- package/data/probe/tests/fixtures/user/AssemblyInfo.cs +3 -0
- package/data/probe/tests/github_extract_tests.rs +234 -0
- package/data/probe/tests/go_comment_test.rs +253 -0
- package/data/probe/tests/go_outline_format_tests.rs +2587 -0
- package/data/probe/tests/go_path_resolver_tests.rs +96 -0
- package/data/probe/tests/html_outline_format_tests.rs +637 -0
- package/data/probe/tests/integration_tests.rs +837 -0
- package/data/probe/tests/ip_whitelist_test.rs +148 -0
- package/data/probe/tests/java_outline_format_tests.rs +1611 -0
- package/data/probe/tests/javascript_extract_tests.rs +315 -0
- package/data/probe/tests/javascript_outline_format_tests.rs +1464 -0
- package/data/probe/tests/json_format_tests.rs +436 -0
- package/data/probe/tests/json_schema_validation_tests.rs +450 -0
- package/data/probe/tests/lib_usage.rs +60 -0
- package/data/probe/tests/line_comment_context_extension_test.rs +459 -0
- package/data/probe/tests/line_map_cache_tests.rs +114 -0
- package/data/probe/tests/markdown_integration_tests.rs +190 -0
- package/data/probe/tests/mocks/test_ip_whitelist.go +11 -0
- package/data/probe/tests/mocks/test_object.js +27 -0
- package/data/probe/tests/mocks/test_struct.go +50 -0
- package/data/probe/tests/multi_keyword_pattern_tests.rs +464 -0
- package/data/probe/tests/multi_language_syntax_integration_tests.rs +218 -0
- package/data/probe/tests/multiple_capture_groups_tests.rs +169 -0
- package/data/probe/tests/negative_compound_word_tests.rs +246 -0
- package/data/probe/tests/nested_symbol_extraction_tests.rs +99 -0
- package/data/probe/tests/outline_cross_file_interference_test.rs +335 -0
- package/data/probe/tests/outline_keyword_preservation_test.rs +67 -0
- package/data/probe/tests/output_format_edge_cases_tests.rs +693 -0
- package/data/probe/tests/parallel_extraction_tests.rs +178 -0
- package/data/probe/tests/parallel_search_tests.rs +355 -0
- package/data/probe/tests/path_resolver_tests.rs +698 -0
- package/data/probe/tests/php_outline_format_extended_tests.rs +928 -0
- package/data/probe/tests/php_outline_format_tests.rs +768 -0
- package/data/probe/tests/property_tests.proptest-regressions +9 -0
- package/data/probe/tests/property_tests.rs +118 -0
- package/data/probe/tests/python_outline_format_tests.rs +1538 -0
- package/data/probe/tests/query_command_json_tests.rs +438 -0
- package/data/probe/tests/query_command_tests.rs +232 -0
- package/data/probe/tests/query_command_xml_tests.rs +569 -0
- package/data/probe/tests/quoted_term_with_negative_keyword_tests.rs +216 -0
- package/data/probe/tests/required_terms_filename_tests.rs +116 -0
- package/data/probe/tests/ruby_outline_format_tests.rs +1011 -0
- package/data/probe/tests/rust_line_comment_context_test.rs +151 -0
- package/data/probe/tests/rust_outline_format_enhanced_tests.rs +725 -0
- package/data/probe/tests/rust_outline_format_tests.rs +843 -0
- package/data/probe/tests/schemas/xml_output_schema.xsd +38 -0
- package/data/probe/tests/search_determinism_tests.rs +451 -0
- package/data/probe/tests/search_hints_tests.rs +253 -0
- package/data/probe/tests/special_character_escaping_tests.rs +417 -0
- package/data/probe/tests/stemming_compound_word_filtering_tests.rs +535 -0
- package/data/probe/tests/strict_elastic_syntax_tests.rs +404 -0
- package/data/probe/tests/swift_outline_format_tests.rs +3319 -0
- package/data/probe/tests/symbols_tests.rs +166 -0
- package/data/probe/tests/test_file.rs +45 -0
- package/data/probe/tests/test_tokenize.rs +28 -0
- package/data/probe/tests/timeout_tests.rs +82 -0
- package/data/probe/tests/tokenization_tests.rs +195 -0
- package/data/probe/tests/tokenized_block_filtering_tests.rs +174 -0
- package/data/probe/tests/typescript_extract_tests.rs +214 -0
- package/data/probe/tests/typescript_outline_format_tests.rs +2188 -0
- package/data/probe/tests/xml_format_tests.rs +568 -0
- package/data/probe/tests/xml_schema_validation_tests.rs +497 -0
- package/data/scripts/postinstall.mjs +9 -0
- package/data/scripts/set-version.js +0 -0
- package/data/scripts/wiki-build.sh +111 -0
- package/data/scripts/wiki-deploy.sh +73 -0
- package/data/serve.json +12 -0
- package/data/test/demo-dynamic.html +134 -0
- package/data/test/demo-esm.html +105 -0
- package/data/test/demo-iife.html +78 -0
- package/data/tsconfig.json +7 -0
- package/data/vite.server.ts +483 -0
- package/data/vitest.config.ts +40 -0
- package/data/wiki/Home.md +58 -0
- package/data/wiki/_Sidebar.md +39 -0
- package/docs-mcp.config.json +20 -0
- package/package.json +56 -0
- package/src/config.js +111 -0
- package/src/index.js +395 -0
|
@@ -0,0 +1,1464 @@
|
|
|
1
|
+
use anyhow::Result;
|
|
2
|
+
use std::fs;
|
|
3
|
+
use tempfile::TempDir;
|
|
4
|
+
|
|
5
|
+
mod common;
|
|
6
|
+
use common::TestContext;
|
|
7
|
+
|
|
8
|
+
#[test]
|
|
9
|
+
fn test_javascript_outline_basic_symbols() -> Result<()> {
|
|
10
|
+
let temp_dir = TempDir::new()?;
|
|
11
|
+
let test_file = temp_dir.path().join("basic.js");
|
|
12
|
+
|
|
13
|
+
let content = r#"// Basic JavaScript classes and functions for testing
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* A simple calculator class for arithmetic operations.
|
|
17
|
+
*/
|
|
18
|
+
class Calculator {
|
|
19
|
+
constructor(name) {
|
|
20
|
+
this.name = name;
|
|
21
|
+
this.history = [];
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Adds two numbers and returns the result.
|
|
26
|
+
*/
|
|
27
|
+
add(x, y) {
|
|
28
|
+
const result = x + y;
|
|
29
|
+
this.history.push(result);
|
|
30
|
+
return result;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Gets the calculation history.
|
|
35
|
+
*/
|
|
36
|
+
getHistory() {
|
|
37
|
+
return [...this.history];
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
static createDefault() {
|
|
41
|
+
return new Calculator('Default Calculator');
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Factory function for creating calculators.
|
|
47
|
+
*/
|
|
48
|
+
function createCalculator(name) {
|
|
49
|
+
return new Calculator(name);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Arrow function for simple calculations.
|
|
54
|
+
*/
|
|
55
|
+
const multiply = (a, b) => a * b;
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Async function for fetching data.
|
|
59
|
+
*/
|
|
60
|
+
async function fetchData(url) {
|
|
61
|
+
try {
|
|
62
|
+
const response = await fetch(url);
|
|
63
|
+
return await response.json();
|
|
64
|
+
} catch (error) {
|
|
65
|
+
console.error('Fetch error:', error);
|
|
66
|
+
throw error;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Generator function for creating sequences.
|
|
72
|
+
*/
|
|
73
|
+
function* numberSequence(start, end) {
|
|
74
|
+
for (let i = start; i <= end; i++) {
|
|
75
|
+
yield i;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Object with methods demonstration.
|
|
81
|
+
*/
|
|
82
|
+
const mathUtils = {
|
|
83
|
+
PI: Math.PI,
|
|
84
|
+
|
|
85
|
+
circleArea(radius) {
|
|
86
|
+
return this.PI * radius * radius;
|
|
87
|
+
},
|
|
88
|
+
|
|
89
|
+
rectangleArea: function(width, height) {
|
|
90
|
+
return width * height;
|
|
91
|
+
},
|
|
92
|
+
|
|
93
|
+
triangleArea: (base, height) => (base * height) / 2
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
// Export for module usage
|
|
97
|
+
module.exports = {
|
|
98
|
+
Calculator,
|
|
99
|
+
createCalculator,
|
|
100
|
+
multiply,
|
|
101
|
+
fetchData,
|
|
102
|
+
numberSequence,
|
|
103
|
+
mathUtils
|
|
104
|
+
};
|
|
105
|
+
"#;
|
|
106
|
+
|
|
107
|
+
fs::write(&test_file, content)?;
|
|
108
|
+
|
|
109
|
+
let ctx = TestContext::new();
|
|
110
|
+
let output = ctx.run_probe(&[
|
|
111
|
+
"search",
|
|
112
|
+
"Calculator", // Search for Calculator-related symbols
|
|
113
|
+
test_file.to_str().unwrap(),
|
|
114
|
+
"--format",
|
|
115
|
+
"outline",
|
|
116
|
+
"--allow-tests",
|
|
117
|
+
"--exact",
|
|
118
|
+
])?;
|
|
119
|
+
|
|
120
|
+
// Verify JavaScript symbols are extracted in outline format
|
|
121
|
+
assert!(
|
|
122
|
+
output.contains("class Calculator") || output.contains("Calculator"),
|
|
123
|
+
"Missing Calculator class - output: {}",
|
|
124
|
+
output
|
|
125
|
+
);
|
|
126
|
+
assert!(
|
|
127
|
+
output.contains("function createCalculator") || output.contains("createCalculator"),
|
|
128
|
+
"Missing createCalculator function - output: {}",
|
|
129
|
+
output
|
|
130
|
+
);
|
|
131
|
+
|
|
132
|
+
// Test a different search term for functions
|
|
133
|
+
let output2 = ctx.run_probe(&[
|
|
134
|
+
"search",
|
|
135
|
+
"function", // Search for function-related symbols
|
|
136
|
+
test_file.to_str().unwrap(),
|
|
137
|
+
"--format",
|
|
138
|
+
"outline",
|
|
139
|
+
"--allow-tests",
|
|
140
|
+
"--exact",
|
|
141
|
+
])?;
|
|
142
|
+
|
|
143
|
+
assert!(
|
|
144
|
+
output2.contains("function") || !output2.trim().is_empty(),
|
|
145
|
+
"Missing function declarations - output: {}",
|
|
146
|
+
output2
|
|
147
|
+
);
|
|
148
|
+
|
|
149
|
+
Ok(())
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
#[test]
|
|
153
|
+
fn test_javascript_outline_control_flow_statements() -> Result<()> {
|
|
154
|
+
let temp_dir = TempDir::new()?;
|
|
155
|
+
let test_file = temp_dir.path().join("control_flow.js");
|
|
156
|
+
|
|
157
|
+
let content = r#"/**
|
|
158
|
+
* Function demonstrating various control flow statements with gaps.
|
|
159
|
+
*/
|
|
160
|
+
function complexAlgorithm(data, threshold) {
|
|
161
|
+
const result = {};
|
|
162
|
+
let counter = 0;
|
|
163
|
+
|
|
164
|
+
// First processing phase
|
|
165
|
+
for (const item of data) {
|
|
166
|
+
if (item > threshold) {
|
|
167
|
+
counter++;
|
|
168
|
+
|
|
169
|
+
// Complex nested conditions
|
|
170
|
+
if (counter % 2 === 0) {
|
|
171
|
+
result[`even_${counter}`] = item;
|
|
172
|
+
} else {
|
|
173
|
+
result[`odd_${counter}`] = item;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// Second processing phase with while loop
|
|
179
|
+
let index = 0;
|
|
180
|
+
while (index < data.length) {
|
|
181
|
+
const value = data[index];
|
|
182
|
+
|
|
183
|
+
switch (true) {
|
|
184
|
+
case value < 0:
|
|
185
|
+
result[`negative_${index}`] = value;
|
|
186
|
+
break;
|
|
187
|
+
case value === 0:
|
|
188
|
+
result['zero'] = 0;
|
|
189
|
+
break;
|
|
190
|
+
default:
|
|
191
|
+
result[`positive_${index}`] = value;
|
|
192
|
+
break;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
index++;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
return result;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* Function with nested loops and complex control flow.
|
|
203
|
+
*/
|
|
204
|
+
function processMatrix(matrix) {
|
|
205
|
+
const processed = [];
|
|
206
|
+
|
|
207
|
+
for (let i = 0; i < matrix.length; i++) {
|
|
208
|
+
const row = matrix[i];
|
|
209
|
+
const newRow = [];
|
|
210
|
+
|
|
211
|
+
for (let j = 0; j < row.length; j++) {
|
|
212
|
+
const cell = row[j];
|
|
213
|
+
|
|
214
|
+
let processedCell;
|
|
215
|
+
if (cell > 0) {
|
|
216
|
+
processedCell = cell * 2;
|
|
217
|
+
} else if (cell < 0) {
|
|
218
|
+
processedCell = Math.abs(cell);
|
|
219
|
+
} else {
|
|
220
|
+
processedCell = 1;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
newRow.push(processedCell);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
processed.push(newRow);
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
return processed;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
/**
|
|
233
|
+
* Function with try-catch and complex error handling.
|
|
234
|
+
*/
|
|
235
|
+
async function fetchWithRetry(url, maxRetries = 3) {
|
|
236
|
+
let attempts = 0;
|
|
237
|
+
|
|
238
|
+
while (attempts < maxRetries) {
|
|
239
|
+
try {
|
|
240
|
+
const response = await fetch(url);
|
|
241
|
+
|
|
242
|
+
if (!response.ok) {
|
|
243
|
+
throw new Error(`HTTP error! status: ${response.status}`);
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
return await response.json();
|
|
247
|
+
} catch (error) {
|
|
248
|
+
attempts++;
|
|
249
|
+
|
|
250
|
+
if (attempts >= maxRetries) {
|
|
251
|
+
throw new Error(`Failed after ${maxRetries} attempts: ${error.message}`);
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
// Wait before retry
|
|
255
|
+
await new Promise(resolve => setTimeout(resolve, 1000 * attempts));
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
"#;
|
|
260
|
+
|
|
261
|
+
fs::write(&test_file, content)?;
|
|
262
|
+
|
|
263
|
+
let ctx = TestContext::new();
|
|
264
|
+
let output = ctx.run_probe(&[
|
|
265
|
+
"search",
|
|
266
|
+
"function", // Search for function declarations
|
|
267
|
+
test_file.to_str().unwrap(),
|
|
268
|
+
"--format",
|
|
269
|
+
"outline",
|
|
270
|
+
"--allow-tests",
|
|
271
|
+
"--exact",
|
|
272
|
+
])?;
|
|
273
|
+
|
|
274
|
+
// Verify control flow structures are shown with proper formatting
|
|
275
|
+
assert!(
|
|
276
|
+
output.contains("function") && !output.trim().is_empty(),
|
|
277
|
+
"Missing function declarations in control flow test - output: {}",
|
|
278
|
+
output
|
|
279
|
+
);
|
|
280
|
+
|
|
281
|
+
// Should contain closing braces for large blocks
|
|
282
|
+
assert!(
|
|
283
|
+
output.contains("}"),
|
|
284
|
+
"Missing closing braces - output: {}",
|
|
285
|
+
output
|
|
286
|
+
);
|
|
287
|
+
|
|
288
|
+
Ok(())
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
#[test]
|
|
292
|
+
fn test_javascript_outline_modern_features() -> Result<()> {
|
|
293
|
+
let temp_dir = TempDir::new()?;
|
|
294
|
+
let test_file = temp_dir.path().join("modern_features.js");
|
|
295
|
+
|
|
296
|
+
let content = r#"// Modern JavaScript features for testing
|
|
297
|
+
|
|
298
|
+
/**
|
|
299
|
+
* ES6+ class with modern syntax.
|
|
300
|
+
*/
|
|
301
|
+
class DataProcessor {
|
|
302
|
+
#privateField = 'secret';
|
|
303
|
+
|
|
304
|
+
constructor(options = {}) {
|
|
305
|
+
this.name = options.name ?? 'DefaultProcessor';
|
|
306
|
+
this.config = { ...options };
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
// Private method
|
|
310
|
+
#validateData(data) {
|
|
311
|
+
return data && typeof data === 'object';
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
// Async method with destructuring
|
|
315
|
+
async processData({ input, format = 'json' } = {}) {
|
|
316
|
+
if (!this.#validateData(input)) {
|
|
317
|
+
throw new Error('Invalid data format');
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
const { processed, metadata } = await this.#transformData(input);
|
|
321
|
+
|
|
322
|
+
return {
|
|
323
|
+
result: processed,
|
|
324
|
+
metadata: {
|
|
325
|
+
...metadata,
|
|
326
|
+
format,
|
|
327
|
+
timestamp: new Date().toISOString()
|
|
328
|
+
}
|
|
329
|
+
};
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
// Static async method
|
|
333
|
+
static async create(options) {
|
|
334
|
+
const processor = new DataProcessor(options);
|
|
335
|
+
await processor.initialize();
|
|
336
|
+
return processor;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
async #transformData(data) {
|
|
340
|
+
// Simulate async processing
|
|
341
|
+
return new Promise(resolve => {
|
|
342
|
+
setTimeout(() => {
|
|
343
|
+
resolve({
|
|
344
|
+
processed: data.map(item => ({ ...item, processed: true })),
|
|
345
|
+
metadata: { count: data.length }
|
|
346
|
+
});
|
|
347
|
+
}, 100);
|
|
348
|
+
});
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
/**
|
|
353
|
+
* Destructuring and spread operator examples.
|
|
354
|
+
*/
|
|
355
|
+
function processUser({ name, age, ...rest }) {
|
|
356
|
+
return {
|
|
357
|
+
displayName: name.toUpperCase(),
|
|
358
|
+
isAdult: age >= 18,
|
|
359
|
+
additionalInfo: { ...rest }
|
|
360
|
+
};
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
/**
|
|
364
|
+
* Template literals and tagged templates.
|
|
365
|
+
*/
|
|
366
|
+
const createMessage = (template, ...values) => {
|
|
367
|
+
return template.reduce((acc, str, i) => {
|
|
368
|
+
const value = values[i] ? `<strong>${values[i]}</strong>` : '';
|
|
369
|
+
return acc + str + value;
|
|
370
|
+
}, '');
|
|
371
|
+
};
|
|
372
|
+
|
|
373
|
+
/**
|
|
374
|
+
* Map and Set operations with symbols.
|
|
375
|
+
*/
|
|
376
|
+
class SymbolRegistry {
|
|
377
|
+
#symbols = new Map();
|
|
378
|
+
#metadata = new WeakMap();
|
|
379
|
+
|
|
380
|
+
register(key, description) {
|
|
381
|
+
const symbol = Symbol(description);
|
|
382
|
+
this.#symbols.set(key, symbol);
|
|
383
|
+
this.#metadata.set(symbol, {
|
|
384
|
+
created: Date.now(),
|
|
385
|
+
description
|
|
386
|
+
});
|
|
387
|
+
return symbol;
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
get(key) {
|
|
391
|
+
return this.#symbols.get(key);
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
*entries() {
|
|
395
|
+
for (const [key, symbol] of this.#symbols) {
|
|
396
|
+
yield [key, symbol, this.#metadata.get(symbol)];
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
/**
|
|
402
|
+
* Proxy usage for advanced object manipulation.
|
|
403
|
+
*/
|
|
404
|
+
function createSmartObject(target = {}) {
|
|
405
|
+
return new Proxy(target, {
|
|
406
|
+
get(obj, prop) {
|
|
407
|
+
if (prop in obj) {
|
|
408
|
+
return obj[prop];
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
// Auto-generate computed properties
|
|
412
|
+
if (prop.startsWith('computed_')) {
|
|
413
|
+
const key = prop.replace('computed_', '');
|
|
414
|
+
return () => `Computed value for ${key}`;
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
return undefined;
|
|
418
|
+
},
|
|
419
|
+
|
|
420
|
+
set(obj, prop, value) {
|
|
421
|
+
// Validate before setting
|
|
422
|
+
if (typeof value === 'function') {
|
|
423
|
+
obj[prop] = value.bind(obj);
|
|
424
|
+
} else {
|
|
425
|
+
obj[prop] = value;
|
|
426
|
+
}
|
|
427
|
+
return true;
|
|
428
|
+
}
|
|
429
|
+
});
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
// Module exports with modern syntax
|
|
433
|
+
export {
|
|
434
|
+
DataProcessor,
|
|
435
|
+
processUser,
|
|
436
|
+
createMessage,
|
|
437
|
+
SymbolRegistry,
|
|
438
|
+
createSmartObject
|
|
439
|
+
};
|
|
440
|
+
|
|
441
|
+
export default DataProcessor;
|
|
442
|
+
"#;
|
|
443
|
+
|
|
444
|
+
fs::write(&test_file, content)?;
|
|
445
|
+
|
|
446
|
+
let ctx = TestContext::new();
|
|
447
|
+
let output = ctx.run_probe(&[
|
|
448
|
+
"search",
|
|
449
|
+
"class", // Search for class declarations
|
|
450
|
+
test_file.to_str().unwrap(),
|
|
451
|
+
"--format",
|
|
452
|
+
"outline",
|
|
453
|
+
"--allow-tests",
|
|
454
|
+
"--exact",
|
|
455
|
+
])?;
|
|
456
|
+
|
|
457
|
+
// Verify modern JavaScript features
|
|
458
|
+
assert!(
|
|
459
|
+
output.contains("class DataProcessor") || output.contains("DataProcessor"),
|
|
460
|
+
"Missing DataProcessor class - output: {}",
|
|
461
|
+
output
|
|
462
|
+
);
|
|
463
|
+
assert!(
|
|
464
|
+
output.contains("class SymbolRegistry") || output.contains("SymbolRegistry"),
|
|
465
|
+
"Missing SymbolRegistry class - output: {}",
|
|
466
|
+
output
|
|
467
|
+
);
|
|
468
|
+
|
|
469
|
+
// Test another search term for functions
|
|
470
|
+
let output2 = ctx.run_probe(&[
|
|
471
|
+
"search",
|
|
472
|
+
"async", // Search for async functions
|
|
473
|
+
test_file.to_str().unwrap(),
|
|
474
|
+
"--format",
|
|
475
|
+
"outline",
|
|
476
|
+
"--allow-tests",
|
|
477
|
+
"--exact",
|
|
478
|
+
])?;
|
|
479
|
+
|
|
480
|
+
assert!(
|
|
481
|
+
output2.contains("async") || !output2.trim().is_empty(),
|
|
482
|
+
"Should find async-related content - output: {}",
|
|
483
|
+
output2
|
|
484
|
+
);
|
|
485
|
+
|
|
486
|
+
Ok(())
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
#[test]
|
|
490
|
+
fn test_javascript_outline_react_components() -> Result<()> {
|
|
491
|
+
let temp_dir = TempDir::new()?;
|
|
492
|
+
let test_file = temp_dir.path().join("react_components.js");
|
|
493
|
+
|
|
494
|
+
let content = r#"import React, { useState, useEffect, useCallback, useMemo } from 'react';
|
|
495
|
+
import PropTypes from 'prop-types';
|
|
496
|
+
|
|
497
|
+
/**
|
|
498
|
+
* Custom hook for managing local storage.
|
|
499
|
+
*/
|
|
500
|
+
function useLocalStorage(key, initialValue) {
|
|
501
|
+
const [storedValue, setStoredValue] = useState(() => {
|
|
502
|
+
try {
|
|
503
|
+
const item = window.localStorage.getItem(key);
|
|
504
|
+
return item ? JSON.parse(item) : initialValue;
|
|
505
|
+
} catch (error) {
|
|
506
|
+
console.error(`Error reading localStorage key "${key}":`, error);
|
|
507
|
+
return initialValue;
|
|
508
|
+
}
|
|
509
|
+
});
|
|
510
|
+
|
|
511
|
+
const setValue = useCallback((value) => {
|
|
512
|
+
try {
|
|
513
|
+
setStoredValue(value);
|
|
514
|
+
window.localStorage.setItem(key, JSON.stringify(value));
|
|
515
|
+
} catch (error) {
|
|
516
|
+
console.error(`Error setting localStorage key "${key}":`, error);
|
|
517
|
+
}
|
|
518
|
+
}, [key]);
|
|
519
|
+
|
|
520
|
+
return [storedValue, setValue];
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
/**
|
|
524
|
+
* Higher-order component for loading states.
|
|
525
|
+
*/
|
|
526
|
+
function withLoading(WrappedComponent) {
|
|
527
|
+
return function WithLoadingComponent(props) {
|
|
528
|
+
const [isLoading, setIsLoading] = useState(false);
|
|
529
|
+
|
|
530
|
+
const startLoading = useCallback(() => setIsLoading(true), []);
|
|
531
|
+
const stopLoading = useCallback(() => setIsLoading(false), []);
|
|
532
|
+
|
|
533
|
+
if (isLoading) {
|
|
534
|
+
return (
|
|
535
|
+
<div className="loading-spinner">
|
|
536
|
+
<div>Loading...</div>
|
|
537
|
+
</div>
|
|
538
|
+
);
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
return (
|
|
542
|
+
<WrappedComponent
|
|
543
|
+
{...props}
|
|
544
|
+
startLoading={startLoading}
|
|
545
|
+
stopLoading={stopLoading}
|
|
546
|
+
/>
|
|
547
|
+
);
|
|
548
|
+
};
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
/**
|
|
552
|
+
* Main functional component with hooks.
|
|
553
|
+
*/
|
|
554
|
+
const UserProfile = ({ userId, onUserUpdate }) => {
|
|
555
|
+
const [user, setUser] = useState(null);
|
|
556
|
+
const [preferences, setPreferences] = useLocalStorage('userPreferences', {});
|
|
557
|
+
const [isEditing, setIsEditing] = useState(false);
|
|
558
|
+
|
|
559
|
+
// Memoized computed values
|
|
560
|
+
const displayName = useMemo(() => {
|
|
561
|
+
if (!user) return '';
|
|
562
|
+
return `${user.firstName} ${user.lastName}`.trim();
|
|
563
|
+
}, [user]);
|
|
564
|
+
|
|
565
|
+
// Effect for fetching user data
|
|
566
|
+
useEffect(() => {
|
|
567
|
+
if (userId) {
|
|
568
|
+
fetchUser(userId)
|
|
569
|
+
.then(userData => {
|
|
570
|
+
setUser(userData);
|
|
571
|
+
onUserUpdate?.(userData);
|
|
572
|
+
})
|
|
573
|
+
.catch(error => {
|
|
574
|
+
console.error('Failed to fetch user:', error);
|
|
575
|
+
});
|
|
576
|
+
}
|
|
577
|
+
}, [userId, onUserUpdate]);
|
|
578
|
+
|
|
579
|
+
// Event handlers
|
|
580
|
+
const handleEdit = useCallback(() => {
|
|
581
|
+
setIsEditing(true);
|
|
582
|
+
}, []);
|
|
583
|
+
|
|
584
|
+
const handleSave = useCallback(async (updatedUser) => {
|
|
585
|
+
try {
|
|
586
|
+
const savedUser = await saveUser(updatedUser);
|
|
587
|
+
setUser(savedUser);
|
|
588
|
+
setIsEditing(false);
|
|
589
|
+
onUserUpdate?.(savedUser);
|
|
590
|
+
} catch (error) {
|
|
591
|
+
console.error('Failed to save user:', error);
|
|
592
|
+
}
|
|
593
|
+
}, [onUserUpdate]);
|
|
594
|
+
|
|
595
|
+
const handleCancel = useCallback(() => {
|
|
596
|
+
setIsEditing(false);
|
|
597
|
+
}, []);
|
|
598
|
+
|
|
599
|
+
// Render methods
|
|
600
|
+
const renderProfile = () => {
|
|
601
|
+
if (!user) {
|
|
602
|
+
return <div>No user data available</div>;
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
return (
|
|
606
|
+
<div className="user-profile">
|
|
607
|
+
<h2>{displayName}</h2>
|
|
608
|
+
<p>Email: {user.email}</p>
|
|
609
|
+
<p>Role: {user.role}</p>
|
|
610
|
+
|
|
611
|
+
<div className="user-preferences">
|
|
612
|
+
<h3>Preferences</h3>
|
|
613
|
+
{Object.entries(preferences).map(([key, value]) => (
|
|
614
|
+
<div key={key}>
|
|
615
|
+
{key}: {JSON.stringify(value)}
|
|
616
|
+
</div>
|
|
617
|
+
))}
|
|
618
|
+
</div>
|
|
619
|
+
</div>
|
|
620
|
+
);
|
|
621
|
+
};
|
|
622
|
+
|
|
623
|
+
const renderEditForm = () => {
|
|
624
|
+
return (
|
|
625
|
+
<UserEditForm
|
|
626
|
+
user={user}
|
|
627
|
+
onSave={handleSave}
|
|
628
|
+
onCancel={handleCancel}
|
|
629
|
+
/>
|
|
630
|
+
);
|
|
631
|
+
};
|
|
632
|
+
|
|
633
|
+
return (
|
|
634
|
+
<div className="user-profile-container">
|
|
635
|
+
{isEditing ? renderEditForm() : renderProfile()}
|
|
636
|
+
|
|
637
|
+
{!isEditing && (
|
|
638
|
+
<button onClick={handleEdit}>
|
|
639
|
+
Edit Profile
|
|
640
|
+
</button>
|
|
641
|
+
)}
|
|
642
|
+
</div>
|
|
643
|
+
);
|
|
644
|
+
};
|
|
645
|
+
|
|
646
|
+
/**
|
|
647
|
+
* Class-based component for comparison.
|
|
648
|
+
*/
|
|
649
|
+
class UserEditForm extends React.Component {
|
|
650
|
+
static propTypes = {
|
|
651
|
+
user: PropTypes.object.isRequired,
|
|
652
|
+
onSave: PropTypes.func.isRequired,
|
|
653
|
+
onCancel: PropTypes.func.isRequired
|
|
654
|
+
};
|
|
655
|
+
|
|
656
|
+
constructor(props) {
|
|
657
|
+
super(props);
|
|
658
|
+
this.state = {
|
|
659
|
+
formData: { ...props.user },
|
|
660
|
+
errors: {}
|
|
661
|
+
};
|
|
662
|
+
}
|
|
663
|
+
|
|
664
|
+
componentDidMount() {
|
|
665
|
+
this.validateForm();
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
componentDidUpdate(prevProps) {
|
|
669
|
+
if (prevProps.user !== this.props.user) {
|
|
670
|
+
this.setState({ formData: { ...this.props.user } });
|
|
671
|
+
}
|
|
672
|
+
}
|
|
673
|
+
|
|
674
|
+
validateForm = () => {
|
|
675
|
+
const { formData } = this.state;
|
|
676
|
+
const errors = {};
|
|
677
|
+
|
|
678
|
+
if (!formData.firstName?.trim()) {
|
|
679
|
+
errors.firstName = 'First name is required';
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
if (!formData.email?.trim()) {
|
|
683
|
+
errors.email = 'Email is required';
|
|
684
|
+
} else if (!/^\S+@\S+\.\S+$/.test(formData.email)) {
|
|
685
|
+
errors.email = 'Email format is invalid';
|
|
686
|
+
}
|
|
687
|
+
|
|
688
|
+
this.setState({ errors });
|
|
689
|
+
return Object.keys(errors).length === 0;
|
|
690
|
+
};
|
|
691
|
+
|
|
692
|
+
handleSubmit = (e) => {
|
|
693
|
+
e.preventDefault();
|
|
694
|
+
|
|
695
|
+
if (this.validateForm()) {
|
|
696
|
+
this.props.onSave(this.state.formData);
|
|
697
|
+
}
|
|
698
|
+
};
|
|
699
|
+
|
|
700
|
+
handleChange = (field) => (e) => {
|
|
701
|
+
this.setState({
|
|
702
|
+
formData: {
|
|
703
|
+
...this.state.formData,
|
|
704
|
+
[field]: e.target.value
|
|
705
|
+
}
|
|
706
|
+
}, this.validateForm);
|
|
707
|
+
};
|
|
708
|
+
|
|
709
|
+
render() {
|
|
710
|
+
const { formData, errors } = this.state;
|
|
711
|
+
const { onCancel } = this.props;
|
|
712
|
+
|
|
713
|
+
return (
|
|
714
|
+
<form onSubmit={this.handleSubmit} className="user-edit-form">
|
|
715
|
+
<div className="form-group">
|
|
716
|
+
<label htmlFor="firstName">First Name:</label>
|
|
717
|
+
<input
|
|
718
|
+
id="firstName"
|
|
719
|
+
type="text"
|
|
720
|
+
value={formData.firstName || ''}
|
|
721
|
+
onChange={this.handleChange('firstName')}
|
|
722
|
+
/>
|
|
723
|
+
{errors.firstName && (
|
|
724
|
+
<span className="error">{errors.firstName}</span>
|
|
725
|
+
)}
|
|
726
|
+
</div>
|
|
727
|
+
|
|
728
|
+
<div className="form-buttons">
|
|
729
|
+
<button type="submit">Save</button>
|
|
730
|
+
<button type="button" onClick={onCancel}>
|
|
731
|
+
Cancel
|
|
732
|
+
</button>
|
|
733
|
+
</div>
|
|
734
|
+
</form>
|
|
735
|
+
);
|
|
736
|
+
}
|
|
737
|
+
}
|
|
738
|
+
|
|
739
|
+
// Utility functions
|
|
740
|
+
async function fetchUser(userId) {
|
|
741
|
+
const response = await fetch(`/api/users/${userId}`);
|
|
742
|
+
if (!response.ok) {
|
|
743
|
+
throw new Error(`Failed to fetch user: ${response.status}`);
|
|
744
|
+
}
|
|
745
|
+
return response.json();
|
|
746
|
+
}
|
|
747
|
+
|
|
748
|
+
async function saveUser(userData) {
|
|
749
|
+
const response = await fetch(`/api/users/${userData.id}`, {
|
|
750
|
+
method: 'PUT',
|
|
751
|
+
headers: {
|
|
752
|
+
'Content-Type': 'application/json',
|
|
753
|
+
},
|
|
754
|
+
body: JSON.stringify(userData),
|
|
755
|
+
});
|
|
756
|
+
|
|
757
|
+
if (!response.ok) {
|
|
758
|
+
throw new Error(`Failed to save user: ${response.status}`);
|
|
759
|
+
}
|
|
760
|
+
|
|
761
|
+
return response.json();
|
|
762
|
+
}
|
|
763
|
+
|
|
764
|
+
export { useLocalStorage, withLoading, UserProfile, UserEditForm };
|
|
765
|
+
export default UserProfile;
|
|
766
|
+
"#;
|
|
767
|
+
|
|
768
|
+
fs::write(&test_file, content)?;
|
|
769
|
+
|
|
770
|
+
let ctx = TestContext::new();
|
|
771
|
+
let output = ctx.run_probe(&[
|
|
772
|
+
"search",
|
|
773
|
+
"React", // Search for React-related symbols
|
|
774
|
+
test_file.to_str().unwrap(),
|
|
775
|
+
"--format",
|
|
776
|
+
"outline",
|
|
777
|
+
"--allow-tests",
|
|
778
|
+
"--exact",
|
|
779
|
+
])?;
|
|
780
|
+
|
|
781
|
+
// Should find React-related content (not currently asserting on this)
|
|
782
|
+
let _has_react_content = output.contains("React")
|
|
783
|
+
|| output.contains("Component")
|
|
784
|
+
|| output.contains("useState")
|
|
785
|
+
|| output.contains("useEffect");
|
|
786
|
+
|
|
787
|
+
// Test for function/class declarations
|
|
788
|
+
let output2 = ctx.run_probe(&[
|
|
789
|
+
"search",
|
|
790
|
+
"function", // Search for function declarations
|
|
791
|
+
test_file.to_str().unwrap(),
|
|
792
|
+
"--format",
|
|
793
|
+
"outline",
|
|
794
|
+
"--allow-tests",
|
|
795
|
+
"--exact",
|
|
796
|
+
])?;
|
|
797
|
+
|
|
798
|
+
assert!(
|
|
799
|
+
output2.contains("function") || output2.contains("const") || output2.contains("class"),
|
|
800
|
+
"Missing React component functions/classes - output: {}",
|
|
801
|
+
output2
|
|
802
|
+
);
|
|
803
|
+
|
|
804
|
+
Ok(())
|
|
805
|
+
}
|
|
806
|
+
|
|
807
|
+
#[test]
|
|
808
|
+
fn test_javascript_outline_test_patterns() -> Result<()> {
|
|
809
|
+
let temp_dir = TempDir::new()?;
|
|
810
|
+
let test_file = temp_dir.path().join("test_patterns.js");
|
|
811
|
+
|
|
812
|
+
let content = r#"// Jest test patterns for JavaScript
|
|
813
|
+
|
|
814
|
+
const { Calculator } = require('./calculator');
|
|
815
|
+
|
|
816
|
+
describe('Calculator', () => {
|
|
817
|
+
let calculator;
|
|
818
|
+
|
|
819
|
+
beforeEach(() => {
|
|
820
|
+
calculator = new Calculator('Test Calculator');
|
|
821
|
+
});
|
|
822
|
+
|
|
823
|
+
afterEach(() => {
|
|
824
|
+
calculator = null;
|
|
825
|
+
});
|
|
826
|
+
|
|
827
|
+
describe('addition', () => {
|
|
828
|
+
test('should add two positive numbers', () => {
|
|
829
|
+
expect(calculator.add(2, 3)).toBe(5);
|
|
830
|
+
});
|
|
831
|
+
|
|
832
|
+
test('should add negative numbers', () => {
|
|
833
|
+
expect(calculator.add(-2, -3)).toBe(-5);
|
|
834
|
+
});
|
|
835
|
+
|
|
836
|
+
test('should handle zero', () => {
|
|
837
|
+
expect(calculator.add(0, 5)).toBe(5);
|
|
838
|
+
});
|
|
839
|
+
});
|
|
840
|
+
|
|
841
|
+
describe('history tracking', () => {
|
|
842
|
+
test('should track calculation history', () => {
|
|
843
|
+
calculator.add(2, 3);
|
|
844
|
+
calculator.add(4, 5);
|
|
845
|
+
|
|
846
|
+
const history = calculator.getHistory();
|
|
847
|
+
expect(history).toEqual([5, 9]);
|
|
848
|
+
});
|
|
849
|
+
|
|
850
|
+
test('should start with empty history', () => {
|
|
851
|
+
expect(calculator.getHistory()).toEqual([]);
|
|
852
|
+
});
|
|
853
|
+
});
|
|
854
|
+
|
|
855
|
+
describe('error handling', () => {
|
|
856
|
+
test('should handle division by zero', () => {
|
|
857
|
+
expect(() => calculator.divide(10, 0)).toThrow('Division by zero');
|
|
858
|
+
});
|
|
859
|
+
|
|
860
|
+
test('should handle invalid inputs', () => {
|
|
861
|
+
expect(() => calculator.add('a', 'b')).toThrow('Invalid input');
|
|
862
|
+
});
|
|
863
|
+
});
|
|
864
|
+
});
|
|
865
|
+
|
|
866
|
+
// Async test patterns
|
|
867
|
+
describe('async operations', () => {
|
|
868
|
+
test('should fetch data successfully', async () => {
|
|
869
|
+
const mockData = { id: 1, name: 'Test' };
|
|
870
|
+
global.fetch = jest.fn().mockResolvedValue({
|
|
871
|
+
ok: true,
|
|
872
|
+
json: () => Promise.resolve(mockData),
|
|
873
|
+
});
|
|
874
|
+
|
|
875
|
+
const result = await fetchUserData(1);
|
|
876
|
+
expect(result).toEqual(mockData);
|
|
877
|
+
expect(fetch).toHaveBeenCalledWith('/api/users/1');
|
|
878
|
+
});
|
|
879
|
+
|
|
880
|
+
test('should handle fetch errors', async () => {
|
|
881
|
+
global.fetch = jest.fn().mockRejectedValue(new Error('Network error'));
|
|
882
|
+
|
|
883
|
+
await expect(fetchUserData(1)).rejects.toThrow('Network error');
|
|
884
|
+
});
|
|
885
|
+
|
|
886
|
+
test('should timeout after specified duration', async () => {
|
|
887
|
+
jest.setTimeout(5000);
|
|
888
|
+
|
|
889
|
+
const slowOperation = () => new Promise(resolve => {
|
|
890
|
+
setTimeout(resolve, 10000);
|
|
891
|
+
});
|
|
892
|
+
|
|
893
|
+
await expect(slowOperation()).resolves.toBe(undefined);
|
|
894
|
+
}, 15000);
|
|
895
|
+
});
|
|
896
|
+
|
|
897
|
+
// Mock implementations
|
|
898
|
+
jest.mock('./external-service', () => ({
|
|
899
|
+
sendNotification: jest.fn(),
|
|
900
|
+
logEvent: jest.fn(),
|
|
901
|
+
}));
|
|
902
|
+
|
|
903
|
+
describe('service integration', () => {
|
|
904
|
+
const mockService = require('./external-service');
|
|
905
|
+
|
|
906
|
+
beforeEach(() => {
|
|
907
|
+
jest.clearAllMocks();
|
|
908
|
+
});
|
|
909
|
+
|
|
910
|
+
test('should call external service', () => {
|
|
911
|
+
const notificationService = new NotificationService();
|
|
912
|
+
notificationService.notify('Test message');
|
|
913
|
+
|
|
914
|
+
expect(mockService.sendNotification).toHaveBeenCalledWith('Test message');
|
|
915
|
+
});
|
|
916
|
+
|
|
917
|
+
test('should log events correctly', () => {
|
|
918
|
+
const eventLogger = new EventLogger();
|
|
919
|
+
eventLogger.log('user_action', { userId: 123 });
|
|
920
|
+
|
|
921
|
+
expect(mockService.logEvent).toHaveBeenCalledWith('user_action', { userId: 123 });
|
|
922
|
+
});
|
|
923
|
+
});
|
|
924
|
+
|
|
925
|
+
// Parameterized tests
|
|
926
|
+
describe.each([
|
|
927
|
+
{ a: 1, b: 2, expected: 3 },
|
|
928
|
+
{ a: -1, b: 1, expected: 0 },
|
|
929
|
+
{ a: 0, b: 0, expected: 0 },
|
|
930
|
+
])('add($a, $b)', ({ a, b, expected }) => {
|
|
931
|
+
test(`should return ${expected}`, () => {
|
|
932
|
+
expect(add(a, b)).toBe(expected);
|
|
933
|
+
});
|
|
934
|
+
});
|
|
935
|
+
|
|
936
|
+
// Snapshot testing
|
|
937
|
+
describe('component rendering', () => {
|
|
938
|
+
test('should render user profile correctly', () => {
|
|
939
|
+
const user = { name: 'John Doe', email: 'john@example.com' };
|
|
940
|
+
const component = renderUserProfile(user);
|
|
941
|
+
expect(component).toMatchSnapshot();
|
|
942
|
+
});
|
|
943
|
+
|
|
944
|
+
test('should render empty state', () => {
|
|
945
|
+
const component = renderUserProfile(null);
|
|
946
|
+
expect(component).toMatchSnapshot();
|
|
947
|
+
});
|
|
948
|
+
});
|
|
949
|
+
|
|
950
|
+
// Utility functions for testing
|
|
951
|
+
function add(a, b) {
|
|
952
|
+
return a + b;
|
|
953
|
+
}
|
|
954
|
+
|
|
955
|
+
async function fetchUserData(userId) {
|
|
956
|
+
const response = await fetch(`/api/users/${userId}`);
|
|
957
|
+
if (!response.ok) {
|
|
958
|
+
throw new Error(`HTTP error! status: ${response.status}`);
|
|
959
|
+
}
|
|
960
|
+
return response.json();
|
|
961
|
+
}
|
|
962
|
+
|
|
963
|
+
class NotificationService {
|
|
964
|
+
notify(message) {
|
|
965
|
+
return require('./external-service').sendNotification(message);
|
|
966
|
+
}
|
|
967
|
+
}
|
|
968
|
+
|
|
969
|
+
class EventLogger {
|
|
970
|
+
log(event, data) {
|
|
971
|
+
return require('./external-service').logEvent(event, data);
|
|
972
|
+
}
|
|
973
|
+
}
|
|
974
|
+
|
|
975
|
+
function renderUserProfile(user) {
|
|
976
|
+
if (!user) {
|
|
977
|
+
return '<div>No user data</div>';
|
|
978
|
+
}
|
|
979
|
+
return `<div><h1>${user.name}</h1><p>${user.email}</p></div>`;
|
|
980
|
+
}
|
|
981
|
+
"#;
|
|
982
|
+
|
|
983
|
+
fs::write(&test_file, content)?;
|
|
984
|
+
|
|
985
|
+
let ctx = TestContext::new();
|
|
986
|
+
let output = ctx.run_probe(&[
|
|
987
|
+
"search",
|
|
988
|
+
"test", // Search for test-related symbols
|
|
989
|
+
test_file.to_str().unwrap(),
|
|
990
|
+
"--format",
|
|
991
|
+
"outline",
|
|
992
|
+
"--allow-tests",
|
|
993
|
+
"--exact",
|
|
994
|
+
])?;
|
|
995
|
+
|
|
996
|
+
// Verify test patterns are detected - should find describe blocks or test functions
|
|
997
|
+
let _has_test_patterns =
|
|
998
|
+
output.contains("describe") || output.contains("test") || output.contains("it(");
|
|
999
|
+
|
|
1000
|
+
// Test for function declarations
|
|
1001
|
+
let output2 = ctx.run_probe(&[
|
|
1002
|
+
"search",
|
|
1003
|
+
"function", // Search for function declarations
|
|
1004
|
+
test_file.to_str().unwrap(),
|
|
1005
|
+
"--format",
|
|
1006
|
+
"outline",
|
|
1007
|
+
"--allow-tests",
|
|
1008
|
+
"--exact",
|
|
1009
|
+
])?;
|
|
1010
|
+
|
|
1011
|
+
assert!(
|
|
1012
|
+
output2.contains("function") || output2.contains("class") || output2.contains("const"),
|
|
1013
|
+
"Missing function/class declarations - output: {}",
|
|
1014
|
+
output2
|
|
1015
|
+
);
|
|
1016
|
+
|
|
1017
|
+
Ok(())
|
|
1018
|
+
}
|
|
1019
|
+
|
|
1020
|
+
#[test]
|
|
1021
|
+
fn test_javascript_outline_large_function_closing_braces() -> Result<()> {
|
|
1022
|
+
let temp_dir = TempDir::new()?;
|
|
1023
|
+
let test_file = temp_dir.path().join("large_function.js");
|
|
1024
|
+
|
|
1025
|
+
let content = r#"/**
|
|
1026
|
+
* Large function with multiple nested blocks to test closing brace comments.
|
|
1027
|
+
* This function has more than 20 lines and should get closing brace comments.
|
|
1028
|
+
*/
|
|
1029
|
+
function complexDataProcessor(data) {
|
|
1030
|
+
const results = [];
|
|
1031
|
+
const categories = new Map();
|
|
1032
|
+
|
|
1033
|
+
// Phase 1: Categorization
|
|
1034
|
+
for (const [index, value] of data.entries()) {
|
|
1035
|
+
let category;
|
|
1036
|
+
|
|
1037
|
+
if (value < 0) {
|
|
1038
|
+
category = 'negative';
|
|
1039
|
+
} else if (value === 0) {
|
|
1040
|
+
category = 'zero';
|
|
1041
|
+
} else if (value < 100) {
|
|
1042
|
+
category = 'small_positive';
|
|
1043
|
+
} else if (value < 1000) {
|
|
1044
|
+
category = 'medium_positive';
|
|
1045
|
+
} else {
|
|
1046
|
+
category = 'large_positive';
|
|
1047
|
+
}
|
|
1048
|
+
|
|
1049
|
+
if (!categories.has(category)) {
|
|
1050
|
+
categories.set(category, []);
|
|
1051
|
+
}
|
|
1052
|
+
categories.get(category).push({ index, value });
|
|
1053
|
+
}
|
|
1054
|
+
|
|
1055
|
+
// Phase 2: Processing each category
|
|
1056
|
+
for (const [category, items] of categories) {
|
|
1057
|
+
if (category === 'negative') {
|
|
1058
|
+
for (const { index, value } of items) {
|
|
1059
|
+
results.push(`NEG[${index}]: ${Math.abs(value)}`);
|
|
1060
|
+
}
|
|
1061
|
+
} else if (category === 'zero') {
|
|
1062
|
+
for (const { index } of items) {
|
|
1063
|
+
results.push(`ZERO[${index}]: neutral`);
|
|
1064
|
+
}
|
|
1065
|
+
} else {
|
|
1066
|
+
// Positive number processing
|
|
1067
|
+
for (const { index, value } of items) {
|
|
1068
|
+
let processed;
|
|
1069
|
+
|
|
1070
|
+
if (value < 10) {
|
|
1071
|
+
processed = `SINGLE_DIGIT[${index}]: ${value}`;
|
|
1072
|
+
} else if (value < 100) {
|
|
1073
|
+
processed = `DOUBLE_DIGIT[${index}]: ${value}`;
|
|
1074
|
+
} else {
|
|
1075
|
+
processed = `MULTI_DIGIT[${index}]: ${value}`;
|
|
1076
|
+
}
|
|
1077
|
+
|
|
1078
|
+
results.push(processed);
|
|
1079
|
+
}
|
|
1080
|
+
}
|
|
1081
|
+
}
|
|
1082
|
+
|
|
1083
|
+
// Phase 3: Final sorting and validation
|
|
1084
|
+
results.sort();
|
|
1085
|
+
|
|
1086
|
+
// Validation phase
|
|
1087
|
+
const validatedResults = [];
|
|
1088
|
+
for (const result of results) {
|
|
1089
|
+
if (result.length > 5) {
|
|
1090
|
+
validatedResults.push(result);
|
|
1091
|
+
}
|
|
1092
|
+
}
|
|
1093
|
+
|
|
1094
|
+
return validatedResults;
|
|
1095
|
+
}
|
|
1096
|
+
|
|
1097
|
+
/**
|
|
1098
|
+
* Small function that should NOT get closing brace comments.
|
|
1099
|
+
*/
|
|
1100
|
+
function smallFunction(x, y) {
|
|
1101
|
+
return x + y;
|
|
1102
|
+
}
|
|
1103
|
+
|
|
1104
|
+
/**
|
|
1105
|
+
* Another small function for testing.
|
|
1106
|
+
*/
|
|
1107
|
+
const anotherSmallFunction = (a, b) => {
|
|
1108
|
+
const result = a * b;
|
|
1109
|
+
return result > 0 ? result : 0;
|
|
1110
|
+
};
|
|
1111
|
+
"#;
|
|
1112
|
+
|
|
1113
|
+
fs::write(&test_file, content)?;
|
|
1114
|
+
|
|
1115
|
+
let ctx = TestContext::new();
|
|
1116
|
+
let output = ctx.run_probe(&[
|
|
1117
|
+
"search",
|
|
1118
|
+
"complexDataProcessor", // Search for the specific large function
|
|
1119
|
+
test_file.to_str().unwrap(),
|
|
1120
|
+
"--format",
|
|
1121
|
+
"outline",
|
|
1122
|
+
"--allow-tests",
|
|
1123
|
+
"--exact",
|
|
1124
|
+
])?;
|
|
1125
|
+
|
|
1126
|
+
// Verify large function is shown with closing braces
|
|
1127
|
+
assert!(
|
|
1128
|
+
output.contains("function complexDataProcessor") || output.contains("complexDataProcessor"),
|
|
1129
|
+
"Missing complexDataProcessor function - output: {}",
|
|
1130
|
+
output
|
|
1131
|
+
);
|
|
1132
|
+
|
|
1133
|
+
// Should have closing braces for large blocks
|
|
1134
|
+
let closing_braces_count = output.matches("}").count();
|
|
1135
|
+
assert!(
|
|
1136
|
+
closing_braces_count >= 1,
|
|
1137
|
+
"Should have closing braces for function - output: {}",
|
|
1138
|
+
output
|
|
1139
|
+
);
|
|
1140
|
+
|
|
1141
|
+
Ok(())
|
|
1142
|
+
}
|
|
1143
|
+
|
|
1144
|
+
#[test]
|
|
1145
|
+
fn test_javascript_outline_small_function_no_closing_braces() -> Result<()> {
|
|
1146
|
+
let temp_dir = TempDir::new()?;
|
|
1147
|
+
let test_file = temp_dir.path().join("small_functions.js");
|
|
1148
|
+
|
|
1149
|
+
let content = r#"/**
|
|
1150
|
+
* Collection of small functions that should NOT get closing brace comments.
|
|
1151
|
+
*/
|
|
1152
|
+
|
|
1153
|
+
function add(x, y) {
|
|
1154
|
+
return x + y;
|
|
1155
|
+
}
|
|
1156
|
+
|
|
1157
|
+
function multiply(a, b) {
|
|
1158
|
+
return a * b;
|
|
1159
|
+
}
|
|
1160
|
+
|
|
1161
|
+
const subtract = (x, y) => {
|
|
1162
|
+
return x - y;
|
|
1163
|
+
};
|
|
1164
|
+
|
|
1165
|
+
async function fetchData(url) {
|
|
1166
|
+
const response = await fetch(url);
|
|
1167
|
+
return response.json();
|
|
1168
|
+
}
|
|
1169
|
+
|
|
1170
|
+
class SimpleCalculator {
|
|
1171
|
+
add(x, y) {
|
|
1172
|
+
return x + y;
|
|
1173
|
+
}
|
|
1174
|
+
}
|
|
1175
|
+
"#;
|
|
1176
|
+
|
|
1177
|
+
fs::write(&test_file, content)?;
|
|
1178
|
+
|
|
1179
|
+
let ctx = TestContext::new();
|
|
1180
|
+
let output = ctx.run_probe(&[
|
|
1181
|
+
"search",
|
|
1182
|
+
"function", // Search for function declarations
|
|
1183
|
+
test_file.to_str().unwrap(),
|
|
1184
|
+
"--format",
|
|
1185
|
+
"outline",
|
|
1186
|
+
"--allow-tests",
|
|
1187
|
+
"--exact",
|
|
1188
|
+
])?;
|
|
1189
|
+
|
|
1190
|
+
// Verify small functions are found but don't have excessive closing braces
|
|
1191
|
+
assert!(
|
|
1192
|
+
output.contains("function add") || output.contains("add") || output.contains("function"),
|
|
1193
|
+
"Missing small function declarations - output: {}",
|
|
1194
|
+
output
|
|
1195
|
+
);
|
|
1196
|
+
|
|
1197
|
+
Ok(())
|
|
1198
|
+
}
|
|
1199
|
+
|
|
1200
|
+
#[test]
|
|
1201
|
+
fn test_javascript_outline_keyword_highlighting() -> Result<()> {
|
|
1202
|
+
let temp_dir = TempDir::new()?;
|
|
1203
|
+
let test_file = temp_dir.path().join("keyword_test.js");
|
|
1204
|
+
|
|
1205
|
+
let content = r#"// JavaScript with various keywords for highlighting tests
|
|
1206
|
+
|
|
1207
|
+
/**
|
|
1208
|
+
* Function with async/await keywords
|
|
1209
|
+
*/
|
|
1210
|
+
async function processAsync(data) {
|
|
1211
|
+
try {
|
|
1212
|
+
const result = await performOperation(data);
|
|
1213
|
+
return { success: true, result };
|
|
1214
|
+
} catch (error) {
|
|
1215
|
+
throw new Error(`Processing failed: ${error.message}`);
|
|
1216
|
+
}
|
|
1217
|
+
}
|
|
1218
|
+
|
|
1219
|
+
/**
|
|
1220
|
+
* Function with control flow keywords
|
|
1221
|
+
*/
|
|
1222
|
+
function processWithControlFlow(items) {
|
|
1223
|
+
for (const item of items) {
|
|
1224
|
+
if (item.type === 'special') {
|
|
1225
|
+
continue;
|
|
1226
|
+
}
|
|
1227
|
+
|
|
1228
|
+
switch (item.status) {
|
|
1229
|
+
case 'active':
|
|
1230
|
+
processActiveItem(item);
|
|
1231
|
+
break;
|
|
1232
|
+
case 'inactive':
|
|
1233
|
+
processInactiveItem(item);
|
|
1234
|
+
break;
|
|
1235
|
+
default:
|
|
1236
|
+
processDefaultItem(item);
|
|
1237
|
+
break;
|
|
1238
|
+
}
|
|
1239
|
+
}
|
|
1240
|
+
}
|
|
1241
|
+
|
|
1242
|
+
/**
|
|
1243
|
+
* Class with static and private keywords
|
|
1244
|
+
*/
|
|
1245
|
+
class KeywordProcessor {
|
|
1246
|
+
static instances = [];
|
|
1247
|
+
#privateData = {};
|
|
1248
|
+
|
|
1249
|
+
constructor() {
|
|
1250
|
+
KeywordProcessor.instances.push(this);
|
|
1251
|
+
}
|
|
1252
|
+
|
|
1253
|
+
static getInstance() {
|
|
1254
|
+
return KeywordProcessor.instances[0];
|
|
1255
|
+
}
|
|
1256
|
+
|
|
1257
|
+
#privateMethod() {
|
|
1258
|
+
return this.#privateData;
|
|
1259
|
+
}
|
|
1260
|
+
}
|
|
1261
|
+
|
|
1262
|
+
// Export keywords
|
|
1263
|
+
export { processAsync, processWithControlFlow, KeywordProcessor };
|
|
1264
|
+
export default KeywordProcessor;
|
|
1265
|
+
"#;
|
|
1266
|
+
|
|
1267
|
+
fs::write(&test_file, content)?;
|
|
1268
|
+
|
|
1269
|
+
let ctx = TestContext::new();
|
|
1270
|
+
|
|
1271
|
+
// Search for specific keywords and verify they're highlighted in outline
|
|
1272
|
+
let test_cases = vec![
|
|
1273
|
+
("async", "async function processAsync"),
|
|
1274
|
+
("static", "static getInstance"),
|
|
1275
|
+
("class", "class KeywordProcessor"),
|
|
1276
|
+
("export", "export"),
|
|
1277
|
+
];
|
|
1278
|
+
|
|
1279
|
+
for (keyword, expected_content) in test_cases {
|
|
1280
|
+
let output = ctx.run_probe(&[
|
|
1281
|
+
"search",
|
|
1282
|
+
keyword,
|
|
1283
|
+
test_file.to_str().unwrap(),
|
|
1284
|
+
"--format",
|
|
1285
|
+
"outline",
|
|
1286
|
+
"--allow-tests",
|
|
1287
|
+
])?;
|
|
1288
|
+
|
|
1289
|
+
// Should find the keyword in outline format
|
|
1290
|
+
assert!(
|
|
1291
|
+
output.contains(keyword)
|
|
1292
|
+
|| output.contains(expected_content)
|
|
1293
|
+
|| !output.trim().is_empty(),
|
|
1294
|
+
"Missing {} keyword in outline - output: {}",
|
|
1295
|
+
keyword,
|
|
1296
|
+
output
|
|
1297
|
+
);
|
|
1298
|
+
}
|
|
1299
|
+
|
|
1300
|
+
Ok(())
|
|
1301
|
+
}
|
|
1302
|
+
|
|
1303
|
+
#[test]
|
|
1304
|
+
fn test_javascript_outline_array_object_truncation() -> Result<()> {
|
|
1305
|
+
let temp_dir = TempDir::new()?;
|
|
1306
|
+
let test_file = temp_dir.path().join("truncation_test.js");
|
|
1307
|
+
|
|
1308
|
+
let content = r#"// JavaScript with large arrays and objects for truncation testing
|
|
1309
|
+
|
|
1310
|
+
const largeArray = [
|
|
1311
|
+
'item1', 'item2', 'item3', 'item4', 'item5',
|
|
1312
|
+
'item6', 'item7', 'item8', 'item9', 'item10',
|
|
1313
|
+
'keyword', 'important', 'special', 'data',
|
|
1314
|
+
'item11', 'item12', 'item13', 'item14', 'item15',
|
|
1315
|
+
'item16', 'item17', 'item18', 'item19', 'item20',
|
|
1316
|
+
'item21', 'item22', 'item23', 'item24', 'item25'
|
|
1317
|
+
];
|
|
1318
|
+
|
|
1319
|
+
const largeObject = {
|
|
1320
|
+
property1: 'value1',
|
|
1321
|
+
property2: 'value2',
|
|
1322
|
+
property3: 'value3',
|
|
1323
|
+
importantKeyword: 'special value',
|
|
1324
|
+
property4: 'value4',
|
|
1325
|
+
property5: 'value5',
|
|
1326
|
+
property6: 'value6',
|
|
1327
|
+
property7: 'value7',
|
|
1328
|
+
property8: 'value8',
|
|
1329
|
+
property9: 'value9',
|
|
1330
|
+
property10: 'value10',
|
|
1331
|
+
anotherKeyword: 'another special value',
|
|
1332
|
+
property11: 'value11',
|
|
1333
|
+
property12: 'value12'
|
|
1334
|
+
};
|
|
1335
|
+
|
|
1336
|
+
function processLargeData() {
|
|
1337
|
+
const config = {
|
|
1338
|
+
timeout: 5000,
|
|
1339
|
+
retries: 3,
|
|
1340
|
+
important: true,
|
|
1341
|
+
special: 'keyword',
|
|
1342
|
+
endpoints: [
|
|
1343
|
+
'/api/users',
|
|
1344
|
+
'/api/posts',
|
|
1345
|
+
'/api/comments',
|
|
1346
|
+
'/api/important',
|
|
1347
|
+
'/api/data',
|
|
1348
|
+
'/api/special',
|
|
1349
|
+
'/api/keyword'
|
|
1350
|
+
],
|
|
1351
|
+
settings: {
|
|
1352
|
+
debug: false,
|
|
1353
|
+
verbose: true,
|
|
1354
|
+
important: 'setting',
|
|
1355
|
+
keyword: 'value'
|
|
1356
|
+
}
|
|
1357
|
+
};
|
|
1358
|
+
|
|
1359
|
+
return config;
|
|
1360
|
+
}
|
|
1361
|
+
"#;
|
|
1362
|
+
|
|
1363
|
+
fs::write(&test_file, content)?;
|
|
1364
|
+
|
|
1365
|
+
let ctx = TestContext::new();
|
|
1366
|
+
let output = ctx.run_probe(&[
|
|
1367
|
+
"search",
|
|
1368
|
+
"keyword", // Search for keyword that should be preserved even in truncated arrays/objects
|
|
1369
|
+
test_file.to_str().unwrap(),
|
|
1370
|
+
"--format",
|
|
1371
|
+
"outline",
|
|
1372
|
+
"--allow-tests",
|
|
1373
|
+
"--exact",
|
|
1374
|
+
])?;
|
|
1375
|
+
|
|
1376
|
+
// Should find the keyword even in truncated content
|
|
1377
|
+
assert!(
|
|
1378
|
+
output.contains("keyword") || !output.trim().is_empty(),
|
|
1379
|
+
"Missing keyword in truncated arrays/objects - output: {}",
|
|
1380
|
+
output
|
|
1381
|
+
);
|
|
1382
|
+
|
|
1383
|
+
// Test for truncation indicators
|
|
1384
|
+
let output2 = ctx.run_probe(&[
|
|
1385
|
+
"search",
|
|
1386
|
+
"largeArray",
|
|
1387
|
+
test_file.to_str().unwrap(),
|
|
1388
|
+
"--format",
|
|
1389
|
+
"outline",
|
|
1390
|
+
"--allow-tests",
|
|
1391
|
+
"--exact",
|
|
1392
|
+
])?;
|
|
1393
|
+
|
|
1394
|
+
// Should contain array/object content, possibly with truncation
|
|
1395
|
+
assert!(
|
|
1396
|
+
output2.contains("largeArray") || output2.contains("const") || !output2.trim().is_empty(),
|
|
1397
|
+
"Missing large array content - output: {}",
|
|
1398
|
+
output2
|
|
1399
|
+
);
|
|
1400
|
+
|
|
1401
|
+
Ok(())
|
|
1402
|
+
}
|
|
1403
|
+
|
|
1404
|
+
#[test]
|
|
1405
|
+
fn test_javascript_outline_search_command() -> Result<()> {
|
|
1406
|
+
let temp_dir = TempDir::new()?;
|
|
1407
|
+
let test_file = temp_dir.path().join("search_test.js");
|
|
1408
|
+
|
|
1409
|
+
let content = r#"class DataProcessor {
|
|
1410
|
+
constructor() {
|
|
1411
|
+
this.processedCount = 0;
|
|
1412
|
+
}
|
|
1413
|
+
|
|
1414
|
+
processData(data) {
|
|
1415
|
+
this.processedCount++;
|
|
1416
|
+
return data.filter(item => item != null);
|
|
1417
|
+
}
|
|
1418
|
+
|
|
1419
|
+
getProcessedCount() {
|
|
1420
|
+
return this.processedCount;
|
|
1421
|
+
}
|
|
1422
|
+
}
|
|
1423
|
+
|
|
1424
|
+
function processFile(filename) {
|
|
1425
|
+
return `Processed ${filename}`;
|
|
1426
|
+
}
|
|
1427
|
+
|
|
1428
|
+
async function processAsync(data) {
|
|
1429
|
+
return { processed: true, ...data };
|
|
1430
|
+
}
|
|
1431
|
+
|
|
1432
|
+
function testDataProcessing() {
|
|
1433
|
+
const processor = new DataProcessor();
|
|
1434
|
+
const result = processor.processData([1, 2, null, 3]);
|
|
1435
|
+
console.assert(result.length === 3);
|
|
1436
|
+
}
|
|
1437
|
+
"#;
|
|
1438
|
+
|
|
1439
|
+
fs::write(&test_file, content)?;
|
|
1440
|
+
|
|
1441
|
+
let ctx = TestContext::new();
|
|
1442
|
+
let output = ctx.run_probe(&[
|
|
1443
|
+
"search",
|
|
1444
|
+
"process",
|
|
1445
|
+
temp_dir.path().to_str().unwrap(),
|
|
1446
|
+
"--format",
|
|
1447
|
+
"outline",
|
|
1448
|
+
"--allow-tests",
|
|
1449
|
+
"--exact",
|
|
1450
|
+
])?;
|
|
1451
|
+
|
|
1452
|
+
// Should find symbols containing "process"
|
|
1453
|
+
assert!(
|
|
1454
|
+
output.contains("DataProcessor")
|
|
1455
|
+
|| output.contains("processData")
|
|
1456
|
+
|| output.contains("processFile")
|
|
1457
|
+
|| output.contains("processAsync")
|
|
1458
|
+
|| output.contains("process"),
|
|
1459
|
+
"Should find process-related symbols - output: {}",
|
|
1460
|
+
output
|
|
1461
|
+
);
|
|
1462
|
+
|
|
1463
|
+
Ok(())
|
|
1464
|
+
}
|