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