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,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
+ });