ai-first-cli 1.3.1 → 1.3.6

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 (514) hide show
  1. package/.ai-dev/index.db +0 -0
  2. package/CHANGELOG.md +241 -0
  3. package/PHASE1_USER_SIMULATION.md +56 -0
  4. package/PHASE2_USER_SIMULATION.md +81 -0
  5. package/PHASE3_USER_SIMULATION.md +176 -0
  6. package/README.es.md +73 -0
  7. package/README.md +119 -15
  8. package/ai/graph/knowledge-graph.json +10 -0
  9. package/ai-context/ai_context.md +130 -0
  10. package/{test-projects/react-app/.ai-dev → ai-context}/ai_rules.md +10 -5
  11. package/ai-context/architecture.md +136 -0
  12. package/ai-context/context/features/src.json +69 -0
  13. package/ai-context/context/features/test-projects.json +69 -0
  14. package/ai-context/context/flows/ai-first.json +9 -0
  15. package/ai-context/context/flows/auth.json +13 -0
  16. package/ai-context/context/flows/doctor.json +9 -0
  17. package/ai-context/context/flows/explore.json +9 -0
  18. package/ai-context/context/flows/routes.json +15 -0
  19. package/ai-context/context/flows/user.json +23 -0
  20. package/ai-context/context/flows/views.json +12 -0
  21. package/{test-projects/react-app/.ai-dev → ai-context}/conventions.md +3 -2
  22. package/ai-context/dependencies.json +3360 -0
  23. package/ai-context/entrypoints.md +45 -0
  24. package/ai-context/index-state.json +196 -0
  25. package/ai-context/modules.json +901 -0
  26. package/ai-context/project.json +33 -0
  27. package/ai-context/repo_map.json +8857 -0
  28. package/ai-context/repo_map.md +2002 -0
  29. package/{test-projects/flask-app/.ai-dev → ai-context}/schema.json +1 -1
  30. package/ai-context/summary.md +46 -0
  31. package/ai-context/symbols.json +82467 -0
  32. package/{test-projects/react-app/.ai-dev → ai-context}/tech_stack.md +15 -7
  33. package/ai-context-evaluation-report-1774223059505.md +206 -0
  34. package/dist/analyzers/architecture.d.ts.map +1 -1
  35. package/dist/analyzers/architecture.js +78 -5
  36. package/dist/analyzers/architecture.js.map +1 -1
  37. package/dist/analyzers/entrypoints.d.ts.map +1 -1
  38. package/dist/analyzers/entrypoints.js +358 -0
  39. package/dist/analyzers/entrypoints.js.map +1 -1
  40. package/dist/analyzers/symbols.d.ts.map +1 -1
  41. package/dist/analyzers/symbols.js +119 -3
  42. package/dist/analyzers/symbols.js.map +1 -1
  43. package/dist/analyzers/techStack.d.ts +8 -0
  44. package/dist/analyzers/techStack.d.ts.map +1 -1
  45. package/dist/analyzers/techStack.js +118 -0
  46. package/dist/analyzers/techStack.js.map +1 -1
  47. package/dist/utils/fileUtils.d.ts.map +1 -1
  48. package/dist/utils/fileUtils.js +5 -0
  49. package/dist/utils/fileUtils.js.map +1 -1
  50. package/package.json +1 -1
  51. package/scripts/ai-context-evaluator.ts +440 -0
  52. package/src/analyzers/architecture.ts +83 -6
  53. package/src/analyzers/entrypoints.ts +400 -0
  54. package/src/analyzers/symbols.ts +129 -3
  55. package/src/analyzers/techStack.ts +137 -0
  56. package/src/utils/fileUtils.ts +5 -0
  57. package/tests/apex-parser.test.ts +193 -0
  58. package/tests/cli-commands-batch1.test.ts +808 -0
  59. package/tests/cli-commands-batch2.test.ts +1113 -0
  60. package/tests/cli-commands-batch3.test.ts +1128 -0
  61. package/tests/cli-index.test.ts +1007 -0
  62. package/tests/cli-init.test.ts +761 -0
  63. package/tests/entrypoints-languages.test.ts +373 -0
  64. package/tests/framework-detection.test.ts +296 -0
  65. package/tests/salesforce-apex-classes.test.ts +713 -0
  66. package/tests/salesforce-apex-triggers.test.ts +871 -0
  67. package/tests/salesforce-custom-objects.test.ts +918 -0
  68. package/tests/salesforce-flows.test.ts +710 -0
  69. package/tests/salesforce-lwc.test.ts +963 -0
  70. package/tests/salesforce-sfdx-integration.test.ts +1125 -0
  71. package/ANALISIS_COMPLETO.md +0 -424
  72. package/ANALISIS_MEJORAS.md +0 -327
  73. package/CONTRIBUTING.md +0 -89
  74. package/FLOW.md +0 -129
  75. package/TEST_RESULTS.md +0 -198
  76. package/TEST_RESULTS_COMPARATIVE.md +0 -159
  77. package/TEST_RESULTS_COMPLETE.md +0 -127
  78. package/TEST_RESULTS_COMPREHENSIVE.md +0 -208
  79. package/install.sh +0 -188
  80. package/run-all-tests.sh +0 -184
  81. package/test-ai-context-understanding.sh +0 -21
  82. package/test-projects/django-app/.ai-dev/ai_context.md +0 -92
  83. package/test-projects/django-app/.ai-dev/ai_rules.md +0 -47
  84. package/test-projects/django-app/.ai-dev/architecture.md +0 -57
  85. package/test-projects/django-app/.ai-dev/cache.json +0 -169
  86. package/test-projects/django-app/.ai-dev/context/flows/views.json +0 -10
  87. package/test-projects/django-app/.ai-dev/conventions.md +0 -51
  88. package/test-projects/django-app/.ai-dev/dependencies.json +0 -312
  89. package/test-projects/django-app/.ai-dev/entrypoints.md +0 -4
  90. package/test-projects/django-app/.ai-dev/files.json +0 -209
  91. package/test-projects/django-app/.ai-dev/graph/knowledge-graph.json +0 -36
  92. package/test-projects/django-app/.ai-dev/graph/module-graph.json +0 -145
  93. package/test-projects/django-app/.ai-dev/graph/symbol-graph.json +0 -1488
  94. package/test-projects/django-app/.ai-dev/graph/symbol-references.json +0 -1
  95. package/test-projects/django-app/.ai-dev/index-state.json +0 -294
  96. package/test-projects/django-app/.ai-dev/modules.json +0 -35
  97. package/test-projects/django-app/.ai-dev/project.json +0 -11
  98. package/test-projects/django-app/.ai-dev/repo_map.json +0 -412
  99. package/test-projects/django-app/.ai-dev/repo_map.md +0 -105
  100. package/test-projects/django-app/.ai-dev/schema.json +0 -5
  101. package/test-projects/django-app/.ai-dev/summary.md +0 -15
  102. package/test-projects/django-app/.ai-dev/symbols.json +0 -1
  103. package/test-projects/django-app/.ai-dev/tech_stack.md +0 -32
  104. package/test-projects/django-app/README.md +0 -91
  105. package/test-projects/django-app/blog/__init__.py +0 -0
  106. package/test-projects/django-app/blog/admin.py +0 -31
  107. package/test-projects/django-app/blog/models.py +0 -55
  108. package/test-projects/django-app/blog/serializers.py +0 -69
  109. package/test-projects/django-app/blog/urls.py +0 -14
  110. package/test-projects/django-app/blog/views.py +0 -96
  111. package/test-projects/django-app/django_app/__init__.py +0 -0
  112. package/test-projects/django-app/django_app/settings.py +0 -90
  113. package/test-projects/django-app/django_app/urls.py +0 -11
  114. package/test-projects/django-app/django_app/wsgi.py +0 -9
  115. package/test-projects/django-app/manage.py +0 -23
  116. package/test-projects/django-app/requirements.txt +0 -3
  117. package/test-projects/django-app/users/__init__.py +0 -0
  118. package/test-projects/django-app/users/admin.py +0 -42
  119. package/test-projects/django-app/users/models.py +0 -54
  120. package/test-projects/django-app/users/serializers.py +0 -113
  121. package/test-projects/django-app/users/urls.py +0 -13
  122. package/test-projects/django-app/users/views.py +0 -135
  123. package/test-projects/express-api/.ai-dev/ai_context.md +0 -112
  124. package/test-projects/express-api/.ai-dev/ai_rules.md +0 -50
  125. package/test-projects/express-api/.ai-dev/architecture.md +0 -62
  126. package/test-projects/express-api/.ai-dev/context/features/controllers.json +0 -13
  127. package/test-projects/express-api/.ai-dev/context/features/services.json +0 -13
  128. package/test-projects/express-api/.ai-dev/context/flows/auth.json +0 -12
  129. package/test-projects/express-api/.ai-dev/context/flows/user.json +0 -13
  130. package/test-projects/express-api/.ai-dev/conventions.md +0 -51
  131. package/test-projects/express-api/.ai-dev/dependencies.json +0 -54
  132. package/test-projects/express-api/.ai-dev/entrypoints.md +0 -17
  133. package/test-projects/express-api/.ai-dev/modules.json +0 -30
  134. package/test-projects/express-api/.ai-dev/project.json +0 -15
  135. package/test-projects/express-api/.ai-dev/repo_map.json +0 -100
  136. package/test-projects/express-api/.ai-dev/repo_map.md +0 -36
  137. package/test-projects/express-api/.ai-dev/schema.json +0 -5
  138. package/test-projects/express-api/.ai-dev/summary.md +0 -14
  139. package/test-projects/express-api/.ai-dev/symbols.json +0 -7
  140. package/test-projects/express-api/.ai-dev/tech_stack.md +0 -38
  141. package/test-projects/express-api/.ai-dev/tools.json +0 -10
  142. package/test-projects/express-api/controllers/authController.js +0 -32
  143. package/test-projects/express-api/controllers/userController.js +0 -51
  144. package/test-projects/express-api/index.js +0 -30
  145. package/test-projects/express-api/middleware/authMiddleware.js +0 -30
  146. package/test-projects/express-api/models/userRepository.js +0 -25
  147. package/test-projects/express-api/package.json +0 -18
  148. package/test-projects/express-api/services/authService.js +0 -17
  149. package/test-projects/express-api/services/userService.js +0 -28
  150. package/test-projects/fastapi-app/.ai-dev/ai_context.md +0 -89
  151. package/test-projects/fastapi-app/.ai-dev/ai_rules.md +0 -47
  152. package/test-projects/fastapi-app/.ai-dev/architecture.md +0 -39
  153. package/test-projects/fastapi-app/.ai-dev/cache.json +0 -125
  154. package/test-projects/fastapi-app/.ai-dev/conventions.md +0 -51
  155. package/test-projects/fastapi-app/.ai-dev/dependencies.json +0 -244
  156. package/test-projects/fastapi-app/.ai-dev/entrypoints.md +0 -4
  157. package/test-projects/fastapi-app/.ai-dev/files.json +0 -154
  158. package/test-projects/fastapi-app/.ai-dev/graph/knowledge-graph.json +0 -15
  159. package/test-projects/fastapi-app/.ai-dev/graph/module-graph.json +0 -78
  160. package/test-projects/fastapi-app/.ai-dev/graph/symbol-graph.json +0 -1724
  161. package/test-projects/fastapi-app/.ai-dev/graph/symbol-references.json +0 -51
  162. package/test-projects/fastapi-app/.ai-dev/index-state.json +0 -217
  163. package/test-projects/fastapi-app/.ai-dev/modules.json +0 -16
  164. package/test-projects/fastapi-app/.ai-dev/project.json +0 -9
  165. package/test-projects/fastapi-app/.ai-dev/repo_map.json +0 -298
  166. package/test-projects/fastapi-app/.ai-dev/repo_map.md +0 -74
  167. package/test-projects/fastapi-app/.ai-dev/schema.json +0 -5
  168. package/test-projects/fastapi-app/.ai-dev/summary.md +0 -12
  169. package/test-projects/fastapi-app/.ai-dev/symbols.json +0 -1
  170. package/test-projects/fastapi-app/.ai-dev/tech_stack.md +0 -32
  171. package/test-projects/fastapi-app/.ai-dev/tools.json +0 -10
  172. package/test-projects/fastapi-app/README.md +0 -118
  173. package/test-projects/fastapi-app/app/database.py +0 -21
  174. package/test-projects/fastapi-app/app/dependencies.py +0 -107
  175. package/test-projects/fastapi-app/app/main.py +0 -47
  176. package/test-projects/fastapi-app/app/models.py +0 -149
  177. package/test-projects/fastapi-app/app/routers/auth.py +0 -117
  178. package/test-projects/fastapi-app/app/routers/posts.py +0 -272
  179. package/test-projects/fastapi-app/app/schemas.py +0 -191
  180. package/test-projects/fastapi-app/requirements.txt +0 -10
  181. package/test-projects/flask-app/.ai-dev/ai_context.md +0 -94
  182. package/test-projects/flask-app/.ai-dev/ai_rules.md +0 -47
  183. package/test-projects/flask-app/.ai-dev/architecture.md +0 -49
  184. package/test-projects/flask-app/.ai-dev/cache.json +0 -157
  185. package/test-projects/flask-app/.ai-dev/context/features/app.json +0 -25
  186. package/test-projects/flask-app/.ai-dev/context/flows/routes.json +0 -14
  187. package/test-projects/flask-app/.ai-dev/conventions.md +0 -51
  188. package/test-projects/flask-app/.ai-dev/dependencies.json +0 -298
  189. package/test-projects/flask-app/.ai-dev/entrypoints.md +0 -4
  190. package/test-projects/flask-app/.ai-dev/files.json +0 -194
  191. package/test-projects/flask-app/.ai-dev/graph/knowledge-graph.json +0 -60
  192. package/test-projects/flask-app/.ai-dev/graph/module-graph.json +0 -95
  193. package/test-projects/flask-app/.ai-dev/graph/symbol-graph.json +0 -1448
  194. package/test-projects/flask-app/.ai-dev/graph/symbol-references.json +0 -45
  195. package/test-projects/flask-app/.ai-dev/index-state.json +0 -273
  196. package/test-projects/flask-app/.ai-dev/modules.json +0 -21
  197. package/test-projects/flask-app/.ai-dev/project.json +0 -13
  198. package/test-projects/flask-app/.ai-dev/repo_map.json +0 -400
  199. package/test-projects/flask-app/.ai-dev/repo_map.md +0 -98
  200. package/test-projects/flask-app/.ai-dev/summary.md +0 -13
  201. package/test-projects/flask-app/.ai-dev/symbols.json +0 -1
  202. package/test-projects/flask-app/.ai-dev/tech_stack.md +0 -32
  203. package/test-projects/flask-app/.ai-dev/tools.json +0 -10
  204. package/test-projects/flask-app/README.md +0 -129
  205. package/test-projects/flask-app/app/__init__.py +0 -46
  206. package/test-projects/flask-app/app/api/__init__.py +0 -7
  207. package/test-projects/flask-app/app/api/routes.py +0 -122
  208. package/test-projects/flask-app/app/auth/__init__.py +0 -7
  209. package/test-projects/flask-app/app/auth/forms.py +0 -52
  210. package/test-projects/flask-app/app/auth/routes.py +0 -68
  211. package/test-projects/flask-app/app/blog/__init__.py +0 -7
  212. package/test-projects/flask-app/app/blog/forms.py +0 -35
  213. package/test-projects/flask-app/app/blog/routes.py +0 -140
  214. package/test-projects/flask-app/app/main/__init__.py +0 -7
  215. package/test-projects/flask-app/app/main/routes.py +0 -88
  216. package/test-projects/flask-app/app/models.py +0 -177
  217. package/test-projects/flask-app/config.py +0 -64
  218. package/test-projects/flask-app/requirements.txt +0 -10
  219. package/test-projects/laravel-app/.ai-dev/ai_context.md +0 -97
  220. package/test-projects/laravel-app/.ai-dev/ai_rules.md +0 -47
  221. package/test-projects/laravel-app/.ai-dev/architecture.md +0 -60
  222. package/test-projects/laravel-app/.ai-dev/cache.json +0 -161
  223. package/test-projects/laravel-app/.ai-dev/context/features/app.json +0 -21
  224. package/test-projects/laravel-app/.ai-dev/context/flows/.json +0 -9
  225. package/test-projects/laravel-app/.ai-dev/context/flows/category.json +0 -12
  226. package/test-projects/laravel-app/.ai-dev/context/flows/comment.json +0 -12
  227. package/test-projects/laravel-app/.ai-dev/context/flows/post.json +0 -12
  228. package/test-projects/laravel-app/.ai-dev/context/flows/unnamed.json +0 -9
  229. package/test-projects/laravel-app/.ai-dev/conventions.md +0 -51
  230. package/test-projects/laravel-app/.ai-dev/dependencies.json +0 -6
  231. package/test-projects/laravel-app/.ai-dev/entrypoints.md +0 -4
  232. package/test-projects/laravel-app/.ai-dev/files.json +0 -199
  233. package/test-projects/laravel-app/.ai-dev/graph/knowledge-graph.json +0 -98
  234. package/test-projects/laravel-app/.ai-dev/graph/module-graph.json +0 -30
  235. package/test-projects/laravel-app/.ai-dev/graph/symbol-graph.json +0 -5
  236. package/test-projects/laravel-app/.ai-dev/graph/symbol-references.json +0 -1
  237. package/test-projects/laravel-app/.ai-dev/index-state.json +0 -280
  238. package/test-projects/laravel-app/.ai-dev/modules.json +0 -29
  239. package/test-projects/laravel-app/.ai-dev/project.json +0 -17
  240. package/test-projects/laravel-app/.ai-dev/repo_map.json +0 -419
  241. package/test-projects/laravel-app/.ai-dev/repo_map.md +0 -106
  242. package/test-projects/laravel-app/.ai-dev/schema.json +0 -5
  243. package/test-projects/laravel-app/.ai-dev/summary.md +0 -15
  244. package/test-projects/laravel-app/.ai-dev/symbols.json +0 -1
  245. package/test-projects/laravel-app/.ai-dev/tech_stack.md +0 -34
  246. package/test-projects/laravel-app/.ai-dev/tools.json +0 -10
  247. package/test-projects/laravel-app/README.md +0 -107
  248. package/test-projects/laravel-app/app/Http/Controllers/Api/CategoryController.php +0 -88
  249. package/test-projects/laravel-app/app/Http/Controllers/Api/CommentController.php +0 -56
  250. package/test-projects/laravel-app/app/Http/Controllers/Api/PostController.php +0 -174
  251. package/test-projects/laravel-app/app/Http/Controllers/Controller.php +0 -12
  252. package/test-projects/laravel-app/app/Models/Category.php +0 -34
  253. package/test-projects/laravel-app/app/Models/Comment.php +0 -51
  254. package/test-projects/laravel-app/app/Models/Post.php +0 -108
  255. package/test-projects/laravel-app/app/Models/User.php +0 -85
  256. package/test-projects/laravel-app/bootstrap/app.php +0 -25
  257. package/test-projects/laravel-app/composer.json +0 -35
  258. package/test-projects/laravel-app/routes/api.php +0 -40
  259. package/test-projects/nestjs-backend/.ai-dev/ai_context.md +0 -111
  260. package/test-projects/nestjs-backend/.ai-dev/ai_rules.md +0 -52
  261. package/test-projects/nestjs-backend/.ai-dev/architecture.md +0 -49
  262. package/test-projects/nestjs-backend/.ai-dev/cache.json +0 -169
  263. package/test-projects/nestjs-backend/.ai-dev/context/features/src.json +0 -23
  264. package/test-projects/nestjs-backend/.ai-dev/context/flows/auth.controller.json +0 -14
  265. package/test-projects/nestjs-backend/.ai-dev/context/flows/auth.json +0 -10
  266. package/test-projects/nestjs-backend/.ai-dev/context/flows/users..json +0 -10
  267. package/test-projects/nestjs-backend/.ai-dev/context/flows/users.controller.json +0 -14
  268. package/test-projects/nestjs-backend/.ai-dev/context/flows/users.json +0 -10
  269. package/test-projects/nestjs-backend/.ai-dev/conventions.md +0 -52
  270. package/test-projects/nestjs-backend/.ai-dev/dependencies.json +0 -152
  271. package/test-projects/nestjs-backend/.ai-dev/entrypoints.md +0 -18
  272. package/test-projects/nestjs-backend/.ai-dev/files.json +0 -209
  273. package/test-projects/nestjs-backend/.ai-dev/graph/knowledge-graph.json +0 -132
  274. package/test-projects/nestjs-backend/.ai-dev/graph/module-graph.json +0 -29
  275. package/test-projects/nestjs-backend/.ai-dev/graph/symbol-graph.json +0 -304
  276. package/test-projects/nestjs-backend/.ai-dev/graph/symbol-references.json +0 -5
  277. package/test-projects/nestjs-backend/.ai-dev/index-state.json +0 -294
  278. package/test-projects/nestjs-backend/.ai-dev/modules.json +0 -19
  279. package/test-projects/nestjs-backend/.ai-dev/project.json +0 -18
  280. package/test-projects/nestjs-backend/.ai-dev/repo_map.json +0 -427
  281. package/test-projects/nestjs-backend/.ai-dev/repo_map.md +0 -104
  282. package/test-projects/nestjs-backend/.ai-dev/schema.json +0 -5
  283. package/test-projects/nestjs-backend/.ai-dev/summary.md +0 -13
  284. package/test-projects/nestjs-backend/.ai-dev/symbols.json +0 -1
  285. package/test-projects/nestjs-backend/.ai-dev/tech_stack.md +0 -38
  286. package/test-projects/nestjs-backend/.ai-dev/tools.json +0 -10
  287. package/test-projects/nestjs-backend/package.json +0 -22
  288. package/test-projects/nestjs-backend/src/app.module.ts +0 -8
  289. package/test-projects/nestjs-backend/src/auth/auth.controller.ts +0 -22
  290. package/test-projects/nestjs-backend/src/auth/auth.module.ts +0 -11
  291. package/test-projects/nestjs-backend/src/auth/auth.service.ts +0 -28
  292. package/test-projects/nestjs-backend/src/auth/dto/login.dto.ts +0 -4
  293. package/test-projects/nestjs-backend/src/auth/strategies/jwt.strategy.ts +0 -18
  294. package/test-projects/nestjs-backend/src/main.ts +0 -9
  295. package/test-projects/nestjs-backend/src/users/users.controller.ts +0 -32
  296. package/test-projects/nestjs-backend/src/users/users.module.ts +0 -10
  297. package/test-projects/nestjs-backend/src/users/users.service.ts +0 -42
  298. package/test-projects/nestjs-backend/tsconfig.json +0 -21
  299. package/test-projects/python-cli/.ai-dev/ai_context.md +0 -95
  300. package/test-projects/python-cli/.ai-dev/ai_rules.md +0 -47
  301. package/test-projects/python-cli/.ai-dev/architecture.md +0 -55
  302. package/test-projects/python-cli/.ai-dev/cache.json +0 -149
  303. package/test-projects/python-cli/.ai-dev/context/features/cli.json +0 -16
  304. package/test-projects/python-cli/.ai-dev/context/flows/list_.json +0 -9
  305. package/test-projects/python-cli/.ai-dev/context/flows/remove_.json +0 -9
  306. package/test-projects/python-cli/.ai-dev/conventions.md +0 -51
  307. package/test-projects/python-cli/.ai-dev/dependencies.json +0 -66
  308. package/test-projects/python-cli/.ai-dev/entrypoints.md +0 -4
  309. package/test-projects/python-cli/.ai-dev/files.json +0 -184
  310. package/test-projects/python-cli/.ai-dev/graph/knowledge-graph.json +0 -83
  311. package/test-projects/python-cli/.ai-dev/graph/module-graph.json +0 -31
  312. package/test-projects/python-cli/.ai-dev/graph/symbol-graph.json +0 -358
  313. package/test-projects/python-cli/.ai-dev/graph/symbol-references.json +0 -11
  314. package/test-projects/python-cli/.ai-dev/index-state.json +0 -259
  315. package/test-projects/python-cli/.ai-dev/modules.json +0 -21
  316. package/test-projects/python-cli/.ai-dev/project.json +0 -15
  317. package/test-projects/python-cli/.ai-dev/repo_map.json +0 -367
  318. package/test-projects/python-cli/.ai-dev/repo_map.md +0 -93
  319. package/test-projects/python-cli/.ai-dev/schema.json +0 -5
  320. package/test-projects/python-cli/.ai-dev/summary.md +0 -14
  321. package/test-projects/python-cli/.ai-dev/symbols.json +0 -1
  322. package/test-projects/python-cli/.ai-dev/tech_stack.md +0 -32
  323. package/test-projects/python-cli/.ai-dev/tools.json +0 -10
  324. package/test-projects/python-cli/__init__.py +0 -1
  325. package/test-projects/python-cli/cli/__init__.py +0 -1
  326. package/test-projects/python-cli/cli/add_command.py +0 -6
  327. package/test-projects/python-cli/cli/list_command.py +0 -7
  328. package/test-projects/python-cli/cli/remove_command.py +0 -6
  329. package/test-projects/python-cli/main.py +0 -34
  330. package/test-projects/python-cli/models/__init__.py +0 -2
  331. package/test-projects/python-cli/models/task.py +0 -19
  332. package/test-projects/python-cli/models/task_repository.py +0 -44
  333. package/test-projects/rails-app/.ai-dev/ai_context.md +0 -94
  334. package/test-projects/rails-app/.ai-dev/ai_rules.md +0 -47
  335. package/test-projects/rails-app/.ai-dev/architecture.md +0 -49
  336. package/test-projects/rails-app/.ai-dev/cache.json +0 -193
  337. package/test-projects/rails-app/.ai-dev/context/features/app.json +0 -24
  338. package/test-projects/rails-app/.ai-dev/context/features/config.json +0 -13
  339. package/test-projects/rails-app/.ai-dev/context/flows/application.json +0 -9
  340. package/test-projects/rails-app/.ai-dev/context/flows/application_.json +0 -9
  341. package/test-projects/rails-app/.ai-dev/context/flows/comments.json +0 -11
  342. package/test-projects/rails-app/.ai-dev/context/flows/comments_.json +0 -11
  343. package/test-projects/rails-app/.ai-dev/context/flows/posts.json +0 -11
  344. package/test-projects/rails-app/.ai-dev/context/flows/posts_.json +0 -11
  345. package/test-projects/rails-app/.ai-dev/context/flows/routes.json +0 -9
  346. package/test-projects/rails-app/.ai-dev/context/flows/users.json +0 -11
  347. package/test-projects/rails-app/.ai-dev/context/flows/users_.json +0 -11
  348. package/test-projects/rails-app/.ai-dev/conventions.md +0 -51
  349. package/test-projects/rails-app/.ai-dev/dependencies.json +0 -6
  350. package/test-projects/rails-app/.ai-dev/entrypoints.md +0 -4
  351. package/test-projects/rails-app/.ai-dev/files.json +0 -239
  352. package/test-projects/rails-app/.ai-dev/graph/knowledge-graph.json +0 -130
  353. package/test-projects/rails-app/.ai-dev/graph/module-graph.json +0 -27
  354. package/test-projects/rails-app/.ai-dev/graph/symbol-graph.json +0 -5
  355. package/test-projects/rails-app/.ai-dev/graph/symbol-references.json +0 -1
  356. package/test-projects/rails-app/.ai-dev/index-state.json +0 -336
  357. package/test-projects/rails-app/.ai-dev/modules.json +0 -26
  358. package/test-projects/rails-app/.ai-dev/project.json +0 -22
  359. package/test-projects/rails-app/.ai-dev/repo_map.json +0 -486
  360. package/test-projects/rails-app/.ai-dev/repo_map.md +0 -117
  361. package/test-projects/rails-app/.ai-dev/schema.json +0 -5
  362. package/test-projects/rails-app/.ai-dev/summary.md +0 -13
  363. package/test-projects/rails-app/.ai-dev/symbols.json +0 -1
  364. package/test-projects/rails-app/.ai-dev/tech_stack.md +0 -32
  365. package/test-projects/rails-app/.ai-dev/tools.json +0 -10
  366. package/test-projects/rails-app/Gemfile +0 -38
  367. package/test-projects/rails-app/README.md +0 -140
  368. package/test-projects/rails-app/Rakefile +0 -8
  369. package/test-projects/rails-app/app/controllers/api/comments_controller.rb +0 -75
  370. package/test-projects/rails-app/app/controllers/api/posts_controller.rb +0 -68
  371. package/test-projects/rails-app/app/controllers/api/users_controller.rb +0 -54
  372. package/test-projects/rails-app/app/controllers/application_controller.rb +0 -31
  373. package/test-projects/rails-app/app/models/comment.rb +0 -34
  374. package/test-projects/rails-app/app/models/post.rb +0 -36
  375. package/test-projects/rails-app/app/models/user.rb +0 -28
  376. package/test-projects/rails-app/app/services/post_service.rb +0 -92
  377. package/test-projects/rails-app/app/services/user_service.rb +0 -76
  378. package/test-projects/rails-app/config/application.rb +0 -27
  379. package/test-projects/rails-app/config/environment.rb +0 -7
  380. package/test-projects/rails-app/config/routes.rb +0 -15
  381. package/test-projects/react-app/.ai-dev/ai_context.md +0 -96
  382. package/test-projects/react-app/.ai-dev/architecture.md +0 -39
  383. package/test-projects/react-app/.ai-dev/cache.json +0 -153
  384. package/test-projects/react-app/.ai-dev/context/features/src.json +0 -18
  385. package/test-projects/react-app/.ai-dev/context/flows/UsersPage.json +0 -14
  386. package/test-projects/react-app/.ai-dev/context/flows/dashboard.json +0 -9
  387. package/test-projects/react-app/.ai-dev/context/flows/login.json +0 -9
  388. package/test-projects/react-app/.ai-dev/context/flows/users.json +0 -9
  389. package/test-projects/react-app/.ai-dev/dependencies.json +0 -128
  390. package/test-projects/react-app/.ai-dev/entrypoints.md +0 -4
  391. package/test-projects/react-app/.ai-dev/files.json +0 -189
  392. package/test-projects/react-app/.ai-dev/graph/knowledge-graph.json +0 -112
  393. package/test-projects/react-app/.ai-dev/graph/module-graph.json +0 -31
  394. package/test-projects/react-app/.ai-dev/graph/symbol-graph.json +0 -868
  395. package/test-projects/react-app/.ai-dev/graph/symbol-references.json +0 -31
  396. package/test-projects/react-app/.ai-dev/index-state.json +0 -266
  397. package/test-projects/react-app/.ai-dev/modules.json +0 -17
  398. package/test-projects/react-app/.ai-dev/project.json +0 -16
  399. package/test-projects/react-app/.ai-dev/repo_map.json +0 -391
  400. package/test-projects/react-app/.ai-dev/repo_map.md +0 -94
  401. package/test-projects/react-app/.ai-dev/schema.json +0 -5
  402. package/test-projects/react-app/.ai-dev/summary.md +0 -13
  403. package/test-projects/react-app/.ai-dev/symbols.json +0 -1
  404. package/test-projects/react-app/.ai-dev/tools.json +0 -10
  405. package/test-projects/react-app/package.json +0 -16
  406. package/test-projects/react-app/src/App.tsx +0 -21
  407. package/test-projects/react-app/src/context/AuthContext.tsx +0 -41
  408. package/test-projects/react-app/src/hooks/useAuth.ts +0 -10
  409. package/test-projects/react-app/src/main.tsx +0 -10
  410. package/test-projects/react-app/src/pages/DashboardPage.tsx +0 -17
  411. package/test-projects/react-app/src/pages/LoginPage.tsx +0 -41
  412. package/test-projects/react-app/src/pages/UsersPage.tsx +0 -36
  413. package/test-projects/react-app/src/services/userService.ts +0 -37
  414. package/test-projects/salesforce-cli/.ai-dev/ai_context.md +0 -89
  415. package/test-projects/salesforce-cli/.ai-dev/ai_rules.md +0 -47
  416. package/test-projects/salesforce-cli/.ai-dev/architecture.md +0 -39
  417. package/test-projects/salesforce-cli/.ai-dev/cache.json +0 -125
  418. package/test-projects/salesforce-cli/.ai-dev/context/features/force-app.json +0 -14
  419. package/test-projects/salesforce-cli/.ai-dev/context/flows/account.json +0 -9
  420. package/test-projects/salesforce-cli/.ai-dev/context/flows/opportunity.json +0 -9
  421. package/test-projects/salesforce-cli/.ai-dev/conventions.md +0 -51
  422. package/test-projects/salesforce-cli/.ai-dev/dependencies.json +0 -6
  423. package/test-projects/salesforce-cli/.ai-dev/entrypoints.md +0 -4
  424. package/test-projects/salesforce-cli/.ai-dev/files.json +0 -154
  425. package/test-projects/salesforce-cli/.ai-dev/graph/knowledge-graph.json +0 -64
  426. package/test-projects/salesforce-cli/.ai-dev/graph/module-graph.json +0 -13
  427. package/test-projects/salesforce-cli/.ai-dev/graph/symbol-graph.json +0 -148
  428. package/test-projects/salesforce-cli/.ai-dev/graph/symbol-references.json +0 -1
  429. package/test-projects/salesforce-cli/.ai-dev/index-state.json +0 -217
  430. package/test-projects/salesforce-cli/.ai-dev/modules.json +0 -12
  431. package/test-projects/salesforce-cli/.ai-dev/project.json +0 -14
  432. package/test-projects/salesforce-cli/.ai-dev/repo_map.json +0 -328
  433. package/test-projects/salesforce-cli/.ai-dev/repo_map.md +0 -80
  434. package/test-projects/salesforce-cli/.ai-dev/schema.json +0 -5
  435. package/test-projects/salesforce-cli/.ai-dev/summary.md +0 -13
  436. package/test-projects/salesforce-cli/.ai-dev/symbols.json +0 -1
  437. package/test-projects/salesforce-cli/.ai-dev/tech_stack.md +0 -31
  438. package/test-projects/salesforce-cli/.ai-dev/tools.json +0 -10
  439. package/test-projects/salesforce-cli/.forceignore +0 -27
  440. package/test-projects/salesforce-cli/force-app/main/default/classes/AccountController.cls +0 -24
  441. package/test-projects/salesforce-cli/force-app/main/default/classes/OpportunityController.cls +0 -25
  442. package/test-projects/salesforce-cli/force-app/main/default/objects/Project__c.object.xml +0 -45
  443. package/test-projects/salesforce-cli/force-app/main/default/triggers/AccountTrigger.trigger +0 -33
  444. package/test-projects/salesforce-cli/sfdx-project.json +0 -11
  445. package/test-projects/spring-boot-app/.ai-dev/ai_context.md +0 -91
  446. package/test-projects/spring-boot-app/.ai-dev/ai_rules.md +0 -48
  447. package/test-projects/spring-boot-app/.ai-dev/architecture.md +0 -39
  448. package/test-projects/spring-boot-app/.ai-dev/cache.json +0 -173
  449. package/test-projects/spring-boot-app/.ai-dev/context/features/src.json +0 -26
  450. package/test-projects/spring-boot-app/.ai-dev/context/flows/PostController.json +0 -19
  451. package/test-projects/spring-boot-app/.ai-dev/context/flows/UserController.json +0 -19
  452. package/test-projects/spring-boot-app/.ai-dev/context/flows/comment.json +0 -11
  453. package/test-projects/spring-boot-app/.ai-dev/context/flows/post.json +0 -14
  454. package/test-projects/spring-boot-app/.ai-dev/context/flows/user.json +0 -14
  455. package/test-projects/spring-boot-app/.ai-dev/conventions.md +0 -52
  456. package/test-projects/spring-boot-app/.ai-dev/dependencies.json +0 -326
  457. package/test-projects/spring-boot-app/.ai-dev/entrypoints.md +0 -4
  458. package/test-projects/spring-boot-app/.ai-dev/files.json +0 -214
  459. package/test-projects/spring-boot-app/.ai-dev/graph/knowledge-graph.json +0 -231
  460. package/test-projects/spring-boot-app/.ai-dev/graph/module-graph.json +0 -22
  461. package/test-projects/spring-boot-app/.ai-dev/graph/symbol-graph.json +0 -794
  462. package/test-projects/spring-boot-app/.ai-dev/graph/symbol-references.json +0 -70
  463. package/test-projects/spring-boot-app/.ai-dev/index-state.json +0 -301
  464. package/test-projects/spring-boot-app/.ai-dev/modules.json +0 -21
  465. package/test-projects/spring-boot-app/.ai-dev/project.json +0 -17
  466. package/test-projects/spring-boot-app/.ai-dev/repo_map.json +0 -461
  467. package/test-projects/spring-boot-app/.ai-dev/repo_map.md +0 -109
  468. package/test-projects/spring-boot-app/.ai-dev/schema.json +0 -5
  469. package/test-projects/spring-boot-app/.ai-dev/summary.md +0 -12
  470. package/test-projects/spring-boot-app/.ai-dev/symbols.json +0 -1
  471. package/test-projects/spring-boot-app/.ai-dev/tech_stack.md +0 -32
  472. package/test-projects/spring-boot-app/.ai-dev/tools.json +0 -10
  473. package/test-projects/spring-boot-app/.classpath +0 -57
  474. package/test-projects/spring-boot-app/.factorypath +0 -69
  475. package/test-projects/spring-boot-app/.project +0 -34
  476. package/test-projects/spring-boot-app/.settings/org.eclipse.core.resources.prefs +0 -4
  477. package/test-projects/spring-boot-app/.settings/org.eclipse.jdt.apt.core.prefs +0 -4
  478. package/test-projects/spring-boot-app/.settings/org.eclipse.jdt.core.prefs +0 -10
  479. package/test-projects/spring-boot-app/.settings/org.eclipse.m2e.core.prefs +0 -4
  480. package/test-projects/spring-boot-app/README.md +0 -122
  481. package/test-projects/spring-boot-app/pom.xml +0 -79
  482. package/test-projects/spring-boot-app/src/main/java/com/example/demo/DemoApplication.java +0 -12
  483. package/test-projects/spring-boot-app/src/main/java/com/example/demo/controllers/CommentController.java +0 -89
  484. package/test-projects/spring-boot-app/src/main/java/com/example/demo/controllers/PostController.java +0 -92
  485. package/test-projects/spring-boot-app/src/main/java/com/example/demo/controllers/UserController.java +0 -84
  486. package/test-projects/spring-boot-app/src/main/java/com/example/demo/models/Comment.java +0 -38
  487. package/test-projects/spring-boot-app/src/main/java/com/example/demo/models/Post.java +0 -56
  488. package/test-projects/spring-boot-app/src/main/java/com/example/demo/models/User.java +0 -44
  489. package/test-projects/spring-boot-app/src/main/java/com/example/demo/repositories/CommentRepository.java +0 -21
  490. package/test-projects/spring-boot-app/src/main/java/com/example/demo/repositories/PostRepository.java +0 -18
  491. package/test-projects/spring-boot-app/src/main/java/com/example/demo/repositories/UserRepository.java +0 -15
  492. package/test-projects/spring-boot-app/src/main/java/com/example/demo/services/PostService.java +0 -83
  493. package/test-projects/spring-boot-app/src/main/java/com/example/demo/services/UserService.java +0 -62
  494. package/test-projects/spring-boot-app/src/main/resources/application.properties +0 -22
  495. package/test-projects/spring-boot-app/target/classes/com/example/demo/DemoApplication.class +0 -0
  496. package/test-projects/spring-boot-app/target/classes/com/example/demo/controllers/CommentController$CommentCreateRequest.class +0 -0
  497. package/test-projects/spring-boot-app/target/classes/com/example/demo/controllers/CommentController$CommentUpdateRequest.class +0 -0
  498. package/test-projects/spring-boot-app/target/classes/com/example/demo/controllers/CommentController.class +0 -0
  499. package/test-projects/spring-boot-app/target/classes/com/example/demo/controllers/PostController$PostCreateRequest.class +0 -0
  500. package/test-projects/spring-boot-app/target/classes/com/example/demo/controllers/PostController$PostUpdateRequest.class +0 -0
  501. package/test-projects/spring-boot-app/target/classes/com/example/demo/controllers/PostController.class +0 -0
  502. package/test-projects/spring-boot-app/target/classes/com/example/demo/controllers/UserController$UserCreateRequest.class +0 -0
  503. package/test-projects/spring-boot-app/target/classes/com/example/demo/controllers/UserController$UserUpdateRequest.class +0 -0
  504. package/test-projects/spring-boot-app/target/classes/com/example/demo/controllers/UserController.class +0 -0
  505. package/test-projects/spring-boot-app/target/classes/com/example/demo/models/Comment.class +0 -0
  506. package/test-projects/spring-boot-app/target/classes/com/example/demo/models/Post.class +0 -0
  507. package/test-projects/spring-boot-app/target/classes/com/example/demo/models/User.class +0 -0
  508. package/test-projects/spring-boot-app/target/classes/com/example/demo/repositories/CommentRepository.class +0 -0
  509. package/test-projects/spring-boot-app/target/classes/com/example/demo/repositories/PostRepository.class +0 -0
  510. package/test-projects/spring-boot-app/target/classes/com/example/demo/repositories/UserRepository.class +0 -0
  511. package/test-projects/spring-boot-app/target/classes/com/example/demo/services/PostService.class +0 -0
  512. package/test-projects/spring-boot-app/target/classes/com/example/demo/services/UserService.class +0 -0
  513. package/tests/e2e/run-e2e.sh +0 -88
  514. /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
+ });