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,918 @@
1
+ import { describe, it, expect, beforeAll } from "vitest";
2
+ import fs from "fs";
3
+ import path from "path";
4
+
5
+ const SALESFORCE_ENTERPRISE_PATH = path.join(process.cwd(), "test-projects/salesforce-enterprise");
6
+
7
+ describe("Salesforce Custom Objects Detection", () => {
8
+
9
+ function extractFieldContent(content: string, fieldName: string): string {
10
+ const nameIdx = content.indexOf(`<name>${fieldName}</name>`);
11
+ if (nameIdx === -1) return "";
12
+
13
+ const beforeContent = content.substring(0, nameIdx);
14
+ const fieldsStart = beforeContent.lastIndexOf("<fields>");
15
+
16
+ const afterContent = content.substring(nameIdx);
17
+ const fieldsEndIdx = afterContent.indexOf("</fields>");
18
+ const fieldsEnd = fieldsStart + fieldsEndIdx + "</fields>".length;
19
+
20
+ return content.substring(fieldsStart, fieldsEnd);
21
+ }
22
+
23
+ // =========================================================================
24
+ // INTEGRATION TESTS - Using real Salesforce Enterprise test project
25
+ // =========================================================================
26
+
27
+ describe("Integration: Real Salesforce Enterprise Project", () => {
28
+ it("should detect CustomObject__c directory", () => {
29
+ const objectsDir = path.join(SALESFORCE_ENTERPRISE_PATH, "force-app/main/default/objects");
30
+ const customObjectDir = path.join(objectsDir, "CustomObject__c");
31
+
32
+ expect(fs.existsSync(objectsDir)).toBe(true);
33
+ expect(fs.existsSync(customObjectDir)).toBe(true);
34
+ });
35
+
36
+ it("should find CustomObject__c.object-meta.xml file", () => {
37
+ const objectMetaPath = path.join(SALESFORCE_ENTERPRISE_PATH, "force-app/main/default/objects/CustomObject__c/CustomObject__c.object-meta.xml");
38
+ expect(fs.existsSync(objectMetaPath)).toBe(true);
39
+ });
40
+
41
+ it("should read CustomObject__c metadata successfully", () => {
42
+ const objectMetaPath = path.join(SALESFORCE_ENTERPRISE_PATH, "force-app/main/default/objects/CustomObject__c/CustomObject__c.object-meta.xml");
43
+ const content = fs.readFileSync(objectMetaPath, "utf-8");
44
+
45
+ expect(content).toContain("<CustomObject xmlns=");
46
+ expect(content).toContain("http://soap.sforce.com/2006/04/metadata");
47
+ });
48
+ });
49
+
50
+ // =========================================================================
51
+ // CUSTOM OBJECT METADATA VERIFICATION
52
+ // =========================================================================
53
+
54
+ describe("CustomObject__c Metadata", () => {
55
+ let customObjectContent: string;
56
+
57
+ beforeAll(() => {
58
+ const objectMetaPath = path.join(SALESFORCE_ENTERPRISE_PATH, "force-app/main/default/objects/CustomObject__c/CustomObject__c.object-meta.xml");
59
+ customObjectContent = fs.readFileSync(objectMetaPath, "utf-8");
60
+ });
61
+
62
+ describe("Object Properties", () => {
63
+ it("should have correct XML declaration", () => {
64
+ expect(customObjectContent).toContain('<?xml version="1.0" encoding="UTF-8"?>');
65
+ });
66
+
67
+ it("should have correct Salesforce namespace", () => {
68
+ expect(customObjectContent).toContain('xmlns="http://soap.sforce.com/2006/04/metadata"');
69
+ });
70
+
71
+ it("should have CustomObject as root element", () => {
72
+ expect(customObjectContent).toContain("<CustomObject xmlns=");
73
+ });
74
+
75
+ it("should have label 'Custom Object'", () => {
76
+ expect(customObjectContent).toContain("<label>Custom Object</label>");
77
+ });
78
+
79
+ it("should have pluralLabel 'Custom Objects'", () => {
80
+ expect(customObjectContent).toContain("<pluralLabel>Custom Objects</pluralLabel>");
81
+ });
82
+
83
+ it("should have deploymentStatus as Deployed", () => {
84
+ expect(customObjectContent).toContain("<deploymentStatus>Deployed</deploymentStatus>");
85
+ });
86
+
87
+ it("should have sharingModel as ReadWrite", () => {
88
+ expect(customObjectContent).toContain("<sharingModel>ReadWrite</sharingModel>");
89
+ });
90
+
91
+ it("should have visibility as Public", () => {
92
+ expect(customObjectContent).toContain("<visibility>Public</visibility>");
93
+ });
94
+
95
+ it("should have allowInChatterGroups as true", () => {
96
+ expect(customObjectContent).toContain("<allowInChatterGroups>true</allowInChatterGroups>");
97
+ });
98
+
99
+ it("should have nameField of type Text", () => {
100
+ expect(customObjectContent).toMatch(/<nameField>[\s\S]*?<type>Text<\/type>[\s\S]*?<\/nameField>/);
101
+ expect(customObjectContent).toContain("<label>Custom Object Name</label>");
102
+ });
103
+ });
104
+
105
+ describe("Enable Flags", () => {
106
+ it("should have enableActivities as true", () => {
107
+ expect(customObjectContent).toContain("<enableActivities>true</enableActivities>");
108
+ });
109
+
110
+ it("should have enableBulkApi as true", () => {
111
+ expect(customObjectContent).toContain("<enableBulkApi>true</enableBulkApi>");
112
+ });
113
+
114
+ it("should have enableChangeDataCapture as true", () => {
115
+ expect(customObjectContent).toContain("<enableChangeDataCapture>true</enableChangeDataCapture>");
116
+ });
117
+
118
+ it("should have enableFeeds as true", () => {
119
+ expect(customObjectContent).toContain("<enableFeeds>true</enableFeeds>");
120
+ });
121
+
122
+ it("should have enableHistory as true", () => {
123
+ expect(customObjectContent).toContain("<enableHistory>true</enableHistory>");
124
+ });
125
+
126
+ it("should have enableLicensing as false", () => {
127
+ expect(customObjectContent).toContain("<enableLicensing>false</enableLicensing>");
128
+ });
129
+
130
+ it("should have enableReports as true", () => {
131
+ expect(customObjectContent).toContain("<enableReports>true</enableReports>");
132
+ });
133
+
134
+ it("should have enableSearch as true", () => {
135
+ expect(customObjectContent).toContain("<enableSearch>true</enableSearch>");
136
+ });
137
+
138
+ it("should have enableSharing as true", () => {
139
+ expect(customObjectContent).toContain("<enableSharing>true</enableSharing>");
140
+ });
141
+
142
+ it("should have enableStreamingApi as true", () => {
143
+ expect(customObjectContent).toContain("<enableStreamingApi>true</enableStreamingApi>");
144
+ });
145
+
146
+ it("should have compactLayoutAssignment as SYSTEM", () => {
147
+ expect(customObjectContent).toContain("<compactLayoutAssignment>SYSTEM</compactLayoutAssignment>");
148
+ });
149
+ });
150
+
151
+ describe("Search Layouts", () => {
152
+ it("should have searchLayouts section", () => {
153
+ expect(customObjectContent).toMatch(/<searchLayouts>[\s\S]*?<\/searchLayouts>/);
154
+ });
155
+
156
+ it("should include NAME in searchColumns", () => {
157
+ expect(customObjectContent).toContain("<searchColumns>NAME</searchColumns>");
158
+ });
159
+
160
+ it("should include CUSTOM_ACCOUNT__C in searchColumns", () => {
161
+ expect(customObjectContent).toContain("<searchColumns>CUSTOM_ACCOUNT__C</searchColumns>");
162
+ });
163
+
164
+ it("should include STATUS__C in searchColumns", () => {
165
+ expect(customObjectContent).toContain("<searchColumns>STATUS__C</searchColumns>");
166
+ });
167
+
168
+ it("should include AMOUNT__C in searchColumns", () => {
169
+ expect(customObjectContent).toContain("<searchColumns>AMOUNT__C</searchColumns>");
170
+ });
171
+
172
+ it("should include CREATED_DATE in searchColumns", () => {
173
+ expect(customObjectContent).toContain("<searchColumns>CREATED_DATE</searchColumns>");
174
+ });
175
+ });
176
+
177
+ describe("List Views", () => {
178
+ it("should have listViews section", () => {
179
+ expect(customObjectContent).toMatch(/<listViews>[\s\S]*?<\/listViews>/);
180
+ });
181
+
182
+ it("should have All listView with filterScope Everything", () => {
183
+ expect(customObjectContent).toContain("<fullName>All</fullName>");
184
+ expect(customObjectContent).toContain("<filterScope>Everything</filterScope>");
185
+ expect(customObjectContent).toContain("<label>All</label>");
186
+ });
187
+ });
188
+ });
189
+
190
+ // =========================================================================
191
+ // ACTION OVERRIDES
192
+ // =========================================================================
193
+
194
+ describe("Action Overrides", () => {
195
+ let customObjectContent: string;
196
+
197
+ beforeAll(() => {
198
+ const objectMetaPath = path.join(SALESFORCE_ENTERPRISE_PATH, "force-app/main/default/objects/CustomObject__c/CustomObject__c.object-meta.xml");
199
+ customObjectContent = fs.readFileSync(objectMetaPath, "utf-8");
200
+ });
201
+
202
+ it("should have 10 actionOverrides", () => {
203
+ const actionOverrideMatches = customObjectContent.match(/<actionName>/g);
204
+ expect(actionOverrideMatches).toHaveLength(10);
205
+ });
206
+
207
+ it("should have Accept action override", () => {
208
+ expect(customObjectContent).toMatch(/<actionOverrides>[\s\S]*?<actionName>Accept<\/actionName>[\s\S]*?<type>Default<\/type>[\s\S]*?<\/actionOverrides>/);
209
+ });
210
+
211
+ it("should have CancelEdit action override", () => {
212
+ expect(customObjectContent).toMatch(/<actionOverrides>[\s\S]*?<actionName>CancelEdit<\/actionName>[\s\S]*?<type>Default<\/type>[\s\S]*?<\/actionOverrides>/);
213
+ });
214
+
215
+ it("should have Clone action override", () => {
216
+ expect(customObjectContent).toMatch(/<actionOverrides>[\s\S]*?<actionName>Clone<\/actionName>[\s\S]*?<type>Default<\/type>[\s\S]*?<\/actionOverrides>/);
217
+ });
218
+
219
+ it("should have Delete action override", () => {
220
+ expect(customObjectContent).toMatch(/<actionOverrides>[\s\S]*?<actionName>Delete<\/actionName>[\s\S]*?<type>Default<\/type>[\s\S]*?<\/actionOverrides>/);
221
+ });
222
+
223
+ it("should have Edit action override", () => {
224
+ expect(customObjectContent).toMatch(/<actionOverrides>[\s\S]*?<actionName>Edit<\/actionName>[\s\S]*?<type>Default<\/type>[\s\S]*?<\/actionOverrides>/);
225
+ });
226
+
227
+ it("should have Follow action override", () => {
228
+ expect(customObjectContent).toMatch(/<actionOverrides>[\s\S]*?<actionName>Follow<\/actionName>[\s\S]*?<type>Default<\/type>[\s\S]*?<\/actionOverrides>/);
229
+ });
230
+
231
+ it("should have List action override", () => {
232
+ expect(customObjectContent).toMatch(/<actionOverrides>[\s\S]*?<actionName>List<\/actionName>[\s\S]*?<type>Default<\/type>[\s\S]*?<\/actionOverrides>/);
233
+ });
234
+
235
+ it("should have New action override", () => {
236
+ expect(customObjectContent).toMatch(/<actionOverrides>[\s\S]*?<actionName>New<\/actionName>[\s\S]*?<type>Default<\/type>[\s\S]*?<\/actionOverrides>/);
237
+ });
238
+
239
+ it("should have SaveEdit action override", () => {
240
+ expect(customObjectContent).toMatch(/<actionOverrides>[\s\S]*?<actionName>SaveEdit<\/actionName>[\s\S]*?<type>Default<\/type>[\s\S]*?<\/actionOverrides>/);
241
+ });
242
+
243
+ it("should have Tab action override", () => {
244
+ expect(customObjectContent).toMatch(/<actionOverrides>[\s\S]*?<actionName>Tab<\/actionName>[\s\S]*?<type>Default<\/type>[\s\S]*?<\/actionOverrides>/);
245
+ });
246
+
247
+ it("should have all action overrides with type Default", () => {
248
+ const typeMatches = customObjectContent.match(/<type>Default<\/type>/g);
249
+ expect(typeMatches).toHaveLength(10);
250
+ });
251
+ });
252
+
253
+ // =========================================================================
254
+ // CUSTOM FIELDS - 9 FIELDS TOTAL
255
+ // =========================================================================
256
+
257
+ describe("Custom Fields Detection", () => {
258
+ let customObjectContent: string;
259
+
260
+ beforeAll(() => {
261
+ const objectMetaPath = path.join(SALESFORCE_ENTERPRISE_PATH, "force-app/main/default/objects/CustomObject__c/CustomObject__c.object-meta.xml");
262
+ customObjectContent = fs.readFileSync(objectMetaPath, "utf-8");
263
+ });
264
+
265
+ it("should have 9 custom fields", () => {
266
+ const fieldMatches = customObjectContent.match(/<fields>[\s\S]*?<\/fields>/g);
267
+ expect(fieldMatches).toHaveLength(9);
268
+ });
269
+
270
+ // =========================================================================
271
+ // Amount__c - Currency field
272
+ // =========================================================================
273
+
274
+ describe("Amount__c (Currency)", () => {
275
+ it("should have Amount__c field defined", () => {
276
+ expect(customObjectContent).toMatch(/<fields>[\s\S]*?<name>Amount__c<\/name>[\s\S]*?<\/fields>/);
277
+ });
278
+
279
+ it("should have type Currency", () => {
280
+ expect(customObjectContent).toMatch(/<fields>[\s\S]*?<name>Amount__c<\/name>[\s\S]*?<type>Currency<\/type>[\s\S]*?<\/fields>/);
281
+ });
282
+
283
+ it("should have label Amount", () => {
284
+ expect(customObjectContent).toMatch(/<fields>[\s\S]*?<name>Amount__c<\/name>[\s\S]*?<label>Amount<\/label>[\s\S]*?<\/fields>/);
285
+ });
286
+
287
+ it("should have precision 18", () => {
288
+ expect(customObjectContent).toMatch(/<fields>[\s\S]*?<name>Amount__c<\/name>[\s\S]*?<precision>18<\/precision>[\s\S]*?<\/fields>/);
289
+ });
290
+
291
+ it("should have scale 2", () => {
292
+ expect(customObjectContent).toMatch(/<fields>[\s\S]*?<name>Amount__c<\/name>[\s\S]*?<scale>2<\/scale>[\s\S]*?<\/fields>/);
293
+ });
294
+
295
+ it("should have displayFormat #,##0.00", () => {
296
+ expect(customObjectContent).toMatch(/<fields>[\s\S]*?<name>Amount__c<\/name>[\s\S]*?<displayFormat>#,##0.00<\/displayFormat>[\s\S]*?<\/fields>/);
297
+ });
298
+
299
+ it("should not be required", () => {
300
+ expect(customObjectContent).toMatch(/<fields>[\s\S]*?<name>Amount__c<\/name>[\s\S]*?<required>false<\/required>[\s\S]*?<\/fields>/);
301
+ });
302
+
303
+ it("should not track history", () => {
304
+ expect(customObjectContent).toMatch(/<fields>[\s\S]*?<name>Amount__c<\/name>[\s\S]*?<trackHistory>false<\/trackHistory>[\s\S]*?<\/fields>/);
305
+ });
306
+ });
307
+
308
+ // =========================================================================
309
+ // Category__c - Picklist field
310
+ // =========================================================================
311
+
312
+ describe("Category__c (Picklist)", () => {
313
+ it("should have Category__c field defined", () => {
314
+ expect(customObjectContent).toMatch(/<fields>[\s\S]*?<name>Category__c<\/name>[\s\S]*?<\/fields>/);
315
+ });
316
+
317
+ it("should have type Picklist", () => {
318
+ expect(customObjectContent).toMatch(/<fields>[\s\S]*?<name>Category__c<\/name>[\s\S]*?<type>Picklist<\/type>[\s\S]*?<\/fields>/);
319
+ });
320
+
321
+ it("should have label Category", () => {
322
+ expect(customObjectContent).toMatch(/<fields>[\s\S]*?<name>Category__c<\/name>[\s\S]*?<label>Category<\/label>[\s\S]*?<\/fields>/);
323
+ });
324
+
325
+ it("should have picklist with 4 values", () => {
326
+ const categoryFieldMatch = customObjectContent.match(/<fields>[\s\S]*?<name>Category__c<\/name>[\s\S]*?<\/fields>/);
327
+ expect(categoryFieldMatch).toBeTruthy();
328
+ const categoryField = categoryFieldMatch?.[0] || "";
329
+ const picklistValues = categoryField.match(/<picklistValues>/g);
330
+ expect(picklistValues).toHaveLength(4);
331
+ });
332
+
333
+ it("should have Electronics picklist value", () => {
334
+ expect(customObjectContent).toMatch(/<fields>[\s\S]*?<name>Category__c<\/name>[\s\S]*?<fullName>Electronics<\/fullName>[\s\S]*?<\/fields>/);
335
+ });
336
+
337
+ it("should have Furniture picklist value", () => {
338
+ expect(customObjectContent).toMatch(/<fields>[\s\S]*?<name>Category__c<\/name>[\s\S]*?<fullName>Furniture<\/fullName>[\s\S]*?<\/fields>/);
339
+ });
340
+
341
+ it("should have Office Supplies picklist value", () => {
342
+ expect(customObjectContent).toMatch(/<fields>[\s\S]*?<name>Category__c<\/name>[\s\S]*?<fullName>Office Supplies<\/fullName>[\s\S]*?<\/fields>/);
343
+ });
344
+
345
+ it("should have Software picklist value", () => {
346
+ expect(customObjectContent).toMatch(/<fields>[\s\S]*?<name>Category__c<\/name>[\s\S]*?<fullName>Software<\/fullName>[\s\S]*?<\/fields>/);
347
+ });
348
+
349
+ it("should have Electronics as default value", () => {
350
+ expect(customObjectContent).toMatch(/<fields>[\s\S]*?<name>Category__c<\/name>[\s\S]*?<fullName>Electronics<\/fullName>[\s\S]*?<default>true<\/default>[\s\S]*?<\/fields>/);
351
+ });
352
+
353
+ it("should not be required", () => {
354
+ expect(customObjectContent).toMatch(/<fields>[\s\S]*?<name>Category__c<\/name>[\s\S]*?<required>false<\/required>[\s\S]*?<\/fields>/);
355
+ });
356
+
357
+ it("should not track history", () => {
358
+ expect(customObjectContent).toMatch(/<fields>[\s\S]*?<name>Category__c<\/name>[\s\S]*?<trackHistory>false<\/trackHistory>[\s\S]*?<\/fields>/);
359
+ });
360
+ });
361
+
362
+ // =========================================================================
363
+ // CustomAccount__c - Lookup field to Account
364
+ // =========================================================================
365
+
366
+ describe("CustomAccount__c (Lookup to Account)", () => {
367
+ it("should have CustomAccount__c field defined", () => {
368
+ expect(customObjectContent).toMatch(/<fields>[\s\S]*?<name>CustomAccount__c<\/name>[\s\S]*?<\/fields>/);
369
+ });
370
+
371
+ it("should have type Lookup", () => {
372
+ expect(customObjectContent).toMatch(/<fields>[\s\S]*?<name>CustomAccount__c<\/name>[\s\S]*?<type>Lookup<\/type>[\s\S]*?<\/fields>/);
373
+ });
374
+
375
+ it("should have label Related Account", () => {
376
+ expect(customObjectContent).toMatch(/<fields>[\s\S]*?<name>CustomAccount__c<\/name>[\s\S]*?<label>Related Account<\/label>[\s\S]*?<\/fields>/);
377
+ });
378
+
379
+ it("should reference Account object", () => {
380
+ expect(customObjectContent).toMatch(/<fields>[\s\S]*?<name>CustomAccount__c<\/name>[\s\S]*?<referenceTo>Account<\/referenceTo>[\s\S]*?<\/fields>/);
381
+ });
382
+
383
+ it("should have relationshipLabel Custom Objects", () => {
384
+ expect(customObjectContent).toMatch(/<fields>[\s\S]*?<name>CustomAccount__c<\/name>[\s\S]*?<relationshipLabel>Custom Objects<\/relationshipLabel>[\s\S]*?<\/fields>/);
385
+ });
386
+
387
+ it("should have relationshipName CustomObjects", () => {
388
+ expect(customObjectContent).toMatch(/<fields>[\s\S]*?<name>CustomAccount__c<\/name>[\s\S]*?<relationshipName>CustomObjects<\/relationshipName>[\s\S]*?<\/fields>/);
389
+ });
390
+
391
+ it("should not be required", () => {
392
+ expect(customObjectContent).toMatch(/<fields>[\s\S]*?<name>CustomAccount__c<\/name>[\s\S]*?<required>false<\/required>[\s\S]*?<\/fields>/);
393
+ });
394
+
395
+ it("should not track history", () => {
396
+ expect(customObjectContent).toMatch(/<fields>[\s\S]*?<name>CustomAccount__c<\/name>[\s\S]*?<trackHistory>false<\/trackHistory>[\s\S]*?<\/fields>/);
397
+ });
398
+ });
399
+
400
+ // =========================================================================
401
+ // Description__c - LongTextArea field
402
+ // =========================================================================
403
+
404
+ describe("Description__c (LongTextArea)", () => {
405
+ it("should have Description__c field defined", () => {
406
+ expect(customObjectContent).toMatch(/<fields>[\s\S]*?<name>Description__c<\/name>[\s\S]*?<\/fields>/);
407
+ });
408
+
409
+ it("should have type LongTextArea", () => {
410
+ expect(customObjectContent).toMatch(/<fields>[\s\S]*?<name>Description__c<\/name>[\s\S]*?<type>LongTextArea<\/type>[\s\S]*?<\/fields>/);
411
+ });
412
+
413
+ it("should have label Description", () => {
414
+ expect(customObjectContent).toMatch(/<fields>[\s\S]*?<name>Description__c<\/name>[\s\S]*?<label>Description<\/label>[\s\S]*?<\/fields>/);
415
+ });
416
+
417
+ it("should have length 32768", () => {
418
+ expect(customObjectContent).toMatch(/<fields>[\s\S]*?<name>Description__c<\/name>[\s\S]*?<length>32768<\/length>[\s\S]*?<\/fields>/);
419
+ });
420
+
421
+ it("should have visibleLines 3", () => {
422
+ expect(customObjectContent).toMatch(/<fields>[\s\S]*?<name>Description__c<\/name>[\s\S]*?<visibleLines>3<\/visibleLines>[\s\S]*?<\/fields>/);
423
+ });
424
+
425
+ it("should track history", () => {
426
+ expect(customObjectContent).toMatch(/<fields>[\s\S]*?<name>Description__c<\/name>[\s\S]*?<trackHistory>true<\/trackHistory>[\s\S]*?<\/fields>/);
427
+ });
428
+ });
429
+
430
+ // =========================================================================
431
+ // IsActive__c - Checkbox field
432
+ // =========================================================================
433
+
434
+ describe("IsActive__c (Checkbox)", () => {
435
+ it("should have IsActive__c field defined", () => {
436
+ expect(customObjectContent).toMatch(/<fields>[\s\S]*?<name>IsActive__c<\/name>[\s\S]*?<\/fields>/);
437
+ });
438
+
439
+ it("should have type Checkbox", () => {
440
+ expect(customObjectContent).toMatch(/<fields>[\s\S]*?<name>IsActive__c<\/name>[\s\S]*?<type>Checkbox<\/type>[\s\S]*?<\/fields>/);
441
+ });
442
+
443
+ it("should have label Is Active", () => {
444
+ expect(customObjectContent).toMatch(/<fields>[\s\S]*?<name>IsActive__c<\/name>[\s\S]*?<label>Is Active<\/label>[\s\S]*?<\/fields>/);
445
+ });
446
+
447
+ it("should have defaultValue false", () => {
448
+ expect(customObjectContent).toMatch(/<fields>[\s\S]*?<name>IsActive__c<\/name>[\s\S]*?<defaultValue>false<\/defaultValue>[\s\S]*?<\/fields>/);
449
+ });
450
+
451
+ it("should not track history", () => {
452
+ expect(customObjectContent).toMatch(/<fields>[\s\S]*?<name>IsActive__c<\/name>[\s\S]*?<trackHistory>false<\/trackHistory>[\s\S]*?<\/fields>/);
453
+ });
454
+ });
455
+
456
+ // =========================================================================
457
+ // Name__c - Text field
458
+ // =========================================================================
459
+
460
+ describe("Name__c (Text)", () => {
461
+ it("should have Name__c field defined", () => {
462
+ expect(customObjectContent).toMatch(/<fields>[\s\S]*?<name>Name__c<\/name>[\s\S]*?<\/fields>/);
463
+ });
464
+
465
+ it("should have type Text", () => {
466
+ expect(customObjectContent).toMatch(/<fields>[\s\S]*?<name>Name__c<\/name>[\s\S]*?<type>Text<\/type>[\s\S]*?<\/fields>/);
467
+ });
468
+
469
+ it("should have label Name", () => {
470
+ expect(customObjectContent).toMatch(/<fields>[\s\S]*?<name>Name__c<\/name>[\s\S]*?<label>Name<\/label>[\s\S]*?<\/fields>/);
471
+ });
472
+
473
+ it("should be required", () => {
474
+ expect(customObjectContent).toMatch(/<fields>[\s\S]*?<name>Name__c<\/name>[\s\S]*?<required>true<\/required>[\s\S]*?<\/fields>/);
475
+ });
476
+
477
+ it("should not be unique", () => {
478
+ expect(customObjectContent).toMatch(/<fields>[\s\S]*?<name>Name__c<\/name>[\s\S]*?<unique>false<\/unique>[\s\S]*?<\/fields>/);
479
+ });
480
+
481
+ it("should not track history", () => {
482
+ expect(customObjectContent).toMatch(/<fields>[\s\S]*?<name>Name__c<\/name>[\s\S]*?<trackHistory>false<\/trackHistory>[\s\S]*?<\/fields>/);
483
+ });
484
+ });
485
+
486
+ // =========================================================================
487
+ // Quantity__c - Number field
488
+ // =========================================================================
489
+
490
+ describe("Quantity__c (Number)", () => {
491
+ it("should have Quantity__c field defined", () => {
492
+ expect(customObjectContent).toMatch(/<fields>[\s\S]*?<name>Quantity__c<\/name>[\s\S]*?<\/fields>/);
493
+ });
494
+
495
+ it("should have type Number", () => {
496
+ expect(customObjectContent).toMatch(/<fields>[\s\S]*?<name>Quantity__c<\/name>[\s\S]*?<type>Number<\/type>[\s\S]*?<\/fields>/);
497
+ });
498
+
499
+ it("should have label Quantity", () => {
500
+ expect(customObjectContent).toMatch(/<fields>[\s\S]*?<name>Quantity__c<\/name>[\s\S]*?<label>Quantity<\/label>[\s\S]*?<\/fields>/);
501
+ });
502
+
503
+ it("should have displayFormat #,##0", () => {
504
+ expect(customObjectContent).toMatch(/<fields>[\s\S]*?<name>Quantity__c<\/name>[\s\S]*?<displayFormat>#,##0<\/displayFormat>[\s\S]*?<\/fields>/);
505
+ });
506
+
507
+ it("should have precision 18", () => {
508
+ expect(customObjectContent).toMatch(/<fields>[\s\S]*?<name>Quantity__c<\/name>[\s\S]*?<precision>18<\/precision>[\s\S]*?<\/fields>/);
509
+ });
510
+
511
+ it("should have scale 0", () => {
512
+ expect(customObjectContent).toMatch(/<fields>[\s\S]*?<name>Quantity__c<\/name>[\s\S]*?<scale>0<\/scale>[\s\S]*?<\/fields>/);
513
+ });
514
+
515
+ it("should not be required", () => {
516
+ expect(customObjectContent).toMatch(/<fields>[\s\S]*?<name>Quantity__c<\/name>[\s\S]*?<required>false<\/required>[\s\S]*?<\/fields>/);
517
+ });
518
+
519
+ it("should not track history", () => {
520
+ expect(customObjectContent).toMatch(/<fields>[\s\S]*?<name>Quantity__c<\/name>[\s\S]*?<trackHistory>false<\/trackHistory>[\s\S]*?<\/fields>/);
521
+ });
522
+ });
523
+
524
+ // =========================================================================
525
+ // Stage__c - Picklist field with trackHistory
526
+ // =========================================================================
527
+
528
+ describe("Stage__c (Picklist with trackHistory)", () => {
529
+ it("should have Stage__c field defined", () => {
530
+ expect(customObjectContent).toMatch(/<fields>[\s\S]*?<name>Stage__c<\/name>[\s\S]*?<\/fields>/);
531
+ });
532
+
533
+ it("should have type Picklist", () => {
534
+ expect(customObjectContent).toMatch(/<fields>[\s\S]*?<name>Stage__c<\/name>[\s\S]*?<type>Picklist<\/type>[\s\S]*?<\/fields>/);
535
+ });
536
+
537
+ it("should have label Stage", () => {
538
+ expect(customObjectContent).toMatch(/<fields>[\s\S]*?<name>Stage__c<\/name>[\s\S]*?<label>Stage<\/label>[\s\S]*?<\/fields>/);
539
+ });
540
+
541
+ it("should have picklist with 5 values", () => {
542
+ const stageField = extractFieldContent(customObjectContent, "Stage__c");
543
+ expect(stageField).toContain("<name>Stage__c</name>");
544
+ const picklistValues = stageField.match(/<picklistValues>/g);
545
+ expect(picklistValues).toHaveLength(5);
546
+ });
547
+
548
+ it("should have Draft picklist value (default)", () => {
549
+ expect(customObjectContent).toMatch(/<fields>[\s\S]*?<name>Stage__c<\/name>[\s\S]*?<fullName>Draft<\/fullName>[\s\S]*?<default>true<\/default>[\s\S]*?<\/fields>/);
550
+ });
551
+
552
+ it("should have Pending Approval picklist value", () => {
553
+ expect(customObjectContent).toMatch(/<fields>[\s\S]*?<name>Stage__c<\/name>[\s\S]*?<fullName>Pending Approval<\/fullName>[\s\S]*?<\/fields>/);
554
+ });
555
+
556
+ it("should have Approved picklist value", () => {
557
+ expect(customObjectContent).toMatch(/<fields>[\s\S]*?<name>Stage__c<\/name>[\s\S]*?<fullName>Approved<\/fullName>[\s\S]*?<\/fields>/);
558
+ });
559
+
560
+ it("should have Rejected picklist value", () => {
561
+ expect(customObjectContent).toMatch(/<fields>[\s\S]*?<name>Stage__c<\/name>[\s\S]*?<fullName>Rejected<\/fullName>[\s\S]*?<\/fields>/);
562
+ });
563
+
564
+ it("should have Completed picklist value", () => {
565
+ expect(customObjectContent).toMatch(/<fields>[\s\S]*?<name>Stage__c<\/name>[\s\S]*?<fullName>Completed<\/fullName>[\s\S]*?<\/fields>/);
566
+ });
567
+
568
+ it("should not be required", () => {
569
+ expect(customObjectContent).toMatch(/<fields>[\s\S]*?<name>Stage__c<\/name>[\s\S]*?<required>false<\/required>[\s\S]*?<\/fields>/);
570
+ });
571
+
572
+ it("should track history", () => {
573
+ expect(customObjectContent).toMatch(/<fields>[\s\S]*?<name>Stage__c<\/name>[\s\S]*?<trackHistory>true<\/trackHistory>[\s\S]*?<\/fields>/);
574
+ });
575
+ });
576
+
577
+ // =========================================================================
578
+ // Status__c - Picklist field
579
+ // =========================================================================
580
+
581
+ describe("Status__c (Picklist)", () => {
582
+ it("should have Status__c field defined", () => {
583
+ expect(customObjectContent).toMatch(/<fields>[\s\S]*?<name>Status__c<\/name>[\s\S]*?<\/fields>/);
584
+ });
585
+
586
+ it("should have type Picklist", () => {
587
+ expect(customObjectContent).toMatch(/<fields>[\s\S]*?<name>Status__c<\/name>[\s\S]*?<type>Picklist<\/type>[\s\S]*?<\/fields>/);
588
+ });
589
+
590
+ it("should have label Status", () => {
591
+ expect(customObjectContent).toMatch(/<fields>[\s\S]*?<name>Status__c<\/name>[\s\S]*?<label>Status<\/label>[\s\S]*?<\/fields>/);
592
+ });
593
+
594
+ it("should have picklist with 3 values", () => {
595
+ const statusField = extractFieldContent(customObjectContent, "Status__c");
596
+ expect(statusField).toContain("<name>Status__c</name>");
597
+ const picklistValues = statusField.match(/<picklistValues>/g);
598
+ expect(picklistValues).toHaveLength(3);
599
+ });
600
+
601
+ it("should have Active picklist value (default)", () => {
602
+ expect(customObjectContent).toMatch(/<fields>[\s\S]*?<name>Status__c<\/name>[\s\S]*?<fullName>Active<\/fullName>[\s\S]*?<default>true<\/default>[\s\S]*?<\/fields>/);
603
+ });
604
+
605
+ it("should have Inactive picklist value", () => {
606
+ expect(customObjectContent).toMatch(/<fields>[\s\S]*?<name>Status__c<\/name>[\s\S]*?<fullName>Inactive<\/fullName>[\s\S]*?<\/fields>/);
607
+ });
608
+
609
+ it("should have Pending picklist value", () => {
610
+ expect(customObjectContent).toMatch(/<fields>[\s\S]*?<name>Status__c<\/name>[\s\S]*?<fullName>Pending<\/fullName>[\s\S]*?<\/fields>/);
611
+ });
612
+
613
+ it("should not be required", () => {
614
+ expect(customObjectContent).toMatch(/<fields>[\s\S]*?<name>Status__c<\/name>[\s\S]*?<required>false<\/required>[\s\S]*?<\/fields>/);
615
+ });
616
+
617
+ it("should not track history", () => {
618
+ expect(customObjectContent).toMatch(/<fields>[\s\S]*?<name>Status__c<\/name>[\s\S]*?<trackHistory>false<\/trackHistory>[\s\S]*?<\/fields>/);
619
+ });
620
+ });
621
+ });
622
+
623
+ // =========================================================================
624
+ // FIELD TYPES SUMMARY
625
+ // =========================================================================
626
+
627
+ describe("Field Types Summary", () => {
628
+ let customObjectContent: string;
629
+
630
+ beforeAll(() => {
631
+ const objectMetaPath = path.join(SALESFORCE_ENTERPRISE_PATH, "force-app/main/default/objects/CustomObject__c/CustomObject__c.object-meta.xml");
632
+ customObjectContent = fs.readFileSync(objectMetaPath, "utf-8");
633
+ });
634
+
635
+ it("should have Currency field type", () => {
636
+ expect(customObjectContent).toMatch(/<type>Currency<\/type>/);
637
+ });
638
+
639
+ it("should have 3 Picklist field types", () => {
640
+ const picklistMatches = customObjectContent.match(/<type>Picklist<\/type>/g);
641
+ expect(picklistMatches).toHaveLength(3);
642
+ });
643
+
644
+ it("should have Lookup field type", () => {
645
+ expect(customObjectContent).toMatch(/<type>Lookup<\/type>/);
646
+ });
647
+
648
+ it("should have LongTextArea field type", () => {
649
+ expect(customObjectContent).toMatch(/<type>LongTextArea<\/type>/);
650
+ });
651
+
652
+ it("should have Checkbox field type", () => {
653
+ expect(customObjectContent).toMatch(/<type>Checkbox<\/type>/);
654
+ });
655
+
656
+ it("should have Text field type", () => {
657
+ expect(customObjectContent).toMatch(/<type>Text<\/type>/);
658
+ });
659
+
660
+ it("should have Number field type", () => {
661
+ expect(customObjectContent).toMatch(/<type>Number<\/type>/);
662
+ });
663
+
664
+ it("should have 9 total fields with type elements", () => {
665
+ const fieldBlocks = customObjectContent.match(/<fields>[\s\S]*?<\/fields>/g) || [];
666
+ let typeCount = 0;
667
+ for (const block of fieldBlocks) {
668
+ const types = block.match(/<type>\w+<\/type>/g);
669
+ if (types) typeCount += types.length;
670
+ }
671
+ expect(typeCount).toBe(9);
672
+ });
673
+ });
674
+
675
+ // =========================================================================
676
+ // FIELD PROPERTIES SUMMARY
677
+ // =========================================================================
678
+
679
+ describe("Field Properties Summary", () => {
680
+ let customObjectContent: string;
681
+
682
+ beforeAll(() => {
683
+ const objectMetaPath = path.join(SALESFORCE_ENTERPRISE_PATH, "force-app/main/default/objects/CustomObject__c/CustomObject__c.object-meta.xml");
684
+ customObjectContent = fs.readFileSync(objectMetaPath, "utf-8");
685
+ });
686
+
687
+ it("should have 1 required field (Name__c)", () => {
688
+ const requiredMatches = customObjectContent.match(/<required>true<\/required>/g);
689
+ expect(requiredMatches).toHaveLength(1);
690
+ });
691
+
692
+ it("should have 2 fields with trackHistory true", () => {
693
+ const trackHistoryMatches = customObjectContent.match(/<trackHistory>true<\/trackHistory>/g);
694
+ expect(trackHistoryMatches).toHaveLength(2);
695
+ });
696
+
697
+ it("should have 8 elements with trackHistory false (7 fields + nameField)", () => {
698
+ const trackHistoryFalseMatches = customObjectContent.match(/<trackHistory>false<\/trackHistory>/g);
699
+ expect(trackHistoryFalseMatches).toHaveLength(8);
700
+ });
701
+
702
+ it("should have 1 unique field check (Name__c unique=false)", () => {
703
+ expect(customObjectContent).toMatch(/<unique>false<\/unique>/);
704
+ });
705
+ });
706
+
707
+ // =========================================================================
708
+ // UNIT TESTS - Custom Object XML parsing patterns
709
+ // =========================================================================
710
+
711
+ describe("Unit: Custom Object XML parsing patterns", () => {
712
+ it("should parse CustomObject metadata elements", () => {
713
+ const objectXml = `<?xml version="1.0" encoding="UTF-8"?>
714
+ <CustomObject xmlns="http://soap.sforce.com/2006/04/metadata">
715
+ <label>Test Object</label>
716
+ <pluralLabel>Test Objects</pluralLabel>
717
+ <deploymentStatus>Deployed</deploymentStatus>
718
+ <sharingModel>ReadWrite</sharingModel>
719
+ </CustomObject>`;
720
+
721
+ expect(objectXml).toContain("<label>Test Object</label>");
722
+ expect(objectXml).toContain("<pluralLabel>Test Objects</pluralLabel>");
723
+ expect(objectXml).toContain("<deploymentStatus>Deployed</deploymentStatus>");
724
+ expect(objectXml).toContain("<sharingModel>ReadWrite</sharingModel>");
725
+ });
726
+
727
+ it("should parse enable flags", () => {
728
+ const objectXml = `<?xml version="1.0" encoding="UTF-8"?>
729
+ <CustomObject xmlns="http://soap.sforce.com/2006/04/metadata">
730
+ <enableActivities>true</enableActivities>
731
+ <enableBulkApi>true</enableBulkApi>
732
+ <enableReports>true</enableReports>
733
+ <enableSearch>true</enableSearch>
734
+ </CustomObject>`;
735
+
736
+ expect(objectXml).toContain("<enableActivities>true</enableActivities>");
737
+ expect(objectXml).toContain("<enableBulkApi>true</enableBulkApi>");
738
+ expect(objectXml).toContain("<enableReports>true</enableReports>");
739
+ expect(objectXml).toContain("<enableSearch>true</enableSearch>");
740
+ });
741
+
742
+ it("should parse field elements", () => {
743
+ const fieldXml = `<?xml version="1.0" encoding="UTF-8"?>
744
+ <CustomObject xmlns="http://soap.sforce.com/2006/04/metadata">
745
+ <fields>
746
+ <name>TestField__c</name>
747
+ <label>Test Field</label>
748
+ <type>Text</type>
749
+ <required>false</required>
750
+ <trackHistory>false</trackHistory>
751
+ </fields>
752
+ </CustomObject>`;
753
+
754
+ expect(fieldXml).toMatch(/<fields>[\s\S]*?<name>TestField__c<\/name>[\s\S]*?<\/fields>/);
755
+ expect(fieldXml).toContain("<type>Text</type>");
756
+ expect(fieldXml).toContain("<required>false</required>");
757
+ });
758
+
759
+ it("should parse Currency field with precision and scale", () => {
760
+ const currencyFieldXml = `<?xml version="1.0" encoding="UTF-8"?>
761
+ <CustomObject xmlns="http://soap.sforce.com/2006/04/metadata">
762
+ <fields>
763
+ <name>Amount__c</name>
764
+ <label>Amount</label>
765
+ <type>Currency</type>
766
+ <precision>18</precision>
767
+ <scale>2</scale>
768
+ <displayFormat>#,##0.00</displayFormat>
769
+ </fields>
770
+ </CustomObject>`;
771
+
772
+ expect(currencyFieldXml).toContain("<type>Currency</type>");
773
+ expect(currencyFieldXml).toContain("<precision>18</precision>");
774
+ expect(currencyFieldXml).toContain("<scale>2</scale>");
775
+ });
776
+
777
+ it("should parse Picklist field with values", () => {
778
+ const picklistFieldXml = `<?xml version="1.0" encoding="UTF-8"?>
779
+ <CustomObject xmlns="http://soap.sforce.com/2006/04/metadata">
780
+ <fields>
781
+ <name>Status__c</name>
782
+ <label>Status</label>
783
+ <type>Picklist</type>
784
+ <picklist>
785
+ <picklistValues>
786
+ <fullName>Active</fullName>
787
+ <default>true</default>
788
+ </picklistValues>
789
+ <picklistValues>
790
+ <fullName>Inactive</fullName>
791
+ <default>false</default>
792
+ </picklistValues>
793
+ </picklist>
794
+ </fields>
795
+ </CustomObject>`;
796
+
797
+ expect(picklistFieldXml).toContain("<type>Picklist</type>");
798
+ expect(picklistFieldXml).toContain("<fullName>Active</fullName>");
799
+ expect(picklistFieldXml).toContain("<default>true</default>");
800
+ });
801
+
802
+ it("should parse Lookup field with referenceTo", () => {
803
+ const lookupFieldXml = `<?xml version="1.0" encoding="UTF-8"?>
804
+ <CustomObject xmlns="http://soap.sforce.com/2006/04/metadata">
805
+ <fields>
806
+ <name>Account__c</name>
807
+ <label>Account</label>
808
+ <type>Lookup</type>
809
+ <referenceTo>Account</referenceTo>
810
+ <relationshipLabel>Custom Objects</relationshipLabel>
811
+ <relationshipName>CustomObjects</relationshipName>
812
+ </fields>
813
+ </CustomObject>`;
814
+
815
+ expect(lookupFieldXml).toContain("<type>Lookup</type>");
816
+ expect(lookupFieldXml).toContain("<referenceTo>Account</referenceTo>");
817
+ expect(lookupFieldXml).toContain("<relationshipLabel>Custom Objects</relationshipLabel>");
818
+ });
819
+
820
+ it("should parse LongTextArea field with length and visibleLines", () => {
821
+ const textAreaFieldXml = `<?xml version="1.0" encoding="UTF-8"?>
822
+ <CustomObject xmlns="http://soap.sforce.com/2006/04/metadata">
823
+ <fields>
824
+ <name>Description__c</name>
825
+ <label>Description</label>
826
+ <type>LongTextArea</type>
827
+ <length>32768</length>
828
+ <visibleLines>3</visibleLines>
829
+ <trackHistory>true</trackHistory>
830
+ </fields>
831
+ </CustomObject>`;
832
+
833
+ expect(textAreaFieldXml).toContain("<type>LongTextArea</type>");
834
+ expect(textAreaFieldXml).toContain("<length>32768</length>");
835
+ expect(textAreaFieldXml).toContain("<visibleLines>3</visibleLines>");
836
+ });
837
+
838
+ it("should parse actionOverrides", () => {
839
+ const actionOverrideXml = `<?xml version="1.0" encoding="UTF-8"?>
840
+ <CustomObject xmlns="http://soap.sforce.com/2006/04/metadata">
841
+ <actionOverrides>
842
+ <actionName>Edit</actionName>
843
+ <type>Default</type>
844
+ </actionOverrides>
845
+ </CustomObject>`;
846
+
847
+ expect(actionOverrideXml).toMatch(/<actionOverrides>[\s\S]*?<actionName>Edit<\/actionName>[\s\S]*?<\/actionOverrides>/);
848
+ expect(actionOverrideXml).toContain("<type>Default</type>");
849
+ });
850
+ });
851
+
852
+ // =========================================================================
853
+ // EDGE CASES
854
+ // =========================================================================
855
+
856
+ describe("Edge Cases", () => {
857
+ let customObjectContent: string;
858
+
859
+ beforeAll(() => {
860
+ const objectMetaPath = path.join(SALESFORCE_ENTERPRISE_PATH, "force-app/main/default/objects/CustomObject__c/CustomObject__c.object-meta.xml");
861
+ customObjectContent = fs.readFileSync(objectMetaPath, "utf-8");
862
+ });
863
+
864
+ it("should handle fields with displayFormat patterns", () => {
865
+ expect(customObjectContent).toContain("<displayFormat>#,##0.00</displayFormat>");
866
+ expect(customObjectContent).toContain("<displayFormat>#,##0</displayFormat>");
867
+ });
868
+
869
+ it("should handle fields with varying precision/scale combinations", () => {
870
+ expect(customObjectContent).toMatch(/<name>Amount__c<\/name>[\s\S]*?<precision>18<\/precision>[\s\S]*?<scale>2<\/scale>/);
871
+ expect(customObjectContent).toMatch(/<name>Quantity__c<\/name>[\s\S]*?<precision>18<\/precision>[\s\S]*?<scale>0<\/scale>/);
872
+ });
873
+
874
+ it("should handle picklist with multiple non-default values", () => {
875
+ const stageField = extractFieldContent(customObjectContent, "Stage__c");
876
+ expect(stageField).toContain("<name>Stage__c</name>");
877
+ const defaultTrueCount = (stageField.match(/<default>true<\/default>/g) || []).length;
878
+ const defaultFalseCount = (stageField.match(/<default>false<\/default>/g) || []).length;
879
+ expect(defaultTrueCount).toBe(1);
880
+ expect(defaultFalseCount).toBe(4);
881
+ });
882
+
883
+ it("should handle fields with same type but different properties", () => {
884
+ const picklistFields = customObjectContent.match(/<fields>[\s\S]*?<type>Picklist<\/type>[\s\S]*?<\/fields>/g);
885
+ expect(picklistFields).toHaveLength(3);
886
+ });
887
+
888
+ it("should handle fields with different trackHistory settings", () => {
889
+ const trackHistoryTrueMatches = customObjectContent.match(/<trackHistory>true<\/trackHistory>/g);
890
+ expect(trackHistoryTrueMatches).toHaveLength(2);
891
+ });
892
+
893
+ it("should handle LongTextArea with large length value", () => {
894
+ expect(customObjectContent).toMatch(/<name>Description__c<\/name>[\s\S]*?<length>32768<\/length>[\s\S]*?<\/fields>/);
895
+ });
896
+
897
+ it("should handle lookup field referencing standard object (Account)", () => {
898
+ expect(customObjectContent).toMatch(/<name>CustomAccount__c<\/name>[\s\S]*?<referenceTo>Account<\/referenceTo>[\s\S]*?<\/fields>/);
899
+ });
900
+
901
+ it("should handle checkbox field with boolean defaultValue", () => {
902
+ expect(customObjectContent).toMatch(/<name>IsActive__c<\/name>[\s\S]*?<defaultValue>false<\/defaultValue>[\s\S]*?<\/fields>/);
903
+ });
904
+
905
+ it("should handle text field with unique constraint", () => {
906
+ expect(customObjectContent).toMatch(/<name>Name__c<\/name>[\s\S]*?<unique>false<\/unique>[\s\S]*?<\/fields>/);
907
+ });
908
+
909
+ it("should handle search layouts with multiple column types", () => {
910
+ // Search columns include NAME, CUSTOM_ACCOUNT__C, STATUS__C, AMOUNT__C, CREATED_DATE
911
+ expect(customObjectContent).toContain("<searchColumns>NAME</searchColumns>");
912
+ expect(customObjectContent).toContain("<searchColumns>CUSTOM_ACCOUNT__C</searchColumns>");
913
+ expect(customObjectContent).toContain("<searchColumns>STATUS__C</searchColumns>");
914
+ expect(customObjectContent).toContain("<searchColumns>AMOUNT__C</searchColumns>");
915
+ expect(customObjectContent).toContain("<searchColumns>CREATED_DATE</searchColumns>");
916
+ });
917
+ });
918
+ });