ai-first-cli 1.3.1 → 1.3.5

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 (532) hide show
  1. package/.ai-dev/index.db +0 -0
  2. package/BETA_EVALUATION_REPORT.md +151 -0
  3. package/CHANGELOG.md +178 -0
  4. package/PHASE1_USER_SIMULATION.md +56 -0
  5. package/PHASE2_USER_SIMULATION.md +81 -0
  6. package/PHASE3_USER_SIMULATION.md +176 -0
  7. package/README.es.md +18 -0
  8. package/README.md +80 -1
  9. package/ai/graph/knowledge-graph.json +10 -0
  10. package/ai-context/ai_context.md +130 -0
  11. package/{test-projects/react-app/.ai-dev → ai-context}/ai_rules.md +10 -5
  12. package/ai-context/architecture.md +136 -0
  13. package/ai-context/context/features/src.json +69 -0
  14. package/ai-context/context/features/test-projects.json +69 -0
  15. package/ai-context/context/flows/App.json +17 -0
  16. package/ai-context/context/flows/DashboardPage.json +14 -0
  17. package/ai-context/context/flows/LoginPage.json +14 -0
  18. package/ai-context/context/flows/admin.json +10 -0
  19. package/ai-context/context/flows/ai-first.json +9 -0
  20. package/ai-context/context/flows/androidresources.json +11 -0
  21. package/ai-context/context/flows/auth.json +13 -0
  22. package/ai-context/context/flows/authController.json +14 -0
  23. package/ai-context/context/flows/doctor.json +9 -0
  24. package/ai-context/context/flows/entrypoints.json +9 -0
  25. package/ai-context/context/flows/explore.json +9 -0
  26. package/ai-context/context/flows/fastapiAdapter.json +14 -0
  27. package/ai-context/context/flows/fastapiadapter.json +11 -0
  28. package/ai-context/context/flows/index.json +19 -0
  29. package/ai-context/context/flows/indexer.json +9 -0
  30. package/ai-context/context/flows/indexstate.json +9 -0
  31. package/ai-context/context/flows/init.json +22 -0
  32. package/ai-context/context/flows/main.json +18 -0
  33. package/ai-context/context/flows/mainactivity.json +9 -0
  34. package/ai-context/context/flows/models.json +15 -0
  35. package/ai-context/context/flows/posts.json +15 -0
  36. package/ai-context/context/flows/repoMapper.json +20 -0
  37. package/ai-context/context/flows/repomapper.json +11 -0
  38. package/ai-context/context/flows/routes.json +15 -0
  39. package/ai-context/context/flows/serializers.json +10 -0
  40. package/ai-context/context/flows/user.json +23 -0
  41. package/ai-context/context/flows/views.json +12 -0
  42. package/{test-projects/react-app/.ai-dev → ai-context}/conventions.md +3 -2
  43. package/ai-context/dependencies.json +3360 -0
  44. package/ai-context/entrypoints.md +45 -0
  45. package/ai-context/index-state.json +196 -0
  46. package/ai-context/modules.json +901 -0
  47. package/ai-context/project.json +33 -0
  48. package/ai-context/repo_map.json +8857 -0
  49. package/ai-context/repo_map.md +2002 -0
  50. package/{test-projects/flask-app/.ai-dev → ai-context}/schema.json +1 -1
  51. package/ai-context/summary.md +46 -0
  52. package/ai-context/symbols.json +82467 -0
  53. package/{test-projects/react-app/.ai-dev → ai-context}/tech_stack.md +15 -7
  54. package/ai-context-evaluation-report-1774223059505.md +206 -0
  55. package/dist/analyzers/architecture.d.ts.map +1 -1
  56. package/dist/analyzers/architecture.js +6 -0
  57. package/dist/analyzers/architecture.js.map +1 -1
  58. package/dist/analyzers/entrypoints.d.ts.map +1 -1
  59. package/dist/analyzers/entrypoints.js +105 -0
  60. package/dist/analyzers/entrypoints.js.map +1 -1
  61. package/dist/analyzers/symbols.d.ts.map +1 -1
  62. package/dist/analyzers/symbols.js +72 -1
  63. package/dist/analyzers/symbols.js.map +1 -1
  64. package/dist/analyzers/techStack.d.ts +8 -0
  65. package/dist/analyzers/techStack.d.ts.map +1 -1
  66. package/dist/analyzers/techStack.js +75 -0
  67. package/dist/analyzers/techStack.js.map +1 -1
  68. package/dist/scripts/ai-context-evaluator.js +367 -0
  69. package/package.json +1 -1
  70. package/quick-evaluation-report-1774396002305.md +64 -0
  71. package/quick-evaluator.ts +200 -0
  72. package/scripts/ai-context-evaluator.ts +440 -0
  73. package/src/analyzers/architecture.ts +8 -0
  74. package/src/analyzers/entrypoints.ts +115 -0
  75. package/src/analyzers/symbols.ts +77 -1
  76. package/src/analyzers/techStack.ts +93 -0
  77. package/tests/apex-parser.test.ts +193 -0
  78. package/tests/cli-commands-batch1.test.ts +808 -0
  79. package/tests/cli-commands-batch2.test.ts +1113 -0
  80. package/tests/cli-commands-batch3.test.ts +1128 -0
  81. package/tests/cli-index.test.ts +1007 -0
  82. package/tests/cli-init.test.ts +761 -0
  83. package/tests/salesforce-apex-classes.test.ts +713 -0
  84. package/tests/salesforce-apex-triggers.test.ts +871 -0
  85. package/tests/salesforce-custom-objects.test.ts +918 -0
  86. package/tests/salesforce-flows.test.ts +710 -0
  87. package/tests/salesforce-lwc.test.ts +963 -0
  88. package/tests/salesforce-sfdx-integration.test.ts +1125 -0
  89. package/ANALISIS_COMPLETO.md +0 -424
  90. package/ANALISIS_MEJORAS.md +0 -327
  91. package/CONTRIBUTING.md +0 -89
  92. package/FLOW.md +0 -129
  93. package/TEST_RESULTS.md +0 -198
  94. package/TEST_RESULTS_COMPARATIVE.md +0 -159
  95. package/TEST_RESULTS_COMPLETE.md +0 -127
  96. package/TEST_RESULTS_COMPREHENSIVE.md +0 -208
  97. package/install.sh +0 -188
  98. package/run-all-tests.sh +0 -184
  99. package/test-ai-context-understanding.sh +0 -21
  100. package/test-projects/django-app/.ai-dev/ai_context.md +0 -92
  101. package/test-projects/django-app/.ai-dev/ai_rules.md +0 -47
  102. package/test-projects/django-app/.ai-dev/architecture.md +0 -57
  103. package/test-projects/django-app/.ai-dev/cache.json +0 -169
  104. package/test-projects/django-app/.ai-dev/context/flows/views.json +0 -10
  105. package/test-projects/django-app/.ai-dev/conventions.md +0 -51
  106. package/test-projects/django-app/.ai-dev/dependencies.json +0 -312
  107. package/test-projects/django-app/.ai-dev/entrypoints.md +0 -4
  108. package/test-projects/django-app/.ai-dev/files.json +0 -209
  109. package/test-projects/django-app/.ai-dev/graph/knowledge-graph.json +0 -36
  110. package/test-projects/django-app/.ai-dev/graph/module-graph.json +0 -145
  111. package/test-projects/django-app/.ai-dev/graph/symbol-graph.json +0 -1488
  112. package/test-projects/django-app/.ai-dev/graph/symbol-references.json +0 -1
  113. package/test-projects/django-app/.ai-dev/index-state.json +0 -294
  114. package/test-projects/django-app/.ai-dev/modules.json +0 -35
  115. package/test-projects/django-app/.ai-dev/project.json +0 -11
  116. package/test-projects/django-app/.ai-dev/repo_map.json +0 -412
  117. package/test-projects/django-app/.ai-dev/repo_map.md +0 -105
  118. package/test-projects/django-app/.ai-dev/schema.json +0 -5
  119. package/test-projects/django-app/.ai-dev/summary.md +0 -15
  120. package/test-projects/django-app/.ai-dev/symbols.json +0 -1
  121. package/test-projects/django-app/.ai-dev/tech_stack.md +0 -32
  122. package/test-projects/django-app/README.md +0 -91
  123. package/test-projects/django-app/blog/__init__.py +0 -0
  124. package/test-projects/django-app/blog/admin.py +0 -31
  125. package/test-projects/django-app/blog/models.py +0 -55
  126. package/test-projects/django-app/blog/serializers.py +0 -69
  127. package/test-projects/django-app/blog/urls.py +0 -14
  128. package/test-projects/django-app/blog/views.py +0 -96
  129. package/test-projects/django-app/django_app/__init__.py +0 -0
  130. package/test-projects/django-app/django_app/settings.py +0 -90
  131. package/test-projects/django-app/django_app/urls.py +0 -11
  132. package/test-projects/django-app/django_app/wsgi.py +0 -9
  133. package/test-projects/django-app/manage.py +0 -23
  134. package/test-projects/django-app/requirements.txt +0 -3
  135. package/test-projects/django-app/users/__init__.py +0 -0
  136. package/test-projects/django-app/users/admin.py +0 -42
  137. package/test-projects/django-app/users/models.py +0 -54
  138. package/test-projects/django-app/users/serializers.py +0 -113
  139. package/test-projects/django-app/users/urls.py +0 -13
  140. package/test-projects/django-app/users/views.py +0 -135
  141. package/test-projects/express-api/.ai-dev/ai_context.md +0 -112
  142. package/test-projects/express-api/.ai-dev/ai_rules.md +0 -50
  143. package/test-projects/express-api/.ai-dev/architecture.md +0 -62
  144. package/test-projects/express-api/.ai-dev/context/features/controllers.json +0 -13
  145. package/test-projects/express-api/.ai-dev/context/features/services.json +0 -13
  146. package/test-projects/express-api/.ai-dev/context/flows/auth.json +0 -12
  147. package/test-projects/express-api/.ai-dev/context/flows/user.json +0 -13
  148. package/test-projects/express-api/.ai-dev/conventions.md +0 -51
  149. package/test-projects/express-api/.ai-dev/dependencies.json +0 -54
  150. package/test-projects/express-api/.ai-dev/entrypoints.md +0 -17
  151. package/test-projects/express-api/.ai-dev/modules.json +0 -30
  152. package/test-projects/express-api/.ai-dev/project.json +0 -15
  153. package/test-projects/express-api/.ai-dev/repo_map.json +0 -100
  154. package/test-projects/express-api/.ai-dev/repo_map.md +0 -36
  155. package/test-projects/express-api/.ai-dev/schema.json +0 -5
  156. package/test-projects/express-api/.ai-dev/summary.md +0 -14
  157. package/test-projects/express-api/.ai-dev/symbols.json +0 -7
  158. package/test-projects/express-api/.ai-dev/tech_stack.md +0 -38
  159. package/test-projects/express-api/.ai-dev/tools.json +0 -10
  160. package/test-projects/express-api/controllers/authController.js +0 -32
  161. package/test-projects/express-api/controllers/userController.js +0 -51
  162. package/test-projects/express-api/index.js +0 -30
  163. package/test-projects/express-api/middleware/authMiddleware.js +0 -30
  164. package/test-projects/express-api/models/userRepository.js +0 -25
  165. package/test-projects/express-api/package.json +0 -18
  166. package/test-projects/express-api/services/authService.js +0 -17
  167. package/test-projects/express-api/services/userService.js +0 -28
  168. package/test-projects/fastapi-app/.ai-dev/ai_context.md +0 -89
  169. package/test-projects/fastapi-app/.ai-dev/ai_rules.md +0 -47
  170. package/test-projects/fastapi-app/.ai-dev/architecture.md +0 -39
  171. package/test-projects/fastapi-app/.ai-dev/cache.json +0 -125
  172. package/test-projects/fastapi-app/.ai-dev/conventions.md +0 -51
  173. package/test-projects/fastapi-app/.ai-dev/dependencies.json +0 -244
  174. package/test-projects/fastapi-app/.ai-dev/entrypoints.md +0 -4
  175. package/test-projects/fastapi-app/.ai-dev/files.json +0 -154
  176. package/test-projects/fastapi-app/.ai-dev/graph/knowledge-graph.json +0 -15
  177. package/test-projects/fastapi-app/.ai-dev/graph/module-graph.json +0 -78
  178. package/test-projects/fastapi-app/.ai-dev/graph/symbol-graph.json +0 -1724
  179. package/test-projects/fastapi-app/.ai-dev/graph/symbol-references.json +0 -51
  180. package/test-projects/fastapi-app/.ai-dev/index-state.json +0 -217
  181. package/test-projects/fastapi-app/.ai-dev/modules.json +0 -16
  182. package/test-projects/fastapi-app/.ai-dev/project.json +0 -9
  183. package/test-projects/fastapi-app/.ai-dev/repo_map.json +0 -298
  184. package/test-projects/fastapi-app/.ai-dev/repo_map.md +0 -74
  185. package/test-projects/fastapi-app/.ai-dev/schema.json +0 -5
  186. package/test-projects/fastapi-app/.ai-dev/summary.md +0 -12
  187. package/test-projects/fastapi-app/.ai-dev/symbols.json +0 -1
  188. package/test-projects/fastapi-app/.ai-dev/tech_stack.md +0 -32
  189. package/test-projects/fastapi-app/.ai-dev/tools.json +0 -10
  190. package/test-projects/fastapi-app/README.md +0 -118
  191. package/test-projects/fastapi-app/app/database.py +0 -21
  192. package/test-projects/fastapi-app/app/dependencies.py +0 -107
  193. package/test-projects/fastapi-app/app/main.py +0 -47
  194. package/test-projects/fastapi-app/app/models.py +0 -149
  195. package/test-projects/fastapi-app/app/routers/auth.py +0 -117
  196. package/test-projects/fastapi-app/app/routers/posts.py +0 -272
  197. package/test-projects/fastapi-app/app/schemas.py +0 -191
  198. package/test-projects/fastapi-app/requirements.txt +0 -10
  199. package/test-projects/flask-app/.ai-dev/ai_context.md +0 -94
  200. package/test-projects/flask-app/.ai-dev/ai_rules.md +0 -47
  201. package/test-projects/flask-app/.ai-dev/architecture.md +0 -49
  202. package/test-projects/flask-app/.ai-dev/cache.json +0 -157
  203. package/test-projects/flask-app/.ai-dev/context/features/app.json +0 -25
  204. package/test-projects/flask-app/.ai-dev/context/flows/routes.json +0 -14
  205. package/test-projects/flask-app/.ai-dev/conventions.md +0 -51
  206. package/test-projects/flask-app/.ai-dev/dependencies.json +0 -298
  207. package/test-projects/flask-app/.ai-dev/entrypoints.md +0 -4
  208. package/test-projects/flask-app/.ai-dev/files.json +0 -194
  209. package/test-projects/flask-app/.ai-dev/graph/knowledge-graph.json +0 -60
  210. package/test-projects/flask-app/.ai-dev/graph/module-graph.json +0 -95
  211. package/test-projects/flask-app/.ai-dev/graph/symbol-graph.json +0 -1448
  212. package/test-projects/flask-app/.ai-dev/graph/symbol-references.json +0 -45
  213. package/test-projects/flask-app/.ai-dev/index-state.json +0 -273
  214. package/test-projects/flask-app/.ai-dev/modules.json +0 -21
  215. package/test-projects/flask-app/.ai-dev/project.json +0 -13
  216. package/test-projects/flask-app/.ai-dev/repo_map.json +0 -400
  217. package/test-projects/flask-app/.ai-dev/repo_map.md +0 -98
  218. package/test-projects/flask-app/.ai-dev/summary.md +0 -13
  219. package/test-projects/flask-app/.ai-dev/symbols.json +0 -1
  220. package/test-projects/flask-app/.ai-dev/tech_stack.md +0 -32
  221. package/test-projects/flask-app/.ai-dev/tools.json +0 -10
  222. package/test-projects/flask-app/README.md +0 -129
  223. package/test-projects/flask-app/app/__init__.py +0 -46
  224. package/test-projects/flask-app/app/api/__init__.py +0 -7
  225. package/test-projects/flask-app/app/api/routes.py +0 -122
  226. package/test-projects/flask-app/app/auth/__init__.py +0 -7
  227. package/test-projects/flask-app/app/auth/forms.py +0 -52
  228. package/test-projects/flask-app/app/auth/routes.py +0 -68
  229. package/test-projects/flask-app/app/blog/__init__.py +0 -7
  230. package/test-projects/flask-app/app/blog/forms.py +0 -35
  231. package/test-projects/flask-app/app/blog/routes.py +0 -140
  232. package/test-projects/flask-app/app/main/__init__.py +0 -7
  233. package/test-projects/flask-app/app/main/routes.py +0 -88
  234. package/test-projects/flask-app/app/models.py +0 -177
  235. package/test-projects/flask-app/config.py +0 -64
  236. package/test-projects/flask-app/requirements.txt +0 -10
  237. package/test-projects/laravel-app/.ai-dev/ai_context.md +0 -97
  238. package/test-projects/laravel-app/.ai-dev/ai_rules.md +0 -47
  239. package/test-projects/laravel-app/.ai-dev/architecture.md +0 -60
  240. package/test-projects/laravel-app/.ai-dev/cache.json +0 -161
  241. package/test-projects/laravel-app/.ai-dev/context/features/app.json +0 -21
  242. package/test-projects/laravel-app/.ai-dev/context/flows/.json +0 -9
  243. package/test-projects/laravel-app/.ai-dev/context/flows/category.json +0 -12
  244. package/test-projects/laravel-app/.ai-dev/context/flows/comment.json +0 -12
  245. package/test-projects/laravel-app/.ai-dev/context/flows/post.json +0 -12
  246. package/test-projects/laravel-app/.ai-dev/context/flows/unnamed.json +0 -9
  247. package/test-projects/laravel-app/.ai-dev/conventions.md +0 -51
  248. package/test-projects/laravel-app/.ai-dev/dependencies.json +0 -6
  249. package/test-projects/laravel-app/.ai-dev/entrypoints.md +0 -4
  250. package/test-projects/laravel-app/.ai-dev/files.json +0 -199
  251. package/test-projects/laravel-app/.ai-dev/graph/knowledge-graph.json +0 -98
  252. package/test-projects/laravel-app/.ai-dev/graph/module-graph.json +0 -30
  253. package/test-projects/laravel-app/.ai-dev/graph/symbol-graph.json +0 -5
  254. package/test-projects/laravel-app/.ai-dev/graph/symbol-references.json +0 -1
  255. package/test-projects/laravel-app/.ai-dev/index-state.json +0 -280
  256. package/test-projects/laravel-app/.ai-dev/modules.json +0 -29
  257. package/test-projects/laravel-app/.ai-dev/project.json +0 -17
  258. package/test-projects/laravel-app/.ai-dev/repo_map.json +0 -419
  259. package/test-projects/laravel-app/.ai-dev/repo_map.md +0 -106
  260. package/test-projects/laravel-app/.ai-dev/schema.json +0 -5
  261. package/test-projects/laravel-app/.ai-dev/summary.md +0 -15
  262. package/test-projects/laravel-app/.ai-dev/symbols.json +0 -1
  263. package/test-projects/laravel-app/.ai-dev/tech_stack.md +0 -34
  264. package/test-projects/laravel-app/.ai-dev/tools.json +0 -10
  265. package/test-projects/laravel-app/README.md +0 -107
  266. package/test-projects/laravel-app/app/Http/Controllers/Api/CategoryController.php +0 -88
  267. package/test-projects/laravel-app/app/Http/Controllers/Api/CommentController.php +0 -56
  268. package/test-projects/laravel-app/app/Http/Controllers/Api/PostController.php +0 -174
  269. package/test-projects/laravel-app/app/Http/Controllers/Controller.php +0 -12
  270. package/test-projects/laravel-app/app/Models/Category.php +0 -34
  271. package/test-projects/laravel-app/app/Models/Comment.php +0 -51
  272. package/test-projects/laravel-app/app/Models/Post.php +0 -108
  273. package/test-projects/laravel-app/app/Models/User.php +0 -85
  274. package/test-projects/laravel-app/bootstrap/app.php +0 -25
  275. package/test-projects/laravel-app/composer.json +0 -35
  276. package/test-projects/laravel-app/routes/api.php +0 -40
  277. package/test-projects/nestjs-backend/.ai-dev/ai_context.md +0 -111
  278. package/test-projects/nestjs-backend/.ai-dev/ai_rules.md +0 -52
  279. package/test-projects/nestjs-backend/.ai-dev/architecture.md +0 -49
  280. package/test-projects/nestjs-backend/.ai-dev/cache.json +0 -169
  281. package/test-projects/nestjs-backend/.ai-dev/context/features/src.json +0 -23
  282. package/test-projects/nestjs-backend/.ai-dev/context/flows/auth.controller.json +0 -14
  283. package/test-projects/nestjs-backend/.ai-dev/context/flows/auth.json +0 -10
  284. package/test-projects/nestjs-backend/.ai-dev/context/flows/users..json +0 -10
  285. package/test-projects/nestjs-backend/.ai-dev/context/flows/users.controller.json +0 -14
  286. package/test-projects/nestjs-backend/.ai-dev/context/flows/users.json +0 -10
  287. package/test-projects/nestjs-backend/.ai-dev/conventions.md +0 -52
  288. package/test-projects/nestjs-backend/.ai-dev/dependencies.json +0 -152
  289. package/test-projects/nestjs-backend/.ai-dev/entrypoints.md +0 -18
  290. package/test-projects/nestjs-backend/.ai-dev/files.json +0 -209
  291. package/test-projects/nestjs-backend/.ai-dev/graph/knowledge-graph.json +0 -132
  292. package/test-projects/nestjs-backend/.ai-dev/graph/module-graph.json +0 -29
  293. package/test-projects/nestjs-backend/.ai-dev/graph/symbol-graph.json +0 -304
  294. package/test-projects/nestjs-backend/.ai-dev/graph/symbol-references.json +0 -5
  295. package/test-projects/nestjs-backend/.ai-dev/index-state.json +0 -294
  296. package/test-projects/nestjs-backend/.ai-dev/modules.json +0 -19
  297. package/test-projects/nestjs-backend/.ai-dev/project.json +0 -18
  298. package/test-projects/nestjs-backend/.ai-dev/repo_map.json +0 -427
  299. package/test-projects/nestjs-backend/.ai-dev/repo_map.md +0 -104
  300. package/test-projects/nestjs-backend/.ai-dev/schema.json +0 -5
  301. package/test-projects/nestjs-backend/.ai-dev/summary.md +0 -13
  302. package/test-projects/nestjs-backend/.ai-dev/symbols.json +0 -1
  303. package/test-projects/nestjs-backend/.ai-dev/tech_stack.md +0 -38
  304. package/test-projects/nestjs-backend/.ai-dev/tools.json +0 -10
  305. package/test-projects/nestjs-backend/package.json +0 -22
  306. package/test-projects/nestjs-backend/src/app.module.ts +0 -8
  307. package/test-projects/nestjs-backend/src/auth/auth.controller.ts +0 -22
  308. package/test-projects/nestjs-backend/src/auth/auth.module.ts +0 -11
  309. package/test-projects/nestjs-backend/src/auth/auth.service.ts +0 -28
  310. package/test-projects/nestjs-backend/src/auth/dto/login.dto.ts +0 -4
  311. package/test-projects/nestjs-backend/src/auth/strategies/jwt.strategy.ts +0 -18
  312. package/test-projects/nestjs-backend/src/main.ts +0 -9
  313. package/test-projects/nestjs-backend/src/users/users.controller.ts +0 -32
  314. package/test-projects/nestjs-backend/src/users/users.module.ts +0 -10
  315. package/test-projects/nestjs-backend/src/users/users.service.ts +0 -42
  316. package/test-projects/nestjs-backend/tsconfig.json +0 -21
  317. package/test-projects/python-cli/.ai-dev/ai_context.md +0 -95
  318. package/test-projects/python-cli/.ai-dev/ai_rules.md +0 -47
  319. package/test-projects/python-cli/.ai-dev/architecture.md +0 -55
  320. package/test-projects/python-cli/.ai-dev/cache.json +0 -149
  321. package/test-projects/python-cli/.ai-dev/context/features/cli.json +0 -16
  322. package/test-projects/python-cli/.ai-dev/context/flows/list_.json +0 -9
  323. package/test-projects/python-cli/.ai-dev/context/flows/remove_.json +0 -9
  324. package/test-projects/python-cli/.ai-dev/conventions.md +0 -51
  325. package/test-projects/python-cli/.ai-dev/dependencies.json +0 -66
  326. package/test-projects/python-cli/.ai-dev/entrypoints.md +0 -4
  327. package/test-projects/python-cli/.ai-dev/files.json +0 -184
  328. package/test-projects/python-cli/.ai-dev/graph/knowledge-graph.json +0 -83
  329. package/test-projects/python-cli/.ai-dev/graph/module-graph.json +0 -31
  330. package/test-projects/python-cli/.ai-dev/graph/symbol-graph.json +0 -358
  331. package/test-projects/python-cli/.ai-dev/graph/symbol-references.json +0 -11
  332. package/test-projects/python-cli/.ai-dev/index-state.json +0 -259
  333. package/test-projects/python-cli/.ai-dev/modules.json +0 -21
  334. package/test-projects/python-cli/.ai-dev/project.json +0 -15
  335. package/test-projects/python-cli/.ai-dev/repo_map.json +0 -367
  336. package/test-projects/python-cli/.ai-dev/repo_map.md +0 -93
  337. package/test-projects/python-cli/.ai-dev/schema.json +0 -5
  338. package/test-projects/python-cli/.ai-dev/summary.md +0 -14
  339. package/test-projects/python-cli/.ai-dev/symbols.json +0 -1
  340. package/test-projects/python-cli/.ai-dev/tech_stack.md +0 -32
  341. package/test-projects/python-cli/.ai-dev/tools.json +0 -10
  342. package/test-projects/python-cli/__init__.py +0 -1
  343. package/test-projects/python-cli/cli/__init__.py +0 -1
  344. package/test-projects/python-cli/cli/add_command.py +0 -6
  345. package/test-projects/python-cli/cli/list_command.py +0 -7
  346. package/test-projects/python-cli/cli/remove_command.py +0 -6
  347. package/test-projects/python-cli/main.py +0 -34
  348. package/test-projects/python-cli/models/__init__.py +0 -2
  349. package/test-projects/python-cli/models/task.py +0 -19
  350. package/test-projects/python-cli/models/task_repository.py +0 -44
  351. package/test-projects/rails-app/.ai-dev/ai_context.md +0 -94
  352. package/test-projects/rails-app/.ai-dev/ai_rules.md +0 -47
  353. package/test-projects/rails-app/.ai-dev/architecture.md +0 -49
  354. package/test-projects/rails-app/.ai-dev/cache.json +0 -193
  355. package/test-projects/rails-app/.ai-dev/context/features/app.json +0 -24
  356. package/test-projects/rails-app/.ai-dev/context/features/config.json +0 -13
  357. package/test-projects/rails-app/.ai-dev/context/flows/application.json +0 -9
  358. package/test-projects/rails-app/.ai-dev/context/flows/application_.json +0 -9
  359. package/test-projects/rails-app/.ai-dev/context/flows/comments.json +0 -11
  360. package/test-projects/rails-app/.ai-dev/context/flows/comments_.json +0 -11
  361. package/test-projects/rails-app/.ai-dev/context/flows/posts.json +0 -11
  362. package/test-projects/rails-app/.ai-dev/context/flows/posts_.json +0 -11
  363. package/test-projects/rails-app/.ai-dev/context/flows/routes.json +0 -9
  364. package/test-projects/rails-app/.ai-dev/context/flows/users.json +0 -11
  365. package/test-projects/rails-app/.ai-dev/context/flows/users_.json +0 -11
  366. package/test-projects/rails-app/.ai-dev/conventions.md +0 -51
  367. package/test-projects/rails-app/.ai-dev/dependencies.json +0 -6
  368. package/test-projects/rails-app/.ai-dev/entrypoints.md +0 -4
  369. package/test-projects/rails-app/.ai-dev/files.json +0 -239
  370. package/test-projects/rails-app/.ai-dev/graph/knowledge-graph.json +0 -130
  371. package/test-projects/rails-app/.ai-dev/graph/module-graph.json +0 -27
  372. package/test-projects/rails-app/.ai-dev/graph/symbol-graph.json +0 -5
  373. package/test-projects/rails-app/.ai-dev/graph/symbol-references.json +0 -1
  374. package/test-projects/rails-app/.ai-dev/index-state.json +0 -336
  375. package/test-projects/rails-app/.ai-dev/modules.json +0 -26
  376. package/test-projects/rails-app/.ai-dev/project.json +0 -22
  377. package/test-projects/rails-app/.ai-dev/repo_map.json +0 -486
  378. package/test-projects/rails-app/.ai-dev/repo_map.md +0 -117
  379. package/test-projects/rails-app/.ai-dev/schema.json +0 -5
  380. package/test-projects/rails-app/.ai-dev/summary.md +0 -13
  381. package/test-projects/rails-app/.ai-dev/symbols.json +0 -1
  382. package/test-projects/rails-app/.ai-dev/tech_stack.md +0 -32
  383. package/test-projects/rails-app/.ai-dev/tools.json +0 -10
  384. package/test-projects/rails-app/Gemfile +0 -38
  385. package/test-projects/rails-app/README.md +0 -140
  386. package/test-projects/rails-app/Rakefile +0 -8
  387. package/test-projects/rails-app/app/controllers/api/comments_controller.rb +0 -75
  388. package/test-projects/rails-app/app/controllers/api/posts_controller.rb +0 -68
  389. package/test-projects/rails-app/app/controllers/api/users_controller.rb +0 -54
  390. package/test-projects/rails-app/app/controllers/application_controller.rb +0 -31
  391. package/test-projects/rails-app/app/models/comment.rb +0 -34
  392. package/test-projects/rails-app/app/models/post.rb +0 -36
  393. package/test-projects/rails-app/app/models/user.rb +0 -28
  394. package/test-projects/rails-app/app/services/post_service.rb +0 -92
  395. package/test-projects/rails-app/app/services/user_service.rb +0 -76
  396. package/test-projects/rails-app/config/application.rb +0 -27
  397. package/test-projects/rails-app/config/environment.rb +0 -7
  398. package/test-projects/rails-app/config/routes.rb +0 -15
  399. package/test-projects/react-app/.ai-dev/ai_context.md +0 -96
  400. package/test-projects/react-app/.ai-dev/architecture.md +0 -39
  401. package/test-projects/react-app/.ai-dev/cache.json +0 -153
  402. package/test-projects/react-app/.ai-dev/context/features/src.json +0 -18
  403. package/test-projects/react-app/.ai-dev/context/flows/UsersPage.json +0 -14
  404. package/test-projects/react-app/.ai-dev/context/flows/dashboard.json +0 -9
  405. package/test-projects/react-app/.ai-dev/context/flows/login.json +0 -9
  406. package/test-projects/react-app/.ai-dev/context/flows/users.json +0 -9
  407. package/test-projects/react-app/.ai-dev/dependencies.json +0 -128
  408. package/test-projects/react-app/.ai-dev/entrypoints.md +0 -4
  409. package/test-projects/react-app/.ai-dev/files.json +0 -189
  410. package/test-projects/react-app/.ai-dev/graph/knowledge-graph.json +0 -112
  411. package/test-projects/react-app/.ai-dev/graph/module-graph.json +0 -31
  412. package/test-projects/react-app/.ai-dev/graph/symbol-graph.json +0 -868
  413. package/test-projects/react-app/.ai-dev/graph/symbol-references.json +0 -31
  414. package/test-projects/react-app/.ai-dev/index-state.json +0 -266
  415. package/test-projects/react-app/.ai-dev/modules.json +0 -17
  416. package/test-projects/react-app/.ai-dev/project.json +0 -16
  417. package/test-projects/react-app/.ai-dev/repo_map.json +0 -391
  418. package/test-projects/react-app/.ai-dev/repo_map.md +0 -94
  419. package/test-projects/react-app/.ai-dev/schema.json +0 -5
  420. package/test-projects/react-app/.ai-dev/summary.md +0 -13
  421. package/test-projects/react-app/.ai-dev/symbols.json +0 -1
  422. package/test-projects/react-app/.ai-dev/tools.json +0 -10
  423. package/test-projects/react-app/package.json +0 -16
  424. package/test-projects/react-app/src/App.tsx +0 -21
  425. package/test-projects/react-app/src/context/AuthContext.tsx +0 -41
  426. package/test-projects/react-app/src/hooks/useAuth.ts +0 -10
  427. package/test-projects/react-app/src/main.tsx +0 -10
  428. package/test-projects/react-app/src/pages/DashboardPage.tsx +0 -17
  429. package/test-projects/react-app/src/pages/LoginPage.tsx +0 -41
  430. package/test-projects/react-app/src/pages/UsersPage.tsx +0 -36
  431. package/test-projects/react-app/src/services/userService.ts +0 -37
  432. package/test-projects/salesforce-cli/.ai-dev/ai_context.md +0 -89
  433. package/test-projects/salesforce-cli/.ai-dev/ai_rules.md +0 -47
  434. package/test-projects/salesforce-cli/.ai-dev/architecture.md +0 -39
  435. package/test-projects/salesforce-cli/.ai-dev/cache.json +0 -125
  436. package/test-projects/salesforce-cli/.ai-dev/context/features/force-app.json +0 -14
  437. package/test-projects/salesforce-cli/.ai-dev/context/flows/account.json +0 -9
  438. package/test-projects/salesforce-cli/.ai-dev/context/flows/opportunity.json +0 -9
  439. package/test-projects/salesforce-cli/.ai-dev/conventions.md +0 -51
  440. package/test-projects/salesforce-cli/.ai-dev/dependencies.json +0 -6
  441. package/test-projects/salesforce-cli/.ai-dev/entrypoints.md +0 -4
  442. package/test-projects/salesforce-cli/.ai-dev/files.json +0 -154
  443. package/test-projects/salesforce-cli/.ai-dev/graph/knowledge-graph.json +0 -64
  444. package/test-projects/salesforce-cli/.ai-dev/graph/module-graph.json +0 -13
  445. package/test-projects/salesforce-cli/.ai-dev/graph/symbol-graph.json +0 -148
  446. package/test-projects/salesforce-cli/.ai-dev/graph/symbol-references.json +0 -1
  447. package/test-projects/salesforce-cli/.ai-dev/index-state.json +0 -217
  448. package/test-projects/salesforce-cli/.ai-dev/modules.json +0 -12
  449. package/test-projects/salesforce-cli/.ai-dev/project.json +0 -14
  450. package/test-projects/salesforce-cli/.ai-dev/repo_map.json +0 -328
  451. package/test-projects/salesforce-cli/.ai-dev/repo_map.md +0 -80
  452. package/test-projects/salesforce-cli/.ai-dev/schema.json +0 -5
  453. package/test-projects/salesforce-cli/.ai-dev/summary.md +0 -13
  454. package/test-projects/salesforce-cli/.ai-dev/symbols.json +0 -1
  455. package/test-projects/salesforce-cli/.ai-dev/tech_stack.md +0 -31
  456. package/test-projects/salesforce-cli/.ai-dev/tools.json +0 -10
  457. package/test-projects/salesforce-cli/.forceignore +0 -27
  458. package/test-projects/salesforce-cli/force-app/main/default/classes/AccountController.cls +0 -24
  459. package/test-projects/salesforce-cli/force-app/main/default/classes/OpportunityController.cls +0 -25
  460. package/test-projects/salesforce-cli/force-app/main/default/objects/Project__c.object.xml +0 -45
  461. package/test-projects/salesforce-cli/force-app/main/default/triggers/AccountTrigger.trigger +0 -33
  462. package/test-projects/salesforce-cli/sfdx-project.json +0 -11
  463. package/test-projects/spring-boot-app/.ai-dev/ai_context.md +0 -91
  464. package/test-projects/spring-boot-app/.ai-dev/ai_rules.md +0 -48
  465. package/test-projects/spring-boot-app/.ai-dev/architecture.md +0 -39
  466. package/test-projects/spring-boot-app/.ai-dev/cache.json +0 -173
  467. package/test-projects/spring-boot-app/.ai-dev/context/features/src.json +0 -26
  468. package/test-projects/spring-boot-app/.ai-dev/context/flows/PostController.json +0 -19
  469. package/test-projects/spring-boot-app/.ai-dev/context/flows/UserController.json +0 -19
  470. package/test-projects/spring-boot-app/.ai-dev/context/flows/comment.json +0 -11
  471. package/test-projects/spring-boot-app/.ai-dev/context/flows/post.json +0 -14
  472. package/test-projects/spring-boot-app/.ai-dev/context/flows/user.json +0 -14
  473. package/test-projects/spring-boot-app/.ai-dev/conventions.md +0 -52
  474. package/test-projects/spring-boot-app/.ai-dev/dependencies.json +0 -326
  475. package/test-projects/spring-boot-app/.ai-dev/entrypoints.md +0 -4
  476. package/test-projects/spring-boot-app/.ai-dev/files.json +0 -214
  477. package/test-projects/spring-boot-app/.ai-dev/graph/knowledge-graph.json +0 -231
  478. package/test-projects/spring-boot-app/.ai-dev/graph/module-graph.json +0 -22
  479. package/test-projects/spring-boot-app/.ai-dev/graph/symbol-graph.json +0 -794
  480. package/test-projects/spring-boot-app/.ai-dev/graph/symbol-references.json +0 -70
  481. package/test-projects/spring-boot-app/.ai-dev/index-state.json +0 -301
  482. package/test-projects/spring-boot-app/.ai-dev/modules.json +0 -21
  483. package/test-projects/spring-boot-app/.ai-dev/project.json +0 -17
  484. package/test-projects/spring-boot-app/.ai-dev/repo_map.json +0 -461
  485. package/test-projects/spring-boot-app/.ai-dev/repo_map.md +0 -109
  486. package/test-projects/spring-boot-app/.ai-dev/schema.json +0 -5
  487. package/test-projects/spring-boot-app/.ai-dev/summary.md +0 -12
  488. package/test-projects/spring-boot-app/.ai-dev/symbols.json +0 -1
  489. package/test-projects/spring-boot-app/.ai-dev/tech_stack.md +0 -32
  490. package/test-projects/spring-boot-app/.ai-dev/tools.json +0 -10
  491. package/test-projects/spring-boot-app/.classpath +0 -57
  492. package/test-projects/spring-boot-app/.factorypath +0 -69
  493. package/test-projects/spring-boot-app/.project +0 -34
  494. package/test-projects/spring-boot-app/.settings/org.eclipse.core.resources.prefs +0 -4
  495. package/test-projects/spring-boot-app/.settings/org.eclipse.jdt.apt.core.prefs +0 -4
  496. package/test-projects/spring-boot-app/.settings/org.eclipse.jdt.core.prefs +0 -10
  497. package/test-projects/spring-boot-app/.settings/org.eclipse.m2e.core.prefs +0 -4
  498. package/test-projects/spring-boot-app/README.md +0 -122
  499. package/test-projects/spring-boot-app/pom.xml +0 -79
  500. package/test-projects/spring-boot-app/src/main/java/com/example/demo/DemoApplication.java +0 -12
  501. package/test-projects/spring-boot-app/src/main/java/com/example/demo/controllers/CommentController.java +0 -89
  502. package/test-projects/spring-boot-app/src/main/java/com/example/demo/controllers/PostController.java +0 -92
  503. package/test-projects/spring-boot-app/src/main/java/com/example/demo/controllers/UserController.java +0 -84
  504. package/test-projects/spring-boot-app/src/main/java/com/example/demo/models/Comment.java +0 -38
  505. package/test-projects/spring-boot-app/src/main/java/com/example/demo/models/Post.java +0 -56
  506. package/test-projects/spring-boot-app/src/main/java/com/example/demo/models/User.java +0 -44
  507. package/test-projects/spring-boot-app/src/main/java/com/example/demo/repositories/CommentRepository.java +0 -21
  508. package/test-projects/spring-boot-app/src/main/java/com/example/demo/repositories/PostRepository.java +0 -18
  509. package/test-projects/spring-boot-app/src/main/java/com/example/demo/repositories/UserRepository.java +0 -15
  510. package/test-projects/spring-boot-app/src/main/java/com/example/demo/services/PostService.java +0 -83
  511. package/test-projects/spring-boot-app/src/main/java/com/example/demo/services/UserService.java +0 -62
  512. package/test-projects/spring-boot-app/src/main/resources/application.properties +0 -22
  513. package/test-projects/spring-boot-app/target/classes/com/example/demo/DemoApplication.class +0 -0
  514. package/test-projects/spring-boot-app/target/classes/com/example/demo/controllers/CommentController$CommentCreateRequest.class +0 -0
  515. package/test-projects/spring-boot-app/target/classes/com/example/demo/controllers/CommentController$CommentUpdateRequest.class +0 -0
  516. package/test-projects/spring-boot-app/target/classes/com/example/demo/controllers/CommentController.class +0 -0
  517. package/test-projects/spring-boot-app/target/classes/com/example/demo/controllers/PostController$PostCreateRequest.class +0 -0
  518. package/test-projects/spring-boot-app/target/classes/com/example/demo/controllers/PostController$PostUpdateRequest.class +0 -0
  519. package/test-projects/spring-boot-app/target/classes/com/example/demo/controllers/PostController.class +0 -0
  520. package/test-projects/spring-boot-app/target/classes/com/example/demo/controllers/UserController$UserCreateRequest.class +0 -0
  521. package/test-projects/spring-boot-app/target/classes/com/example/demo/controllers/UserController$UserUpdateRequest.class +0 -0
  522. package/test-projects/spring-boot-app/target/classes/com/example/demo/controllers/UserController.class +0 -0
  523. package/test-projects/spring-boot-app/target/classes/com/example/demo/models/Comment.class +0 -0
  524. package/test-projects/spring-boot-app/target/classes/com/example/demo/models/Post.class +0 -0
  525. package/test-projects/spring-boot-app/target/classes/com/example/demo/models/User.class +0 -0
  526. package/test-projects/spring-boot-app/target/classes/com/example/demo/repositories/CommentRepository.class +0 -0
  527. package/test-projects/spring-boot-app/target/classes/com/example/demo/repositories/PostRepository.class +0 -0
  528. package/test-projects/spring-boot-app/target/classes/com/example/demo/repositories/UserRepository.class +0 -0
  529. package/test-projects/spring-boot-app/target/classes/com/example/demo/services/PostService.class +0 -0
  530. package/test-projects/spring-boot-app/target/classes/com/example/demo/services/UserService.class +0 -0
  531. package/tests/e2e/run-e2e.sh +0 -88
  532. /package/{test-projects/django-app/.ai-dev → ai-context}/tools.json +0 -0
@@ -0,0 +1,963 @@
1
+ import { describe, it, expect, beforeAll, afterAll } from "vitest";
2
+ import { extractSymbols } from "../src/analyzers/symbols";
3
+ import { FileInfo } from "../src/core/repoScanner";
4
+ import { detectAdapter } from "../src/core/adapters/index.js";
5
+ import fs from "fs";
6
+ import path from "path";
7
+ import os from "os";
8
+
9
+ const SALESFORCE_ENTERPRISE_PATH = path.join(process.cwd(), "test-projects/salesforce-enterprise");
10
+
11
+ describe("Salesforce LWC Detection", () => {
12
+ let tempDir: string;
13
+
14
+ beforeAll(() => {
15
+ tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "lwc-test-"));
16
+ });
17
+
18
+ afterAll(() => {
19
+ fs.rmSync(tempDir, { recursive: true, force: true });
20
+ });
21
+
22
+ const createFileInfo = (filePath: string, extension: string, content: string): FileInfo => {
23
+ const fullPath = path.join(tempDir, filePath);
24
+ fs.mkdirSync(path.dirname(fullPath), { recursive: true });
25
+ fs.writeFileSync(fullPath, content);
26
+
27
+ return {
28
+ path: fullPath,
29
+ relativePath: filePath,
30
+ extension,
31
+ name: filePath.split("/").pop()?.replace(`.${extension}`, "") || "",
32
+ };
33
+ };
34
+
35
+ // =========================================================================
36
+ // INTEGRATION TESTS - Using real Salesforce Enterprise test project
37
+ // =========================================================================
38
+
39
+ describe("Integration: Real Salesforce Enterprise Project", () => {
40
+ it("should detect Salesforce adapter from sfdx-project.json", () => {
41
+ const adapter = detectAdapter(SALESFORCE_ENTERPRISE_PATH);
42
+ expect(adapter.name).toBe("salesforce");
43
+ });
44
+
45
+ it("should detect LWC directory in the enterprise project", () => {
46
+ const lwcDir = path.join(SALESFORCE_ENTERPRISE_PATH, "force-app/main/default/lwc");
47
+ const exists = fs.existsSync(lwcDir);
48
+ expect(exists).toBe(true);
49
+
50
+ const components = fs.readdirSync(lwcDir);
51
+ expect(components).toContain("accountList");
52
+ expect(components).toContain("opportunityCard");
53
+ });
54
+
55
+ it("should have 2 LWC components in the enterprise project", () => {
56
+ const lwcDir = path.join(SALESFORCE_ENTERPRISE_PATH, "force-app/main/default/lwc");
57
+ const components = fs.readdirSync(lwcDir).filter(f => {
58
+ const componentDir = path.join(lwcDir, f);
59
+ return fs.statSync(componentDir).isDirectory();
60
+ });
61
+
62
+ expect(components).toHaveLength(2);
63
+ expect(components).toContain("accountList");
64
+ expect(components).toContain("opportunityCard");
65
+ });
66
+ });
67
+
68
+ // =========================================================================
69
+ // accountList LWC Component - All 4 Files
70
+ // =========================================================================
71
+
72
+ describe("accountList LWC Component", () => {
73
+ const accountListPath = path.join(SALESFORCE_ENTERPRISE_PATH, "force-app/main/default/lwc/accountList");
74
+
75
+ it("should have accountList.js file with LWC class", () => {
76
+ const jsPath = path.join(accountListPath, "accountList.js");
77
+ expect(fs.existsSync(jsPath)).toBe(true);
78
+
79
+ const content = fs.readFileSync(jsPath, "utf-8");
80
+ expect(content).toContain("import { LightningElement");
81
+ expect(content).toContain("export default class AccountList");
82
+ expect(content).toContain("extends LightningElement");
83
+ });
84
+
85
+ it("should have accountList.html file with template markup", () => {
86
+ const htmlPath = path.join(accountListPath, "accountList.html");
87
+ expect(fs.existsSync(htmlPath)).toBe(true);
88
+
89
+ const content = fs.readFileSync(htmlPath, "utf-8");
90
+ expect(content).toContain("<template>");
91
+ expect(content).toContain("<lightning-card");
92
+ expect(content).toContain("for:each={filteredAccounts}");
93
+ expect(content).toContain("onchange={handleSearchTermChange}");
94
+ });
95
+
96
+ it("should have accountList.css file with styling", () => {
97
+ const cssPath = path.join(accountListPath, "accountList.css");
98
+ expect(fs.existsSync(cssPath)).toBe(true);
99
+
100
+ const content = fs.readFileSync(cssPath, "utf-8");
101
+ expect(content).toContain(".slds-table");
102
+ expect(content).toContain(".slds-truncate");
103
+ expect(content).toContain(".account-link");
104
+ });
105
+
106
+ it("should have accountList.js-meta.xml file with exposed targets", () => {
107
+ const metaPath = path.join(accountListPath, "accountList.js-meta.xml");
108
+ expect(fs.existsSync(metaPath)).toBe(true);
109
+
110
+ const content = fs.readFileSync(metaPath, "utf-8");
111
+ expect(content).toContain("isExposed");
112
+ expect(content).toContain("lightning__RecordPage");
113
+ expect(content).toContain("lightning__AppPage");
114
+ expect(content).toContain("lightning__HomePage");
115
+ });
116
+ });
117
+
118
+ // =========================================================================
119
+ // opportunityCard LWC Component - All 4 Files
120
+ // =========================================================================
121
+
122
+ describe("opportunityCard LWC Component", () => {
123
+ const opportunityCardPath = path.join(SALESFORCE_ENTERPRISE_PATH, "force-app/main/default/lwc/opportunityCard");
124
+
125
+ it("should have opportunityCard.js file with LWC class", () => {
126
+ const jsPath = path.join(opportunityCardPath, "opportunityCard.js");
127
+ expect(fs.existsSync(jsPath)).toBe(true);
128
+
129
+ const content = fs.readFileSync(jsPath, "utf-8");
130
+ expect(content).toContain("import { LightningElement");
131
+ expect(content).toContain("export default class OpportunityCard");
132
+ expect(content).toContain("NavigationMixin(LightningElement)");
133
+ expect(content).toContain("NavigationMixin");
134
+ });
135
+
136
+ it("should have opportunityCard.html file with card markup", () => {
137
+ const htmlPath = path.join(opportunityCardPath, "opportunityCard.html");
138
+ expect(fs.existsSync(htmlPath)).toBe(true);
139
+
140
+ const content = fs.readFileSync(htmlPath, "utf-8");
141
+ expect(content).toContain("<template>");
142
+ expect(content).toContain("<lightning-card");
143
+ expect(content).toContain("if:true={");
144
+ expect(content).toContain("onclick={handleViewRecord}");
145
+ });
146
+
147
+ it("should have opportunityCard.css file with urgency styling", () => {
148
+ const cssPath = path.join(opportunityCardPath, "opportunityCard.css");
149
+ expect(fs.existsSync(cssPath)).toBe(true);
150
+
151
+ const content = fs.readFileSync(cssPath, "utf-8");
152
+ expect(content).toContain(".urgency-past");
153
+ expect(content).toContain(".urgency-critical");
154
+ expect(content).toContain(".urgency-warning");
155
+ expect(content).toContain(".urgency-normal");
156
+ });
157
+
158
+ it("should have opportunityCard.js-meta.xml file with exposed targets", () => {
159
+ const metaPath = path.join(opportunityCardPath, "opportunityCard.js-meta.xml");
160
+ expect(fs.existsSync(metaPath)).toBe(true);
161
+
162
+ const content = fs.readFileSync(metaPath, "utf-8");
163
+ expect(content).toContain("isExposed");
164
+ expect(content).toContain("lightning__RecordPage");
165
+ expect(content).toContain("lightning__AppPage");
166
+ });
167
+ });
168
+
169
+ // =========================================================================
170
+ // accountList JS - LWC Decorators and Features
171
+ // =========================================================================
172
+
173
+ describe("accountList.js - LWC Decorators and Features", () => {
174
+ it("should detect @track decorator for reactive properties", () => {
175
+ const content = fs.readFileSync(
176
+ path.join(SALESFORCE_ENTERPRISE_PATH, "force-app/main/default/lwc/accountList/accountList.js"),
177
+ "utf-8"
178
+ );
179
+
180
+ // @track decorator pattern
181
+ expect(content).toContain("@track");
182
+ expect(content).toMatch(/@track\s+accounts\s*=/);
183
+ expect(content).toMatch(/@track\s+filteredAccounts\s*=/);
184
+ expect(content).toMatch(/@track\s+searchTerm\s*=/);
185
+ expect(content).toMatch(/@track\s+industryFilter\s*=/);
186
+ expect(content).toMatch(/@track\s+isLoading\s*=/);
187
+ expect(content).toMatch(/@track\s+error\s*=/);
188
+ });
189
+
190
+ it("should detect @wire decorator for apex methods", () => {
191
+ const content = fs.readFileSync(
192
+ path.join(SALESFORCE_ENTERPRISE_PATH, "force-app/main/default/lwc/accountList/accountList.js"),
193
+ "utf-8"
194
+ );
195
+
196
+ expect(content).toContain("@wire");
197
+ expect(content).toContain("getAccounts");
198
+ expect(content).toContain("@salesforce/apex");
199
+ });
200
+
201
+ it("should detect LightningElement as base class", () => {
202
+ const content = fs.readFileSync(
203
+ path.join(SALESFORCE_ENTERPRISE_PATH, "force-app/main/default/lwc/accountList/accountList.js"),
204
+ "utf-8"
205
+ );
206
+
207
+ expect(content).toContain("extends LightningElement");
208
+ });
209
+
210
+ it("should detect getAccounts import from @salesforce/apex", () => {
211
+ const content = fs.readFileSync(
212
+ path.join(SALESFORCE_ENTERPRISE_PATH, "force-app/main/default/lwc/accountList/accountList.js"),
213
+ "utf-8"
214
+ );
215
+
216
+ expect(content).toContain("import getAccounts from '@salesforce/apex/AccountController.getAccounts'");
217
+ });
218
+
219
+ it("should detect ShowToastEvent import", () => {
220
+ const content = fs.readFileSync(
221
+ path.join(SALESFORCE_ENTERPRISE_PATH, "force-app/main/default/lwc/accountList/accountList.js"),
222
+ "utf-8"
223
+ );
224
+
225
+ expect(content).toContain("import { ShowToastEvent } from 'lightning/platformShowToastEvent'");
226
+ });
227
+
228
+ it("should detect getter for hasAccounts", () => {
229
+ const content = fs.readFileSync(
230
+ path.join(SALESFORCE_ENTERPRISE_PATH, "force-app/main/default/lwc/accountList/accountList.js"),
231
+ "utf-8"
232
+ );
233
+
234
+ expect(content).toContain("get hasAccounts");
235
+ expect(content).toMatch(/get\s+hasAccounts\s*\(\)\s*\{/);
236
+ });
237
+
238
+ it("should detect event handlers", () => {
239
+ const content = fs.readFileSync(
240
+ path.join(SALESFORCE_ENTERPRISE_PATH, "force-app/main/default/lwc/accountList/accountList.js"),
241
+ "utf-8"
242
+ );
243
+
244
+ expect(content).toContain("handleSearchTermChange");
245
+ expect(content).toContain("handleIndustryChange");
246
+ expect(content).toContain("handleRefresh");
247
+ expect(content).toContain("handleAccountClick");
248
+ });
249
+
250
+ it("should detect custom event dispatch", () => {
251
+ const content = fs.readFileSync(
252
+ path.join(SALESFORCE_ENTERPRISE_PATH, "force-app/main/default/lwc/accountList/accountList.js"),
253
+ "utf-8"
254
+ );
255
+
256
+ expect(content).toContain("dispatchEvent(new CustomEvent('accountselect'");
257
+ });
258
+
259
+ it("should extract symbols from accountList.js", () => {
260
+ const content = fs.readFileSync(
261
+ path.join(SALESFORCE_ENTERPRISE_PATH, "force-app/main/default/lwc/accountList/accountList.js"),
262
+ "utf-8"
263
+ );
264
+
265
+ const file = createFileInfo("force-app/main/default/lwc/accountList/accountList.js", "js", content);
266
+ const result = extractSymbols([file]);
267
+
268
+ // Should detect the class
269
+ const classSymbols = result.symbols.filter(s => s.type === "class");
270
+ const accountListClass = classSymbols.find(s => s.name === "AccountList");
271
+ expect(accountListClass).toBeDefined();
272
+ });
273
+ });
274
+
275
+ // =========================================================================
276
+ // opportunityCard JS - LWC Decorators and Features
277
+ // =========================================================================
278
+
279
+ describe("opportunityCard.js - LWC Decorators and Features", () => {
280
+ it("should detect @api decorator for public properties", () => {
281
+ const content = fs.readFileSync(
282
+ path.join(SALESFORCE_ENTERPRISE_PATH, "force-app/main/default/lwc/opportunityCard/opportunityCard.js"),
283
+ "utf-8"
284
+ );
285
+
286
+ expect(content).toContain("@api");
287
+ expect(content).toMatch(/@api\s+recordId/);
288
+ });
289
+
290
+ it("should detect @track decorator for reactive properties", () => {
291
+ const content = fs.readFileSync(
292
+ path.join(SALESFORCE_ENTERPRISE_PATH, "force-app/main/default/lwc/opportunityCard/opportunityCard.js"),
293
+ "utf-8"
294
+ );
295
+
296
+ expect(content).toContain("@track");
297
+ expect(content).toMatch(/@track\s+opportunity\s*=/);
298
+ expect(content).toMatch(/@track\s+isLoading\s*=/);
299
+ });
300
+
301
+ it("should detect @wire decorator for uiRecordApi", () => {
302
+ const content = fs.readFileSync(
303
+ path.join(SALESFORCE_ENTERPRISE_PATH, "force-app/main/default/lwc/opportunityCard/opportunityCard.js"),
304
+ "utf-8"
305
+ );
306
+
307
+ expect(content).toContain("@wire");
308
+ expect(content).toContain("getRecord");
309
+ expect(content).toContain("lightning/uiRecordApi");
310
+ });
311
+
312
+ it("should detect NavigationMixin import", () => {
313
+ const content = fs.readFileSync(
314
+ path.join(SALESFORCE_ENTERPRISE_PATH, "force-app/main/default/lwc/opportunityCard/opportunityCard.js"),
315
+ "utf-8"
316
+ );
317
+
318
+ expect(content).toContain("import { NavigationMixin } from 'lightning/navigation'");
319
+ expect(content).toContain("extends NavigationMixin(LightningElement)");
320
+ });
321
+
322
+ it("should detect lightning/uiRecordApi imports", () => {
323
+ const content = fs.readFileSync(
324
+ path.join(SALESFORCE_ENTERPRISE_PATH, "force-app/main/default/lwc/opportunityCard/opportunityCard.js"),
325
+ "utf-8"
326
+ );
327
+
328
+ expect(content).toContain("import { getRecord, getFieldValue } from 'lightning/uiRecordApi'");
329
+ });
330
+
331
+ it("should detect @salesforce/schema imports", () => {
332
+ const content = fs.readFileSync(
333
+ path.join(SALESFORCE_ENTERPRISE_PATH, "force-app/main/default/lwc/opportunityCard/opportunityCard.js"),
334
+ "utf-8"
335
+ );
336
+
337
+ expect(content).toContain("@salesforce/schema/Opportunity.Name");
338
+ expect(content).toContain("@salesforce/schema/Opportunity.StageName");
339
+ expect(content).toContain("@salesforce/schema/Opportunity.Amount");
340
+ expect(content).toContain("@salesforce/schema/Opportunity.CloseDate");
341
+ expect(content).toContain("@salesforce/schema/Opportunity.Account.Name");
342
+ });
343
+
344
+ it("should detect getter methods for computed properties", () => {
345
+ const content = fs.readFileSync(
346
+ path.join(SALESFORCE_ENTERPRISE_PATH, "force-app/main/default/lwc/opportunityCard/opportunityCard.js"),
347
+ "utf-8"
348
+ );
349
+
350
+ expect(content).toContain("get name");
351
+ expect(content).toContain("get stage");
352
+ expect(content).toContain("get amount");
353
+ expect(content).toContain("get closeDate");
354
+ expect(content).toContain("get accountName");
355
+ expect(content).toContain("get stageColor");
356
+ expect(content).toContain("get formattedAmount");
357
+ expect(content).toContain("get formattedCloseDate");
358
+ expect(content).toContain("get daysUntilClose");
359
+ expect(content).toContain("get urgencyClass");
360
+ });
361
+
362
+ it("should detect NavigationMixin.Navigate usage", () => {
363
+ const content = fs.readFileSync(
364
+ path.join(SALESFORCE_ENTERPRISE_PATH, "force-app/main/default/lwc/opportunityCard/opportunityCard.js"),
365
+ "utf-8"
366
+ );
367
+
368
+ expect(content).toContain("NavigationMixin.Navigate");
369
+ expect(content).toContain("handleViewRecord");
370
+ expect(content).toContain("handleEditRecord");
371
+ });
372
+
373
+ it("should extract symbols from opportunityCard.js", () => {
374
+ const content = fs.readFileSync(
375
+ path.join(SALESFORCE_ENTERPRISE_PATH, "force-app/main/default/lwc/opportunityCard/opportunityCard.js"),
376
+ "utf-8"
377
+ );
378
+
379
+ const file = createFileInfo("force-app/main/default/lwc/opportunityCard/opportunityCard.js", "js", content);
380
+ const result = extractSymbols([file]);
381
+
382
+ // Should detect the class
383
+ const classSymbols = result.symbols.filter(s => s.type === "class");
384
+ const opportunityCardClass = classSymbols.find(s => s.name === "OpportunityCard");
385
+ expect(opportunityCardClass).toBeDefined();
386
+ });
387
+ });
388
+
389
+ // =========================================================================
390
+ // LWC HTML Template Tests
391
+ // =========================================================================
392
+
393
+ describe("LWC HTML Templates", () => {
394
+ describe("accountList.html", () => {
395
+ it("should have proper template tag", () => {
396
+ const content = fs.readFileSync(
397
+ path.join(SALESFORCE_ENTERPRISE_PATH, "force-app/main/default/lwc/accountList/accountList.html"),
398
+ "utf-8"
399
+ );
400
+
401
+ expect(content).toContain("<template>");
402
+ expect(content).toContain("</template>");
403
+ });
404
+
405
+ it("should use lightning-base components", () => {
406
+ const content = fs.readFileSync(
407
+ path.join(SALESFORCE_ENTERPRISE_PATH, "force-app/main/default/lwc/accountList/accountList.html"),
408
+ "utf-8"
409
+ );
410
+
411
+ expect(content).toContain("<lightning-card");
412
+ expect(content).toContain("<lightning-input");
413
+ expect(content).toContain("<lightning-combobox");
414
+ expect(content).toContain("<lightning-button");
415
+ expect(content).toContain("<lightning-spinner");
416
+ expect(content).toContain("<lightning-layout");
417
+ expect(content).toContain("<lightning-formatted-number");
418
+ });
419
+
420
+ it("should have for:each iteration", () => {
421
+ const content = fs.readFileSync(
422
+ path.join(SALESFORCE_ENTERPRISE_PATH, "force-app/main/default/lwc/accountList/accountList.html"),
423
+ "utf-8"
424
+ );
425
+
426
+ expect(content).toContain("for:each={filteredAccounts}");
427
+ expect(content).toContain("for:item=");
428
+ });
429
+
430
+ it("should have conditional rendering with if:true/if:false", () => {
431
+ const content = fs.readFileSync(
432
+ path.join(SALESFORCE_ENTERPRISE_PATH, "force-app/main/default/lwc/accountList/accountList.html"),
433
+ "utf-8"
434
+ );
435
+
436
+ expect(content).toContain("if:true={isLoading}");
437
+ expect(content).toContain("if:true={hasAccounts}");
438
+ expect(content).toContain("if:false={hasAccounts}");
439
+ });
440
+
441
+ it("should have slot elements", () => {
442
+ const content = fs.readFileSync(
443
+ path.join(SALESFORCE_ENTERPRISE_PATH, "force-app/main/default/lwc/accountList/accountList.html"),
444
+ "utf-8"
445
+ );
446
+
447
+ expect(content).toContain("slot=");
448
+ });
449
+
450
+ it("should reference JS methods as event handlers", () => {
451
+ const content = fs.readFileSync(
452
+ path.join(SALESFORCE_ENTERPRISE_PATH, "force-app/main/default/lwc/accountList/accountList.html"),
453
+ "utf-8"
454
+ );
455
+
456
+ expect(content).toContain("onchange={handleSearchTermChange}");
457
+ expect(content).toContain("onchange={handleIndustryChange}");
458
+ expect(content).toContain("onclick={handleRefresh}");
459
+ expect(content).toContain("onclick={handleAccountClick}");
460
+ });
461
+ });
462
+
463
+ describe("opportunityCard.html", () => {
464
+ it("should have proper template tag", () => {
465
+ const content = fs.readFileSync(
466
+ path.join(SALESFORCE_ENTERPRISE_PATH, "force-app/main/default/lwc/opportunityCard/opportunityCard.html"),
467
+ "utf-8"
468
+ );
469
+
470
+ expect(content).toContain("<template>");
471
+ expect(content).toContain("</template>");
472
+ });
473
+
474
+ it("should use lightning-base components", () => {
475
+ const content = fs.readFileSync(
476
+ path.join(SALESFORCE_ENTERPRISE_PATH, "force-app/main/default/lwc/opportunityCard/opportunityCard.html"),
477
+ "utf-8"
478
+ );
479
+
480
+ expect(content).toContain("<lightning-card");
481
+ expect(content).toContain("<lightning-button");
482
+ expect(content).toContain("<lightning-button-group");
483
+ expect(content).toContain("<lightning-icon");
484
+ });
485
+
486
+ it("should have conditional rendering", () => {
487
+ const content = fs.readFileSync(
488
+ path.join(SALESFORCE_ENTERPRISE_PATH, "force-app/main/default/lwc/opportunityCard/opportunityCard.html"),
489
+ "utf-8"
490
+ );
491
+
492
+ expect(content).toContain("if:true={");
493
+ expect(content).toContain("if:true={daysUntilClose}");
494
+ });
495
+
496
+ it("should reference computed getters", () => {
497
+ const content = fs.readFileSync(
498
+ path.join(SALESFORCE_ENTERPRISE_PATH, "force-app/main/default/lwc/opportunityCard/opportunityCard.html"),
499
+ "utf-8"
500
+ );
501
+
502
+ expect(content).toContain("{name}");
503
+ expect(content).toContain("{stage}");
504
+ expect(content).toContain("{formattedAmount}");
505
+ expect(content).toContain("{formattedCloseDate}");
506
+ expect(content).toContain("{urgencyClass}");
507
+ expect(content).toContain("{stageColor}");
508
+ expect(content).toContain("{daysUntilClose}");
509
+ });
510
+
511
+ it("should reference JS methods as event handlers", () => {
512
+ const content = fs.readFileSync(
513
+ path.join(SALESFORCE_ENTERPRISE_PATH, "force-app/main/default/lwc/opportunityCard/opportunityCard.html"),
514
+ "utf-8"
515
+ );
516
+
517
+ expect(content).toContain("onclick={handleViewRecord}");
518
+ expect(content).toContain("onclick={handleEditRecord}");
519
+ });
520
+ });
521
+ });
522
+
523
+ // =========================================================================
524
+ // LWC CSS Tests
525
+ // =========================================================================
526
+
527
+ describe("LWC CSS", () => {
528
+ describe("accountList.css", () => {
529
+ it("should have CSS class selectors", () => {
530
+ const content = fs.readFileSync(
531
+ path.join(SALESFORCE_ENTERPRISE_PATH, "force-app/main/default/lwc/accountList/accountList.css"),
532
+ "utf-8"
533
+ );
534
+
535
+ expect(content).toContain(".slds-table");
536
+ expect(content).toContain(".slds-card");
537
+ expect(content).toContain(".account-link");
538
+ });
539
+
540
+ it("should have SLDS design tokens", () => {
541
+ const content = fs.readFileSync(
542
+ path.join(SALESFORCE_ENTERPRISE_PATH, "force-app/main/default/lwc/accountList/accountList.css"),
543
+ "utf-8"
544
+ );
545
+
546
+ // SLDS color tokens
547
+ expect(content).toMatch(/rgb\(\d+,\s*\d+,\s*\d+\)/);
548
+ expect(content).toContain("background-color");
549
+ expect(content).toContain("border");
550
+ expect(content).toContain("padding");
551
+ });
552
+
553
+ it("should define hover states", () => {
554
+ const content = fs.readFileSync(
555
+ path.join(SALESFORCE_ENTERPRISE_PATH, "force-app/main/default/lwc/accountList/accountList.css"),
556
+ "utf-8"
557
+ );
558
+
559
+ expect(content).toContain(":hover");
560
+ expect(content).toContain(".account-link:hover");
561
+ });
562
+ });
563
+
564
+ describe("opportunityCard.css", () => {
565
+ it("should have CSS class selectors", () => {
566
+ const content = fs.readFileSync(
567
+ path.join(SALESFORCE_ENTERPRISE_PATH, "force-app/main/default/lwc/opportunityCard/opportunityCard.css"),
568
+ "utf-8"
569
+ );
570
+
571
+ expect(content).toContain(".opportunity-card");
572
+ expect(content).toContain(".opportunity-name");
573
+ expect(content).toContain(".info-label");
574
+ expect(content).toContain(".info-value");
575
+ });
576
+
577
+ it("should have urgency color classes", () => {
578
+ const content = fs.readFileSync(
579
+ path.join(SALESFORCE_ENTERPRISE_PATH, "force-app/main/default/lwc/opportunityCard/opportunityCard.css"),
580
+ "utf-8"
581
+ );
582
+
583
+ expect(content).toContain(".urgency-past");
584
+ expect(content).toContain(".urgency-critical");
585
+ expect(content).toContain(".urgency-warning");
586
+ expect(content).toContain(".urgency-normal");
587
+ });
588
+
589
+ it("should have SLDS theme classes", () => {
590
+ const content = fs.readFileSync(
591
+ path.join(SALESFORCE_ENTERPRISE_PATH, "force-app/main/default/lwc/opportunityCard/opportunityCard.css"),
592
+ "utf-8"
593
+ );
594
+
595
+ expect(content).toContain(".slds-theme_warning");
596
+ expect(content).toContain(".slds-theme_info");
597
+ expect(content).toContain(".slds-theme_success");
598
+ expect(content).toContain(".slds-theme_error");
599
+ });
600
+
601
+ it("should have urgency styling classes", () => {
602
+ const content = fs.readFileSync(
603
+ path.join(SALESFORCE_ENTERPRISE_PATH, "force-app/main/default/lwc/opportunityCard/opportunityCard.css"),
604
+ "utf-8"
605
+ );
606
+
607
+ expect(content).toContain(".urgency-past");
608
+ expect(content).toContain(".urgency-critical");
609
+ expect(content).toContain(".urgency-warning");
610
+ expect(content).toContain(".urgency-normal");
611
+ });
612
+ });
613
+ });
614
+
615
+ // =========================================================================
616
+ // LWC Metadata Tests
617
+ // =========================================================================
618
+
619
+ describe("LWC Metadata (js-meta.xml)", () => {
620
+ describe("accountList.js-meta.xml", () => {
621
+ it("should be valid JSON or XML metadata", () => {
622
+ const content = fs.readFileSync(
623
+ path.join(SALESFORCE_ENTERPRISE_PATH, "force-app/main/default/lwc/accountList/accountList.js-meta.xml"),
624
+ "utf-8"
625
+ );
626
+
627
+ // Should contain key metadata fields
628
+ expect(content).toContain("apiVersion");
629
+ expect(content).toContain("isExposed");
630
+ expect(content).toContain("masterLabel");
631
+ expect(content).toContain("targets");
632
+ });
633
+
634
+ it("should expose targets for Lightning Experience", () => {
635
+ const content = fs.readFileSync(
636
+ path.join(SALESFORCE_ENTERPRISE_PATH, "force-app/main/default/lwc/accountList/accountList.js-meta.xml"),
637
+ "utf-8"
638
+ );
639
+
640
+ expect(content).toContain("lightning__RecordPage");
641
+ expect(content).toContain("lightning__AppPage");
642
+ expect(content).toContain("lightning__HomePage");
643
+ });
644
+
645
+ it("should define properties for component configuration", () => {
646
+ const content = fs.readFileSync(
647
+ path.join(SALESFORCE_ENTERPRISE_PATH, "force-app/main/default/lwc/accountList/accountList.js-meta.xml"),
648
+ "utf-8"
649
+ );
650
+
651
+ expect(content).toContain("properties");
652
+ expect(content).toContain("searchTerm");
653
+ expect(content).toContain("industryFilter");
654
+ });
655
+
656
+ it("should have correct API version", () => {
657
+ const content = fs.readFileSync(
658
+ path.join(SALESFORCE_ENTERPRISE_PATH, "force-app/main/default/lwc/accountList/accountList.js-meta.xml"),
659
+ "utf-8"
660
+ );
661
+
662
+ expect(content).toContain("59.0");
663
+ });
664
+ });
665
+
666
+ describe("opportunityCard.js-meta.xml", () => {
667
+ it("should be valid JSON or XML metadata", () => {
668
+ const content = fs.readFileSync(
669
+ path.join(SALESFORCE_ENTERPRISE_PATH, "force-app/main/default/lwc/opportunityCard/opportunityCard.js-meta.xml"),
670
+ "utf-8"
671
+ );
672
+
673
+ expect(content).toContain("apiVersion");
674
+ expect(content).toContain("isExposed");
675
+ expect(content).toContain("masterLabel");
676
+ expect(content).toContain("targets");
677
+ });
678
+
679
+ it("should expose targets for Lightning Experience", () => {
680
+ const content = fs.readFileSync(
681
+ path.join(SALESFORCE_ENTERPRISE_PATH, "force-app/main/default/lwc/opportunityCard/opportunityCard.js-meta.xml"),
682
+ "utf-8"
683
+ );
684
+
685
+ expect(content).toContain("lightning__RecordPage");
686
+ expect(content).toContain("lightning__AppPage");
687
+ });
688
+
689
+ it("should define properties for component configuration", () => {
690
+ const content = fs.readFileSync(
691
+ path.join(SALESFORCE_ENTERPRISE_PATH, "force-app/main/default/lwc/opportunityCard/opportunityCard.js-meta.xml"),
692
+ "utf-8"
693
+ );
694
+
695
+ expect(content).toContain("properties");
696
+ expect(content).toContain("recordId");
697
+ });
698
+
699
+ it("should have correct API version", () => {
700
+ const content = fs.readFileSync(
701
+ path.join(SALESFORCE_ENTERPRISE_PATH, "force-app/main/default/lwc/opportunityCard/opportunityCard.js-meta.xml"),
702
+ "utf-8"
703
+ );
704
+
705
+ expect(content).toContain("59.0");
706
+ });
707
+ });
708
+ });
709
+
710
+ // =========================================================================
711
+ // LWC Component Detection Tests
712
+ // =========================================================================
713
+
714
+ describe("LWC Component Detection", () => {
715
+ it("should detect LWC JavaScript files as entrypoints", () => {
716
+ const accountListJs = path.join(SALESFORCE_ENTERPRISE_PATH, "force-app/main/default/lwc/accountList/accountList.js");
717
+ const opportunityCardJs = path.join(SALESFORCE_ENTERPRISE_PATH, "force-app/main/default/lwc/opportunityCard/opportunityCard.js");
718
+
719
+ expect(fs.existsSync(accountListJs)).toBe(true);
720
+ expect(fs.existsSync(opportunityCardJs)).toBe(true);
721
+ });
722
+
723
+ it("should detect LWC HTML templates", () => {
724
+ const accountListHtml = path.join(SALESFORCE_ENTERPRISE_PATH, "force-app/main/default/lwc/accountList/accountList.html");
725
+ const opportunityCardHtml = path.join(SALESFORCE_ENTERPRISE_PATH, "force-app/main/default/lwc/opportunityCard/opportunityCard.html");
726
+
727
+ expect(fs.existsSync(accountListHtml)).toBe(true);
728
+ expect(fs.existsSync(opportunityCardHtml)).toBe(true);
729
+ });
730
+
731
+ it("should detect LWC CSS files", () => {
732
+ const accountListCss = path.join(SALESFORCE_ENTERPRISE_PATH, "force-app/main/default/lwc/accountList/accountList.css");
733
+ const opportunityCardCss = path.join(SALESFORCE_ENTERPRISE_PATH, "force-app/main/default/lwc/opportunityCard/opportunityCard.css");
734
+
735
+ expect(fs.existsSync(accountListCss)).toBe(true);
736
+ expect(fs.existsSync(opportunityCardCss)).toBe(true);
737
+ });
738
+
739
+ it("should detect LWC metadata files", () => {
740
+ const accountListMeta = path.join(SALESFORCE_ENTERPRISE_PATH, "force-app/main/default/lwc/accountList/accountList.js-meta.xml");
741
+ const opportunityCardMeta = path.join(SALESFORCE_ENTERPRISE_PATH, "force-app/main/default/lwc/opportunityCard/opportunityCard.js-meta.xml");
742
+
743
+ expect(fs.existsSync(accountListMeta)).toBe(true);
744
+ expect(fs.existsSync(opportunityCardMeta)).toBe(true);
745
+ });
746
+
747
+ it("should verify all 4 files exist for each LWC component", () => {
748
+ const components = ["accountList", "opportunityCard"];
749
+
750
+ for (const component of components) {
751
+ const basePath = path.join(SALESFORCE_ENTERPRISE_PATH, "force-app/main/default/lwc", component);
752
+ expect(fs.existsSync(path.join(basePath, `${component}.js`))).toBe(true);
753
+ expect(fs.existsSync(path.join(basePath, `${component}.html`))).toBe(true);
754
+ expect(fs.existsSync(path.join(basePath, `${component}.css`))).toBe(true);
755
+ expect(fs.existsSync(path.join(basePath, `${component}.js-meta.xml`))).toBe(true);
756
+ }
757
+ });
758
+
759
+ it("should detect LightningElement imports from lwc", () => {
760
+ const accountListContent = fs.readFileSync(
761
+ path.join(SALESFORCE_ENTERPRISE_PATH, "force-app/main/default/lwc/accountList/accountList.js"),
762
+ "utf-8"
763
+ );
764
+ const opportunityCardContent = fs.readFileSync(
765
+ path.join(SALESFORCE_ENTERPRISE_PATH, "force-app/main/default/lwc/opportunityCard/opportunityCard.js"),
766
+ "utf-8"
767
+ );
768
+
769
+ expect(accountListContent).toContain("from 'lwc'");
770
+ expect(opportunityCardContent).toContain("from 'lwc'");
771
+ });
772
+ });
773
+
774
+ // =========================================================================
775
+ // UNIT TESTS - LWC Patterns
776
+ // =========================================================================
777
+
778
+ describe("Unit: LWC JavaScript patterns", () => {
779
+ it("should parse LWC class declaration", () => {
780
+ const content = `import { LightningElement } from 'lwc';
781
+ export default class MyComponent extends LightningElement {}`;
782
+
783
+ const file = createFileInfo("test.js", "js", content);
784
+ const result = extractSymbols([file]);
785
+
786
+ const classSymbol = result.symbols.find(s => s.name === "MyComponent");
787
+ expect(classSymbol).toBeDefined();
788
+ expect(classSymbol?.type).toBe("class");
789
+ });
790
+
791
+ it("should detect @api decorator pattern", () => {
792
+ const content = `import { LightningElement, api } from 'lwc';
793
+ export default class TestComponent extends LightningElement {
794
+ @api recordId;
795
+ }`;
796
+
797
+ const file = createFileInfo("test.js", "js", content);
798
+ const result = extractSymbols([file]);
799
+
800
+ // Class should be detected
801
+ const classSymbol = result.symbols.find(s => s.name === "TestComponent");
802
+ expect(classSymbol).toBeDefined();
803
+ expect(content).toContain("@api");
804
+ });
805
+
806
+ it("should detect @track decorator pattern", () => {
807
+ const content = `import { LightningElement, track } from 'lwc';
808
+ export default class TestComponent extends LightningElement {
809
+ @track items = [];
810
+ }`;
811
+
812
+ const file = createFileInfo("test.js", "js", content);
813
+ const result = extractSymbols([file]);
814
+
815
+ const classSymbol = result.symbols.find(s => s.name === "TestComponent");
816
+ expect(classSymbol).toBeDefined();
817
+ expect(content).toContain("@track");
818
+ });
819
+
820
+ it("should detect @wire decorator pattern", () => {
821
+ const content = `import { LightningElement, wire } from 'lwc';
822
+ import getRecords from '@salesforce/apex/MyController.getRecords';
823
+ export default class TestComponent extends LightningElement {
824
+ @wire(getRecords, { object: 'Account' })
825
+ wiredRecords;
826
+ }`;
827
+
828
+ const file = createFileInfo("test.js", "js", content);
829
+ const result = extractSymbols([file]);
830
+
831
+ const classSymbol = result.symbols.find(s => s.name === "TestComponent");
832
+ expect(classSymbol).toBeDefined();
833
+ expect(content).toContain("@wire");
834
+ });
835
+
836
+ it("should detect getter methods", () => {
837
+ const content = `import { LightningElement } from 'lwc';
838
+ export default class TestComponent extends LightningElement {
839
+ get items() { return this._items; }
840
+ }`;
841
+
842
+ const file = createFileInfo("test.js", "js", content);
843
+ const result = extractSymbols([file]);
844
+
845
+ const classSymbol = result.symbols.find(s => s.name === "TestComponent");
846
+ expect(classSymbol).toBeDefined();
847
+ expect(content).toContain("get items");
848
+ });
849
+
850
+ it("should detect NavigationMixin pattern", () => {
851
+ const content = `import { LightningElement } from 'lwc';
852
+ import { NavigationMixin } from 'lightning/navigation';
853
+ export default class TestComponent extends NavigationMixin(LightningElement) {}`;
854
+
855
+ const file = createFileInfo("test.js", "js", content);
856
+ const result = extractSymbols([file]);
857
+
858
+ expect(content).toContain("NavigationMixin");
859
+ expect(content).toContain("NavigationMixin(LightningElement)");
860
+ });
861
+ });
862
+
863
+ // =========================================================================
864
+ // Symbol Extraction Accuracy
865
+ // =========================================================================
866
+
867
+ describe("Symbol Extraction Accuracy for LWC", () => {
868
+ it("should extract class symbol from accountList.js", () => {
869
+ const content = fs.readFileSync(
870
+ path.join(SALESFORCE_ENTERPRISE_PATH, "force-app/main/default/lwc/accountList/accountList.js"),
871
+ "utf-8"
872
+ );
873
+
874
+ const file = createFileInfo("force-app/main/default/lwc/accountList/accountList.js", "js", content);
875
+ const result = extractSymbols([file]);
876
+
877
+ const classSymbol = result.symbols.find(s => s.type === "class" && s.name === "AccountList");
878
+ expect(classSymbol).toBeDefined();
879
+ expect(classSymbol?.file).toBe("force-app/main/default/lwc/accountList/accountList.js");
880
+ });
881
+
882
+ it("should extract class symbol from opportunityCard.js", () => {
883
+ const content = fs.readFileSync(
884
+ path.join(SALESFORCE_ENTERPRISE_PATH, "force-app/main/default/lwc/opportunityCard/opportunityCard.js"),
885
+ "utf-8"
886
+ );
887
+
888
+ const file = createFileInfo("force-app/main/default/lwc/opportunityCard/opportunityCard.js", "js", content);
889
+ const result = extractSymbols([file]);
890
+
891
+ const classSymbol = result.symbols.find(s => s.type === "class" && s.name === "OpportunityCard");
892
+ expect(classSymbol).toBeDefined();
893
+ expect(classSymbol?.file).toBe("force-app/main/default/lwc/opportunityCard/opportunityCard.js");
894
+ });
895
+
896
+ it("should detect exported LWC classes", () => {
897
+ const accountListContent = fs.readFileSync(
898
+ path.join(SALESFORCE_ENTERPRISE_PATH, "force-app/main/default/lwc/accountList/accountList.js"),
899
+ "utf-8"
900
+ );
901
+
902
+ const file = createFileInfo("force-app/main/default/lwc/accountList/accountList.js", "js", accountListContent);
903
+ const result = extractSymbols([file]);
904
+
905
+ // Find AccountList class - it should be exported
906
+ const accountListClass = result.symbols.find(s => s.name === "AccountList");
907
+ expect(accountListClass).toBeDefined();
908
+ expect(accountListClass?.export).toBe(true);
909
+ });
910
+ });
911
+
912
+ // =========================================================================
913
+ // Entrypoint Detection for LWC
914
+ // =========================================================================
915
+
916
+ describe("Entrypoint Detection for LWC Components", () => {
917
+ it("should identify LWC components as entrypoints", () => {
918
+ const accountListContent = fs.readFileSync(
919
+ path.join(SALESFORCE_ENTERPRISE_PATH, "force-app/main/default/lwc/accountList/accountList.js"),
920
+ "utf-8"
921
+ );
922
+
923
+ const opportunityCardContent = fs.readFileSync(
924
+ path.join(SALESFORCE_ENTERPRISE_PATH, "force-app/main/default/lwc/opportunityCard/opportunityCard.js"),
925
+ "utf-8"
926
+ );
927
+
928
+ // LWC components are always entrypoints - they extend LightningElement
929
+ expect(accountListContent).toContain("extends LightningElement");
930
+ expect(opportunityCardContent).toContain("LightningElement");
931
+
932
+ // LWC components use decorators
933
+ expect(accountListContent).toMatch(/@(?:api|track|wire)/);
934
+ expect(opportunityCardContent).toMatch(/@(?:api|track|wire)/);
935
+ });
936
+
937
+ it("should identify LWC as frontend component type", () => {
938
+ const accountListContent = fs.readFileSync(
939
+ path.join(SALESFORCE_ENTERPRISE_PATH, "force-app/main/default/lwc/accountList/accountList.js"),
940
+ "utf-8"
941
+ );
942
+
943
+ // LWC components have specific patterns
944
+ expect(accountListContent).toContain("LightningElement");
945
+ expect(accountListContent).toContain("from 'lwc'");
946
+ });
947
+
948
+ it("should verify LWC metadata marks components as exposed", () => {
949
+ const accountListMeta = fs.readFileSync(
950
+ path.join(SALESFORCE_ENTERPRISE_PATH, "force-app/main/default/lwc/accountList/accountList.js-meta.xml"),
951
+ "utf-8"
952
+ );
953
+
954
+ const opportunityCardMeta = fs.readFileSync(
955
+ path.join(SALESFORCE_ENTERPRISE_PATH, "force-app/main/default/lwc/opportunityCard/opportunityCard.js-meta.xml"),
956
+ "utf-8"
957
+ );
958
+
959
+ expect(accountListMeta).toContain("isExposed");
960
+ expect(opportunityCardMeta).toContain("isExposed");
961
+ });
962
+ });
963
+ });