@opensip-cli/simulation 0.1.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 (348) hide show
  1. package/LICENSE +202 -0
  2. package/NOTICE +8 -0
  3. package/README.md +31 -0
  4. package/dist/__tests__/internal-surface.test.d.ts +9 -0
  5. package/dist/__tests__/internal-surface.test.d.ts.map +1 -0
  6. package/dist/__tests__/internal-surface.test.js +38 -0
  7. package/dist/__tests__/internal-surface.test.js.map +1 -0
  8. package/dist/__tests__/plugin-loader.test.d.ts +2 -0
  9. package/dist/__tests__/plugin-loader.test.d.ts.map +1 -0
  10. package/dist/__tests__/plugin-loader.test.js +64 -0
  11. package/dist/__tests__/plugin-loader.test.js.map +1 -0
  12. package/dist/__tests__/public-api.test.d.ts +15 -0
  13. package/dist/__tests__/public-api.test.d.ts.map +1 -0
  14. package/dist/__tests__/public-api.test.js +73 -0
  15. package/dist/__tests__/public-api.test.js.map +1 -0
  16. package/dist/__tests__/registry-cross-kind.test.d.ts +6 -0
  17. package/dist/__tests__/registry-cross-kind.test.d.ts.map +1 -0
  18. package/dist/__tests__/registry-cross-kind.test.js +86 -0
  19. package/dist/__tests__/registry-cross-kind.test.js.map +1 -0
  20. package/dist/__tests__/scenario-execution.test.d.ts +10 -0
  21. package/dist/__tests__/scenario-execution.test.d.ts.map +1 -0
  22. package/dist/__tests__/scenario-execution.test.js +92 -0
  23. package/dist/__tests__/scenario-execution.test.js.map +1 -0
  24. package/dist/__tests__/sim-capability-contract.test.d.ts +10 -0
  25. package/dist/__tests__/sim-capability-contract.test.d.ts.map +1 -0
  26. package/dist/__tests__/sim-capability-contract.test.js +131 -0
  27. package/dist/__tests__/sim-capability-contract.test.js.map +1 -0
  28. package/dist/__tests__/sim-config-schema.test.d.ts +5 -0
  29. package/dist/__tests__/sim-config-schema.test.d.ts.map +1 -0
  30. package/dist/__tests__/sim-config-schema.test.js +23 -0
  31. package/dist/__tests__/sim-config-schema.test.js.map +1 -0
  32. package/dist/__tests__/sim-failure-signal.test.d.ts +10 -0
  33. package/dist/__tests__/sim-failure-signal.test.d.ts.map +1 -0
  34. package/dist/__tests__/sim-failure-signal.test.js +86 -0
  35. package/dist/__tests__/sim-failure-signal.test.js.map +1 -0
  36. package/dist/__tests__/surviving-surface-edges.test.d.ts +10 -0
  37. package/dist/__tests__/surviving-surface-edges.test.d.ts.map +1 -0
  38. package/dist/__tests__/surviving-surface-edges.test.js +122 -0
  39. package/dist/__tests__/surviving-surface-edges.test.js.map +1 -0
  40. package/dist/__tests__/test-utils/targets.d.ts +26 -0
  41. package/dist/__tests__/test-utils/targets.d.ts.map +1 -0
  42. package/dist/__tests__/test-utils/targets.js +38 -0
  43. package/dist/__tests__/test-utils/targets.js.map +1 -0
  44. package/dist/__tests__/test-utils/with-sim-scope.d.ts +12 -0
  45. package/dist/__tests__/test-utils/with-sim-scope.d.ts.map +1 -0
  46. package/dist/__tests__/test-utils/with-sim-scope.js +22 -0
  47. package/dist/__tests__/test-utils/with-sim-scope.js.map +1 -0
  48. package/dist/__tests__/tool-live-view.test.d.ts +20 -0
  49. package/dist/__tests__/tool-live-view.test.d.ts.map +1 -0
  50. package/dist/__tests__/tool-live-view.test.js +146 -0
  51. package/dist/__tests__/tool-live-view.test.js.map +1 -0
  52. package/dist/__tests__/tool-show-mode.test.d.ts +10 -0
  53. package/dist/__tests__/tool-show-mode.test.d.ts.map +1 -0
  54. package/dist/__tests__/tool-show-mode.test.js +156 -0
  55. package/dist/__tests__/tool-show-mode.test.js.map +1 -0
  56. package/dist/__tests__/tool.test.d.ts +15 -0
  57. package/dist/__tests__/tool.test.d.ts.map +1 -0
  58. package/dist/__tests__/tool.test.js +250 -0
  59. package/dist/__tests__/tool.test.js.map +1 -0
  60. package/dist/cli/__tests__/sim-config.test.d.ts +2 -0
  61. package/dist/cli/__tests__/sim-config.test.d.ts.map +1 -0
  62. package/dist/cli/__tests__/sim-config.test.js +94 -0
  63. package/dist/cli/__tests__/sim-config.test.js.map +1 -0
  64. package/dist/cli/__tests__/sim-runner.test.d.ts +23 -0
  65. package/dist/cli/__tests__/sim-runner.test.d.ts.map +1 -0
  66. package/dist/cli/__tests__/sim-runner.test.js +188 -0
  67. package/dist/cli/__tests__/sim-runner.test.js.map +1 -0
  68. package/dist/cli/__tests__/sim-worker.test.d.ts +12 -0
  69. package/dist/cli/__tests__/sim-worker.test.d.ts.map +1 -0
  70. package/dist/cli/__tests__/sim-worker.test.js +69 -0
  71. package/dist/cli/__tests__/sim-worker.test.js.map +1 -0
  72. package/dist/cli/__tests__/sim.test.d.ts +2 -0
  73. package/dist/cli/__tests__/sim.test.d.ts.map +1 -0
  74. package/dist/cli/__tests__/sim.test.js +232 -0
  75. package/dist/cli/__tests__/sim.test.js.map +1 -0
  76. package/dist/cli/sim-config-schema.d.ts +30 -0
  77. package/dist/cli/sim-config-schema.d.ts.map +1 -0
  78. package/dist/cli/sim-config-schema.js +33 -0
  79. package/dist/cli/sim-config-schema.js.map +1 -0
  80. package/dist/cli/sim-config.d.ts +22 -0
  81. package/dist/cli/sim-config.d.ts.map +1 -0
  82. package/dist/cli/sim-config.js +73 -0
  83. package/dist/cli/sim-config.js.map +1 -0
  84. package/dist/cli/sim-runner.d.ts +60 -0
  85. package/dist/cli/sim-runner.d.ts.map +1 -0
  86. package/dist/cli/sim-runner.js +175 -0
  87. package/dist/cli/sim-runner.js.map +1 -0
  88. package/dist/cli/sim-worker.d.ts +24 -0
  89. package/dist/cli/sim-worker.d.ts.map +1 -0
  90. package/dist/cli/sim-worker.js +65 -0
  91. package/dist/cli/sim-worker.js.map +1 -0
  92. package/dist/cli/sim.d.ts +56 -0
  93. package/dist/cli/sim.d.ts.map +1 -0
  94. package/dist/cli/sim.js +265 -0
  95. package/dist/cli/sim.js.map +1 -0
  96. package/dist/framework/__tests__/assertions.test.d.ts +2 -0
  97. package/dist/framework/__tests__/assertions.test.d.ts.map +1 -0
  98. package/dist/framework/__tests__/assertions.test.js +122 -0
  99. package/dist/framework/__tests__/assertions.test.js.map +1 -0
  100. package/dist/framework/__tests__/misc-coverage.test.d.ts +18 -0
  101. package/dist/framework/__tests__/misc-coverage.test.d.ts.map +1 -0
  102. package/dist/framework/__tests__/misc-coverage.test.js +142 -0
  103. package/dist/framework/__tests__/misc-coverage.test.js.map +1 -0
  104. package/dist/framework/__tests__/resolve-metric.test.d.ts +12 -0
  105. package/dist/framework/__tests__/resolve-metric.test.d.ts.map +1 -0
  106. package/dist/framework/__tests__/resolve-metric.test.js +124 -0
  107. package/dist/framework/__tests__/resolve-metric.test.js.map +1 -0
  108. package/dist/framework/__tests__/result-builder.test.d.ts +2 -0
  109. package/dist/framework/__tests__/result-builder.test.d.ts.map +1 -0
  110. package/dist/framework/__tests__/result-builder.test.js +180 -0
  111. package/dist/framework/__tests__/result-builder.test.js.map +1 -0
  112. package/dist/framework/__tests__/scenario-logger.test.d.ts +9 -0
  113. package/dist/framework/__tests__/scenario-logger.test.d.ts.map +1 -0
  114. package/dist/framework/__tests__/scenario-logger.test.js +110 -0
  115. package/dist/framework/__tests__/scenario-logger.test.js.map +1 -0
  116. package/dist/framework/__tests__/validation.test.d.ts +9 -0
  117. package/dist/framework/__tests__/validation.test.d.ts.map +1 -0
  118. package/dist/framework/__tests__/validation.test.js +126 -0
  119. package/dist/framework/__tests__/validation.test.js.map +1 -0
  120. package/dist/framework/assertions.d.ts +106 -0
  121. package/dist/framework/assertions.d.ts.map +1 -0
  122. package/dist/framework/assertions.js +256 -0
  123. package/dist/framework/assertions.js.map +1 -0
  124. package/dist/framework/execution/__tests__/execution-engine.test.d.ts +9 -0
  125. package/dist/framework/execution/__tests__/execution-engine.test.d.ts.map +1 -0
  126. package/dist/framework/execution/__tests__/execution-engine.test.js +138 -0
  127. package/dist/framework/execution/__tests__/execution-engine.test.js.map +1 -0
  128. package/dist/framework/execution/__tests__/fault-builders.test.d.ts +5 -0
  129. package/dist/framework/execution/__tests__/fault-builders.test.d.ts.map +1 -0
  130. package/dist/framework/execution/__tests__/fault-builders.test.js +23 -0
  131. package/dist/framework/execution/__tests__/fault-builders.test.js.map +1 -0
  132. package/dist/framework/execution/__tests__/fault-model.test.d.ts +6 -0
  133. package/dist/framework/execution/__tests__/fault-model.test.d.ts.map +1 -0
  134. package/dist/framework/execution/__tests__/fault-model.test.js +64 -0
  135. package/dist/framework/execution/__tests__/fault-model.test.js.map +1 -0
  136. package/dist/framework/execution/__tests__/http-target.test.d.ts +5 -0
  137. package/dist/framework/execution/__tests__/http-target.test.d.ts.map +1 -0
  138. package/dist/framework/execution/__tests__/http-target.test.js +36 -0
  139. package/dist/framework/execution/__tests__/http-target.test.js.map +1 -0
  140. package/dist/framework/execution/__tests__/run-load-window.test.d.ts +7 -0
  141. package/dist/framework/execution/__tests__/run-load-window.test.d.ts.map +1 -0
  142. package/dist/framework/execution/__tests__/run-load-window.test.js +89 -0
  143. package/dist/framework/execution/__tests__/run-load-window.test.js.map +1 -0
  144. package/dist/framework/execution/execution-engine.d.ts +55 -0
  145. package/dist/framework/execution/execution-engine.d.ts.map +1 -0
  146. package/dist/framework/execution/execution-engine.js +111 -0
  147. package/dist/framework/execution/execution-engine.js.map +1 -0
  148. package/dist/framework/execution/fault-builders.d.ts +26 -0
  149. package/dist/framework/execution/fault-builders.d.ts.map +1 -0
  150. package/dist/framework/execution/fault-builders.js +24 -0
  151. package/dist/framework/execution/fault-builders.js.map +1 -0
  152. package/dist/framework/execution/fault-model.d.ts +49 -0
  153. package/dist/framework/execution/fault-model.d.ts.map +1 -0
  154. package/dist/framework/execution/fault-model.js +108 -0
  155. package/dist/framework/execution/fault-model.js.map +1 -0
  156. package/dist/framework/execution/fault-spec.d.ts +40 -0
  157. package/dist/framework/execution/fault-spec.d.ts.map +1 -0
  158. package/dist/framework/execution/fault-spec.js +23 -0
  159. package/dist/framework/execution/fault-spec.js.map +1 -0
  160. package/dist/framework/execution/http-target.d.ts +34 -0
  161. package/dist/framework/execution/http-target.d.ts.map +1 -0
  162. package/dist/framework/execution/http-target.js +41 -0
  163. package/dist/framework/execution/http-target.js.map +1 -0
  164. package/dist/framework/execution/latency-tracker.d.ts +44 -0
  165. package/dist/framework/execution/latency-tracker.d.ts.map +1 -0
  166. package/dist/framework/execution/latency-tracker.js +76 -0
  167. package/dist/framework/execution/latency-tracker.js.map +1 -0
  168. package/dist/framework/execution/run-load-window.d.ts +45 -0
  169. package/dist/framework/execution/run-load-window.d.ts.map +1 -0
  170. package/dist/framework/execution/run-load-window.js +136 -0
  171. package/dist/framework/execution/run-load-window.js.map +1 -0
  172. package/dist/framework/execution/scenario-aborted-error.d.ts +14 -0
  173. package/dist/framework/execution/scenario-aborted-error.d.ts.map +1 -0
  174. package/dist/framework/execution/scenario-aborted-error.js +24 -0
  175. package/dist/framework/execution/scenario-aborted-error.js.map +1 -0
  176. package/dist/framework/execution/target.d.ts +35 -0
  177. package/dist/framework/execution/target.d.ts.map +1 -0
  178. package/dist/framework/execution/target.js +21 -0
  179. package/dist/framework/execution/target.js.map +1 -0
  180. package/dist/framework/registry.d.ts +67 -0
  181. package/dist/framework/registry.d.ts.map +1 -0
  182. package/dist/framework/registry.js +113 -0
  183. package/dist/framework/registry.js.map +1 -0
  184. package/dist/framework/resolve-metric.d.ts +79 -0
  185. package/dist/framework/resolve-metric.d.ts.map +1 -0
  186. package/dist/framework/resolve-metric.js +135 -0
  187. package/dist/framework/resolve-metric.js.map +1 -0
  188. package/dist/framework/result-builder.d.ts +72 -0
  189. package/dist/framework/result-builder.d.ts.map +1 -0
  190. package/dist/framework/result-builder.js +214 -0
  191. package/dist/framework/result-builder.js.map +1 -0
  192. package/dist/framework/result-renderers.d.ts +37 -0
  193. package/dist/framework/result-renderers.d.ts.map +1 -0
  194. package/dist/framework/result-renderers.js +62 -0
  195. package/dist/framework/result-renderers.js.map +1 -0
  196. package/dist/framework/runnable-scenario.d.ts +37 -0
  197. package/dist/framework/runnable-scenario.d.ts.map +1 -0
  198. package/dist/framework/runnable-scenario.js +9 -0
  199. package/dist/framework/runnable-scenario.js.map +1 -0
  200. package/dist/framework/scenario-executor-result.d.ts +44 -0
  201. package/dist/framework/scenario-executor-result.d.ts.map +1 -0
  202. package/dist/framework/scenario-executor-result.js +13 -0
  203. package/dist/framework/scenario-executor-result.js.map +1 -0
  204. package/dist/framework/scenario-logger.d.ts +18 -0
  205. package/dist/framework/scenario-logger.d.ts.map +1 -0
  206. package/dist/framework/scenario-logger.js +39 -0
  207. package/dist/framework/scenario-logger.js.map +1 -0
  208. package/dist/framework/scenario-metric-key.d.ts +24 -0
  209. package/dist/framework/scenario-metric-key.d.ts.map +1 -0
  210. package/dist/framework/scenario-metric-key.js +17 -0
  211. package/dist/framework/scenario-metric-key.js.map +1 -0
  212. package/dist/framework/validation.d.ts +83 -0
  213. package/dist/framework/validation.d.ts.map +1 -0
  214. package/dist/framework/validation.js +93 -0
  215. package/dist/framework/validation.js.map +1 -0
  216. package/dist/index.d.ts +35 -0
  217. package/dist/index.d.ts.map +1 -0
  218. package/dist/index.js +53 -0
  219. package/dist/index.js.map +1 -0
  220. package/dist/internal.d.ts +19 -0
  221. package/dist/internal.d.ts.map +1 -0
  222. package/dist/internal.js +16 -0
  223. package/dist/internal.js.map +1 -0
  224. package/dist/kinds/chaos/__tests__/executor.test.d.ts +6 -0
  225. package/dist/kinds/chaos/__tests__/executor.test.d.ts.map +1 -0
  226. package/dist/kinds/chaos/__tests__/executor.test.js +117 -0
  227. package/dist/kinds/chaos/__tests__/executor.test.js.map +1 -0
  228. package/dist/kinds/chaos/config.d.ts +48 -0
  229. package/dist/kinds/chaos/config.d.ts.map +1 -0
  230. package/dist/kinds/chaos/config.js +15 -0
  231. package/dist/kinds/chaos/config.js.map +1 -0
  232. package/dist/kinds/chaos/define.d.ts +32 -0
  233. package/dist/kinds/chaos/define.d.ts.map +1 -0
  234. package/dist/kinds/chaos/define.js +111 -0
  235. package/dist/kinds/chaos/define.js.map +1 -0
  236. package/dist/kinds/chaos/executor.d.ts +21 -0
  237. package/dist/kinds/chaos/executor.d.ts.map +1 -0
  238. package/dist/kinds/chaos/executor.js +107 -0
  239. package/dist/kinds/chaos/executor.js.map +1 -0
  240. package/dist/kinds/chaos/result.d.ts +43 -0
  241. package/dist/kinds/chaos/result.d.ts.map +1 -0
  242. package/dist/kinds/chaos/result.js +12 -0
  243. package/dist/kinds/chaos/result.js.map +1 -0
  244. package/dist/kinds/load/__tests__/executor.test.d.ts +6 -0
  245. package/dist/kinds/load/__tests__/executor.test.d.ts.map +1 -0
  246. package/dist/kinds/load/__tests__/executor.test.js +75 -0
  247. package/dist/kinds/load/__tests__/executor.test.js.map +1 -0
  248. package/dist/kinds/load/config.d.ts +30 -0
  249. package/dist/kinds/load/config.d.ts.map +1 -0
  250. package/dist/kinds/load/config.js +9 -0
  251. package/dist/kinds/load/config.js.map +1 -0
  252. package/dist/kinds/load/define.d.ts +47 -0
  253. package/dist/kinds/load/define.d.ts.map +1 -0
  254. package/dist/kinds/load/define.js +76 -0
  255. package/dist/kinds/load/define.js.map +1 -0
  256. package/dist/kinds/load/executor.d.ts +16 -0
  257. package/dist/kinds/load/executor.d.ts.map +1 -0
  258. package/dist/kinds/load/executor.js +90 -0
  259. package/dist/kinds/load/executor.js.map +1 -0
  260. package/dist/kinds/load/result.d.ts +21 -0
  261. package/dist/kinds/load/result.d.ts.map +1 -0
  262. package/dist/kinds/load/result.js +10 -0
  263. package/dist/kinds/load/result.js.map +1 -0
  264. package/dist/persistence/session-payload.d.ts +32 -0
  265. package/dist/persistence/session-payload.d.ts.map +1 -0
  266. package/dist/persistence/session-payload.js +46 -0
  267. package/dist/persistence/session-payload.js.map +1 -0
  268. package/dist/persistence/session-replay.d.ts +13 -0
  269. package/dist/persistence/session-replay.d.ts.map +1 -0
  270. package/dist/persistence/session-replay.js +76 -0
  271. package/dist/persistence/session-replay.js.map +1 -0
  272. package/dist/persistence/session-replay.test.d.ts +10 -0
  273. package/dist/persistence/session-replay.test.d.ts.map +1 -0
  274. package/dist/persistence/session-replay.test.js +169 -0
  275. package/dist/persistence/session-replay.test.js.map +1 -0
  276. package/dist/plugins/__tests__/loader-scenarios.test.d.ts +12 -0
  277. package/dist/plugins/__tests__/loader-scenarios.test.d.ts.map +1 -0
  278. package/dist/plugins/__tests__/loader-scenarios.test.js +61 -0
  279. package/dist/plugins/__tests__/loader-scenarios.test.js.map +1 -0
  280. package/dist/plugins/__tests__/scenario-package-discovery.test.d.ts +2 -0
  281. package/dist/plugins/__tests__/scenario-package-discovery.test.d.ts.map +1 -0
  282. package/dist/plugins/__tests__/scenario-package-discovery.test.js +43 -0
  283. package/dist/plugins/__tests__/scenario-package-discovery.test.js.map +1 -0
  284. package/dist/plugins/loader.d.ts +32 -0
  285. package/dist/plugins/loader.d.ts.map +1 -0
  286. package/dist/plugins/loader.js +119 -0
  287. package/dist/plugins/loader.js.map +1 -0
  288. package/dist/plugins/scenario-package-discovery.d.ts +23 -0
  289. package/dist/plugins/scenario-package-discovery.d.ts.map +1 -0
  290. package/dist/plugins/scenario-package-discovery.js +42 -0
  291. package/dist/plugins/scenario-package-discovery.js.map +1 -0
  292. package/dist/plugins/types.d.ts +24 -0
  293. package/dist/plugins/types.d.ts.map +1 -0
  294. package/dist/plugins/types.js +18 -0
  295. package/dist/plugins/types.js.map +1 -0
  296. package/dist/recipes/__tests__/recipes.test.d.ts +2 -0
  297. package/dist/recipes/__tests__/recipes.test.d.ts.map +1 -0
  298. package/dist/recipes/__tests__/recipes.test.js +515 -0
  299. package/dist/recipes/__tests__/recipes.test.js.map +1 -0
  300. package/dist/recipes/built-in-recipes.d.ts +16 -0
  301. package/dist/recipes/built-in-recipes.d.ts.map +1 -0
  302. package/dist/recipes/built-in-recipes.js +37 -0
  303. package/dist/recipes/built-in-recipes.js.map +1 -0
  304. package/dist/recipes/define-recipe.d.ts +29 -0
  305. package/dist/recipes/define-recipe.d.ts.map +1 -0
  306. package/dist/recipes/define-recipe.js +68 -0
  307. package/dist/recipes/define-recipe.js.map +1 -0
  308. package/dist/recipes/registry.d.ts +54 -0
  309. package/dist/recipes/registry.d.ts.map +1 -0
  310. package/dist/recipes/registry.js +89 -0
  311. package/dist/recipes/registry.js.map +1 -0
  312. package/dist/recipes/service.d.ts +61 -0
  313. package/dist/recipes/service.d.ts.map +1 -0
  314. package/dist/recipes/service.js +205 -0
  315. package/dist/recipes/service.js.map +1 -0
  316. package/dist/recipes/types.d.ts +62 -0
  317. package/dist/recipes/types.d.ts.map +1 -0
  318. package/dist/recipes/types.js +10 -0
  319. package/dist/recipes/types.js.map +1 -0
  320. package/dist/scaffold/examples.d.ts +22 -0
  321. package/dist/scaffold/examples.d.ts.map +1 -0
  322. package/dist/scaffold/examples.js +91 -0
  323. package/dist/scaffold/examples.js.map +1 -0
  324. package/dist/scope-augmentation.d.ts +70 -0
  325. package/dist/scope-augmentation.d.ts.map +1 -0
  326. package/dist/scope-augmentation.js +28 -0
  327. package/dist/scope-augmentation.js.map +1 -0
  328. package/dist/tool.d.ts +21 -0
  329. package/dist/tool.d.ts.map +1 -0
  330. package/dist/tool.js +347 -0
  331. package/dist/tool.js.map +1 -0
  332. package/dist/types/base-types.d.ts +35 -0
  333. package/dist/types/base-types.d.ts.map +1 -0
  334. package/dist/types/base-types.js +8 -0
  335. package/dist/types/base-types.js.map +1 -0
  336. package/dist/types/framework-types.d.ts +62 -0
  337. package/dist/types/framework-types.d.ts.map +1 -0
  338. package/dist/types/framework-types.js +15 -0
  339. package/dist/types/framework-types.js.map +1 -0
  340. package/dist/types/kind-types.d.ts +24 -0
  341. package/dist/types/kind-types.d.ts.map +1 -0
  342. package/dist/types/kind-types.js +22 -0
  343. package/dist/types/kind-types.js.map +1 -0
  344. package/dist/types/workload.d.ts +30 -0
  345. package/dist/types/workload.d.ts.map +1 -0
  346. package/dist/types/workload.js +20 -0
  347. package/dist/types/workload.js.map +1 -0
  348. package/package.json +120 -0
@@ -0,0 +1,92 @@
1
+ /**
2
+ * @fileoverview Integration tests that run scenarios end-to-end so the
3
+ * execution-engine + per-kind executor paths are exercised. Each
4
+ * scenario uses a tiny duration so the test runs quickly.
5
+ *
6
+ * This file focuses on actually running the executor for the load and
7
+ * chaos kinds.
8
+ */
9
+ import { enterScope } from '@opensip-cli/core';
10
+ import { beforeEach, describe, expect, it } from 'vitest';
11
+ import { ASSERTIONS } from '../framework/assertions.js';
12
+ import { fault } from '../framework/execution/fault-builders.js';
13
+ import { ScenarioAbortedError } from '../framework/execution/scenario-aborted-error.js';
14
+ import { defineChaosScenario } from '../kinds/chaos/define.js';
15
+ import { defineLoadScenario } from '../kinds/load/define.js';
16
+ import { makeSimTestScope } from './test-utils/with-sim-scope.js';
17
+ const noopTarget = () => Promise.resolve();
18
+ beforeEach(() => {
19
+ // Item 1: scenarioRegistry is per-RunScope. Enter a fresh scope.
20
+ enterScope(makeSimTestScope());
21
+ });
22
+ describe('Load scenario execution', () => {
23
+ it('runs to completion and returns a load-kind result', async () => {
24
+ const scenario = defineLoadScenario({
25
+ id: 'load-exec-1',
26
+ name: 'load-exec-1',
27
+ description: 'tiny load run',
28
+ tags: [],
29
+ target: noopTarget,
30
+ workload: { rps: 1 },
31
+ duration: 1,
32
+ assertions: [ASSERTIONS.lowErrorRate(1)],
33
+ });
34
+ const result = await scenario.run(new AbortController().signal);
35
+ expect(result.kind).toBe('load');
36
+ expect(result.scenarioId).toBe('load-exec-1');
37
+ expect(typeof result.passed).toBe('boolean');
38
+ expect(typeof result.durationMs).toBe('number');
39
+ });
40
+ it('throws ScenarioAbortedError on a pre-aborted signal', async () => {
41
+ const scenario = defineLoadScenario({
42
+ id: 'load-exec-aborted',
43
+ name: 'load-exec-aborted',
44
+ description: 'aborted',
45
+ tags: [],
46
+ target: noopTarget,
47
+ workload: { rps: 1 },
48
+ duration: 5,
49
+ assertions: [ASSERTIONS.lowErrorRate(1)],
50
+ });
51
+ const ac = new AbortController();
52
+ ac.abort();
53
+ await expect(scenario.run(ac.signal)).rejects.toThrow(ScenarioAbortedError);
54
+ });
55
+ it('honors an explicit workload rps + concurrency', async () => {
56
+ const scenario = defineLoadScenario({
57
+ id: 'load-targetrps',
58
+ name: 'load-targetrps',
59
+ description: 'load with explicit RPS',
60
+ tags: [],
61
+ target: noopTarget,
62
+ workload: { rps: 10, concurrency: 4 },
63
+ duration: 1,
64
+ assertions: [ASSERTIONS.lowErrorRate(1)],
65
+ });
66
+ const result = await scenario.run(new AbortController().signal);
67
+ expect(result.kind).toBe('load');
68
+ expect(typeof result.passed).toBe('boolean');
69
+ });
70
+ });
71
+ describe('Chaos scenario execution', () => {
72
+ it('runs to completion and returns a chaos-kind result', async () => {
73
+ const scenario = defineChaosScenario({
74
+ id: 'chaos-exec-1',
75
+ name: 'chaos-exec-1',
76
+ description: 'tiny chaos run',
77
+ tags: [],
78
+ target: noopTarget,
79
+ workload: { rps: 1 },
80
+ duration: 1,
81
+ fault: fault.of([fault.drop()], { probability: 0.1 }),
82
+ steadyStateAssertions: [ASSERTIONS.lowErrorRate(1)],
83
+ recoveryAssertions: [ASSERTIONS.lowErrorRate(1)],
84
+ recoveryWindow: 100,
85
+ });
86
+ const result = await scenario.run(new AbortController().signal);
87
+ expect(result.kind).toBe('chaos');
88
+ expect(result.scenarioId).toBe('chaos-exec-1');
89
+ expect(typeof result.passed).toBe('boolean');
90
+ });
91
+ });
92
+ //# sourceMappingURL=scenario-execution.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scenario-execution.test.js","sourceRoot":"","sources":["../../src/__tests__/scenario-execution.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Capability contract for the `sim` tool.
3
+ *
4
+ * A Tier-2 guardrail (audit "Done Definition"): lock the promised surface so a
5
+ * flag can't be added/removed without an explicit contract update, and prove
6
+ * the scheduler applies recipe selectors BEFORE invoking any scenario runner
7
+ * (so a narrowed-out scenario never runs). Scoped to the non-cloud sim domain.
8
+ */
9
+ export {};
10
+ //# sourceMappingURL=sim-capability-contract.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sim-capability-contract.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/sim-capability-contract.test.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG"}
@@ -0,0 +1,131 @@
1
+ /**
2
+ * Capability contract for the `sim` tool.
3
+ *
4
+ * A Tier-2 guardrail (audit "Done Definition"): lock the promised surface so a
5
+ * flag can't be added/removed without an explicit contract update, and prove
6
+ * the scheduler applies recipe selectors BEFORE invoking any scenario runner
7
+ * (so a narrowed-out scenario never runs). Scoped to the non-cloud sim domain.
8
+ */
9
+ import { commonFlags } from '@opensip-cli/contracts';
10
+ import { runWithScope, runWithScopeSync } from '@opensip-cli/core';
11
+ import { afterEach, beforeEach, describe, expect, it } from 'vitest';
12
+ import { clearScenarioRegistry, currentScenarioRegistry } from '../framework/registry.js';
13
+ import { defineSimulationRecipe } from '../recipes/define-recipe.js';
14
+ import { SimulationRecipeService } from '../recipes/service.js';
15
+ import { simulationTool } from '../tool.js';
16
+ import { makeSimTestScope } from './test-utils/with-sim-scope.js';
17
+ // ---------------------------------------------------------------------------
18
+ // 1. Flag-surface lock
19
+ // ---------------------------------------------------------------------------
20
+ /**
21
+ * Derive the `--long` flag set sim declares from its `CommandSpec` (release
22
+ * 2.11.0 Phase 3): the ADR-0021 `commonFlags` keys mapped to their registry
23
+ * `--long` strings, plus each tool-specific `OptionSpec.flag`. This locks the
24
+ * exported command surface — adding/removing a flag must be a deliberate edit
25
+ * to the expected list below, so nothing ships undocumented or vanishes silently.
26
+ */
27
+ function recordRegisteredFlags() {
28
+ const spec = simulationTool.commandSpecs?.[0];
29
+ if (spec === undefined)
30
+ throw new Error('simulationTool exposes no commandSpecs');
31
+ const flags = [];
32
+ for (const key of spec.commonFlags) {
33
+ const match = /--[a-z][a-z-]*/.exec(commonFlags[key].flags);
34
+ if (match)
35
+ flags.push(match[0]);
36
+ }
37
+ for (const opt of spec.options ?? []) {
38
+ const match = /--[a-z][a-z-]*/.exec(opt.flag);
39
+ if (match)
40
+ flags.push(match[0]);
41
+ }
42
+ return flags.sort();
43
+ }
44
+ describe('sim tool — flag-surface contract', () => {
45
+ it('registers exactly the documented flag set (drift fails here)', () => {
46
+ // Adding or removing a `sim` flag must be a deliberate change to this list,
47
+ // so a new flag can't ship undocumented or an old one vanish silently.
48
+ expect(recordRegisteredFlags()).toEqual(
49
+ // ADR-0011 (Phase 4): sim gained cloud egress (--report-to / --api-key)
50
+ // when it began emitting the signal envelope.
51
+ // ADR-0021: sim gained -v/--verbose (cross-tool flag parity).
52
+ [
53
+ '--cwd',
54
+ '--debug',
55
+ '--json',
56
+ '--open',
57
+ '--quiet',
58
+ '--verbose',
59
+ '--recipe',
60
+ '--report-to',
61
+ '--api-key',
62
+ '--show',
63
+ ].sort());
64
+ });
65
+ });
66
+ // ---------------------------------------------------------------------------
67
+ // 2. Scheduler-order: filters/selectors narrow BEFORE the runner
68
+ // ---------------------------------------------------------------------------
69
+ /** A scenario that records execution and rejects if ever run. */
70
+ function tripwire(id, kind, fired) {
71
+ return {
72
+ id,
73
+ name: id,
74
+ description: id,
75
+ kind,
76
+ tags: [],
77
+ run: () => {
78
+ fired.ran = true;
79
+ return Promise.reject(new Error(`${id} must not run — it was narrowed out before execution`));
80
+ },
81
+ };
82
+ }
83
+ describe('sim scheduler — narrowing precedes execution', () => {
84
+ let scope;
85
+ beforeEach(() => {
86
+ scope = makeSimTestScope();
87
+ });
88
+ afterEach(() => {
89
+ runWithScopeSync(scope, () => clearScenarioRegistry());
90
+ });
91
+ function inSimScope(fn) {
92
+ return runWithScope(scope, fn);
93
+ }
94
+ it('a recipe selector excludes scenarios before they run', async () => {
95
+ await inSimScope(async () => {
96
+ const fired = { ran: false };
97
+ currentScenarioRegistry().register(tripwire('excluded-by-selector', 'load', fired));
98
+ const recipe = defineSimulationRecipe({
99
+ id: 'URCP_sel_exclude',
100
+ name: 'sel-exclude',
101
+ displayName: 'Selector exclude',
102
+ description: 'x',
103
+ scenarios: { type: 'all', exclude: ['excluded-by-selector'] },
104
+ execution: { mode: 'sequential' },
105
+ });
106
+ const result = await new SimulationRecipeService().runRecipe(recipe);
107
+ expect(fired.ran).toBe(false);
108
+ expect(result.totalScenarios).toBe(0);
109
+ });
110
+ });
111
+ it('a kind recipe selector excludes other-kind scenarios before they run', async () => {
112
+ await inSimScope(async () => {
113
+ const fired = { ran: false };
114
+ currentScenarioRegistry().register(tripwire('excluded-by-kind', 'load', fired));
115
+ const recipe = defineSimulationRecipe({
116
+ id: 'URCP_kind_exclude',
117
+ name: 'kind-exclude',
118
+ displayName: 'Kind exclude',
119
+ description: 'x',
120
+ // The recipe selects only chaos scenarios; the 'load' tripwire is dropped
121
+ // before execution.
122
+ scenarios: { type: 'kind', kinds: ['chaos'] },
123
+ execution: { mode: 'sequential' },
124
+ });
125
+ const result = await new SimulationRecipeService().runRecipe(recipe);
126
+ expect(fired.ran).toBe(false);
127
+ expect(result.totalScenarios).toBe(0);
128
+ });
129
+ });
130
+ });
131
+ //# sourceMappingURL=sim-capability-contract.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sim-capability-contract.test.js","sourceRoot":"","sources":["../../src/__tests__/sim-capability-contract.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Unit coverage for the simulation namespace config schema (Phase 4 Task 4.2).
3
+ */
4
+ export {};
5
+ //# sourceMappingURL=sim-config-schema.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sim-config-schema.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/sim-config-schema.test.ts"],"names":[],"mappings":"AAAA;;GAEG"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Unit coverage for the simulation namespace config schema (Phase 4 Task 4.2).
3
+ */
4
+ import { describe, expect, it } from 'vitest';
5
+ import { SimulationNamespaceSchema, simulationConfigDeclaration, } from '../cli/sim-config-schema.js';
6
+ describe('SimulationNamespaceSchema', () => {
7
+ it('accepts a block with a recipe', () => {
8
+ expect(SimulationNamespaceSchema.parse({ recipe: 'example' })).toEqual({ recipe: 'example' });
9
+ });
10
+ it('accepts an empty block', () => {
11
+ expect(SimulationNamespaceSchema.parse({})).toEqual({});
12
+ });
13
+ it('rejects a non-string recipe', () => {
14
+ expect(SimulationNamespaceSchema.safeParse({ recipe: 3 }).success).toBe(false);
15
+ });
16
+ it('rejects an unknown key once strict (composer behaviour)', () => {
17
+ expect(SimulationNamespaceSchema.strict().safeParse({ recpe: 'x' }).success).toBe(false);
18
+ });
19
+ it('declares namespace simulation', () => {
20
+ expect(simulationConfigDeclaration.namespace).toBe('simulation');
21
+ });
22
+ });
23
+ //# sourceMappingURL=sim-config-schema.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sim-config-schema.test.js","sourceRoot":"","sources":["../../src/__tests__/sim-config-schema.test.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAE9C,OAAO,EACL,yBAAyB,EACzB,2BAA2B,GAC5B,MAAM,6BAA6B,CAAC;AAErC,QAAQ,CAAC,2BAA2B,EAAE,GAAG,EAAE;IACzC,EAAE,CAAC,+BAA+B,EAAE,GAAG,EAAE;QACvC,MAAM,CAAC,yBAAyB,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC;IAChG,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wBAAwB,EAAE,GAAG,EAAE;QAChC,MAAM,CAAC,yBAAyB,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IAC1D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6BAA6B,EAAE,GAAG,EAAE;QACrC,MAAM,CAAC,yBAAyB,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACjF,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,yDAAyD,EAAE,GAAG,EAAE;QACjE,MAAM,CAAC,yBAAyB,CAAC,MAAM,EAAE,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC3F,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,+BAA+B,EAAE,GAAG,EAAE;QACvC,MAAM,CAAC,2BAA2B,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IACnE,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * @fileoverview ADR-0035 gate precondition: a failed sim scenario must surface
3
+ * an error-severity signal (the signal currency), for BOTH kinds — load (via
4
+ * the result builder) and chaos (which builds its own payload). Before this,
5
+ * a failing run had `passed: false` but `signals: []`, so the host verdict
6
+ * computed `errors === 0` and would flip the run to PASS. These tests pin the
7
+ * fix against the real executors.
8
+ */
9
+ export {};
10
+ //# sourceMappingURL=sim-failure-signal.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sim-failure-signal.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/sim-failure-signal.test.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG"}
@@ -0,0 +1,86 @@
1
+ /**
2
+ * @fileoverview ADR-0035 gate precondition: a failed sim scenario must surface
3
+ * an error-severity signal (the signal currency), for BOTH kinds — load (via
4
+ * the result builder) and chaos (which builds its own payload). Before this,
5
+ * a failing run had `passed: false` but `signals: []`, so the host verdict
6
+ * computed `errors === 0` and would flip the run to PASS. These tests pin the
7
+ * fix against the real executors.
8
+ */
9
+ import { isErrorSignal } from '@opensip-cli/core';
10
+ import { describe, expect, it } from 'vitest';
11
+ import { ASSERTIONS } from '../framework/assertions.js';
12
+ import { fault } from '../framework/execution/fault-builders.js';
13
+ import { buildFailedScenarioSignal } from '../framework/result-builder.js';
14
+ import { createChaosScenarioRunner } from '../kinds/chaos/executor.js';
15
+ import { createLoadScenarioRunner } from '../kinds/load/executor.js';
16
+ import { failingTarget, noopTarget } from './test-utils/targets.js';
17
+ const loadCfg = (o = {}) => ({
18
+ id: 'load-x',
19
+ name: 'load-x',
20
+ description: 'load-x',
21
+ tags: [],
22
+ target: noopTarget,
23
+ workload: { rps: 50 },
24
+ duration: 0.3,
25
+ assertions: [ASSERTIONS.lowErrorRate(0.5)],
26
+ ...o,
27
+ });
28
+ const chaosCfg = (o = {}) => ({
29
+ id: 'chaos-x',
30
+ name: 'chaos-x',
31
+ description: 'chaos-x',
32
+ tags: [],
33
+ target: noopTarget,
34
+ workload: { rps: 50 },
35
+ duration: 0.3,
36
+ fault: fault.of([fault.drop()], { probability: 1 }),
37
+ steadyStateAssertions: [ASSERTIONS.lowErrorRate(0.1)],
38
+ recoveryAssertions: [ASSERTIONS.lowErrorRate(0.5)],
39
+ recoveryWindow: 100,
40
+ ...o,
41
+ });
42
+ describe('ADR-0035 · failed scenario emits an error-severity signal', () => {
43
+ it('load: a failing scenario emits ≥1 error signal attributed to its id', async () => {
44
+ const r = await createLoadScenarioRunner(loadCfg({ target: failingTarget, assertions: [ASSERTIONS.lowErrorRate(0.1)] })).run(new AbortController().signal);
45
+ if (r.kind !== 'load')
46
+ throw new Error('expected load result');
47
+ expect(r.passed).toBe(false);
48
+ const errors = r.signals.filter(isErrorSignal);
49
+ expect(errors.length).toBeGreaterThanOrEqual(1);
50
+ expect(errors[0]?.source).toBe('load-x');
51
+ });
52
+ it('load: a passing scenario emits no error signal', async () => {
53
+ const r = await createLoadScenarioRunner(loadCfg()).run(new AbortController().signal);
54
+ if (r.kind !== 'load')
55
+ throw new Error('expected load result');
56
+ expect(r.passed).toBe(true);
57
+ expect(r.signals.filter(isErrorSignal)).toHaveLength(0);
58
+ });
59
+ it('chaos: a failing scenario emits ≥1 error signal attributed to its id', async () => {
60
+ const r = await createChaosScenarioRunner(chaosCfg()).run(new AbortController().signal);
61
+ if (r.kind !== 'chaos')
62
+ throw new Error('expected chaos result');
63
+ expect(r.passed).toBe(false);
64
+ const errors = r.signals.filter(isErrorSignal);
65
+ expect(errors.length).toBeGreaterThanOrEqual(1);
66
+ expect(errors[0]?.source).toBe('chaos-x');
67
+ });
68
+ it('chaos: a passing scenario (no faults) emits no error signal', async () => {
69
+ const r = await createChaosScenarioRunner(chaosCfg({ fault: fault.of([fault.drop()], { probability: 0 }) })).run(new AbortController().signal);
70
+ if (r.kind !== 'chaos')
71
+ throw new Error('expected chaos result');
72
+ expect(r.passed).toBe(true);
73
+ expect(r.signals.filter(isErrorSignal)).toHaveLength(0);
74
+ });
75
+ it('buildFailedScenarioSignal: high severity, scenario-attributed, summarizes assertions', () => {
76
+ const sig = buildFailedScenarioSignal('s1', [
77
+ { metric: 'error_rate', operator: 'lte', value: 0.1, message: 'low errors', actual: 0.9 },
78
+ ]);
79
+ expect(sig.severity).toBe('high');
80
+ expect(isErrorSignal(sig)).toBe(true);
81
+ expect(sig.source).toBe('s1');
82
+ expect(sig.message).toContain('error_rate');
83
+ expect(sig.message).toContain('0.9');
84
+ });
85
+ });
86
+ //# sourceMappingURL=sim-failure-signal.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sim-failure-signal.test.js","sourceRoot":"","sources":["../../src/__tests__/sim-failure-signal.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * @fileoverview Cross-cutting surface tests that don't belong to a single
3
+ * kind: the metric resolver's latency aliases, registry/recipe scope guards,
4
+ * and the recipe service's live-progress callback.
5
+ *
6
+ * The driver, fault model, and per-kind executor behaviour are covered by the
7
+ * dedicated framework/execution and per-kind executor test suites.
8
+ */
9
+ export {};
10
+ //# sourceMappingURL=surviving-surface-edges.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"surviving-surface-edges.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/surviving-surface-edges.test.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG"}
@@ -0,0 +1,122 @@
1
+ /**
2
+ * @fileoverview Cross-cutting surface tests that don't belong to a single
3
+ * kind: the metric resolver's latency aliases, registry/recipe scope guards,
4
+ * and the recipe service's live-progress callback.
5
+ *
6
+ * The driver, fault model, and per-kind executor behaviour are covered by the
7
+ * dedicated framework/execution and per-kind executor test suites.
8
+ */
9
+ import { enterScope, RunScope, runWithScopeSync } from '@opensip-cli/core';
10
+ import { afterEach, beforeEach, describe, expect, it } from 'vitest';
11
+ import { ASSERTIONS } from '../framework/assertions.js';
12
+ import { clearScenarioRegistry, currentScenarioRegistry } from '../framework/registry.js';
13
+ import { resolveMetric } from '../framework/resolve-metric.js';
14
+ import { defineLoadScenario } from '../kinds/load/define.js';
15
+ import { currentSimulationRecipeRegistry } from '../recipes/registry.js';
16
+ import { SimulationRecipeService } from '../recipes/service.js';
17
+ import { noopTarget } from './test-utils/targets.js';
18
+ import { makeSimTestScope } from './test-utils/with-sim-scope.js';
19
+ beforeEach(() => {
20
+ enterScope(makeSimTestScope());
21
+ });
22
+ afterEach(() => {
23
+ try {
24
+ clearScenarioRegistry();
25
+ }
26
+ catch {
27
+ // some tests deliberately run outside a scope
28
+ }
29
+ });
30
+ const loadConfig = (overrides = {}) => ({
31
+ id: 'load-edge',
32
+ name: 'load-edge',
33
+ description: 'load edge',
34
+ tags: [],
35
+ target: noopTarget,
36
+ workload: { rps: 1 },
37
+ duration: 1,
38
+ assertions: [ASSERTIONS.lowErrorRate(1)],
39
+ ...overrides,
40
+ });
41
+ // ===========================================================================
42
+ // registry scope guards
43
+ // ===========================================================================
44
+ describe('scenario/recipe registry scope guards', () => {
45
+ it('currentScenarioRegistry throws when the active scope has no simulation subscope', () => {
46
+ // A bare RunScope (no simulationTool.contributeScope applied) is a real
47
+ // misconfiguration: the tool wasn't registered before a scenario read.
48
+ runWithScopeSync(new RunScope(), () => {
49
+ expect(() => currentScenarioRegistry()).toThrow(/scope\.simulation is missing/);
50
+ });
51
+ });
52
+ it('currentSimulationRecipeRegistry throws when the active scope has no simulation subscope', () => {
53
+ runWithScopeSync(new RunScope(), () => {
54
+ expect(() => currentSimulationRecipeRegistry()).toThrow(/scope\.simulation is missing/);
55
+ });
56
+ });
57
+ it('currentSimulationRecipeRegistry resolves the scope-bound registry inside a sim scope', () => {
58
+ // Inside the beforeEach sim scope the recipe registry is reachable and has
59
+ // the built-in default recipe.
60
+ expect(currentSimulationRecipeRegistry().getByName('default')).toBeDefined();
61
+ });
62
+ });
63
+ // ===========================================================================
64
+ // resolve-metric — non-`_ms` latency aliases
65
+ // ===========================================================================
66
+ describe('resolveMetric — latency key aliases', () => {
67
+ const m = {
68
+ totalRequests: 100,
69
+ successfulRequests: 90,
70
+ failedRequests: 10,
71
+ avgLatencyMs: 41,
72
+ p50LatencyMs: 30,
73
+ p95LatencyMs: 70,
74
+ p99LatencyMs: 120,
75
+ errorsGenerated: 10,
76
+ };
77
+ it.each([
78
+ ['avg_latency', 41],
79
+ ['p50_latency', 30],
80
+ ['p95_latency', 70],
81
+ ['p99_latency', 120],
82
+ ])('resolves the %s alias to the corresponding *_ms field', (key, expected) => {
83
+ expect(resolveMetric(key, m)).toBe(expected);
84
+ });
85
+ it('resolves requests_per_second using the supplied duration', () => {
86
+ expect(resolveMetric('requests_per_second', m, 10)).toBeCloseTo(10);
87
+ });
88
+ it('returns 0 for errors_generated passthrough when none recorded', () => {
89
+ expect(resolveMetric('errors_generated', { ...m, errorsGenerated: 0 })).toBe(0);
90
+ });
91
+ });
92
+ // ===========================================================================
93
+ // recipe service — live-progress callback
94
+ // ===========================================================================
95
+ describe('SimulationRecipeService — onProgress', () => {
96
+ it('fires (0, total) up front then a monotonic completed count per scenario', async () => {
97
+ currentScenarioRegistry().register(defineLoadScenario(loadConfig({ id: 'prog-a', name: 'prog-a' })));
98
+ currentScenarioRegistry().register(defineLoadScenario(loadConfig({ id: 'prog-b', name: 'prog-b' })));
99
+ const events = [];
100
+ const service = new SimulationRecipeService({
101
+ onProgress: (completed, total) => events.push([completed, total]),
102
+ });
103
+ await service.runRecipe({
104
+ id: 'URCP_prog',
105
+ name: 'prog',
106
+ displayName: 'Prog',
107
+ description: 'progress',
108
+ scenarios: { type: 'all' },
109
+ execution: { mode: 'sequential' },
110
+ });
111
+ // First event is the (0, total) kickoff.
112
+ expect(events[0]).toEqual([0, 2]);
113
+ // Final event reports both scenarios complete.
114
+ expect(events.at(-1)).toEqual([2, 2]);
115
+ // The completed counter never decreases.
116
+ const completedSeq = events.map(([c]) => c);
117
+ for (let i = 1; i < completedSeq.length; i++) {
118
+ expect(completedSeq[i]).toBeGreaterThanOrEqual(completedSeq[i - 1] ?? 0);
119
+ }
120
+ });
121
+ });
122
+ //# sourceMappingURL=surviving-surface-edges.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"surviving-surface-edges.test.js","sourceRoot":"","sources":["../../src/__tests__/surviving-surface-edges.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * @fileoverview Shared in-process `Target`s for simulation tests.
3
+ *
4
+ * These let scenario fixtures drive the real load-window driver without any
5
+ * network I/O. `noopTarget` always succeeds; `countingTarget` records how many
6
+ * times it was invoked (and how many were concurrent) for driver assertions.
7
+ */
8
+ import type { Target } from '../../framework/execution/target.js';
9
+ /** A target that always succeeds immediately. */
10
+ export declare const noopTarget: Target;
11
+ /** A target that always fails (throws) immediately. */
12
+ export declare const failingTarget: Target;
13
+ /** A counting target plus its observed call/concurrency stats. */
14
+ export interface CountingTarget {
15
+ readonly target: Target;
16
+ /** Total invocations. */
17
+ calls(): number;
18
+ /** Peak simultaneous in-flight invocations observed. */
19
+ maxConcurrent(): number;
20
+ }
21
+ /**
22
+ * Build a target that resolves after `delayMs` and tracks invocation count +
23
+ * peak concurrency. `delayMs` defaults to 0 (resolve on the next microtask).
24
+ */
25
+ export declare function countingTarget(delayMs?: number): CountingTarget;
26
+ //# sourceMappingURL=targets.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"targets.d.ts","sourceRoot":"","sources":["../../../src/__tests__/test-utils/targets.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qCAAqC,CAAC;AAElE,iDAAiD;AACjD,eAAO,MAAM,UAAU,EAAE,MAAgC,CAAC;AAE1D,uDAAuD;AACvD,eAAO,MAAM,aAAa,EAAE,MAAuE,CAAC;AAEpG,kEAAkE;AAClE,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,yBAAyB;IACzB,KAAK,IAAI,MAAM,CAAC;IAChB,wDAAwD;IACxD,aAAa,IAAI,MAAM,CAAC;CACzB;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,OAAO,SAAI,GAAG,cAAc,CAoB1D"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * @fileoverview Shared in-process `Target`s for simulation tests.
3
+ *
4
+ * These let scenario fixtures drive the real load-window driver without any
5
+ * network I/O. `noopTarget` always succeeds; `countingTarget` records how many
6
+ * times it was invoked (and how many were concurrent) for driver assertions.
7
+ */
8
+ /** A target that always succeeds immediately. */
9
+ export const noopTarget = () => Promise.resolve();
10
+ /** A target that always fails (throws) immediately. */
11
+ export const failingTarget = () => Promise.reject(new Error('test-target: forced failure'));
12
+ /**
13
+ * Build a target that resolves after `delayMs` and tracks invocation count +
14
+ * peak concurrency. `delayMs` defaults to 0 (resolve on the next microtask).
15
+ */
16
+ export function countingTarget(delayMs = 0) {
17
+ let calls = 0;
18
+ let inFlight = 0;
19
+ let peak = 0;
20
+ return {
21
+ target: async () => {
22
+ calls++;
23
+ inFlight++;
24
+ peak = Math.max(peak, inFlight);
25
+ try {
26
+ if (delayMs > 0) {
27
+ await new Promise((resolve) => setTimeout(resolve, delayMs));
28
+ }
29
+ }
30
+ finally {
31
+ inFlight--;
32
+ }
33
+ },
34
+ calls: () => calls,
35
+ maxConcurrent: () => peak,
36
+ };
37
+ }
38
+ //# sourceMappingURL=targets.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"targets.js","sourceRoot":"","sources":["../../../src/__tests__/test-utils/targets.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,iDAAiD;AACjD,MAAM,CAAC,MAAM,UAAU,GAAW,GAAG,EAAE,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;AAE1D,uDAAuD;AACvD,MAAM,CAAC,MAAM,aAAa,GAAW,GAAG,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,6BAA6B,CAAC,CAAC,CAAC;AAWpG;;;GAGG;AACH,MAAM,UAAU,cAAc,CAAC,OAAO,GAAG,CAAC;IACxC,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,IAAI,QAAQ,GAAG,CAAC,CAAC;IACjB,IAAI,IAAI,GAAG,CAAC,CAAC;IACb,OAAO;QACL,MAAM,EAAE,KAAK,IAAI,EAAE;YACjB,KAAK,EAAE,CAAC;YACR,QAAQ,EAAE,CAAC;YACX,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;YAChC,IAAI,CAAC;gBACH,IAAI,OAAO,GAAG,CAAC,EAAE,CAAC;oBAChB,MAAM,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC;gBAC/D,CAAC;YACH,CAAC;oBAAS,CAAC;gBACT,QAAQ,EAAE,CAAC;YACb,CAAC;QACH,CAAC;QACD,KAAK,EAAE,GAAG,EAAE,CAAC,KAAK;QAClB,aAAa,EAAE,GAAG,EAAE,CAAC,IAAI;KAC1B,CAAC;AACJ,CAAC"}