@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.
Files changed (444) hide show
  1. package/README.md +138 -0
  2. package/data/.env.example +22 -0
  3. package/data/.gitattributes +47 -0
  4. package/data/.glfrc.json +7 -0
  5. package/data/.husky/pre-commit +5 -0
  6. package/data/.nvmrc +1 -0
  7. package/data/CHANGELOG.md +75 -0
  8. package/data/CODE_OF_CONDUCT.md +129 -0
  9. package/data/CONTRIBUTING.md +203 -0
  10. package/data/DOCS-STRUCTURE.md +307 -0
  11. package/data/I18N.md +292 -0
  12. package/data/LICENSE +22 -0
  13. package/data/README.md +315 -0
  14. package/data/SECURITY.md +125 -0
  15. package/data/WIKI-DEPLOYMENT.md +348 -0
  16. package/data/docs/AI-FEATURES.md +610 -0
  17. package/data/docs/API-REFERENCE.md +1022 -0
  18. package/data/docs/AUTHENTICATION.md +301 -0
  19. package/data/docs/BACKEND-API.md +468 -0
  20. package/data/docs/DEVELOPMENT.md +375 -0
  21. package/data/docs/EXAMPLES.md +622 -0
  22. package/data/docs/MCP-SERVER.md +307 -0
  23. package/data/docs/MIGRATION-GUIDE.md +367 -0
  24. package/data/docs/NPM-PUBLISH.md +193 -0
  25. package/data/docs/QUICKSTART.md +206 -0
  26. package/data/docs/REDIS-SETUP.md +162 -0
  27. package/data/docs/SERVER.md +228 -0
  28. package/data/docs/TROUBLESHOOTING.md +657 -0
  29. package/data/docs/WIDGET-GUIDE.md +638 -0
  30. package/data/docs/WIKI-HOME.md +58 -0
  31. package/data/docs/WIKI-SIDEBAR.md +39 -0
  32. package/data/package.json +171 -0
  33. package/data/playwright.config.ts +64 -0
  34. package/data/probe/.cargo/config.toml +10 -0
  35. package/data/probe/.claude/commands/performance-review.md +15 -0
  36. package/data/probe/.clinerules +288 -0
  37. package/data/probe/.dockerignore +57 -0
  38. package/data/probe/.githooks/post-commit +11 -0
  39. package/data/probe/.githooks/pre-commit +99 -0
  40. package/data/probe/.githooks/pre-commit-vow +9 -0
  41. package/data/probe/.prompts/engineer.md +41 -0
  42. package/data/probe/.roomodes +28 -0
  43. package/data/probe/.windsurfrules +0 -0
  44. package/data/probe/BASH_TOOL_SUMMARY.md +148 -0
  45. package/data/probe/BENCHMARKING.md +256 -0
  46. package/data/probe/CLAUDE.md +226 -0
  47. package/data/probe/CODE_OF_CONDUCT.md +128 -0
  48. package/data/probe/CONTRIBUTING.md +193 -0
  49. package/data/probe/Cargo.toml +120 -0
  50. package/data/probe/Cross.toml +10 -0
  51. package/data/probe/DOCKER-README.md +224 -0
  52. package/data/probe/Dockerfile +32 -0
  53. package/data/probe/ENHANCED_DEBUG_TELEMETRY.md +188 -0
  54. package/data/probe/LICENSE +201 -0
  55. package/data/probe/Makefile +210 -0
  56. package/data/probe/README.md +824 -0
  57. package/data/probe/SECURITY.md +67 -0
  58. package/data/probe/WINDOWS-GUIDE.md +294 -0
  59. package/data/probe/benches/parsing_benchmarks.rs +370 -0
  60. package/data/probe/benches/search_benchmarks.rs +599 -0
  61. package/data/probe/benches/simd_benchmarks.rs +372 -0
  62. package/data/probe/benches/timing_benchmarks.rs +287 -0
  63. package/data/probe/build-windows.bat +229 -0
  64. package/data/probe/codex-config/config.toml +6 -0
  65. package/data/probe/docs/PERFORMANCE_OPTIMIZATION.md +161 -0
  66. package/data/probe/examples/cache_demo.rs +46 -0
  67. package/data/probe/examples/chat/.dockerignore +37 -0
  68. package/data/probe/examples/chat/ChatSessionManager.js +295 -0
  69. package/data/probe/examples/chat/Dockerfile +98 -0
  70. package/data/probe/examples/chat/LICENSE +201 -0
  71. package/data/probe/examples/chat/LOCAL_IMAGE_SUPPORT.md +195 -0
  72. package/data/probe/examples/chat/MCP_INTEGRATION.md +400 -0
  73. package/data/probe/examples/chat/README.md +338 -0
  74. package/data/probe/examples/chat/TRACING.md +226 -0
  75. package/data/probe/examples/chat/appTracer.js +968 -0
  76. package/data/probe/examples/chat/auth.js +76 -0
  77. package/data/probe/examples/chat/bin/probe-chat.js +13 -0
  78. package/data/probe/examples/chat/build.js +104 -0
  79. package/data/probe/examples/chat/cancelRequest.js +84 -0
  80. package/data/probe/examples/chat/demo-agentic-image-flow.js +88 -0
  81. package/data/probe/examples/chat/demo-local-images.js +128 -0
  82. package/data/probe/examples/chat/fileSpanExporter.js +181 -0
  83. package/data/probe/examples/chat/implement/README.md +228 -0
  84. package/data/probe/examples/chat/implement/backends/AiderBackend.js +750 -0
  85. package/data/probe/examples/chat/implement/backends/BaseBackend.js +276 -0
  86. package/data/probe/examples/chat/implement/backends/ClaudeCodeBackend.js +767 -0
  87. package/data/probe/examples/chat/implement/backends/MockBackend.js +237 -0
  88. package/data/probe/examples/chat/implement/backends/registry.js +85 -0
  89. package/data/probe/examples/chat/implement/core/BackendManager.js +567 -0
  90. package/data/probe/examples/chat/implement/core/ImplementTool.js +354 -0
  91. package/data/probe/examples/chat/implement/core/config.js +428 -0
  92. package/data/probe/examples/chat/implement/core/timeouts.js +58 -0
  93. package/data/probe/examples/chat/implement/core/utils.js +496 -0
  94. package/data/probe/examples/chat/implement/types/BackendTypes.js +126 -0
  95. package/data/probe/examples/chat/index.js +669 -0
  96. package/data/probe/examples/chat/mcpServer.js +341 -0
  97. package/data/probe/examples/chat/npm/LICENSE +15 -0
  98. package/data/probe/examples/chat/npm/README.md +168 -0
  99. package/data/probe/examples/chat/npm/bin/probe-chat.js +156 -0
  100. package/data/probe/examples/chat/npm/index.js +259 -0
  101. package/data/probe/examples/chat/npm/package.json +54 -0
  102. package/data/probe/examples/chat/package.json +102 -0
  103. package/data/probe/examples/chat/probeChat.js +456 -0
  104. package/data/probe/examples/chat/probeTool.js +491 -0
  105. package/data/probe/examples/chat/storage/JsonChatStorage.js +476 -0
  106. package/data/probe/examples/chat/telemetry.js +281 -0
  107. package/data/probe/examples/chat/test/integration/chatFlows.test.js +320 -0
  108. package/data/probe/examples/chat/test/integration/toolCalling.test.js +471 -0
  109. package/data/probe/examples/chat/test/mocks/mockLLMProvider.js +269 -0
  110. package/data/probe/examples/chat/test/test-backends.js +90 -0
  111. package/data/probe/examples/chat/test/testUtils.js +530 -0
  112. package/data/probe/examples/chat/test/unit/backendTimeout.test.js +161 -0
  113. package/data/probe/examples/chat/test/unit/packageFiles.test.js +120 -0
  114. package/data/probe/examples/chat/test/verify-tests.js +118 -0
  115. package/data/probe/examples/chat/test-agentic-image-loading.js +294 -0
  116. package/data/probe/examples/chat/test-ai-sdk-telemetry.js +204 -0
  117. package/data/probe/examples/chat/test-chat-tracing.js +38 -0
  118. package/data/probe/examples/chat/test-direct-function.js +49 -0
  119. package/data/probe/examples/chat/test-file-size-validation.js +103 -0
  120. package/data/probe/examples/chat/test-full-mcp-integration.js +258 -0
  121. package/data/probe/examples/chat/test-github-context.txt +12 -0
  122. package/data/probe/examples/chat/test-hierarchy.js +203 -0
  123. package/data/probe/examples/chat/test-image-spans.js +37 -0
  124. package/data/probe/examples/chat/test-local-image-reading.js +176 -0
  125. package/data/probe/examples/chat/test-mcp-integration.js +136 -0
  126. package/data/probe/examples/chat/test-mcp-probe-server.js +161 -0
  127. package/data/probe/examples/chat/test-mcp-with-ai.js +279 -0
  128. package/data/probe/examples/chat/test-multiple-allowed-dirs.js +111 -0
  129. package/data/probe/examples/chat/test-probe-mcp-server.js +110 -0
  130. package/data/probe/examples/chat/test-security-validation.js +145 -0
  131. package/data/probe/examples/chat/test-simple-tracing.js +32 -0
  132. package/data/probe/examples/chat/test-trace-verification.js +235 -0
  133. package/data/probe/examples/chat/test-tracing.js +114 -0
  134. package/data/probe/examples/chat/tokenCounter.js +419 -0
  135. package/data/probe/examples/chat/tokenUsageDisplay.js +134 -0
  136. package/data/probe/examples/chat/webServer.js +1103 -0
  137. package/data/probe/examples/reranker/Cargo.toml +33 -0
  138. package/data/probe/examples/reranker/DEBUG_OUTPUT_ANALYSIS.md +71 -0
  139. package/data/probe/examples/reranker/MODELS.md +66 -0
  140. package/data/probe/examples/reranker/MODEL_COMPARISON.md +60 -0
  141. package/data/probe/examples/reranker/MULTI_MODEL_ANALYSIS.md +176 -0
  142. package/data/probe/examples/reranker/PERFORMANCE_SUMMARY.md +156 -0
  143. package/data/probe/examples/reranker/README.md +347 -0
  144. package/data/probe/examples/reranker/RUST_BERT_COMPARISON.md +82 -0
  145. package/data/probe/examples/reranker/TOKENIZATION_GUIDE.md +120 -0
  146. package/data/probe/examples/reranker/check_rust_tokenizer.py +108 -0
  147. package/data/probe/examples/reranker/convert_to_torchscript.py +109 -0
  148. package/data/probe/examples/reranker/debug_scoring.py +189 -0
  149. package/data/probe/examples/reranker/debug_tokenization.py +154 -0
  150. package/data/probe/examples/reranker/download_models.sh +73 -0
  151. package/data/probe/examples/reranker/requirements.txt +13 -0
  152. package/data/probe/examples/reranker/run_comprehensive_benchmark.sh +83 -0
  153. package/data/probe/examples/reranker/rust_bert_test/Cargo.toml +12 -0
  154. package/data/probe/examples/reranker/rust_bert_test/README.md +54 -0
  155. package/data/probe/examples/reranker/simple_test.py +50 -0
  156. package/data/probe/examples/reranker/test_all_models.sh +63 -0
  157. package/data/probe/examples/reranker/test_bert_results.sh +44 -0
  158. package/data/probe/examples/reranker/test_cross_encoder.py +334 -0
  159. package/data/probe/examples/reranker/test_cross_encoder.sh +80 -0
  160. package/data/probe/examples/reranker/test_exact_comparison.py +151 -0
  161. package/data/probe/examples/reranker/test_parallel_performance.sh +56 -0
  162. package/data/probe/examples/reranker/test_scores.py +132 -0
  163. package/data/probe/install.ps1 +508 -0
  164. package/data/probe/install.sh +460 -0
  165. package/data/probe/npm/CLONE_METHOD_EXAMPLES.md +596 -0
  166. package/data/probe/npm/CONTEXT_COMPACTION.md +303 -0
  167. package/data/probe/npm/DELEGATE_TOOL_README.md +166 -0
  168. package/data/probe/npm/MAID_INTEGRATION.md +313 -0
  169. package/data/probe/npm/MCP_INTEGRATION_SUMMARY.md +241 -0
  170. package/data/probe/npm/README.md +824 -0
  171. package/data/probe/npm/bin/.gitignore +7 -0
  172. package/data/probe/npm/bin/.gitkeep +0 -0
  173. package/data/probe/npm/bin/README.md +12 -0
  174. package/data/probe/npm/bin/probe +167 -0
  175. package/data/probe/npm/docs/CLAUDE_CODE_INTEGRATION.md +414 -0
  176. package/data/probe/npm/docs/CODEX_INTEGRATION.md +502 -0
  177. package/data/probe/npm/docs/EDIT_CREATE_TOOLS.md +233 -0
  178. package/data/probe/npm/docs/RETRY_AND_FALLBACK.md +674 -0
  179. package/data/probe/npm/example-usage.js +335 -0
  180. package/data/probe/npm/examples/multi-engine-demo.js +117 -0
  181. package/data/probe/npm/examples/probe-agent-cli.js +113 -0
  182. package/data/probe/npm/examples/test-agent-edit.js +114 -0
  183. package/data/probe/npm/examples/test-edit-create.js +120 -0
  184. package/data/probe/npm/examples/test-edit-direct.js +114 -0
  185. package/data/probe/npm/index.d.ts +744 -0
  186. package/data/probe/npm/jest.config.js +52 -0
  187. package/data/probe/npm/package.json +117 -0
  188. package/data/probe/npm/scripts/build-agent.cjs +75 -0
  189. package/data/probe/npm/scripts/build-cjs.js +124 -0
  190. package/data/probe/npm/scripts/build-mcp.cjs +36 -0
  191. package/data/probe/npm/scripts/postinstall.js +216 -0
  192. package/data/probe/npm/test-codex-e2e.js +78 -0
  193. package/data/probe/npm/test-download-lock.js +109 -0
  194. package/data/probe/npm/test-grep-security.js +94 -0
  195. package/data/probe/npm/test-grep-simplified.js +63 -0
  196. package/data/probe/npm/test-grep.js +51 -0
  197. package/data/probe/npm/tests/README.md +96 -0
  198. package/data/probe/npm/tests/agent-compact-history.test.js +174 -0
  199. package/data/probe/npm/tests/allow-tests-default.test.js +151 -0
  200. package/data/probe/npm/tests/contextCompactor.test.js +498 -0
  201. package/data/probe/npm/tests/delegate-config.test.js +353 -0
  202. package/data/probe/npm/tests/delegate-integration.test.js +348 -0
  203. package/data/probe/npm/tests/extractor-integration.test.js +162 -0
  204. package/data/probe/npm/tests/extractor.test.js +317 -0
  205. package/data/probe/npm/tests/fixtures/sampleDiagrams.js +267 -0
  206. package/data/probe/npm/tests/integration/claude-code-auto-fallback.spec.js +148 -0
  207. package/data/probe/npm/tests/integration/claude-code-multi-step.spec.js +127 -0
  208. package/data/probe/npm/tests/integration/claude-code-tool-events.spec.js +163 -0
  209. package/data/probe/npm/tests/integration/codex-auto-fallback.spec.js +191 -0
  210. package/data/probe/npm/tests/integration/codex-tool-events.spec.js +147 -0
  211. package/data/probe/npm/tests/integration/examplesChatMcp.test.js +402 -0
  212. package/data/probe/npm/tests/integration/mcpDotenvSupport.test.js +174 -0
  213. package/data/probe/npm/tests/integration/mcpErrorHandling.test.js +566 -0
  214. package/data/probe/npm/tests/integration/mcpRobustness.test.js +564 -0
  215. package/data/probe/npm/tests/integration/mcpStdoutPurity.test.js +355 -0
  216. package/data/probe/npm/tests/integration/probeAgentMcp.test.js +398 -0
  217. package/data/probe/npm/tests/integration/retryFallback.test.js +368 -0
  218. package/data/probe/npm/tests/integration/schema-in-initial-message.test.js +318 -0
  219. package/data/probe/npm/tests/integration/schema-validation-loop-prevention.test.js +244 -0
  220. package/data/probe/npm/tests/integration/schemaRetryLogic.test.js +94 -0
  221. package/data/probe/npm/tests/integration/validationFlow.test.js +329 -0
  222. package/data/probe/npm/tests/manual/test-codex-basic.js +110 -0
  223. package/data/probe/npm/tests/mcp/mcpClientManager.test.js +614 -0
  224. package/data/probe/npm/tests/mcp/mcpConfig.test.js +359 -0
  225. package/data/probe/npm/tests/mcp/mcpXmlBridge.test.js +436 -0
  226. package/data/probe/npm/tests/mcp/mockMcpServer.js +510 -0
  227. package/data/probe/npm/tests/mcp-strict-syntax.test.js +319 -0
  228. package/data/probe/npm/tests/mermaidQuoteEscaping.test.js +214 -0
  229. package/data/probe/npm/tests/nestedQuoteFix.test.js +40 -0
  230. package/data/probe/npm/tests/setup.js +46 -0
  231. package/data/probe/npm/tests/unit/allowed-tools.test.js +513 -0
  232. package/data/probe/npm/tests/unit/attempt-completion-closing-tag-in-content.test.js +188 -0
  233. package/data/probe/npm/tests/unit/attemptCompletionJsonFix.test.js +238 -0
  234. package/data/probe/npm/tests/unit/attemptCompletionJsonIssue.test.js +128 -0
  235. package/data/probe/npm/tests/unit/backtickAutoFix.test.js +35 -0
  236. package/data/probe/npm/tests/unit/bash-probe-agent-integration.test.js +389 -0
  237. package/data/probe/npm/tests/unit/bash-simple-commands.test.js +324 -0
  238. package/data/probe/npm/tests/unit/bash-tool-comprehensive.test.js +371 -0
  239. package/data/probe/npm/tests/unit/bash-tool-integration.test.js +310 -0
  240. package/data/probe/npm/tests/unit/bash-tool.test.js +341 -0
  241. package/data/probe/npm/tests/unit/completion-prompt.test.js +379 -0
  242. package/data/probe/npm/tests/unit/cwd-path-options.test.js +287 -0
  243. package/data/probe/npm/tests/unit/delegate-limits.test.js +422 -0
  244. package/data/probe/npm/tests/unit/direct-content-attempt-completion.test.js +235 -0
  245. package/data/probe/npm/tests/unit/edit-create-tools.test.js +609 -0
  246. package/data/probe/npm/tests/unit/enhancedMermaidValidation.test.js +577 -0
  247. package/data/probe/npm/tests/unit/extract-content.test.js +83 -0
  248. package/data/probe/npm/tests/unit/extract-multiple-targets.test.js +89 -0
  249. package/data/probe/npm/tests/unit/fallbackManager.test.js +442 -0
  250. package/data/probe/npm/tests/unit/githubCompatibilityValidation.test.js +258 -0
  251. package/data/probe/npm/tests/unit/imageConfig.test.js +149 -0
  252. package/data/probe/npm/tests/unit/imagePathResolution.test.js +345 -0
  253. package/data/probe/npm/tests/unit/json-fixing-agent.test.js +238 -0
  254. package/data/probe/npm/tests/unit/json-validation-enhanced-errors.test.js +199 -0
  255. package/data/probe/npm/tests/unit/jsonValidationInfiniteLoopFix.test.js +228 -0
  256. package/data/probe/npm/tests/unit/maidIntegration.test.js +139 -0
  257. package/data/probe/npm/tests/unit/maxIterationsWarning.test.js +195 -0
  258. package/data/probe/npm/tests/unit/mermaidEdgeLabelFix.test.js +161 -0
  259. package/data/probe/npm/tests/unit/mermaidHtmlEntities.test.js +76 -0
  260. package/data/probe/npm/tests/unit/mermaidInfiniteLoopFix.test.js +64 -0
  261. package/data/probe/npm/tests/unit/mermaidValidation.test.js +723 -0
  262. package/data/probe/npm/tests/unit/mermaidValidationVisorExample.test.js +309 -0
  263. package/data/probe/npm/tests/unit/probe-agent-clone-realistic.test.js +643 -0
  264. package/data/probe/npm/tests/unit/probe-agent-clone.test.js +476 -0
  265. package/data/probe/npm/tests/unit/probe-agent-delegate.test.js +400 -0
  266. package/data/probe/npm/tests/unit/probe-agent-model-option.test.js +118 -0
  267. package/data/probe/npm/tests/unit/probeTool-security.test.js +283 -0
  268. package/data/probe/npm/tests/unit/readImageTool.test.js +418 -0
  269. package/data/probe/npm/tests/unit/retryManager.test.js +317 -0
  270. package/data/probe/npm/tests/unit/schema-aware-reminders.test.js +288 -0
  271. package/data/probe/npm/tests/unit/schemaDefinitionDetection.test.js +115 -0
  272. package/data/probe/npm/tests/unit/schemaUtils.test.js +1268 -0
  273. package/data/probe/npm/tests/unit/simpleTelemetry.test.js +282 -0
  274. package/data/probe/npm/tests/unit/simplified-attempt-completion.test.js +274 -0
  275. package/data/probe/npm/tests/unit/single-quote-json-bug.test.js +231 -0
  276. package/data/probe/npm/tests/unit/subgraphAutoFix.test.js +110 -0
  277. package/data/probe/npm/tests/unit/system-prompt.test.js +32 -0
  278. package/data/probe/npm/tests/unit/types-probe-agent-options.test.js +42 -0
  279. package/data/probe/npm/tests/unit/xmlParsing.test.js +720 -0
  280. package/data/probe/npm/tsconfig.json +21 -0
  281. package/data/probe/result1.txt +19 -0
  282. package/data/probe/result2.txt +26 -0
  283. package/data/probe/scripts/benchmark.sh +270 -0
  284. package/data/probe/scripts/cache_memory_analysis.rs +844 -0
  285. package/data/probe/scripts/claude-hook-wrapper.sh +56 -0
  286. package/data/probe/site/.env.example +10 -0
  287. package/data/probe/site/DEPLOYMENT.md +86 -0
  288. package/data/probe/site/README.md +183 -0
  289. package/data/probe/site/adding-languages.md +135 -0
  290. package/data/probe/site/ai-chat.md +427 -0
  291. package/data/probe/site/ai-integration.md +1488 -0
  292. package/data/probe/site/blog/agentic-flow-custom-xml-protocol.md +407 -0
  293. package/data/probe/site/blog/index.md +118 -0
  294. package/data/probe/site/blog/v0.6.0-release.md +426 -0
  295. package/data/probe/site/blog.md +8 -0
  296. package/data/probe/site/changelog.md +200 -0
  297. package/data/probe/site/cli-mode.md +437 -0
  298. package/data/probe/site/code-extraction.md +436 -0
  299. package/data/probe/site/contributing/README.md +9 -0
  300. package/data/probe/site/contributing/documentation-cross-references.md +215 -0
  301. package/data/probe/site/contributing/documentation-maintenance.md +275 -0
  302. package/data/probe/site/contributing/documentation-structure.md +75 -0
  303. package/data/probe/site/documentation-cross-references.md +215 -0
  304. package/data/probe/site/documentation-guide.md +132 -0
  305. package/data/probe/site/documentation-maintenance.md +275 -0
  306. package/data/probe/site/features.md +147 -0
  307. package/data/probe/site/how-it-works.md +118 -0
  308. package/data/probe/site/index.md +175 -0
  309. package/data/probe/site/index.md.bak +133 -0
  310. package/data/probe/site/installation.md +235 -0
  311. package/data/probe/site/integrations/docker.md +248 -0
  312. package/data/probe/site/integrations/github-actions.md +413 -0
  313. package/data/probe/site/language-support-overview.md +168 -0
  314. package/data/probe/site/mcp-integration.md +587 -0
  315. package/data/probe/site/mcp-server.md +304 -0
  316. package/data/probe/site/navigation-structure.md +76 -0
  317. package/data/probe/site/nodejs-sdk.md +798 -0
  318. package/data/probe/site/output-formats.md +625 -0
  319. package/data/probe/site/package.json +21 -0
  320. package/data/probe/site/public/_headers +28 -0
  321. package/data/probe/site/public/_redirects +11 -0
  322. package/data/probe/site/quick-start.md +289 -0
  323. package/data/probe/site/search-functionality.md +291 -0
  324. package/data/probe/site/search-reference.md +291 -0
  325. package/data/probe/site/supported-languages.md +215 -0
  326. package/data/probe/site/use-cases/README.md +8 -0
  327. package/data/probe/site/use-cases/advanced-cli.md +253 -0
  328. package/data/probe/site/use-cases/ai-code-editors.md +239 -0
  329. package/data/probe/site/use-cases/building-ai-tools.md +529 -0
  330. package/data/probe/site/use-cases/cli-ai-workflows.md +285 -0
  331. package/data/probe/site/use-cases/deploying-probe-web-interface.md +255 -0
  332. package/data/probe/site/use-cases/integrating-probe-into-ai-code-editors.md +161 -0
  333. package/data/probe/site/use-cases/nodejs-sdk.md +596 -0
  334. package/data/probe/site/use-cases/team-chat.md +350 -0
  335. package/data/probe/site/web-interface.md +434 -0
  336. package/data/probe/site/wrangler.toml +9 -0
  337. package/data/probe/test-api-key.sh +1 -0
  338. package/data/probe/test-probe-implementation/hello.js +7 -0
  339. package/data/probe/test_cases/demonstrate_early_termination_issues.sh +176 -0
  340. package/data/probe/test_cases/early_termination_issues.rs +533 -0
  341. package/data/probe/test_data/test_nested_struct.go +26 -0
  342. package/data/probe/tests/README.md +286 -0
  343. package/data/probe/tests/README_search_determinism_tests.md +116 -0
  344. package/data/probe/tests/adjacent_comment_test.rs +152 -0
  345. package/data/probe/tests/apostrophe_handling_tests.rs +132 -0
  346. package/data/probe/tests/block_filtering_with_ast_tests.rs +669 -0
  347. package/data/probe/tests/block_merging_tests.rs +396 -0
  348. package/data/probe/tests/c_outline_format_tests.rs +2179 -0
  349. package/data/probe/tests/cache_invalidation_issues.rs.disabled +682 -0
  350. package/data/probe/tests/cache_order_tests.rs +147 -0
  351. package/data/probe/tests/cache_query_scoping_tests.rs +221 -0
  352. package/data/probe/tests/cli_tests.rs +680 -0
  353. package/data/probe/tests/comment_context_integration_test.rs +240 -0
  354. package/data/probe/tests/common.rs +33 -0
  355. package/data/probe/tests/complex_block_merging_tests.rs +599 -0
  356. package/data/probe/tests/complex_query_block_filtering_tests.rs +422 -0
  357. package/data/probe/tests/control_flow_closing_braces_test.rs +91 -0
  358. package/data/probe/tests/cpp_outline_format_tests.rs +1507 -0
  359. package/data/probe/tests/csharp_outline_format_tests.rs +941 -0
  360. package/data/probe/tests/elastic_query_integration_tests.rs +922 -0
  361. package/data/probe/tests/extract_command_tests.rs +1848 -0
  362. package/data/probe/tests/extract_deduplication_tests.rs +146 -0
  363. package/data/probe/tests/extract_input_file_tests.rs +84 -0
  364. package/data/probe/tests/extract_prompt_tests.rs +102 -0
  365. package/data/probe/tests/filename_search_tests.rs +96 -0
  366. package/data/probe/tests/fixtures/user/AssemblyInfo.cs +3 -0
  367. package/data/probe/tests/github_extract_tests.rs +234 -0
  368. package/data/probe/tests/go_comment_test.rs +253 -0
  369. package/data/probe/tests/go_outline_format_tests.rs +2587 -0
  370. package/data/probe/tests/go_path_resolver_tests.rs +96 -0
  371. package/data/probe/tests/html_outline_format_tests.rs +637 -0
  372. package/data/probe/tests/integration_tests.rs +837 -0
  373. package/data/probe/tests/ip_whitelist_test.rs +148 -0
  374. package/data/probe/tests/java_outline_format_tests.rs +1611 -0
  375. package/data/probe/tests/javascript_extract_tests.rs +315 -0
  376. package/data/probe/tests/javascript_outline_format_tests.rs +1464 -0
  377. package/data/probe/tests/json_format_tests.rs +436 -0
  378. package/data/probe/tests/json_schema_validation_tests.rs +450 -0
  379. package/data/probe/tests/lib_usage.rs +60 -0
  380. package/data/probe/tests/line_comment_context_extension_test.rs +459 -0
  381. package/data/probe/tests/line_map_cache_tests.rs +114 -0
  382. package/data/probe/tests/markdown_integration_tests.rs +190 -0
  383. package/data/probe/tests/mocks/test_ip_whitelist.go +11 -0
  384. package/data/probe/tests/mocks/test_object.js +27 -0
  385. package/data/probe/tests/mocks/test_struct.go +50 -0
  386. package/data/probe/tests/multi_keyword_pattern_tests.rs +464 -0
  387. package/data/probe/tests/multi_language_syntax_integration_tests.rs +218 -0
  388. package/data/probe/tests/multiple_capture_groups_tests.rs +169 -0
  389. package/data/probe/tests/negative_compound_word_tests.rs +246 -0
  390. package/data/probe/tests/nested_symbol_extraction_tests.rs +99 -0
  391. package/data/probe/tests/outline_cross_file_interference_test.rs +335 -0
  392. package/data/probe/tests/outline_keyword_preservation_test.rs +67 -0
  393. package/data/probe/tests/output_format_edge_cases_tests.rs +693 -0
  394. package/data/probe/tests/parallel_extraction_tests.rs +178 -0
  395. package/data/probe/tests/parallel_search_tests.rs +355 -0
  396. package/data/probe/tests/path_resolver_tests.rs +698 -0
  397. package/data/probe/tests/php_outline_format_extended_tests.rs +928 -0
  398. package/data/probe/tests/php_outline_format_tests.rs +768 -0
  399. package/data/probe/tests/property_tests.proptest-regressions +9 -0
  400. package/data/probe/tests/property_tests.rs +118 -0
  401. package/data/probe/tests/python_outline_format_tests.rs +1538 -0
  402. package/data/probe/tests/query_command_json_tests.rs +438 -0
  403. package/data/probe/tests/query_command_tests.rs +232 -0
  404. package/data/probe/tests/query_command_xml_tests.rs +569 -0
  405. package/data/probe/tests/quoted_term_with_negative_keyword_tests.rs +216 -0
  406. package/data/probe/tests/required_terms_filename_tests.rs +116 -0
  407. package/data/probe/tests/ruby_outline_format_tests.rs +1011 -0
  408. package/data/probe/tests/rust_line_comment_context_test.rs +151 -0
  409. package/data/probe/tests/rust_outline_format_enhanced_tests.rs +725 -0
  410. package/data/probe/tests/rust_outline_format_tests.rs +843 -0
  411. package/data/probe/tests/schemas/xml_output_schema.xsd +38 -0
  412. package/data/probe/tests/search_determinism_tests.rs +451 -0
  413. package/data/probe/tests/search_hints_tests.rs +253 -0
  414. package/data/probe/tests/special_character_escaping_tests.rs +417 -0
  415. package/data/probe/tests/stemming_compound_word_filtering_tests.rs +535 -0
  416. package/data/probe/tests/strict_elastic_syntax_tests.rs +404 -0
  417. package/data/probe/tests/swift_outline_format_tests.rs +3319 -0
  418. package/data/probe/tests/symbols_tests.rs +166 -0
  419. package/data/probe/tests/test_file.rs +45 -0
  420. package/data/probe/tests/test_tokenize.rs +28 -0
  421. package/data/probe/tests/timeout_tests.rs +82 -0
  422. package/data/probe/tests/tokenization_tests.rs +195 -0
  423. package/data/probe/tests/tokenized_block_filtering_tests.rs +174 -0
  424. package/data/probe/tests/typescript_extract_tests.rs +214 -0
  425. package/data/probe/tests/typescript_outline_format_tests.rs +2188 -0
  426. package/data/probe/tests/xml_format_tests.rs +568 -0
  427. package/data/probe/tests/xml_schema_validation_tests.rs +497 -0
  428. package/data/scripts/postinstall.mjs +9 -0
  429. package/data/scripts/set-version.js +0 -0
  430. package/data/scripts/wiki-build.sh +111 -0
  431. package/data/scripts/wiki-deploy.sh +73 -0
  432. package/data/serve.json +12 -0
  433. package/data/test/demo-dynamic.html +134 -0
  434. package/data/test/demo-esm.html +105 -0
  435. package/data/test/demo-iife.html +78 -0
  436. package/data/tsconfig.json +7 -0
  437. package/data/vite.server.ts +483 -0
  438. package/data/vitest.config.ts +40 -0
  439. package/data/wiki/Home.md +58 -0
  440. package/data/wiki/_Sidebar.md +39 -0
  441. package/docs-mcp.config.json +20 -0
  442. package/package.json +56 -0
  443. package/src/config.js +111 -0
  444. 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
+ }