@solidxai/core 0.1.2 → 0.1.5-beta.0

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 (469) hide show
  1. package/.claude/settings.local.json +8 -0
  2. package/dist/commands/run-tests.command.d.ts +37 -0
  3. package/dist/commands/run-tests.command.d.ts.map +1 -0
  4. package/dist/commands/run-tests.command.js +345 -0
  5. package/dist/commands/run-tests.command.js.map +1 -0
  6. package/dist/commands/test-data.command.d.ts +6 -6
  7. package/dist/commands/test-data.command.d.ts.map +1 -1
  8. package/dist/commands/test-data.command.js +25 -25
  9. package/dist/commands/test-data.command.js.map +1 -1
  10. package/dist/commands/test.command.d.ts +5 -0
  11. package/dist/commands/test.command.d.ts.map +1 -0
  12. package/dist/commands/test.command.js +26 -0
  13. package/dist/commands/test.command.js.map +1 -0
  14. package/dist/constants/error-messages.d.ts +1 -0
  15. package/dist/constants/error-messages.d.ts.map +1 -1
  16. package/dist/constants/error-messages.js +1 -0
  17. package/dist/constants/error-messages.js.map +1 -1
  18. package/dist/constants.d.ts +3 -3
  19. package/dist/constants.d.ts.map +1 -1
  20. package/dist/constants.js +12 -12
  21. package/dist/constants.js.map +1 -1
  22. package/dist/controllers/otp-authentication.controller.d.ts +1 -4
  23. package/dist/controllers/otp-authentication.controller.d.ts.map +1 -1
  24. package/dist/controllers/otp-authentication.controller.js +1 -1
  25. package/dist/controllers/role-metadata.controller.d.ts +1 -0
  26. package/dist/controllers/role-metadata.controller.d.ts.map +1 -1
  27. package/dist/controllers/role-metadata.controller.js +15 -0
  28. package/dist/controllers/role-metadata.controller.js.map +1 -1
  29. package/dist/controllers/service.controller.d.ts +0 -9
  30. package/dist/controllers/service.controller.d.ts.map +1 -1
  31. package/dist/controllers/service.controller.js +0 -45
  32. package/dist/controllers/service.controller.js.map +1 -1
  33. package/dist/dtos/basic-filters.dto.d.ts.map +1 -1
  34. package/dist/dtos/basic-filters.dto.js.map +1 -1
  35. package/dist/dtos/create-email-template.dto.d.ts.map +1 -1
  36. package/dist/dtos/create-email-template.dto.js.map +1 -1
  37. package/dist/dtos/create-list-of-values.dto.d.ts.map +1 -1
  38. package/dist/dtos/create-list-of-values.dto.js.map +1 -1
  39. package/dist/dtos/create-menu-item-metadata.dto.d.ts.map +1 -1
  40. package/dist/dtos/create-menu-item-metadata.dto.js.map +1 -1
  41. package/dist/dtos/create-role-metadata.dto.d.ts.map +1 -1
  42. package/dist/dtos/create-role-metadata.dto.js.map +1 -1
  43. package/dist/dtos/create-scheduled-job.dto.d.ts.map +1 -1
  44. package/dist/dtos/create-scheduled-job.dto.js.map +1 -1
  45. package/dist/dtos/create-security-rule.dto.d.ts.map +1 -1
  46. package/dist/dtos/create-security-rule.dto.js.map +1 -1
  47. package/dist/dtos/create-sms-template.dto.d.ts.map +1 -1
  48. package/dist/dtos/create-sms-template.dto.js.map +1 -1
  49. package/dist/dtos/create-user.dto.d.ts +1 -0
  50. package/dist/dtos/create-user.dto.d.ts.map +1 -1
  51. package/dist/dtos/create-user.dto.js +2 -1
  52. package/dist/dtos/create-user.dto.js.map +1 -1
  53. package/dist/dtos/create-view-metadata.dto.d.ts.map +1 -1
  54. package/dist/dtos/create-view-metadata.dto.js.map +1 -1
  55. package/dist/dtos/otp-sign-in.dto.d.ts +1 -1
  56. package/dist/dtos/otp-sign-in.dto.d.ts.map +1 -1
  57. package/dist/dtos/otp-sign-in.dto.js +2 -2
  58. package/dist/dtos/otp-sign-in.dto.js.map +1 -1
  59. package/dist/dtos/otp-sign-up.dto.d.ts +2 -2
  60. package/dist/dtos/otp-sign-up.dto.d.ts.map +1 -1
  61. package/dist/dtos/otp-sign-up.dto.js +2 -2
  62. package/dist/dtos/otp-sign-up.dto.js.map +1 -1
  63. package/dist/dtos/resolve-s3-url.dto.d.ts +2 -5
  64. package/dist/dtos/resolve-s3-url.dto.d.ts.map +1 -1
  65. package/dist/dtos/resolve-s3-url.dto.js +1 -13
  66. package/dist/dtos/resolve-s3-url.dto.js.map +1 -1
  67. package/dist/dtos/sign-up.dto.d.ts.map +1 -1
  68. package/dist/dtos/sign-up.dto.js.map +1 -1
  69. package/dist/dtos/update-email-template.dto.d.ts.map +1 -1
  70. package/dist/dtos/update-email-template.dto.js.map +1 -1
  71. package/dist/dtos/update-list-of-values.dto.d.ts.map +1 -1
  72. package/dist/dtos/update-list-of-values.dto.js.map +1 -1
  73. package/dist/dtos/update-menu-item-metadata.dto.d.ts.map +1 -1
  74. package/dist/dtos/update-menu-item-metadata.dto.js.map +1 -1
  75. package/dist/dtos/update-scheduled-job.dto.d.ts.map +1 -1
  76. package/dist/dtos/update-scheduled-job.dto.js.map +1 -1
  77. package/dist/dtos/update-security-rule.dto.d.ts.map +1 -1
  78. package/dist/dtos/update-security-rule.dto.js.map +1 -1
  79. package/dist/dtos/update-sms-template.dto.d.ts.map +1 -1
  80. package/dist/dtos/update-sms-template.dto.js.map +1 -1
  81. package/dist/dtos/update-view-metadata.dto.d.ts.map +1 -1
  82. package/dist/dtos/update-view-metadata.dto.js.map +1 -1
  83. package/dist/entities/user.entity.d.ts +1 -0
  84. package/dist/entities/user.entity.d.ts.map +1 -1
  85. package/dist/entities/user.entity.js +6 -1
  86. package/dist/entities/user.entity.js.map +1 -1
  87. package/dist/helpers/field-crud-managers/ManyToManyRelationFieldCrudManager.d.ts +2 -0
  88. package/dist/helpers/field-crud-managers/ManyToManyRelationFieldCrudManager.d.ts.map +1 -1
  89. package/dist/helpers/field-crud-managers/ManyToManyRelationFieldCrudManager.js +33 -23
  90. package/dist/helpers/field-crud-managers/ManyToManyRelationFieldCrudManager.js.map +1 -1
  91. package/dist/helpers/field-crud-managers/OneToManyRelationFieldCrudManager.d.ts +3 -0
  92. package/dist/helpers/field-crud-managers/OneToManyRelationFieldCrudManager.d.ts.map +1 -1
  93. package/dist/helpers/field-crud-managers/OneToManyRelationFieldCrudManager.js +36 -23
  94. package/dist/helpers/field-crud-managers/OneToManyRelationFieldCrudManager.js.map +1 -1
  95. package/dist/helpers/security.helper.js +1 -0
  96. package/dist/helpers/security.helper.js.map +1 -1
  97. package/dist/index.d.ts +3 -4
  98. package/dist/index.d.ts.map +1 -1
  99. package/dist/index.js +3 -4
  100. package/dist/index.js.map +1 -1
  101. package/dist/repository/solid-base.repository.d.ts +10 -1
  102. package/dist/repository/solid-base.repository.d.ts.map +1 -1
  103. package/dist/repository/solid-base.repository.js +109 -0
  104. package/dist/repository/solid-base.repository.js.map +1 -1
  105. package/dist/seeders/module-metadata-seeder.service.d.ts +2 -0
  106. package/dist/seeders/module-metadata-seeder.service.d.ts.map +1 -1
  107. package/dist/seeders/module-metadata-seeder.service.js +142 -91
  108. package/dist/seeders/module-metadata-seeder.service.js.map +1 -1
  109. package/dist/seeders/module-test-data.service.d.ts.map +1 -1
  110. package/dist/seeders/module-test-data.service.js +3 -3
  111. package/dist/seeders/module-test-data.service.js.map +1 -1
  112. package/dist/seeders/permission-metadata-seeder.service.d.ts +1 -1
  113. package/dist/seeders/permission-metadata-seeder.service.d.ts.map +1 -1
  114. package/dist/seeders/permission-metadata-seeder.service.js +1 -1
  115. package/dist/seeders/permission-metadata-seeder.service.js.map +1 -1
  116. package/dist/seeders/seed-data/solid-core-metadata.json +12 -25
  117. package/dist/services/authentication.service.d.ts +22 -8
  118. package/dist/services/authentication.service.d.ts.map +1 -1
  119. package/dist/services/authentication.service.js +228 -214
  120. package/dist/services/authentication.service.js.map +1 -1
  121. package/dist/services/chatter-message.service.d.ts +2 -0
  122. package/dist/services/chatter-message.service.d.ts.map +1 -1
  123. package/dist/services/chatter-message.service.js +18 -2
  124. package/dist/services/chatter-message.service.js.map +1 -1
  125. package/dist/services/crud-helper.service.d.ts +4 -0
  126. package/dist/services/crud-helper.service.d.ts.map +1 -1
  127. package/dist/services/crud-helper.service.js +66 -32
  128. package/dist/services/crud-helper.service.js.map +1 -1
  129. package/dist/services/crud.service.d.ts.map +1 -1
  130. package/dist/services/crud.service.js +7 -4
  131. package/dist/services/crud.service.js.map +1 -1
  132. package/dist/services/field-metadata.service.d.ts.map +1 -1
  133. package/dist/services/field-metadata.service.js.map +1 -1
  134. package/dist/services/file/disk-file.service.d.ts +0 -2
  135. package/dist/services/file/disk-file.service.d.ts.map +1 -1
  136. package/dist/services/file/disk-file.service.js +7 -16
  137. package/dist/services/file/disk-file.service.js.map +1 -1
  138. package/dist/services/file/index.d.ts +1 -0
  139. package/dist/services/file/index.d.ts.map +1 -1
  140. package/dist/services/file/index.js +1 -0
  141. package/dist/services/file/index.js.map +1 -1
  142. package/dist/services/file/storage-path-builder.d.ts +17 -0
  143. package/dist/services/file/storage-path-builder.d.ts.map +1 -0
  144. package/dist/{seeders/sms-template-seeder.service.js → services/file/storage-path-builder.js} +45 -35
  145. package/dist/services/file/storage-path-builder.js.map +1 -0
  146. package/dist/services/media.service.d.ts +1 -1
  147. package/dist/services/media.service.d.ts.map +1 -1
  148. package/dist/services/media.service.js +45 -6
  149. package/dist/services/media.service.js.map +1 -1
  150. package/dist/services/mediaStorageProviders/file-s3-storage-provider.js.map +1 -1
  151. package/dist/services/mediaStorageProviders/file-storage-provider.d.ts.map +1 -1
  152. package/dist/services/mediaStorageProviders/file-storage-provider.js +46 -7
  153. package/dist/services/mediaStorageProviders/file-storage-provider.js.map +1 -1
  154. package/dist/services/module-metadata.service.d.ts +4 -6
  155. package/dist/services/module-metadata.service.d.ts.map +1 -1
  156. package/dist/services/module-metadata.service.js +16 -14
  157. package/dist/services/module-metadata.service.js.map +1 -1
  158. package/dist/services/queues/common.d.ts +3 -0
  159. package/dist/services/queues/common.d.ts.map +1 -0
  160. package/dist/services/queues/common.js +39 -0
  161. package/dist/services/queues/common.js.map +1 -0
  162. package/dist/services/queues/database-publisher.service.d.ts.map +1 -1
  163. package/dist/services/queues/database-publisher.service.js +3 -1
  164. package/dist/services/queues/database-publisher.service.js.map +1 -1
  165. package/dist/services/queues/database-subscriber.service.d.ts.map +1 -1
  166. package/dist/services/queues/database-subscriber.service.js +5 -2
  167. package/dist/services/queues/database-subscriber.service.js.map +1 -1
  168. package/dist/services/queues/rabbitmq-publisher.service.d.ts.map +1 -1
  169. package/dist/services/queues/rabbitmq-publisher.service.js +13 -6
  170. package/dist/services/queues/rabbitmq-publisher.service.js.map +1 -1
  171. package/dist/services/queues/rabbitmq-subscriber.service.d.ts.map +1 -1
  172. package/dist/services/queues/rabbitmq-subscriber.service.js +9 -5
  173. package/dist/services/queues/rabbitmq-subscriber.service.js.map +1 -1
  174. package/dist/services/setting.service.d.ts +3 -2
  175. package/dist/services/setting.service.d.ts.map +1 -1
  176. package/dist/services/setting.service.js +7 -4
  177. package/dist/services/setting.service.js.map +1 -1
  178. package/dist/services/settings/default-settings-provider.service.d.ts +24 -2
  179. package/dist/services/settings/default-settings-provider.service.d.ts.map +1 -1
  180. package/dist/services/settings/default-settings-provider.service.js +8 -6
  181. package/dist/services/settings/default-settings-provider.service.js.map +1 -1
  182. package/dist/solid-core.module.d.ts +3 -1
  183. package/dist/solid-core.module.d.ts.map +1 -1
  184. package/dist/solid-core.module.js +49 -9
  185. package/dist/solid-core.module.js.map +1 -1
  186. package/dist/testing/__examples__/register-example-specs.d.ts +3 -0
  187. package/dist/testing/__examples__/register-example-specs.d.ts.map +1 -0
  188. package/dist/testing/__examples__/register-example-specs.js +8 -0
  189. package/dist/testing/__examples__/register-example-specs.js.map +1 -0
  190. package/dist/testing/__examples__/specs/custom-health.spec.d.ts +17 -0
  191. package/dist/testing/__examples__/specs/custom-health.spec.d.ts.map +1 -0
  192. package/dist/testing/__examples__/specs/custom-health.spec.js +30 -0
  193. package/dist/testing/__examples__/specs/custom-health.spec.js.map +1 -0
  194. package/dist/testing/adapters/api/api-adapter.d.ts +9 -0
  195. package/dist/testing/adapters/api/api-adapter.d.ts.map +1 -0
  196. package/dist/testing/adapters/api/api-adapter.js +76 -0
  197. package/dist/testing/adapters/api/api-adapter.js.map +1 -0
  198. package/dist/testing/adapters/api/api.types.d.ts +14 -0
  199. package/dist/testing/adapters/api/api.types.d.ts.map +1 -0
  200. package/dist/testing/adapters/api/api.types.js +3 -0
  201. package/dist/testing/adapters/api/api.types.js.map +1 -0
  202. package/dist/testing/adapters/ui/playwright-adapter.d.ts +14 -0
  203. package/dist/testing/adapters/ui/playwright-adapter.d.ts.map +1 -0
  204. package/dist/testing/adapters/ui/playwright-adapter.js +80 -0
  205. package/dist/testing/adapters/ui/playwright-adapter.js.map +1 -0
  206. package/dist/testing/adapters/ui/ui.types.d.ts +5 -0
  207. package/dist/testing/adapters/ui/ui.types.d.ts.map +1 -0
  208. package/dist/testing/adapters/ui/ui.types.js +3 -0
  209. package/dist/testing/adapters/ui/ui.types.js.map +1 -0
  210. package/dist/testing/contracts/runtime-context.types.d.ts +35 -0
  211. package/dist/testing/contracts/runtime-context.types.d.ts.map +1 -0
  212. package/dist/testing/contracts/runtime-context.types.js +3 -0
  213. package/dist/testing/contracts/runtime-context.types.js.map +1 -0
  214. package/dist/testing/contracts/test-spec.types.d.ts +21 -0
  215. package/dist/testing/contracts/test-spec.types.d.ts.map +1 -0
  216. package/dist/testing/contracts/test-spec.types.js +3 -0
  217. package/dist/testing/contracts/test-spec.types.js.map +1 -0
  218. package/dist/testing/contracts/testing-metadata.types.d.ts +41 -0
  219. package/dist/testing/contracts/testing-metadata.types.d.ts.map +1 -0
  220. package/dist/testing/contracts/testing-metadata.types.js +3 -0
  221. package/dist/testing/contracts/testing-metadata.types.js.map +1 -0
  222. package/dist/testing/core/interpolation.d.ts +4 -0
  223. package/dist/testing/core/interpolation.d.ts.map +1 -0
  224. package/dist/testing/core/interpolation.js +180 -0
  225. package/dist/testing/core/interpolation.js.map +1 -0
  226. package/dist/testing/core/normalize-steps.d.ts +7 -0
  227. package/dist/testing/core/normalize-steps.d.ts.map +1 -0
  228. package/dist/testing/core/normalize-steps.js +20 -0
  229. package/dist/testing/core/normalize-steps.js.map +1 -0
  230. package/dist/testing/core/resource-store.d.ts +8 -0
  231. package/dist/testing/core/resource-store.d.ts.map +1 -0
  232. package/dist/testing/core/resource-store.js +41 -0
  233. package/dist/testing/core/resource-store.js.map +1 -0
  234. package/dist/testing/core/spec-registry.d.ts +10 -0
  235. package/dist/testing/core/spec-registry.d.ts.map +1 -0
  236. package/dist/testing/core/spec-registry.js +32 -0
  237. package/dist/testing/core/spec-registry.js.map +1 -0
  238. package/dist/testing/core/step-registry.d.ts +10 -0
  239. package/dist/testing/core/step-registry.d.ts.map +1 -0
  240. package/dist/testing/core/step-registry.js +26 -0
  241. package/dist/testing/core/step-registry.js.map +1 -0
  242. package/dist/testing/core/testing-engine.d.ts +14 -0
  243. package/dist/testing/core/testing-engine.d.ts.map +1 -0
  244. package/dist/testing/core/testing-engine.js +97 -0
  245. package/dist/testing/core/testing-engine.js.map +1 -0
  246. package/dist/testing/core/timeout.d.ts +2 -0
  247. package/dist/testing/core/timeout.d.ts.map +1 -0
  248. package/dist/testing/core/timeout.js +18 -0
  249. package/dist/testing/core/timeout.js.map +1 -0
  250. package/dist/testing/reporter/attachments.d.ts +4 -0
  251. package/dist/testing/reporter/attachments.d.ts.map +1 -0
  252. package/dist/testing/reporter/attachments.js +25 -0
  253. package/dist/testing/reporter/attachments.js.map +1 -0
  254. package/dist/testing/reporter/console-reporter.d.ts +45 -0
  255. package/dist/testing/reporter/console-reporter.d.ts.map +1 -0
  256. package/dist/testing/reporter/console-reporter.js +189 -0
  257. package/dist/testing/reporter/console-reporter.js.map +1 -0
  258. package/dist/testing/reporter/reporter.types.d.ts +37 -0
  259. package/dist/testing/reporter/reporter.types.d.ts.map +1 -0
  260. package/dist/testing/reporter/reporter.types.js +3 -0
  261. package/dist/testing/reporter/reporter.types.js.map +1 -0
  262. package/dist/testing/runner/lifecycle.d.ts +9 -0
  263. package/dist/testing/runner/lifecycle.d.ts.map +1 -0
  264. package/dist/testing/runner/lifecycle.js +33 -0
  265. package/dist/testing/runner/lifecycle.js.map +1 -0
  266. package/dist/testing/runner/run-from-metadata.d.ts +24 -0
  267. package/dist/testing/runner/run-from-metadata.d.ts.map +1 -0
  268. package/dist/testing/runner/run-from-metadata.js +70 -0
  269. package/dist/testing/runner/run-from-metadata.js.map +1 -0
  270. package/dist/testing/runner/scenario-filter.d.ts +9 -0
  271. package/dist/testing/runner/scenario-filter.d.ts.map +1 -0
  272. package/dist/testing/runner/scenario-filter.js +22 -0
  273. package/dist/testing/runner/scenario-filter.js.map +1 -0
  274. package/dist/testing/steps/api/auth.step.d.ts +3 -0
  275. package/dist/testing/steps/api/auth.step.d.ts.map +1 -0
  276. package/dist/testing/steps/api/auth.step.js +38 -0
  277. package/dist/testing/steps/api/auth.step.js.map +1 -0
  278. package/dist/testing/steps/api/index.d.ts +3 -0
  279. package/dist/testing/steps/api/index.d.ts.map +1 -0
  280. package/dist/testing/steps/api/index.js +10 -0
  281. package/dist/testing/steps/api/index.js.map +1 -0
  282. package/dist/testing/steps/api/request.step.d.ts +3 -0
  283. package/dist/testing/steps/api/request.step.d.ts.map +1 -0
  284. package/dist/testing/steps/api/request.step.js +281 -0
  285. package/dist/testing/steps/api/request.step.js.map +1 -0
  286. package/dist/testing/steps/assert/http.step.d.ts +3 -0
  287. package/dist/testing/steps/assert/http.step.d.ts.map +1 -0
  288. package/dist/testing/steps/assert/http.step.js +27 -0
  289. package/dist/testing/steps/assert/http.step.js.map +1 -0
  290. package/dist/testing/steps/assert/index.d.ts +3 -0
  291. package/dist/testing/steps/assert/index.d.ts.map +1 -0
  292. package/dist/testing/steps/assert/index.js +12 -0
  293. package/dist/testing/steps/assert/index.js.map +1 -0
  294. package/dist/testing/steps/assert/jsonpath.step.d.ts +3 -0
  295. package/dist/testing/steps/assert/jsonpath.step.d.ts.map +1 -0
  296. package/dist/testing/steps/assert/jsonpath.step.js +40 -0
  297. package/dist/testing/steps/assert/jsonpath.step.js.map +1 -0
  298. package/dist/testing/steps/assert/primitives.step.d.ts +3 -0
  299. package/dist/testing/steps/assert/primitives.step.d.ts.map +1 -0
  300. package/dist/testing/steps/assert/primitives.step.js +43 -0
  301. package/dist/testing/steps/assert/primitives.step.js.map +1 -0
  302. package/dist/testing/steps/test/index.d.ts +3 -0
  303. package/dist/testing/steps/test/index.d.ts.map +1 -0
  304. package/dist/testing/steps/test/index.js +8 -0
  305. package/dist/testing/steps/test/index.js.map +1 -0
  306. package/dist/testing/steps/test/test-spec.step.d.ts +3 -0
  307. package/dist/testing/steps/test/test-spec.step.d.ts.map +1 -0
  308. package/dist/testing/steps/test/test-spec.step.js +41 -0
  309. package/dist/testing/steps/test/test-spec.step.js.map +1 -0
  310. package/dist/testing/steps/ui/actions.step.d.ts +3 -0
  311. package/dist/testing/steps/ui/actions.step.d.ts.map +1 -0
  312. package/dist/testing/steps/ui/actions.step.js +31 -0
  313. package/dist/testing/steps/ui/actions.step.js.map +1 -0
  314. package/dist/testing/steps/ui/assertions.step.d.ts +3 -0
  315. package/dist/testing/steps/ui/assertions.step.d.ts.map +1 -0
  316. package/dist/testing/steps/ui/assertions.step.js +41 -0
  317. package/dist/testing/steps/ui/assertions.step.js.map +1 -0
  318. package/dist/testing/steps/ui/form.step.d.ts +3 -0
  319. package/dist/testing/steps/ui/form.step.d.ts.map +1 -0
  320. package/dist/testing/steps/ui/form.step.js +34 -0
  321. package/dist/testing/steps/ui/form.step.js.map +1 -0
  322. package/dist/testing/steps/ui/index.d.ts +3 -0
  323. package/dist/testing/steps/ui/index.d.ts.map +1 -0
  324. package/dist/testing/steps/ui/index.js +14 -0
  325. package/dist/testing/steps/ui/index.js.map +1 -0
  326. package/dist/testing/steps/ui/navigation.step.d.ts +3 -0
  327. package/dist/testing/steps/ui/navigation.step.d.ts.map +1 -0
  328. package/dist/testing/steps/ui/navigation.step.js +39 -0
  329. package/dist/testing/steps/ui/navigation.step.js.map +1 -0
  330. package/dist/testing/steps/util/index.d.ts +3 -0
  331. package/dist/testing/steps/util/index.d.ts.map +1 -0
  332. package/dist/testing/steps/util/index.js +12 -0
  333. package/dist/testing/steps/util/index.js.map +1 -0
  334. package/dist/testing/steps/util/log.step.d.ts +3 -0
  335. package/dist/testing/steps/util/log.step.d.ts.map +1 -0
  336. package/dist/testing/steps/util/log.step.js +18 -0
  337. package/dist/testing/steps/util/log.step.js.map +1 -0
  338. package/dist/testing/steps/util/require.step.d.ts +3 -0
  339. package/dist/testing/steps/util/require.step.d.ts.map +1 -0
  340. package/dist/testing/steps/util/require.step.js +16 -0
  341. package/dist/testing/steps/util/require.step.js.map +1 -0
  342. package/dist/testing/steps/util/sleep.step.d.ts +3 -0
  343. package/dist/testing/steps/util/sleep.step.d.ts.map +1 -0
  344. package/dist/testing/steps/util/sleep.step.js +13 -0
  345. package/dist/testing/steps/util/sleep.step.js.map +1 -0
  346. package/docs/test-data-workflow.md +51 -11
  347. package/package.json +10 -2
  348. package/src/commands/run-tests.command.ts +278 -0
  349. package/src/commands/test-data.command.ts +26 -26
  350. package/src/commands/test.command.ts +14 -0
  351. package/src/constants/error-messages.ts +1 -0
  352. package/src/constants.ts +3 -3
  353. package/src/controllers/role-metadata.controller.ts +26 -18
  354. package/src/controllers/service.controller.ts +58 -59
  355. package/src/dtos/basic-filters.dto.ts +0 -2
  356. package/src/dtos/create-email-template.dto.ts +7 -0
  357. package/src/dtos/create-list-of-values.dto.ts +7 -0
  358. package/src/dtos/create-menu-item-metadata.dto.ts +12 -1
  359. package/src/dtos/create-role-metadata.dto.ts +9 -0
  360. package/src/dtos/create-scheduled-job.dto.ts +14 -0
  361. package/src/dtos/create-security-rule.dto.ts +6 -0
  362. package/src/dtos/create-sms-template.dto.ts +6 -0
  363. package/src/dtos/create-user.dto.ts +1 -0
  364. package/src/dtos/create-view-metadata.dto.ts +11 -0
  365. package/src/dtos/otp-sign-in.dto.ts +3 -3
  366. package/src/dtos/otp-sign-up.dto.ts +3 -3
  367. package/src/dtos/resolve-s3-url.dto.ts +2 -12
  368. package/src/dtos/sign-up.dto.ts +0 -2
  369. package/src/dtos/update-email-template.dto.ts +6 -0
  370. package/src/dtos/update-list-of-values.dto.ts +8 -0
  371. package/src/dtos/update-menu-item-metadata.dto.ts +12 -0
  372. package/src/dtos/update-scheduled-job.dto.ts +15 -0
  373. package/src/dtos/update-security-rule.dto.ts +7 -0
  374. package/src/dtos/update-sms-template.dto.ts +32 -32
  375. package/src/dtos/update-view-metadata.dto.ts +12 -0
  376. package/src/entities/user.entity.ts +3 -0
  377. package/src/helpers/field-crud-managers/ManyToManyRelationFieldCrudManager.ts +43 -32
  378. package/src/helpers/field-crud-managers/OneToManyRelationFieldCrudManager.ts +45 -33
  379. package/src/helpers/security.helper.ts +1 -1
  380. package/src/index.ts +3 -4
  381. package/src/repository/solid-base.repository.ts +172 -1
  382. package/src/seeders/module-metadata-seeder.service.ts +191 -150
  383. package/src/seeders/module-test-data.service.ts +5 -3
  384. package/src/seeders/permission-metadata-seeder.service.ts +1 -4
  385. package/src/seeders/seed-data/solid-core-metadata.json +12 -25
  386. package/src/services/authentication.service.ts +268 -266
  387. package/src/services/chatter-message.service.ts +18 -1
  388. package/src/services/crud-helper.service.ts +79 -36
  389. package/src/services/crud.service.ts +10 -4
  390. package/src/services/field-metadata.service.ts +0 -71
  391. package/src/services/file/disk-file.service.ts +8 -18
  392. package/src/services/file/index.ts +1 -0
  393. package/src/services/file/storage-path-builder.ts +56 -0
  394. package/src/services/media.service.ts +13 -7
  395. package/src/services/mediaStorageProviders/file-s3-storage-provider.ts +1 -1
  396. package/src/services/mediaStorageProviders/file-storage-provider.ts +13 -8
  397. package/src/services/module-metadata.service.ts +18 -15
  398. package/src/services/queues/common.ts +75 -0
  399. package/src/services/queues/database-publisher.service.ts +4 -1
  400. package/src/services/queues/database-subscriber.service.ts +5 -3
  401. package/src/services/queues/rabbitmq-publisher.service.ts +17 -7
  402. package/src/services/queues/rabbitmq-subscriber.service.ts +9 -5
  403. package/src/services/setting.service.ts +5 -3
  404. package/src/services/settings/default-settings-provider.service.ts +5 -3
  405. package/src/solid-core.module.ts +20 -12
  406. package/src/testing/README.md +364 -0
  407. package/src/testing/__examples__/register-example-specs.ts +6 -0
  408. package/src/testing/__examples__/specs/custom-health.spec.ts +29 -0
  409. package/src/testing/__examples__/testing.sample.json +82 -0
  410. package/src/testing/adapters/api/api-adapter.ts +85 -0
  411. package/src/testing/adapters/api/api.types.ts +15 -0
  412. package/src/testing/adapters/ui/playwright-adapter.ts +54 -0
  413. package/src/testing/adapters/ui/ui.types.ts +4 -0
  414. package/src/testing/contracts/runtime-context.types.ts +36 -0
  415. package/src/testing/contracts/test-spec.types.ts +24 -0
  416. package/src/testing/contracts/testing-metadata.types.ts +46 -0
  417. package/src/testing/core/interpolation.ts +189 -0
  418. package/src/testing/core/normalize-steps.ts +21 -0
  419. package/src/testing/core/resource-store.ts +38 -0
  420. package/src/testing/core/spec-registry.ts +33 -0
  421. package/src/testing/core/step-registry.ts +27 -0
  422. package/src/testing/core/testing-engine.ts +127 -0
  423. package/src/testing/core/timeout.ts +19 -0
  424. package/src/testing/reporter/attachments.ts +25 -0
  425. package/src/testing/reporter/console-reporter.ts +229 -0
  426. package/src/testing/reporter/reporter.types.ts +36 -0
  427. package/src/testing/runner/lifecycle.ts +31 -0
  428. package/src/testing/runner/run-from-metadata.ts +87 -0
  429. package/src/testing/runner/scenario-filter.ts +33 -0
  430. package/src/testing/steps/api/auth.step.ts +66 -0
  431. package/src/testing/steps/api/index.ts +10 -0
  432. package/src/testing/steps/api/request.step.ts +358 -0
  433. package/src/testing/steps/assert/http.step.ts +33 -0
  434. package/src/testing/steps/assert/index.ts +12 -0
  435. package/src/testing/steps/assert/jsonpath.step.ts +50 -0
  436. package/src/testing/steps/assert/primitives.step.ts +69 -0
  437. package/src/testing/steps/test/index.ts +8 -0
  438. package/src/testing/steps/test/test-spec.step.ts +52 -0
  439. package/src/testing/steps/ui/actions.step.ts +36 -0
  440. package/src/testing/steps/ui/assertions.step.ts +54 -0
  441. package/src/testing/steps/ui/form.step.ts +39 -0
  442. package/src/testing/steps/ui/index.ts +12 -0
  443. package/src/testing/steps/ui/navigation.step.ts +53 -0
  444. package/src/testing/steps/util/index.ts +10 -0
  445. package/src/testing/steps/util/log.step.ts +19 -0
  446. package/src/testing/steps/util/require.step.ts +16 -0
  447. package/src/testing/steps/util/sleep.step.ts +15 -0
  448. package/tsconfig.json +35 -25
  449. package/tsconfig.tests.json +14 -0
  450. package/dist/passport-strategies/local.strategy.d.ts +0 -15
  451. package/dist/passport-strategies/local.strategy.d.ts.map +0 -1
  452. package/dist/passport-strategies/local.strategy.js +0 -44
  453. package/dist/passport-strategies/local.strategy.js.map +0 -1
  454. package/dist/seeders/email-template-seeder.service.d.ts +0 -10
  455. package/dist/seeders/email-template-seeder.service.d.ts.map +0 -1
  456. package/dist/seeders/email-template-seeder.service.js +0 -84
  457. package/dist/seeders/email-template-seeder.service.js.map +0 -1
  458. package/dist/seeders/sms-template-seeder.service.d.ts +0 -10
  459. package/dist/seeders/sms-template-seeder.service.d.ts.map +0 -1
  460. package/dist/seeders/sms-template-seeder.service.js.map +0 -1
  461. package/dist/seeders/user-seeder.service.d.ts +0 -10
  462. package/dist/seeders/user-seeder.service.d.ts.map +0 -1
  463. package/dist/seeders/user-seeder.service.js +0 -44
  464. package/dist/seeders/user-seeder.service.js.map +0 -1
  465. package/dist/tsconfig.tsbuildinfo +0 -1
  466. package/src/passport-strategies/local.strategy.ts +0 -28
  467. package/src/seeders/email-template-seeder.service.ts +0 -49
  468. package/src/seeders/sms-template-seeder.service.ts +0 -50
  469. package/src/seeders/user-seeder.service.ts +0 -33
@@ -0,0 +1 @@
1
+ {"version":3,"file":"request.step.d.ts","sourceRoot":"","sources":["../../../../src/testing/steps/api/request.step.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AA8NxD,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,YAAY,GAAG,IAAI,CAoInE"}
@@ -0,0 +1,281 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.registerApiRequestStep = registerApiRequestStep;
7
+ const attachments_1 = require("../../reporter/attachments");
8
+ const form_data_1 = __importDefault(require("form-data"));
9
+ const crypto_1 = __importDefault(require("crypto"));
10
+ const fs_1 = __importDefault(require("fs"));
11
+ const https_1 = __importDefault(require("https"));
12
+ const path_1 = __importDefault(require("path"));
13
+ const qs_1 = __importDefault(require("qs"));
14
+ const TMP_DIR = "/tmp/.solidx-testing-files";
15
+ const MAX_REDIRECTS = 5;
16
+ function isPlainObject(value) {
17
+ return !!value && typeof value === "object" && !Array.isArray(value);
18
+ }
19
+ function deepMerge(target, source) {
20
+ if (isPlainObject(target) && isPlainObject(source)) {
21
+ const out = { ...target };
22
+ for (const [key, value] of Object.entries(source)) {
23
+ if (key in out) {
24
+ out[key] = deepMerge(out[key], value);
25
+ }
26
+ else {
27
+ out[key] = value;
28
+ }
29
+ }
30
+ return out;
31
+ }
32
+ return source;
33
+ }
34
+ function stripUndefined(value) {
35
+ if (Array.isArray(value)) {
36
+ return value.map(stripUndefined);
37
+ }
38
+ if (isPlainObject(value)) {
39
+ const out = {};
40
+ for (const [key, val] of Object.entries(value)) {
41
+ if (val === undefined)
42
+ continue;
43
+ out[key] = stripUndefined(val);
44
+ }
45
+ return out;
46
+ }
47
+ return value;
48
+ }
49
+ function ensureTmpDir() {
50
+ fs_1.default.mkdirSync(TMP_DIR, { recursive: true });
51
+ }
52
+ function buildTempFilePath(urlObj) {
53
+ const ext = path_1.default.extname(urlObj.pathname);
54
+ const base = path_1.default.basename(urlObj.pathname, ext) || "file";
55
+ const safeBase = base.replace(/[^a-zA-Z0-9-_]/g, "_");
56
+ const suffix = `${Date.now()}-${crypto_1.default.randomBytes(6).toString("hex")}`;
57
+ return path_1.default.join(TMP_DIR, `${safeBase}-${suffix}${ext}`);
58
+ }
59
+ function downloadUrlToFile(urlValue, redirectCount = 0) {
60
+ if (!urlValue.startsWith("https://")) {
61
+ throw new Error(`Only https URLs are allowed for file downloads: ${urlValue}`);
62
+ }
63
+ if (redirectCount > MAX_REDIRECTS) {
64
+ throw new Error(`Too many redirects while downloading file: ${urlValue}`);
65
+ }
66
+ const urlObj = new URL(urlValue);
67
+ ensureTmpDir();
68
+ const filePath = buildTempFilePath(urlObj);
69
+ return new Promise((resolve, reject) => {
70
+ const fileStream = fs_1.default.createWriteStream(filePath);
71
+ const request = https_1.default.get(urlObj, (response) => {
72
+ const status = response.statusCode ?? 0;
73
+ const location = response.headers.location;
74
+ if (status >= 300 && status < 400 && location) {
75
+ response.resume();
76
+ fileStream.close(() => fs_1.default.unlink(filePath, () => { }));
77
+ const nextUrl = new URL(location, urlObj).toString();
78
+ downloadUrlToFile(nextUrl, redirectCount + 1).then(resolve).catch(reject);
79
+ return;
80
+ }
81
+ if (status >= 400) {
82
+ response.resume();
83
+ fileStream.close(() => fs_1.default.unlink(filePath, () => { }));
84
+ reject(new Error(`Failed to download file. HTTP ${status}`));
85
+ return;
86
+ }
87
+ response.pipe(fileStream);
88
+ });
89
+ request.on("error", (err) => {
90
+ fileStream.close(() => fs_1.default.unlink(filePath, () => { }));
91
+ reject(err);
92
+ });
93
+ fileStream.on("error", (err) => {
94
+ request.destroy();
95
+ fs_1.default.unlink(filePath, () => { });
96
+ reject(err);
97
+ });
98
+ fileStream.on("finish", () => {
99
+ fileStream.close(() => resolve(filePath));
100
+ });
101
+ });
102
+ }
103
+ function resolveFilePath(rawValue) {
104
+ const value = rawValue.startsWith("file:") ? rawValue.slice(5) : rawValue;
105
+ if (!value) {
106
+ throw new Error('Invalid file reference. Use "file:/absolute/path".');
107
+ }
108
+ if (!path_1.default.isAbsolute(value)) {
109
+ throw new Error(`File path must be absolute: ${value}`);
110
+ }
111
+ if (!fs_1.default.existsSync(value)) {
112
+ throw new Error(`File does not exist: ${value}`);
113
+ }
114
+ return value;
115
+ }
116
+ async function resolveFileReference(rawValue) {
117
+ if (rawValue.startsWith("url:")) {
118
+ const urlValue = rawValue.slice(4);
119
+ if (!urlValue) {
120
+ throw new Error('Invalid url reference. Use "url:https://...".');
121
+ }
122
+ const filePath = await downloadUrlToFile(urlValue);
123
+ return { filePath, source: "url", url: urlValue };
124
+ }
125
+ return { filePath: resolveFilePath(rawValue), source: "file" };
126
+ }
127
+ function formItemsFromRecord(record) {
128
+ return Object.entries(record).map(([name, value]) => {
129
+ if (typeof value === "string" && (value.startsWith("file:") || value.startsWith("url:"))) {
130
+ return { name, value, type: "file" };
131
+ }
132
+ return { name, value };
133
+ });
134
+ }
135
+ async function buildFormData(items) {
136
+ const form = new form_data_1.default();
137
+ const logItems = [];
138
+ for (const item of items) {
139
+ if (!item?.name) {
140
+ throw new Error('Form item is missing required "name".');
141
+ }
142
+ const rawValue = item.value;
143
+ const isFile = item.type === "file" || (typeof rawValue === "string" && (rawValue.startsWith("file:") || rawValue.startsWith("url:")));
144
+ if (isFile) {
145
+ if (typeof rawValue !== "string") {
146
+ throw new Error(`Form file value must be a string for field: ${item.name}`);
147
+ }
148
+ const resolved = await resolveFileReference(rawValue);
149
+ const filename = item.filename ?? path_1.default.basename(resolved.filePath);
150
+ form.append(item.name, fs_1.default.createReadStream(resolved.filePath), {
151
+ filename,
152
+ contentType: item.contentType,
153
+ });
154
+ logItems.push({
155
+ name: item.name,
156
+ type: "file",
157
+ source: resolved.source,
158
+ url: resolved.url,
159
+ path: resolved.filePath,
160
+ filename,
161
+ contentType: item.contentType,
162
+ });
163
+ }
164
+ else {
165
+ const textValue = rawValue === undefined || rawValue === null ? "" : typeof rawValue === "string" ? rawValue : JSON.stringify(rawValue);
166
+ form.append(item.name, textValue);
167
+ logItems.push({
168
+ name: item.name,
169
+ type: "text",
170
+ value: textValue,
171
+ });
172
+ }
173
+ }
174
+ return { form, logItems };
175
+ }
176
+ function registerApiRequestStep(registry) {
177
+ registry.register("api.request", async (ctx, step) => {
178
+ if (!ctx.api) {
179
+ throw new Error('Missing API adapter on context for op "api.request"');
180
+ }
181
+ const input = (step.with ?? {});
182
+ if (!input.method) {
183
+ throw new Error('Missing "method" in step.with for op "api.request"');
184
+ }
185
+ if (!input.url) {
186
+ throw new Error('Missing "url" in step.with for op "api.request"');
187
+ }
188
+ const rawFormData = input.formData ?? input.body;
189
+ const formItems = Array.isArray(rawFormData) ? rawFormData : isPlainObject(rawFormData) ? formItemsFromRecord(rawFormData) : undefined;
190
+ if (rawFormData !== undefined && !formItems) {
191
+ throw new Error('formData/body must be an array of items or an object, for op "api.request".');
192
+ }
193
+ if (formItems && (input.json !== undefined || input.bodyText !== undefined)) {
194
+ throw new Error('Use either formData/body or json/bodyText, not both, for op "api.request".');
195
+ }
196
+ const rawUrl = input.url;
197
+ const absolute = /^[a-z][a-z0-9+.-]*:/i.test(rawUrl);
198
+ const urlObj = new URL(rawUrl, "http://solid.local");
199
+ const urlQuery = urlObj.search
200
+ ? qs_1.default.parse(urlObj.search, { ignoreQueryPrefix: true, allowDots: true, depth: 10 })
201
+ : {};
202
+ let stepQuery = {};
203
+ if (input.query !== undefined) {
204
+ stepQuery =
205
+ typeof input.query === "string"
206
+ ? qs_1.default.parse(input.query, { ignoreQueryPrefix: true, allowDots: true, depth: 10 })
207
+ : input.query;
208
+ }
209
+ const mergedQuery = deepMerge(urlQuery, stepQuery);
210
+ const queryString = qs_1.default.stringify(mergedQuery, { addQueryPrefix: true, allowDots: true });
211
+ urlObj.search = queryString;
212
+ const finalUrl = absolute
213
+ ? urlObj.toString()
214
+ : `${urlObj.pathname}${urlObj.search}${urlObj.hash}`;
215
+ let formData;
216
+ let formLogItems;
217
+ if (formItems) {
218
+ const built = await buildFormData(formItems);
219
+ formData = built.form;
220
+ formLogItems = built.logItems;
221
+ }
222
+ const req = {
223
+ method: input.method,
224
+ url: finalUrl,
225
+ headers: input.headers,
226
+ json: input.json,
227
+ bodyText: input.bodyText,
228
+ formData,
229
+ };
230
+ const startedAt = Date.now();
231
+ const printApiLogs = ctx.options?.printApiLogs ?? false;
232
+ const logName = `api.request ${req.method} ${finalUrl}`;
233
+ const requestLog = stripUndefined({
234
+ method: req.method,
235
+ url: finalUrl,
236
+ headers: req.headers,
237
+ query: mergedQuery,
238
+ queryString: urlObj.search ? urlObj.search.slice(1) : "",
239
+ json: input.json,
240
+ bodyText: input.bodyText,
241
+ formData: formLogItems,
242
+ });
243
+ let response;
244
+ try {
245
+ response = await ctx.api.http(req);
246
+ }
247
+ catch (err) {
248
+ if (printApiLogs) {
249
+ (0, attachments_1.attachJson)(ctx, logName, {
250
+ request: requestLog,
251
+ durationMs: Date.now() - startedAt,
252
+ error: err instanceof Error ? err.message : String(err),
253
+ });
254
+ }
255
+ throw err;
256
+ }
257
+ const durationMs = Date.now() - startedAt;
258
+ ctx.last = { ...(ctx.last ?? {}), apiResponse: response };
259
+ if (printApiLogs) {
260
+ const responseLog = stripUndefined({
261
+ status: response.status,
262
+ headers: response.headers,
263
+ bodyJson: response.bodyJson,
264
+ bodyText: response.bodyJson === undefined ? response.bodyText : undefined,
265
+ });
266
+ (0, attachments_1.attachJson)(ctx, logName, {
267
+ request: requestLog,
268
+ response: responseLog,
269
+ durationMs,
270
+ });
271
+ }
272
+ return {
273
+ status: response.status,
274
+ headers: response.headers,
275
+ bodyText: response.bodyText,
276
+ bodyJson: response.bodyJson,
277
+ body: response.bodyJson ?? response.bodyText,
278
+ };
279
+ });
280
+ }
281
+ //# sourceMappingURL=request.step.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"request.step.js","sourceRoot":"","sources":["../../../../src/testing/steps/api/request.step.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ApiRequestOptions } from \"../../adapters/api/api.types\";\nimport type { TestContext } from \"../../contracts/runtime-context.types\";\nimport type { OpStep } from \"../../contracts/testing-metadata.types\";\nimport { StepRegistry } from \"../../core/step-registry\";\nimport { attachJson } from \"../../reporter/attachments\";\nimport FormData from \"form-data\";\nimport crypto from \"crypto\";\nimport fs from \"fs\";\nimport https from \"https\";\nimport path from \"path\";\nimport qs from \"qs\";\n\nconst TMP_DIR = \"/tmp/.solidx-testing-files\";\nconst MAX_REDIRECTS = 5;\n\ntype ApiFormItem = {\n name: string;\n value: any;\n type?: \"text\" | \"file\";\n filename?: string;\n contentType?: string;\n};\n\ntype ApiRequestInput = {\n method: string;\n url: string;\n headers?: Record<string, string>;\n json?: unknown;\n bodyText?: string;\n // Extra query params (object or querystring).\n query?: Record<string, any> | string;\n // Form data payload (array of items).\n formData?: ApiFormItem[] | Record<string, any>;\n // Alias for formData (array or object).\n body?: ApiFormItem[] | Record<string, any>;\n};\n\nfunction isPlainObject(value: unknown): value is Record<string, any> {\n // Only merge plain objects.\n return !!value && typeof value === \"object\" && !Array.isArray(value);\n}\n\nfunction deepMerge(target: any, source: any): any {\n if (isPlainObject(target) && isPlainObject(source)) {\n // Clone target to avoid mutation.\n const out: Record<string, any> = { ...target };\n for (const [key, value] of Object.entries(source)) {\n if (key in out) {\n // Merge nested keys.\n out[key] = deepMerge(out[key], value);\n } else {\n // Add new keys.\n out[key] = value;\n }\n }\n // Return merged object.\n return out;\n }\n // For non-objects, source wins.\n return source;\n}\n\nfunction stripUndefined(value: any): any {\n if (Array.isArray(value)) {\n return value.map(stripUndefined);\n }\n if (isPlainObject(value)) {\n const out: Record<string, any> = {};\n for (const [key, val] of Object.entries(value)) {\n if (val === undefined) continue;\n out[key] = stripUndefined(val);\n }\n return out;\n }\n return value;\n}\n\nfunction ensureTmpDir(): void {\n fs.mkdirSync(TMP_DIR, { recursive: true });\n}\n\nfunction buildTempFilePath(urlObj: URL): string {\n const ext = path.extname(urlObj.pathname);\n const base = path.basename(urlObj.pathname, ext) || \"file\";\n const safeBase = base.replace(/[^a-zA-Z0-9-_]/g, \"_\");\n const suffix = `${Date.now()}-${crypto.randomBytes(6).toString(\"hex\")}`;\n return path.join(TMP_DIR, `${safeBase}-${suffix}${ext}`);\n}\n\nfunction downloadUrlToFile(urlValue: string, redirectCount: number = 0): Promise<string> {\n if (!urlValue.startsWith(\"https://\")) {\n throw new Error(`Only https URLs are allowed for file downloads: ${urlValue}`);\n }\n if (redirectCount > MAX_REDIRECTS) {\n throw new Error(`Too many redirects while downloading file: ${urlValue}`);\n }\n\n const urlObj = new URL(urlValue);\n ensureTmpDir();\n const filePath = buildTempFilePath(urlObj);\n\n return new Promise((resolve, reject) => {\n const fileStream = fs.createWriteStream(filePath);\n\n const request = https.get(urlObj, (response) => {\n const status = response.statusCode ?? 0;\n const location = response.headers.location;\n\n if (status >= 300 && status < 400 && location) {\n response.resume();\n fileStream.close(() => fs.unlink(filePath, () => {}));\n const nextUrl = new URL(location, urlObj).toString();\n downloadUrlToFile(nextUrl, redirectCount + 1).then(resolve).catch(reject);\n return;\n }\n\n if (status >= 400) {\n response.resume();\n fileStream.close(() => fs.unlink(filePath, () => {}));\n reject(new Error(`Failed to download file. HTTP ${status}`));\n return;\n }\n\n response.pipe(fileStream);\n });\n\n request.on(\"error\", (err) => {\n fileStream.close(() => fs.unlink(filePath, () => {}));\n reject(err);\n });\n\n fileStream.on(\"error\", (err) => {\n request.destroy();\n fs.unlink(filePath, () => {});\n reject(err);\n });\n\n fileStream.on(\"finish\", () => {\n fileStream.close(() => resolve(filePath));\n });\n });\n}\n\nfunction resolveFilePath(rawValue: string): string {\n const value = rawValue.startsWith(\"file:\") ? rawValue.slice(5) : rawValue;\n if (!value) {\n throw new Error('Invalid file reference. Use \"file:/absolute/path\".');\n }\n if (!path.isAbsolute(value)) {\n throw new Error(`File path must be absolute: ${value}`);\n }\n if (!fs.existsSync(value)) {\n throw new Error(`File does not exist: ${value}`);\n }\n return value;\n}\n\nasync function resolveFileReference(rawValue: string): Promise<{ filePath: string; source: \"file\" | \"url\"; url?: string }>{\n if (rawValue.startsWith(\"url:\")) {\n const urlValue = rawValue.slice(4);\n if (!urlValue) {\n throw new Error('Invalid url reference. Use \"url:https://...\".');\n }\n const filePath = await downloadUrlToFile(urlValue);\n return { filePath, source: \"url\", url: urlValue };\n }\n\n return { filePath: resolveFilePath(rawValue), source: \"file\" };\n}\n\nfunction formItemsFromRecord(record: Record<string, any>): ApiFormItem[] {\n return Object.entries(record).map(([name, value]) => {\n if (typeof value === \"string\" && (value.startsWith(\"file:\") || value.startsWith(\"url:\"))) {\n return { name, value, type: \"file\" };\n }\n return { name, value };\n });\n}\n\nasync function buildFormData(items: ApiFormItem[]): Promise<{ form: FormData; logItems: Record<string, any>[] }>{\n const form = new FormData();\n const logItems: Record<string, any>[] = [];\n\n for (const item of items) {\n if (!item?.name) {\n throw new Error('Form item is missing required \"name\".');\n }\n const rawValue = item.value;\n const isFile = item.type === \"file\" || (typeof rawValue === \"string\" && (rawValue.startsWith(\"file:\") || rawValue.startsWith(\"url:\")));\n\n if (isFile) {\n if (typeof rawValue !== \"string\") {\n throw new Error(`Form file value must be a string for field: ${item.name}`);\n }\n const resolved = await resolveFileReference(rawValue);\n const filename = item.filename ?? path.basename(resolved.filePath);\n form.append(item.name, fs.createReadStream(resolved.filePath), {\n filename,\n contentType: item.contentType,\n });\n logItems.push({\n name: item.name,\n type: \"file\",\n source: resolved.source,\n url: resolved.url,\n path: resolved.filePath,\n filename,\n contentType: item.contentType,\n });\n } else {\n // TODO: Need to test the JSON.stringify(rawValue) functionality here...\n // This scenario will happen only when we try to create embedded one-to-many or many-to-one objects in create API calls...\n const textValue = rawValue === undefined || rawValue === null ? \"\" : typeof rawValue === \"string\" ? rawValue : JSON.stringify(rawValue);\n form.append(item.name, textValue);\n logItems.push({\n name: item.name,\n type: \"text\",\n value: textValue,\n });\n }\n }\n\n return { form, logItems };\n}\n\nexport function registerApiRequestStep(registry: StepRegistry): void {\n registry.register(\"api.request\", async (ctx: TestContext, step: OpStep) => {\n if (!ctx.api) {\n throw new Error('Missing API adapter on context for op \"api.request\"');\n }\n\n const input = (step.with ?? {}) as ApiRequestInput;\n if (!input.method) {\n throw new Error('Missing \"method\" in step.with for op \"api.request\"');\n }\n if (!input.url) {\n throw new Error('Missing \"url\" in step.with for op \"api.request\"');\n }\n\n const rawFormData = input.formData ?? input.body;\n const formItems = Array.isArray(rawFormData) ? rawFormData : isPlainObject(rawFormData) ? formItemsFromRecord(rawFormData) : undefined;\n\n if (rawFormData !== undefined && !formItems) {\n throw new Error('formData/body must be an array of items or an object, for op \"api.request\".');\n }\n\n if (formItems && (input.json !== undefined || input.bodyText !== undefined)) {\n throw new Error('Use either formData/body or json/bodyText, not both, for op \"api.request\".');\n }\n\n // Original URL (may include query).\n const rawUrl = input.url;\n\n // Detect absolute URLs by scheme.\n const absolute = /^[a-z][a-z0-9+.-]*:/i.test(rawUrl);\n\n // Parse with base for relative URLs.\n const urlObj = new URL(rawUrl, \"http://solid.local\");\n\n // Parse URL query into object.\n const urlQuery = urlObj.search\n ? (qs.parse(urlObj.search, { ignoreQueryPrefix: true, allowDots: true, depth: 10 }) as Record<string, any>)\n : {}; // No query in URL.\n let stepQuery: Record<string, any> = {};\n if (input.query !== undefined) {\n stepQuery =\n typeof input.query === \"string\"\n // Parse query string.\n ? (qs.parse(input.query, { ignoreQueryPrefix: true, allowDots: true, depth: 10 }) as Record<string, any>)\n // Use object as-is.\n : (input.query as Record<string, any>);\n }\n\n // Step query overrides URL query.\n const mergedQuery = deepMerge(urlQuery, stepQuery);\n\n // Rebuild query string.\n const queryString = qs.stringify(mergedQuery, { addQueryPrefix: true, allowDots: true });\n\n // Apply merged query to URL.\n urlObj.search = queryString;\n const finalUrl = absolute\n // Preserve absolute URL.\n ? urlObj.toString()\n // Keep relative URL shape.\n : `${urlObj.pathname}${urlObj.search}${urlObj.hash}`;\n\n let formData: FormData | undefined;\n let formLogItems: Record<string, any>[] | undefined;\n if (formItems) {\n const built = await buildFormData(formItems);\n formData = built.form;\n formLogItems = built.logItems;\n }\n\n const req: ApiRequestOptions = {\n method: input.method,\n url: finalUrl,\n headers: input.headers,\n json: input.json,\n bodyText: input.bodyText,\n formData,\n };\n\n const startedAt = Date.now();\n const printApiLogs = ctx.options?.printApiLogs ?? false;\n const logName = `api.request ${req.method} ${finalUrl}`;\n const requestLog = stripUndefined({\n method: req.method,\n url: finalUrl,\n headers: req.headers,\n query: mergedQuery,\n queryString: urlObj.search ? urlObj.search.slice(1) : \"\",\n json: input.json,\n bodyText: input.bodyText,\n formData: formLogItems,\n });\n\n let response;\n try {\n response = await ctx.api.http(req);\n } catch (err: any) {\n if (printApiLogs) {\n attachJson(ctx, logName, {\n request: requestLog,\n durationMs: Date.now() - startedAt,\n error: err instanceof Error ? err.message : String(err),\n });\n }\n throw err;\n }\n\n const durationMs = Date.now() - startedAt;\n ctx.last = { ...(ctx.last ?? {}), apiResponse: response };\n\n if (printApiLogs) {\n const responseLog = stripUndefined({\n status: response.status,\n headers: response.headers,\n bodyJson: response.bodyJson,\n bodyText: response.bodyJson === undefined ? response.bodyText : undefined,\n });\n attachJson(ctx, logName, {\n request: requestLog,\n response: responseLog,\n durationMs,\n });\n }\n\n return {\n status: response.status,\n headers: response.headers,\n bodyText: response.bodyText,\n bodyJson: response.bodyJson,\n body: response.bodyJson ?? response.bodyText,\n };\n });\n}\n"]}
@@ -0,0 +1,3 @@
1
+ import { StepRegistry } from "../../core/step-registry";
2
+ export declare function registerHttpAssertSteps(registry: StepRegistry): void;
3
+ //# sourceMappingURL=http.step.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http.step.d.ts","sourceRoot":"","sources":["../../../../src/testing/steps/assert/http.step.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAKxD,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,YAAY,GAAG,IAAI,CAyBpE"}
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.registerHttpAssertSteps = registerHttpAssertSteps;
4
+ const attachments_1 = require("../../reporter/attachments");
5
+ function registerHttpAssertSteps(registry) {
6
+ registry.register("assert.httpStatus", async (ctx, step) => {
7
+ const input = (step.with ?? {});
8
+ const response = input.from ?? ctx.last?.apiResponse;
9
+ if (!response) {
10
+ throw new Error('Missing ApiResponse for op "assert.httpStatus"');
11
+ }
12
+ if (input.is === undefined) {
13
+ throw new Error('Missing "is" in step.with for op "assert.httpStatus"');
14
+ }
15
+ if (ctx.options?.printApiLogs && ctx.reporter.attach) {
16
+ (0, attachments_1.attachJson)(ctx, "apiResponse", response);
17
+ }
18
+ if (response.status !== input.is) {
19
+ const err = new Error(`Expected HTTP status ${input.is} but got ${response.status}`);
20
+ err.httpResponseBody = response.bodyText;
21
+ err.httpStatus = response.status;
22
+ err.httpExpectedStatus = input.is;
23
+ throw err;
24
+ }
25
+ });
26
+ }
27
+ //# sourceMappingURL=http.step.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http.step.js","sourceRoot":"","sources":["../../../../src/testing/steps/assert/http.step.ts"],"names":[],"mappings":";;AAOA,0DAyBC;AA7BD,4DAAwD;AAIxD,SAAgB,uBAAuB,CAAC,QAAsB;IAC5D,QAAQ,CAAC,QAAQ,CAAC,mBAAmB,EAAE,KAAK,EAAE,GAAgB,EAAE,IAAY,EAAE,EAAE;QAC9E,MAAM,KAAK,GAAG,CAAC,IAAI,CAAC,IAAI,IAAI,EAAE,CAAoB,CAAC;QACnD,MAAM,QAAQ,GAAG,KAAK,CAAC,IAAI,IAAI,GAAG,CAAC,IAAI,EAAE,WAAW,CAAC;QACrD,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,MAAM,IAAI,KAAK,CAAC,gDAAgD,CAAC,CAAC;QACpE,CAAC;QACD,IAAI,KAAK,CAAC,EAAE,KAAK,SAAS,EAAE,CAAC;YAC3B,MAAM,IAAI,KAAK,CAAC,sDAAsD,CAAC,CAAC;QAC1E,CAAC;QAED,IAAI,GAAG,CAAC,OAAO,EAAE,YAAY,IAAI,GAAG,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC;YACrD,IAAA,wBAAU,EAAC,GAAG,EAAE,aAAa,EAAE,QAAQ,CAAC,CAAC;QAC3C,CAAC;QAED,IAAI,QAAQ,CAAC,MAAM,KAAK,KAAK,CAAC,EAAE,EAAE,CAAC;YACjC,MAAM,GAAG,GAAG,IAAI,KAAK,CACnB,wBAAwB,KAAK,CAAC,EAAE,YAAY,QAAQ,CAAC,MAAM,EAAE,CAC9D,CAAC;YACD,GAAW,CAAC,gBAAgB,GAAG,QAAQ,CAAC,QAAQ,CAAC;YACjD,GAAW,CAAC,UAAU,GAAG,QAAQ,CAAC,MAAM,CAAC;YACzC,GAAW,CAAC,kBAAkB,GAAG,KAAK,CAAC,EAAE,CAAC;YAC3C,MAAM,GAAG,CAAC;QACZ,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC","sourcesContent":["import type { ApiResponse, TestContext } from \"../../contracts/runtime-context.types\";\nimport type { OpStep } from \"../../contracts/testing-metadata.types\";\nimport { StepRegistry } from \"../../core/step-registry\";\nimport { attachJson } from \"../../reporter/attachments\";\n\ntype HttpStatusInput = { from?: ApiResponse; is: number };\n\nexport function registerHttpAssertSteps(registry: StepRegistry): void {\n registry.register(\"assert.httpStatus\", async (ctx: TestContext, step: OpStep) => {\n const input = (step.with ?? {}) as HttpStatusInput;\n const response = input.from ?? ctx.last?.apiResponse;\n if (!response) {\n throw new Error('Missing ApiResponse for op \"assert.httpStatus\"');\n }\n if (input.is === undefined) {\n throw new Error('Missing \"is\" in step.with for op \"assert.httpStatus\"');\n }\n\n if (ctx.options?.printApiLogs && ctx.reporter.attach) {\n attachJson(ctx, \"apiResponse\", response);\n }\n\n if (response.status !== input.is) {\n const err = new Error(\n `Expected HTTP status ${input.is} but got ${response.status}`,\n );\n (err as any).httpResponseBody = response.bodyText;\n (err as any).httpStatus = response.status;\n (err as any).httpExpectedStatus = input.is;\n throw err;\n }\n });\n}\n"]}
@@ -0,0 +1,3 @@
1
+ import { StepRegistry } from "../../core/step-registry";
2
+ export declare function registerAssertSteps(registry: StepRegistry): void;
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/testing/steps/assert/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAKxD,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,YAAY,GAAG,IAAI,CAIhE"}
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.registerAssertSteps = registerAssertSteps;
4
+ const http_step_1 = require("./http.step");
5
+ const jsonpath_step_1 = require("./jsonpath.step");
6
+ const primitives_step_1 = require("./primitives.step");
7
+ function registerAssertSteps(registry) {
8
+ (0, primitives_step_1.registerPrimitiveAssertSteps)(registry);
9
+ (0, http_step_1.registerHttpAssertSteps)(registry);
10
+ (0, jsonpath_step_1.registerJsonPathAssertSteps)(registry);
11
+ }
12
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/testing/steps/assert/index.ts"],"names":[],"mappings":";;AAOA,kDAIC;AARD,2CAAsD;AACtD,mDAA8D;AAC9D,uDAAiE;AAEjE,SAAgB,mBAAmB,CAAC,QAAsB;IACxD,IAAA,8CAA4B,EAAC,QAAQ,CAAC,CAAC;IACvC,IAAA,mCAAuB,EAAC,QAAQ,CAAC,CAAC;IAClC,IAAA,2CAA2B,EAAC,QAAQ,CAAC,CAAC;AACxC,CAAC","sourcesContent":["// Purpose: Assert step registrations.\n\nimport { StepRegistry } from \"../../core/step-registry\";\nimport { registerHttpAssertSteps } from \"./http.step\";\nimport { registerJsonPathAssertSteps } from \"./jsonpath.step\";\nimport { registerPrimitiveAssertSteps } from \"./primitives.step\";\n\nexport function registerAssertSteps(registry: StepRegistry): void {\n registerPrimitiveAssertSteps(registry);\n registerHttpAssertSteps(registry);\n registerJsonPathAssertSteps(registry);\n}\n"]}
@@ -0,0 +1,3 @@
1
+ import { StepRegistry } from "../../core/step-registry";
2
+ export declare function registerJsonPathAssertSteps(registry: StepRegistry): void;
3
+ //# sourceMappingURL=jsonpath.step.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jsonpath.step.d.ts","sourceRoot":"","sources":["../../../../src/testing/steps/assert/jsonpath.step.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAuBxD,wBAAgB,2BAA2B,CAAC,QAAQ,EAAE,YAAY,GAAG,IAAI,CAsBxE"}
@@ -0,0 +1,40 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.registerJsonPathAssertSteps = registerJsonPathAssertSteps;
4
+ function resolveJsonPath(from, path) {
5
+ let normalized = path.trim();
6
+ if (normalized.startsWith("$.")) {
7
+ normalized = normalized.slice(2);
8
+ }
9
+ else if (normalized === "$") {
10
+ return from;
11
+ }
12
+ normalized = normalized.replace(/\[(\d+)\]/g, ".$1");
13
+ const parts = normalized.split(".").filter(Boolean);
14
+ let current = from;
15
+ for (const part of parts) {
16
+ if (current == null)
17
+ return undefined;
18
+ current = current[part];
19
+ }
20
+ return current;
21
+ }
22
+ function registerJsonPathAssertSteps(registry) {
23
+ registry.register("assert.jsonPath", async (_ctx, step) => {
24
+ const input = (step.with ?? {});
25
+ if (!("from" in input)) {
26
+ throw new Error('Missing "from" in step.with for op "assert.jsonPath"');
27
+ }
28
+ if (!input.path) {
29
+ throw new Error('Missing "path" in step.with for op "assert.jsonPath"');
30
+ }
31
+ if (!("equals" in input)) {
32
+ throw new Error('Missing "equals" in step.with for op "assert.jsonPath"');
33
+ }
34
+ const actual = resolveJsonPath(input.from, input.path);
35
+ if (actual !== input.equals) {
36
+ throw new Error(`Expected JSONPath "${input.path}" to equal ${String(input.equals)} but got ${String(actual)}`);
37
+ }
38
+ });
39
+ }
40
+ //# sourceMappingURL=jsonpath.step.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jsonpath.step.js","sourceRoot":"","sources":["../../../../src/testing/steps/assert/jsonpath.step.ts"],"names":[],"mappings":";;AA2BA,kEAsBC;AAzCD,SAAS,eAAe,CAAC,IAAS,EAAE,IAAY;IAC9C,IAAI,UAAU,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;IAC7B,IAAI,UAAU,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QAChC,UAAU,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IACnC,CAAC;SAAM,IAAI,UAAU,KAAK,GAAG,EAAE,CAAC;QAC9B,OAAO,IAAI,CAAC;IACd,CAAC;IAED,UAAU,GAAG,UAAU,CAAC,OAAO,CAAC,YAAY,EAAE,KAAK,CAAC,CAAC;IACrD,MAAM,KAAK,GAAG,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAEpD,IAAI,OAAO,GAAQ,IAAI,CAAC;IACxB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,OAAO,IAAI,IAAI;YAAE,OAAO,SAAS,CAAC;QACtC,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,SAAgB,2BAA2B,CAAC,QAAsB;IAChE,QAAQ,CAAC,QAAQ,CAAC,iBAAiB,EAAE,KAAK,EAAE,IAAiB,EAAE,IAAY,EAAE,EAAE;QAC7E,MAAM,KAAK,GAAG,CAAC,IAAI,CAAC,IAAI,IAAI,EAAE,CAAkB,CAAC;QACjD,IAAI,CAAC,CAAC,MAAM,IAAI,KAAK,CAAC,EAAE,CAAC;YACvB,MAAM,IAAI,KAAK,CAAC,sDAAsD,CAAC,CAAC;QAC1E,CAAC;QACD,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;YAChB,MAAM,IAAI,KAAK,CAAC,sDAAsD,CAAC,CAAC;QAC1E,CAAC;QACD,IAAI,CAAC,CAAC,QAAQ,IAAI,KAAK,CAAC,EAAE,CAAC;YACzB,MAAM,IAAI,KAAK,CAAC,wDAAwD,CAAC,CAAC;QAC5E,CAAC;QAED,MAAM,MAAM,GAAG,eAAe,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;QACvD,IAAI,MAAM,KAAK,KAAK,CAAC,MAAM,EAAE,CAAC;YAC5B,MAAM,IAAI,KAAK,CACb,sBAAsB,KAAK,CAAC,IAAI,cAAc,MAAM,CAClD,KAAK,CAAC,MAAM,CACb,YAAY,MAAM,CAAC,MAAM,CAAC,EAAE,CAC9B,CAAC;QACJ,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC","sourcesContent":["// Purpose: JSONPath assertion step registrations.\n\nimport type { TestContext } from \"../../contracts/runtime-context.types\";\nimport type { OpStep } from \"../../contracts/testing-metadata.types\";\nimport { StepRegistry } from \"../../core/step-registry\";\n\ntype JsonPathInput = { from: any; path: string; equals: any };\n\nfunction resolveJsonPath(from: any, path: string): unknown {\n let normalized = path.trim();\n if (normalized.startsWith(\"$.\")) {\n normalized = normalized.slice(2);\n } else if (normalized === \"$\") {\n return from;\n }\n\n normalized = normalized.replace(/\\[(\\d+)\\]/g, \".$1\");\n const parts = normalized.split(\".\").filter(Boolean);\n\n let current: any = from;\n for (const part of parts) {\n if (current == null) return undefined;\n current = current[part];\n }\n return current;\n}\n\nexport function registerJsonPathAssertSteps(registry: StepRegistry): void {\n registry.register(\"assert.jsonPath\", async (_ctx: TestContext, step: OpStep) => {\n const input = (step.with ?? {}) as JsonPathInput;\n if (!(\"from\" in input)) {\n throw new Error('Missing \"from\" in step.with for op \"assert.jsonPath\"');\n }\n if (!input.path) {\n throw new Error('Missing \"path\" in step.with for op \"assert.jsonPath\"');\n }\n if (!(\"equals\" in input)) {\n throw new Error('Missing \"equals\" in step.with for op \"assert.jsonPath\"');\n }\n\n const actual = resolveJsonPath(input.from, input.path);\n if (actual !== input.equals) {\n throw new Error(\n `Expected JSONPath \"${input.path}\" to equal ${String(\n input.equals,\n )} but got ${String(actual)}`,\n );\n }\n });\n}\n"]}
@@ -0,0 +1,3 @@
1
+ import { StepRegistry } from "../../core/step-registry";
2
+ export declare function registerPrimitiveAssertSteps(registry: StepRegistry): void;
3
+ //# sourceMappingURL=primitives.step.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"primitives.step.d.ts","sourceRoot":"","sources":["../../../../src/testing/steps/assert/primitives.step.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAMxD,wBAAgB,4BAA4B,CAAC,QAAQ,EAAE,YAAY,GAAG,IAAI,CA0DzE"}
@@ -0,0 +1,43 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.registerPrimitiveAssertSteps = registerPrimitiveAssertSteps;
4
+ function registerPrimitiveAssertSteps(registry) {
5
+ registry.register("assert.equals", async (_ctx, step) => {
6
+ const input = (step.with ?? {});
7
+ if (!("actual" in input)) {
8
+ throw new Error('Missing "actual" in step.with for op "assert.equals"');
9
+ }
10
+ if (!("expected" in input)) {
11
+ throw new Error('Missing "expected" in step.with for op "assert.equals"');
12
+ }
13
+ if (input.actual !== input.expected) {
14
+ throw new Error(`Expected values to be equal. Actual: ${String(input.actual)}, Expected: ${String(input.expected)}`);
15
+ }
16
+ });
17
+ registry.register("assert.contains", async (_ctx, step) => {
18
+ const input = (step.with ?? {});
19
+ if (!input.actual) {
20
+ throw new Error('Missing "actual" in step.with for op "assert.contains"');
21
+ }
22
+ if (input.expected === undefined) {
23
+ throw new Error('Missing "expected" in step.with for op "assert.contains"');
24
+ }
25
+ if (!input.actual.includes(input.expected)) {
26
+ throw new Error(`Expected "${input.actual}" to contain "${input.expected}"`);
27
+ }
28
+ });
29
+ registry.register("assert.matches", async (_ctx, step) => {
30
+ const input = (step.with ?? {});
31
+ if (!input.actual) {
32
+ throw new Error('Missing "actual" in step.with for op "assert.matches"');
33
+ }
34
+ if (!input.pattern) {
35
+ throw new Error('Missing "pattern" in step.with for op "assert.matches"');
36
+ }
37
+ const regex = new RegExp(input.pattern);
38
+ if (!regex.test(input.actual)) {
39
+ throw new Error(`Expected "${input.actual}" to match /${input.pattern}/`);
40
+ }
41
+ });
42
+ }
43
+ //# sourceMappingURL=primitives.step.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"primitives.step.js","sourceRoot":"","sources":["../../../../src/testing/steps/assert/primitives.step.ts"],"names":[],"mappings":";;AAUA,oEA0DC;AA1DD,SAAgB,4BAA4B,CAAC,QAAsB;IACjE,QAAQ,CAAC,QAAQ,CAAC,eAAe,EAAE,KAAK,EAAE,IAAiB,EAAE,IAAY,EAAE,EAAE;QAC3E,MAAM,KAAK,GAAG,CAAC,IAAI,CAAC,IAAI,IAAI,EAAE,CAAgB,CAAC;QAC/C,IAAI,CAAC,CAAC,QAAQ,IAAI,KAAK,CAAC,EAAE,CAAC;YACzB,MAAM,IAAI,KAAK,CAAC,sDAAsD,CAAC,CAAC;QAC1E,CAAC;QACD,IAAI,CAAC,CAAC,UAAU,IAAI,KAAK,CAAC,EAAE,CAAC;YAC3B,MAAM,IAAI,KAAK,CAAC,wDAAwD,CAAC,CAAC;QAC5E,CAAC;QACD,IAAI,KAAK,CAAC,MAAM,KAAK,KAAK,CAAC,QAAQ,EAAE,CAAC;YACpC,MAAM,IAAI,KAAK,CACb,wCAAwC,MAAM,CAC5C,KAAK,CAAC,MAAM,CACb,eAAe,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,CACzC,CAAC;QACJ,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,QAAQ,CACf,iBAAiB,EACjB,KAAK,EAAE,IAAiB,EAAE,IAAY,EAAE,EAAE;QACxC,MAAM,KAAK,GAAG,CAAC,IAAI,CAAC,IAAI,IAAI,EAAE,CAAkB,CAAC;QACjD,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;YAClB,MAAM,IAAI,KAAK,CAAC,wDAAwD,CAAC,CAAC;QAC5E,CAAC;QACD,IAAI,KAAK,CAAC,QAAQ,KAAK,SAAS,EAAE,CAAC;YACjC,MAAM,IAAI,KAAK,CACb,0DAA0D,CAC3D,CAAC;QACJ,CAAC;QACD,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC3C,MAAM,IAAI,KAAK,CACb,aAAa,KAAK,CAAC,MAAM,iBAAiB,KAAK,CAAC,QAAQ,GAAG,CAC5D,CAAC;QACJ,CAAC;IACH,CAAC,CACF,CAAC;IAEF,QAAQ,CAAC,QAAQ,CACf,gBAAgB,EAChB,KAAK,EAAE,IAAiB,EAAE,IAAY,EAAE,EAAE;QACxC,MAAM,KAAK,GAAG,CAAC,IAAI,CAAC,IAAI,IAAI,EAAE,CAAiB,CAAC;QAChD,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;YAClB,MAAM,IAAI,KAAK,CAAC,uDAAuD,CAAC,CAAC;QAC3E,CAAC;QACD,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC;YACnB,MAAM,IAAI,KAAK,CACb,wDAAwD,CACzD,CAAC;QACJ,CAAC;QACD,MAAM,KAAK,GAAG,IAAI,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QACxC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC;YAC9B,MAAM,IAAI,KAAK,CACb,aAAa,KAAK,CAAC,MAAM,eAAe,KAAK,CAAC,OAAO,GAAG,CACzD,CAAC;QACJ,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC","sourcesContent":["// Purpose: Primitive assertion step registrations.\n\nimport type { TestContext } from \"../../contracts/runtime-context.types\";\nimport type { OpStep } from \"../../contracts/testing-metadata.types\";\nimport { StepRegistry } from \"../../core/step-registry\";\n\ntype EqualsInput = { actual: unknown; expected: unknown };\ntype ContainsInput = { actual: string; expected: string };\ntype MatchesInput = { actual: string; pattern: string };\n\nexport function registerPrimitiveAssertSteps(registry: StepRegistry): void {\n registry.register(\"assert.equals\", async (_ctx: TestContext, step: OpStep) => {\n const input = (step.with ?? {}) as EqualsInput;\n if (!(\"actual\" in input)) {\n throw new Error('Missing \"actual\" in step.with for op \"assert.equals\"');\n }\n if (!(\"expected\" in input)) {\n throw new Error('Missing \"expected\" in step.with for op \"assert.equals\"');\n }\n if (input.actual !== input.expected) {\n throw new Error(\n `Expected values to be equal. Actual: ${String(\n input.actual,\n )}, Expected: ${String(input.expected)}`,\n );\n }\n });\n\n registry.register(\n \"assert.contains\",\n async (_ctx: TestContext, step: OpStep) => {\n const input = (step.with ?? {}) as ContainsInput;\n if (!input.actual) {\n throw new Error('Missing \"actual\" in step.with for op \"assert.contains\"');\n }\n if (input.expected === undefined) {\n throw new Error(\n 'Missing \"expected\" in step.with for op \"assert.contains\"',\n );\n }\n if (!input.actual.includes(input.expected)) {\n throw new Error(\n `Expected \"${input.actual}\" to contain \"${input.expected}\"`,\n );\n }\n },\n );\n\n registry.register(\n \"assert.matches\",\n async (_ctx: TestContext, step: OpStep) => {\n const input = (step.with ?? {}) as MatchesInput;\n if (!input.actual) {\n throw new Error('Missing \"actual\" in step.with for op \"assert.matches\"');\n }\n if (!input.pattern) {\n throw new Error(\n 'Missing \"pattern\" in step.with for op \"assert.matches\"',\n );\n }\n const regex = new RegExp(input.pattern);\n if (!regex.test(input.actual)) {\n throw new Error(\n `Expected \"${input.actual}\" to match /${input.pattern}/`,\n );\n }\n },\n );\n}\n"]}
@@ -0,0 +1,3 @@
1
+ import { StepRegistry } from "../../core/step-registry";
2
+ export declare function registerTestSteps(registry: StepRegistry): void;
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/testing/steps/test/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAGxD,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,YAAY,GAAG,IAAI,CAE9D"}
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.registerTestSteps = registerTestSteps;
4
+ const test_spec_step_1 = require("./test-spec.step");
5
+ function registerTestSteps(registry) {
6
+ (0, test_spec_step_1.registerTestSpecStep)(registry);
7
+ }
8
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/testing/steps/test/index.ts"],"names":[],"mappings":";;AAKA,8CAEC;AAJD,qDAAwD;AAExD,SAAgB,iBAAiB,CAAC,QAAsB;IACtD,IAAA,qCAAoB,EAAC,QAAQ,CAAC,CAAC;AACjC,CAAC","sourcesContent":["// Purpose: Test step registrations.\n\nimport { StepRegistry } from \"../../core/step-registry\";\nimport { registerTestSpecStep } from \"./test-spec.step\";\n\nexport function registerTestSteps(registry: StepRegistry): void {\n registerTestSpecStep(registry);\n}\n"]}
@@ -0,0 +1,3 @@
1
+ import { StepRegistry } from "../../core/step-registry";
2
+ export declare function registerTestSpecStep(registry: StepRegistry): void;
3
+ //# sourceMappingURL=test-spec.step.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test-spec.step.d.ts","sourceRoot":"","sources":["../../../../src/testing/steps/test/test-spec.step.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAExD,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,YAAY,GAAG,IAAI,CA6CjE"}
@@ -0,0 +1,41 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.registerTestSpecStep = registerTestSpecStep;
4
+ function registerTestSpecStep(registry) {
5
+ registry.register("test.spec", async (ctx, step) => {
6
+ const specId = step.spec ?? step.with?.specId;
7
+ if (!specId) {
8
+ throw new Error('Missing "spec" on step (or "specId" in step.with) for op "test.spec"');
9
+ }
10
+ if (!ctx.specRegistry) {
11
+ throw new Error('Missing specRegistry on context for op "test.spec"');
12
+ }
13
+ const input = (step.with?.input ?? {});
14
+ const spec = ctx.specRegistry.create(specId);
15
+ const result = await spec.run({ ctx, input });
16
+ ctx.reporter.onSpecResult?.({
17
+ scenarioId: ctx.scenarioId,
18
+ specId,
19
+ stepName: step.name,
20
+ result,
21
+ });
22
+ if (result.attachments && ctx.reporter.attach) {
23
+ for (const attachment of result.attachments) {
24
+ const data = attachment.encoding === "base64"
25
+ ? Buffer.from(attachment.data, "base64")
26
+ : attachment.data;
27
+ ctx.reporter.attach({
28
+ scenarioId: ctx.scenarioId,
29
+ name: attachment.name,
30
+ contentType: attachment.contentType,
31
+ data,
32
+ });
33
+ }
34
+ }
35
+ if (!result.ok) {
36
+ throw new Error(`test.spec failed: ${specId}`);
37
+ }
38
+ return result;
39
+ });
40
+ }
41
+ //# sourceMappingURL=test-spec.step.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test-spec.step.js","sourceRoot":"","sources":["../../../../src/testing/steps/test/test-spec.step.ts"],"names":[],"mappings":";;AAMA,oDA6CC;AA7CD,SAAgB,oBAAoB,CAAC,QAAsB;IACzD,QAAQ,CAAC,QAAQ,CAAC,WAAW,EAAE,KAAK,EAAE,GAAgB,EAAE,IAAY,EAAE,EAAE;QACtE,MAAM,MAAM,GACV,IAAI,CAAC,IAAI,IAAK,IAAI,CAAC,IAAI,EAAE,MAA6B,CAAC;QACzD,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,IAAI,KAAK,CACb,sEAAsE,CACvE,CAAC;QACJ,CAAC;QACD,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE,CAAC;YACtB,MAAM,IAAI,KAAK,CAAC,oDAAoD,CAAC,CAAC;QACxE,CAAC;QAED,MAAM,KAAK,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,IAAI,EAAE,CAAwB,CAAC;QAC9D,MAAM,IAAI,GAAG,GAAG,CAAC,YAAY,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QAC7C,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC,CAAC;QAE9C,GAAG,CAAC,QAAQ,CAAC,YAAY,EAAE,CAAC;YAC1B,UAAU,EAAE,GAAG,CAAC,UAAU;YAC1B,MAAM;YACN,QAAQ,EAAE,IAAI,CAAC,IAAI;YACnB,MAAM;SACP,CAAC,CAAC;QAEH,IAAI,MAAM,CAAC,WAAW,IAAI,GAAG,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC;YAC9C,KAAK,MAAM,UAAU,IAAI,MAAM,CAAC,WAAW,EAAE,CAAC;gBAC5C,MAAM,IAAI,GACR,UAAU,CAAC,QAAQ,KAAK,QAAQ;oBAC9B,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE,QAAQ,CAAC;oBACxC,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC;gBACtB,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC;oBAClB,UAAU,EAAE,GAAG,CAAC,UAAU;oBAC1B,IAAI,EAAE,UAAU,CAAC,IAAI;oBACrB,WAAW,EAAE,UAAU,CAAC,WAAW;oBACnC,IAAI;iBACL,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QAED,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC;YACf,MAAM,IAAI,KAAK,CAAC,qBAAqB,MAAM,EAAE,CAAC,CAAC;QACjD,CAAC;QAED,OAAO,MAAM,CAAC;IAChB,CAAC,CAAC,CAAC;AACL,CAAC","sourcesContent":["// Purpose: test.spec step registration.\n\nimport type { TestContext } from \"../../contracts/runtime-context.types\";\nimport type { OpStep } from \"../../contracts/testing-metadata.types\";\nimport { StepRegistry } from \"../../core/step-registry\";\n\nexport function registerTestSpecStep(registry: StepRegistry): void {\n registry.register(\"test.spec\", async (ctx: TestContext, step: OpStep) => {\n const specId =\n step.spec ?? (step.with?.specId as string | undefined);\n if (!specId) {\n throw new Error(\n 'Missing \"spec\" on step (or \"specId\" in step.with) for op \"test.spec\"',\n );\n }\n if (!ctx.specRegistry) {\n throw new Error('Missing specRegistry on context for op \"test.spec\"');\n }\n\n const input = (step.with?.input ?? {}) as Record<string, any>;\n const spec = ctx.specRegistry.create(specId);\n const result = await spec.run({ ctx, input });\n\n ctx.reporter.onSpecResult?.({\n scenarioId: ctx.scenarioId,\n specId,\n stepName: step.name,\n result,\n });\n\n if (result.attachments && ctx.reporter.attach) {\n for (const attachment of result.attachments) {\n const data =\n attachment.encoding === \"base64\"\n ? Buffer.from(attachment.data, \"base64\")\n : attachment.data;\n ctx.reporter.attach({\n scenarioId: ctx.scenarioId,\n name: attachment.name,\n contentType: attachment.contentType,\n data,\n });\n }\n }\n\n if (!result.ok) {\n throw new Error(`test.spec failed: ${specId}`);\n }\n\n return result;\n });\n}\n"]}
@@ -0,0 +1,3 @@
1
+ import { StepRegistry } from "../../core/step-registry";
2
+ export declare function registerActionSteps(registry: StepRegistry): void;
3
+ //# sourceMappingURL=actions.step.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"actions.step.d.ts","sourceRoot":"","sources":["../../../../src/testing/steps/ui/actions.step.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAYxD,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,YAAY,GAAG,IAAI,CAqBhE"}