@e2edev/e2e 0.2.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 (399) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +104 -0
  3. package/dist/agent/act-validation.d.ts +27 -0
  4. package/dist/agent/act-validation.d.ts.map +1 -0
  5. package/dist/agent/act-validation.js +121 -0
  6. package/dist/agent/act-validation.js.map +1 -0
  7. package/dist/agent/act.d.ts +27 -0
  8. package/dist/agent/act.d.ts.map +1 -0
  9. package/dist/agent/act.js +775 -0
  10. package/dist/agent/act.js.map +1 -0
  11. package/dist/agent/actions.d.ts +66 -0
  12. package/dist/agent/actions.d.ts.map +1 -0
  13. package/dist/agent/actions.js +82 -0
  14. package/dist/agent/actions.js.map +1 -0
  15. package/dist/agent/ai-sdk.d.ts +16 -0
  16. package/dist/agent/ai-sdk.d.ts.map +1 -0
  17. package/dist/agent/ai-sdk.js +59 -0
  18. package/dist/agent/ai-sdk.js.map +1 -0
  19. package/dist/agent/call-options.d.ts +10 -0
  20. package/dist/agent/call-options.d.ts.map +1 -0
  21. package/dist/agent/call-options.js +28 -0
  22. package/dist/agent/call-options.js.map +1 -0
  23. package/dist/agent/default-agent.d.ts +22 -0
  24. package/dist/agent/default-agent.d.ts.map +1 -0
  25. package/dist/agent/default-agent.js +354 -0
  26. package/dist/agent/default-agent.js.map +1 -0
  27. package/dist/agent/error.d.ts +53 -0
  28. package/dist/agent/error.d.ts.map +1 -0
  29. package/dist/agent/error.js +94 -0
  30. package/dist/agent/error.js.map +1 -0
  31. package/dist/agent/executor.d.ts +238 -0
  32. package/dist/agent/executor.d.ts.map +1 -0
  33. package/dist/agent/executor.js +56 -0
  34. package/dist/agent/executor.js.map +1 -0
  35. package/dist/agent/index.d.ts +15 -0
  36. package/dist/agent/index.d.ts.map +1 -0
  37. package/dist/agent/index.js +304 -0
  38. package/dist/agent/index.js.map +1 -0
  39. package/dist/agent/invocation.d.ts +194 -0
  40. package/dist/agent/invocation.d.ts.map +1 -0
  41. package/dist/agent/invocation.js +389 -0
  42. package/dist/agent/invocation.js.map +1 -0
  43. package/dist/agent/ledger.d.ts +24 -0
  44. package/dist/agent/ledger.d.ts.map +1 -0
  45. package/dist/agent/ledger.js +48 -0
  46. package/dist/agent/ledger.js.map +1 -0
  47. package/dist/agent/loop-guards.d.ts +35 -0
  48. package/dist/agent/loop-guards.d.ts.map +1 -0
  49. package/dist/agent/loop-guards.js +110 -0
  50. package/dist/agent/loop-guards.js.map +1 -0
  51. package/dist/agent/model/adapter.d.ts +97 -0
  52. package/dist/agent/model/adapter.d.ts.map +1 -0
  53. package/dist/agent/model/adapter.js +40 -0
  54. package/dist/agent/model/adapter.js.map +1 -0
  55. package/dist/agent/model/router.d.ts +36 -0
  56. package/dist/agent/model/router.d.ts.map +1 -0
  57. package/dist/agent/model/router.js +45 -0
  58. package/dist/agent/model/router.js.map +1 -0
  59. package/dist/agent/model/schema.d.ts +16 -0
  60. package/dist/agent/model/schema.d.ts.map +1 -0
  61. package/dist/agent/model/schema.js +37 -0
  62. package/dist/agent/model/schema.js.map +1 -0
  63. package/dist/agent/model/sdk.d.ts +28 -0
  64. package/dist/agent/model/sdk.d.ts.map +1 -0
  65. package/dist/agent/model/sdk.js +258 -0
  66. package/dist/agent/model/sdk.js.map +1 -0
  67. package/dist/agent/observation.d.ts +70 -0
  68. package/dist/agent/observation.d.ts.map +1 -0
  69. package/dist/agent/observation.js +174 -0
  70. package/dist/agent/observation.js.map +1 -0
  71. package/dist/agent/phases.d.ts +71 -0
  72. package/dist/agent/phases.d.ts.map +1 -0
  73. package/dist/agent/phases.js +124 -0
  74. package/dist/agent/phases.js.map +1 -0
  75. package/dist/agent/prompts.d.ts +40 -0
  76. package/dist/agent/prompts.d.ts.map +1 -0
  77. package/dist/agent/prompts.js +104 -0
  78. package/dist/agent/prompts.js.map +1 -0
  79. package/dist/agent/protocol.d.ts +31 -0
  80. package/dist/agent/protocol.d.ts.map +1 -0
  81. package/dist/agent/protocol.js +67 -0
  82. package/dist/agent/protocol.js.map +1 -0
  83. package/dist/agent/public.d.ts +12 -0
  84. package/dist/agent/public.d.ts.map +1 -0
  85. package/dist/agent/public.js +12 -0
  86. package/dist/agent/public.js.map +1 -0
  87. package/dist/agent/replay.d.ts +61 -0
  88. package/dist/agent/replay.d.ts.map +1 -0
  89. package/dist/agent/replay.js +185 -0
  90. package/dist/agent/replay.js.map +1 -0
  91. package/dist/agent/secrets.d.ts +22 -0
  92. package/dist/agent/secrets.d.ts.map +1 -0
  93. package/dist/agent/secrets.js +63 -0
  94. package/dist/agent/secrets.js.map +1 -0
  95. package/dist/agent/step-cache.d.ts +156 -0
  96. package/dist/agent/step-cache.d.ts.map +1 -0
  97. package/dist/agent/step-cache.js +301 -0
  98. package/dist/agent/step-cache.js.map +1 -0
  99. package/dist/agent/tool-loop.d.ts +51 -0
  100. package/dist/agent/tool-loop.d.ts.map +1 -0
  101. package/dist/agent/tool-loop.js +331 -0
  102. package/dist/agent/tool-loop.js.map +1 -0
  103. package/dist/agent/tool.d.ts +39 -0
  104. package/dist/agent/tool.d.ts.map +1 -0
  105. package/dist/agent/tool.js +52 -0
  106. package/dist/agent/tool.js.map +1 -0
  107. package/dist/backend/contract.d.ts +186 -0
  108. package/dist/backend/contract.d.ts.map +1 -0
  109. package/dist/backend/contract.js +65 -0
  110. package/dist/backend/contract.js.map +1 -0
  111. package/dist/backend/index.d.ts +316 -0
  112. package/dist/backend/index.d.ts.map +1 -0
  113. package/dist/backend/index.js +219 -0
  114. package/dist/backend/index.js.map +1 -0
  115. package/dist/backend/session.d.ts +23 -0
  116. package/dist/backend/session.d.ts.map +1 -0
  117. package/dist/backend/session.js +213 -0
  118. package/dist/backend/session.js.map +1 -0
  119. package/dist/backend/surface.d.ts +83 -0
  120. package/dist/backend/surface.d.ts.map +1 -0
  121. package/dist/backend/surface.js +11 -0
  122. package/dist/backend/surface.js.map +1 -0
  123. package/dist/cache/anchors.d.ts +37 -0
  124. package/dist/cache/anchors.d.ts.map +1 -0
  125. package/dist/cache/anchors.js +89 -0
  126. package/dist/cache/anchors.js.map +1 -0
  127. package/dist/cache/context.d.ts +74 -0
  128. package/dist/cache/context.d.ts.map +1 -0
  129. package/dist/cache/context.js +82 -0
  130. package/dist/cache/context.js.map +1 -0
  131. package/dist/cache/decide.d.ts +42 -0
  132. package/dist/cache/decide.d.ts.map +1 -0
  133. package/dist/cache/decide.js +47 -0
  134. package/dist/cache/decide.js.map +1 -0
  135. package/dist/cache/identity.d.ts +113 -0
  136. package/dist/cache/identity.d.ts.map +1 -0
  137. package/dist/cache/identity.js +109 -0
  138. package/dist/cache/identity.js.map +1 -0
  139. package/dist/cache/recorder.d.ts +76 -0
  140. package/dist/cache/recorder.d.ts.map +1 -0
  141. package/dist/cache/recorder.js +143 -0
  142. package/dist/cache/recorder.js.map +1 -0
  143. package/dist/cache/relocate.d.ts +69 -0
  144. package/dist/cache/relocate.d.ts.map +1 -0
  145. package/dist/cache/relocate.js +125 -0
  146. package/dist/cache/relocate.js.map +1 -0
  147. package/dist/cache/store.d.ts +68 -0
  148. package/dist/cache/store.d.ts.map +1 -0
  149. package/dist/cache/store.js +106 -0
  150. package/dist/cache/store.js.map +1 -0
  151. package/dist/cache/trace.d.ts +146 -0
  152. package/dist/cache/trace.d.ts.map +1 -0
  153. package/dist/cache/trace.js +249 -0
  154. package/dist/cache/trace.js.map +1 -0
  155. package/dist/cli/bin.d.ts +3 -0
  156. package/dist/cli/bin.d.ts.map +1 -0
  157. package/dist/cli/bin.js +4 -0
  158. package/dist/cli/bin.js.map +1 -0
  159. package/dist/cli/index.d.ts +4 -0
  160. package/dist/cli/index.d.ts.map +1 -0
  161. package/dist/cli/index.js +108 -0
  162. package/dist/cli/index.js.map +1 -0
  163. package/dist/cli/init.d.ts +6 -0
  164. package/dist/cli/init.d.ts.map +1 -0
  165. package/dist/cli/init.js +101 -0
  166. package/dist/cli/init.js.map +1 -0
  167. package/dist/collect/collect.d.ts +44 -0
  168. package/dist/collect/collect.d.ts.map +1 -0
  169. package/dist/collect/collect.js +89 -0
  170. package/dist/collect/collect.js.map +1 -0
  171. package/dist/collect/registry.d.ts +47 -0
  172. package/dist/collect/registry.d.ts.map +1 -0
  173. package/dist/collect/registry.js +262 -0
  174. package/dist/collect/registry.js.map +1 -0
  175. package/dist/collect/select.d.ts +54 -0
  176. package/dist/collect/select.d.ts.map +1 -0
  177. package/dist/collect/select.js +230 -0
  178. package/dist/collect/select.js.map +1 -0
  179. package/dist/config/agent.d.ts +91 -0
  180. package/dist/config/agent.d.ts.map +1 -0
  181. package/dist/config/agent.js +232 -0
  182. package/dist/config/agent.js.map +1 -0
  183. package/dist/config/load.d.ts +23 -0
  184. package/dist/config/load.d.ts.map +1 -0
  185. package/dist/config/load.js +75 -0
  186. package/dist/config/load.js.map +1 -0
  187. package/dist/config/resolve.d.ts +94 -0
  188. package/dist/config/resolve.d.ts.map +1 -0
  189. package/dist/config/resolve.js +500 -0
  190. package/dist/config/resolve.js.map +1 -0
  191. package/dist/config/validate.d.ts +6 -0
  192. package/dist/config/validate.d.ts.map +1 -0
  193. package/dist/config/validate.js +21 -0
  194. package/dist/config/validate.js.map +1 -0
  195. package/dist/credentials.d.ts +7 -0
  196. package/dist/credentials.d.ts.map +1 -0
  197. package/dist/credentials.js +42 -0
  198. package/dist/credentials.js.map +1 -0
  199. package/dist/expect/async.d.ts +5 -0
  200. package/dist/expect/async.d.ts.map +1 -0
  201. package/dist/expect/async.js +186 -0
  202. package/dist/expect/async.js.map +1 -0
  203. package/dist/expect/index.d.ts +7 -0
  204. package/dist/expect/index.d.ts.map +1 -0
  205. package/dist/expect/index.js +23 -0
  206. package/dist/expect/index.js.map +1 -0
  207. package/dist/expect/values.d.ts +4 -0
  208. package/dist/expect/values.d.ts.map +1 -0
  209. package/dist/expect/values.js +108 -0
  210. package/dist/expect/values.js.map +1 -0
  211. package/dist/index.d.ts +13 -0
  212. package/dist/index.d.ts.map +1 -0
  213. package/dist/index.js +15 -0
  214. package/dist/index.js.map +1 -0
  215. package/dist/internal/ai-trace.d.ts +151 -0
  216. package/dist/internal/ai-trace.d.ts.map +1 -0
  217. package/dist/internal/ai-trace.js +360 -0
  218. package/dist/internal/ai-trace.js.map +1 -0
  219. package/dist/internal/brands.d.ts +9 -0
  220. package/dist/internal/brands.d.ts.map +1 -0
  221. package/dist/internal/brands.js +9 -0
  222. package/dist/internal/brands.js.map +1 -0
  223. package/dist/internal/debug.d.ts +43 -0
  224. package/dist/internal/debug.d.ts.map +1 -0
  225. package/dist/internal/debug.js +102 -0
  226. package/dist/internal/debug.js.map +1 -0
  227. package/dist/internal/errors.d.ts +98 -0
  228. package/dist/internal/errors.d.ts.map +1 -0
  229. package/dist/internal/errors.js +212 -0
  230. package/dist/internal/errors.js.map +1 -0
  231. package/dist/internal/globs.d.ts +29 -0
  232. package/dist/internal/globs.d.ts.map +1 -0
  233. package/dist/internal/globs.js +126 -0
  234. package/dist/internal/globs.js.map +1 -0
  235. package/dist/internal/ids.d.ts +32 -0
  236. package/dist/internal/ids.d.ts.map +1 -0
  237. package/dist/internal/ids.js +124 -0
  238. package/dist/internal/ids.js.map +1 -0
  239. package/dist/internal/json-value.d.ts +15 -0
  240. package/dist/internal/json-value.d.ts.map +1 -0
  241. package/dist/internal/json-value.js +61 -0
  242. package/dist/internal/json-value.js.map +1 -0
  243. package/dist/internal/package-version.d.ts +6 -0
  244. package/dist/internal/package-version.d.ts.map +1 -0
  245. package/dist/internal/package-version.js +14 -0
  246. package/dist/internal/package-version.js.map +1 -0
  247. package/dist/internal/realm-slot.d.ts +13 -0
  248. package/dist/internal/realm-slot.d.ts.map +1 -0
  249. package/dist/internal/realm-slot.js +23 -0
  250. package/dist/internal/realm-slot.js.map +1 -0
  251. package/dist/internal/redact.d.ts +33 -0
  252. package/dist/internal/redact.d.ts.map +1 -0
  253. package/dist/internal/redact.js +56 -0
  254. package/dist/internal/redact.js.map +1 -0
  255. package/dist/internal/regexp.d.ts +10 -0
  256. package/dist/internal/regexp.d.ts.map +1 -0
  257. package/dist/internal/regexp.js +27 -0
  258. package/dist/internal/regexp.js.map +1 -0
  259. package/dist/internal/text.d.ts +39 -0
  260. package/dist/internal/text.d.ts.map +1 -0
  261. package/dist/internal/text.js +66 -0
  262. package/dist/internal/text.js.map +1 -0
  263. package/dist/internal/time.d.ts +37 -0
  264. package/dist/internal/time.d.ts.map +1 -0
  265. package/dist/internal/time.js +91 -0
  266. package/dist/internal/time.js.map +1 -0
  267. package/dist/internal/trace.d.ts +18 -0
  268. package/dist/internal/trace.d.ts.map +1 -0
  269. package/dist/internal/trace.js +46 -0
  270. package/dist/internal/trace.js.map +1 -0
  271. package/dist/internal/urls.d.ts +31 -0
  272. package/dist/internal/urls.d.ts.map +1 -0
  273. package/dist/internal/urls.js +95 -0
  274. package/dist/internal/urls.js.map +1 -0
  275. package/dist/locator/engine.d.ts +65 -0
  276. package/dist/locator/engine.d.ts.map +1 -0
  277. package/dist/locator/engine.js +164 -0
  278. package/dist/locator/engine.js.map +1 -0
  279. package/dist/locator/expression.d.ts +19 -0
  280. package/dist/locator/expression.d.ts.map +1 -0
  281. package/dist/locator/expression.js +85 -0
  282. package/dist/locator/expression.js.map +1 -0
  283. package/dist/locator/screen.d.ts +36 -0
  284. package/dist/locator/screen.d.ts.map +1 -0
  285. package/dist/locator/screen.js +281 -0
  286. package/dist/locator/screen.js.map +1 -0
  287. package/dist/report/build.d.ts +214 -0
  288. package/dist/report/build.d.ts.map +1 -0
  289. package/dist/report/build.js +346 -0
  290. package/dist/report/build.js.map +1 -0
  291. package/dist/report/code-frame.d.ts +20 -0
  292. package/dist/report/code-frame.d.ts.map +1 -0
  293. package/dist/report/code-frame.js +73 -0
  294. package/dist/report/code-frame.js.map +1 -0
  295. package/dist/report/debug-steps.d.ts +14 -0
  296. package/dist/report/debug-steps.d.ts.map +1 -0
  297. package/dist/report/debug-steps.js +85 -0
  298. package/dist/report/debug-steps.js.map +1 -0
  299. package/dist/report/list.d.ts +80 -0
  300. package/dist/report/list.d.ts.map +1 -0
  301. package/dist/report/list.js +372 -0
  302. package/dist/report/list.js.map +1 -0
  303. package/dist/report/live-status.d.ts +51 -0
  304. package/dist/report/live-status.d.ts.map +1 -0
  305. package/dist/report/live-status.js +162 -0
  306. package/dist/report/live-status.js.map +1 -0
  307. package/dist/report/write.d.ts +4 -0
  308. package/dist/report/write.d.ts.map +1 -0
  309. package/dist/report/write.js +13 -0
  310. package/dist/report/write.js.map +1 -0
  311. package/dist/run/app-process.d.ts +18 -0
  312. package/dist/run/app-process.d.ts.map +1 -0
  313. package/dist/run/app-process.js +112 -0
  314. package/dist/run/app-process.js.map +1 -0
  315. package/dist/run/artifacts.d.ts +51 -0
  316. package/dist/run/artifacts.d.ts.map +1 -0
  317. package/dist/run/artifacts.js +114 -0
  318. package/dist/run/artifacts.js.map +1 -0
  319. package/dist/run/events.d.ts +100 -0
  320. package/dist/run/events.d.ts.map +1 -0
  321. package/dist/run/events.js +59 -0
  322. package/dist/run/events.js.map +1 -0
  323. package/dist/run/execute.d.ts +119 -0
  324. package/dist/run/execute.d.ts.map +1 -0
  325. package/dist/run/execute.js +555 -0
  326. package/dist/run/execute.js.map +1 -0
  327. package/dist/run/fixtures.d.ts +40 -0
  328. package/dist/run/fixtures.d.ts.map +1 -0
  329. package/dist/run/fixtures.js +408 -0
  330. package/dist/run/fixtures.js.map +1 -0
  331. package/dist/run/in-process.d.ts +24 -0
  332. package/dist/run/in-process.d.ts.map +1 -0
  333. package/dist/run/in-process.js +120 -0
  334. package/dist/run/in-process.js.map +1 -0
  335. package/dist/run/public.d.ts +19 -0
  336. package/dist/run/public.d.ts.map +1 -0
  337. package/dist/run/public.js +11 -0
  338. package/dist/run/public.js.map +1 -0
  339. package/dist/run/realm.d.ts +52 -0
  340. package/dist/run/realm.d.ts.map +1 -0
  341. package/dist/run/realm.js +101 -0
  342. package/dist/run/realm.js.map +1 -0
  343. package/dist/run/records.d.ts +87 -0
  344. package/dist/run/records.d.ts.map +1 -0
  345. package/dist/run/records.js +3 -0
  346. package/dist/run/records.js.map +1 -0
  347. package/dist/run/retry.d.ts +18 -0
  348. package/dist/run/retry.d.ts.map +1 -0
  349. package/dist/run/retry.js +33 -0
  350. package/dist/run/retry.js.map +1 -0
  351. package/dist/run/runner.d.ts +49 -0
  352. package/dist/run/runner.d.ts.map +1 -0
  353. package/dist/run/runner.js +375 -0
  354. package/dist/run/runner.js.map +1 -0
  355. package/dist/run/scheduler.d.ts +45 -0
  356. package/dist/run/scheduler.d.ts.map +1 -0
  357. package/dist/run/scheduler.js +512 -0
  358. package/dist/run/scheduler.js.map +1 -0
  359. package/dist/run/serial.d.ts +52 -0
  360. package/dist/run/serial.d.ts.map +1 -0
  361. package/dist/run/serial.js +247 -0
  362. package/dist/run/serial.js.map +1 -0
  363. package/dist/run/sessions.d.ts +54 -0
  364. package/dist/run/sessions.d.ts.map +1 -0
  365. package/dist/run/sessions.js +221 -0
  366. package/dist/run/sessions.js.map +1 -0
  367. package/dist/run/steps.d.ts +196 -0
  368. package/dist/run/steps.d.ts.map +1 -0
  369. package/dist/run/steps.js +151 -0
  370. package/dist/run/steps.js.map +1 -0
  371. package/dist/run/unit-runner.d.ts +30 -0
  372. package/dist/run/unit-runner.d.ts.map +1 -0
  373. package/dist/run/unit-runner.js +11 -0
  374. package/dist/run/unit-runner.js.map +1 -0
  375. package/dist/run/units.d.ts +50 -0
  376. package/dist/run/units.d.ts.map +1 -0
  377. package/dist/run/units.js +103 -0
  378. package/dist/run/units.js.map +1 -0
  379. package/dist/run/worker/entry.d.ts +8 -0
  380. package/dist/run/worker/entry.d.ts.map +1 -0
  381. package/dist/run/worker/entry.js +137 -0
  382. package/dist/run/worker/entry.js.map +1 -0
  383. package/dist/run/worker/handle.d.ts +10 -0
  384. package/dist/run/worker/handle.d.ts.map +1 -0
  385. package/dist/run/worker/handle.js +74 -0
  386. package/dist/run/worker/handle.js.map +1 -0
  387. package/dist/run/worker/protocol.d.ts +129 -0
  388. package/dist/run/worker/protocol.d.ts.map +1 -0
  389. package/dist/run/worker/protocol.js +18 -0
  390. package/dist/run/worker/protocol.js.map +1 -0
  391. package/dist/run/worker/session.d.ts +69 -0
  392. package/dist/run/worker/session.d.ts.map +1 -0
  393. package/dist/run/worker/session.js +123 -0
  394. package/dist/run/worker/session.js.map +1 -0
  395. package/dist/types.d.ts +630 -0
  396. package/dist/types.d.ts.map +1 -0
  397. package/dist/types.js +6 -0
  398. package/dist/types.js.map +1 -0
  399. package/package.json +91 -0
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Live agent tracing for iterating on agentic tests: `E2E_DEBUG=agent` streams
3
+ * every invocation phase, model selection, and locate-candidate outcome to
4
+ * stderr as it happens, from whichever process runs the attempt. This is a
5
+ * debugging aid, not telemetry: the report stays the canonical record.
6
+ */
7
+ import { sanitizeText, truncateUtf8 } from './errors.js';
8
+ /**
9
+ * Parsed on first use, not at import, so tests and embedders can set
10
+ * `E2E_DEBUG` after this module loads but before the first trace call.
11
+ */
12
+ let cachedFlags;
13
+ function flags() {
14
+ cachedFlags ??= new Set((process.env['E2E_DEBUG'] ?? '')
15
+ .split(',')
16
+ .map((flag) => flag.trim())
17
+ .filter((flag) => flag !== ''));
18
+ return cachedFlags;
19
+ }
20
+ function agentTraceEnabled() {
21
+ return flags().has('agent') || flags().has('all');
22
+ }
23
+ /** `E2E_DEBUG=observations` additionally dumps every observation the model sees. */
24
+ function observationTraceEnabled() {
25
+ return flags().has('observations') || flags().has('all');
26
+ }
27
+ /**
28
+ * Writes one bounded, sanitized trace line when agent tracing is on. Takes a
29
+ * thunk so call sites in polling loops pay nothing while tracing is off.
30
+ */
31
+ export function agentTrace(message) {
32
+ if (!agentTraceEnabled())
33
+ return;
34
+ process.stderr.write(`[e2e agent] ${truncateUtf8(sanitizeText(message()), 2_000)}\n`);
35
+ }
36
+ /**
37
+ * Dumps one full observation as the model will receive it. The text is
38
+ * already redacted and size-bounded by the observation pipeline, so the dump
39
+ * needs no further truncation to stay safe.
40
+ */
41
+ export function observationTrace(header, text) {
42
+ if (!observationTraceEnabled())
43
+ return;
44
+ process.stderr.write(`[e2e observation] ${header()}\n${text}\n[e2e observation] end\n`);
45
+ }
46
+ //# sourceMappingURL=trace.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"trace.js","sourceRoot":"","sources":["../../src/internal/trace.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAEzD;;;GAGG;AACH,IAAI,WAA4C,CAAC;AAEjD,SAAS,KAAK;IACZ,WAAW,KAAK,IAAI,GAAG,CACrB,CAAC,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC;SAC7B,KAAK,CAAC,GAAG,CAAC;SACV,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;SAC1B,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,KAAK,EAAE,CAAC,CACjC,CAAC;IACF,OAAO,WAAW,CAAC;AACrB,CAAC;AAED,SAAS,iBAAiB;IACxB,OAAO,KAAK,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,KAAK,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;AACpD,CAAC;AAED,oFAAoF;AACpF,SAAS,uBAAuB;IAC9B,OAAO,KAAK,EAAE,CAAC,GAAG,CAAC,cAAc,CAAC,IAAI,KAAK,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;AAC3D,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,UAAU,CAAC,OAAqB;IAC9C,IAAI,CAAC,iBAAiB,EAAE;QAAE,OAAO;IACjC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,eAAe,YAAY,CAAC,YAAY,CAAC,OAAO,EAAE,CAAC,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;AACxF,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,gBAAgB,CAAC,MAAoB,EAAE,IAAY;IACjE,IAAI,CAAC,uBAAuB,EAAE;QAAE,OAAO;IACvC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,qBAAqB,MAAM,EAAE,KAAK,IAAI,2BAA2B,CAAC,CAAC;AAC1F,CAAC"}
@@ -0,0 +1,31 @@
1
+ /** URL normalization and origin policy helpers (spec 05-config.md). */
2
+ export interface NormalizedBaseUrl {
3
+ /** Serialized base URL without trailing artifacts beyond the normalized path. */
4
+ readonly href: string;
5
+ readonly origin: string;
6
+ readonly basePath: string;
7
+ }
8
+ /**
9
+ * Parses and normalizes the app base URL. Rejects userinfo, query, and
10
+ * fragment. WHATWG parsing handles IDNA ASCII hosts, dot segments, and
11
+ * default-port removal.
12
+ */
13
+ export declare function normalizeBaseUrl(raw: string): NormalizedBaseUrl;
14
+ /** True for loopback hosts where plain HTTP is allowed. */
15
+ export declare function isLoopbackHost(hostname: string): boolean;
16
+ /** True when environment may default to `test` (loopback, .localhost, .test hosts). */
17
+ export declare function isImplicitTestHost(hostname: string): boolean;
18
+ /**
19
+ * Resolves a navigation URL against the base and enforces the allowed-origin
20
+ * policy. Returns the absolute URL string.
21
+ */
22
+ export declare function resolveNavigationUrl(input: string, base: NormalizedBaseUrl, allowedOrigins: readonly string[]): {
23
+ url: string;
24
+ };
25
+ /**
26
+ * Compares a current URL to an expected string/regexp per 03-assertions.md.
27
+ * Relative expected strings resolve against the base URL; string comparison is
28
+ * exact after WHATWG serialization; regexps test the complete serialized URL.
29
+ */
30
+ export declare function urlMatches(current: string, expected: string | RegExp, baseHref: string): boolean;
31
+ //# sourceMappingURL=urls.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"urls.d.ts","sourceRoot":"","sources":["../../src/internal/urls.ts"],"names":[],"mappings":"AAAA,uEAAuE;AAKvE,MAAM,WAAW,iBAAiB;IAChC,iFAAiF;IACjF,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC3B;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,iBAAiB,CA0B/D;AAED,2DAA2D;AAC3D,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAKxD;AAED,uFAAuF;AACvF,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAE5D;AAID;;;GAGG;AACH,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,iBAAiB,EACvB,cAAc,EAAE,SAAS,MAAM,EAAE,GAChC;IAAE,GAAG,EAAE,MAAM,CAAA;CAAE,CAiBjB;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAWhG"}
@@ -0,0 +1,95 @@
1
+ /** URL normalization and origin policy helpers (spec 05-config.md). */
2
+ import { ConfigurationError } from './errors.js';
3
+ import { testPattern } from './regexp.js';
4
+ /**
5
+ * Parses and normalizes the app base URL. Rejects userinfo, query, and
6
+ * fragment. WHATWG parsing handles IDNA ASCII hosts, dot segments, and
7
+ * default-port removal.
8
+ */
9
+ export function normalizeBaseUrl(raw) {
10
+ let url;
11
+ try {
12
+ url = new URL(raw);
13
+ }
14
+ catch {
15
+ throw new ConfigurationError('INVALID_APP_URL', `invalid app URL: ${raw}`);
16
+ }
17
+ if (url.username !== '' || url.password !== '') {
18
+ throw new ConfigurationError('INVALID_APP_URL', 'app URL must not contain userinfo');
19
+ }
20
+ if (url.search !== '') {
21
+ throw new ConfigurationError('INVALID_APP_URL', 'app URL must not contain a query');
22
+ }
23
+ if (url.hash !== '') {
24
+ throw new ConfigurationError('INVALID_APP_URL', 'app URL must not contain a fragment');
25
+ }
26
+ if (url.protocol !== 'http:' && url.protocol !== 'https:') {
27
+ throw new ConfigurationError('INVALID_APP_URL', `app URL must be http(s): ${raw}`);
28
+ }
29
+ if (url.protocol === 'http:' && !isLoopbackHost(url.hostname)) {
30
+ throw new ConfigurationError('INVALID_APP_URL', `plain HTTP is allowed only for loopback hosts: ${raw}`);
31
+ }
32
+ return { href: url.href, origin: url.origin, basePath: url.pathname };
33
+ }
34
+ /** True for loopback hosts where plain HTTP is allowed. */
35
+ export function isLoopbackHost(hostname) {
36
+ if (hostname === 'localhost' || hostname.endsWith('.localhost'))
37
+ return true;
38
+ if (hostname === '::1' || hostname === '[::1]')
39
+ return true;
40
+ if (/^127(\.\d{1,3}){3}$/.test(hostname))
41
+ return true;
42
+ return false;
43
+ }
44
+ /** True when environment may default to `test` (loopback, .localhost, .test hosts). */
45
+ export function isImplicitTestHost(hostname) {
46
+ return isLoopbackHost(hostname) || hostname.endsWith('.test');
47
+ }
48
+ const FORBIDDEN_PROTOCOLS = new Set(['file:', 'data:', 'javascript:']);
49
+ /**
50
+ * Resolves a navigation URL against the base and enforces the allowed-origin
51
+ * policy. Returns the absolute URL string.
52
+ */
53
+ export function resolveNavigationUrl(input, base, allowedOrigins) {
54
+ let url;
55
+ try {
56
+ url = new URL(input, base.href);
57
+ }
58
+ catch {
59
+ throw new ConfigurationError('POLICY_DENIED', `malformed URL: ${input}`);
60
+ }
61
+ if (FORBIDDEN_PROTOCOLS.has(url.protocol)) {
62
+ throw new ConfigurationError('POLICY_DENIED', `forbidden URL scheme: ${url.protocol}`);
63
+ }
64
+ if (!allowedOrigins.includes(url.origin)) {
65
+ throw new ConfigurationError('POLICY_DENIED', `origin ${url.origin} is not in allowedOrigins`);
66
+ }
67
+ return { url: url.href };
68
+ }
69
+ /**
70
+ * Compares a current URL to an expected string/regexp per 03-assertions.md.
71
+ * Relative expected strings resolve against the base URL; string comparison is
72
+ * exact after WHATWG serialization; regexps test the complete serialized URL.
73
+ */
74
+ export function urlMatches(current, expected, baseHref) {
75
+ if (typeof expected === 'string') {
76
+ let expectedUrl;
77
+ try {
78
+ expectedUrl = new URL(expected, baseHref);
79
+ }
80
+ catch {
81
+ return false;
82
+ }
83
+ return serializeForComparison(current) === expectedUrl.href;
84
+ }
85
+ return testPattern(expected.source, expected.flags, serializeForComparison(current));
86
+ }
87
+ function serializeForComparison(url) {
88
+ try {
89
+ return new URL(url).href;
90
+ }
91
+ catch {
92
+ return url;
93
+ }
94
+ }
95
+ //# sourceMappingURL=urls.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"urls.js","sourceRoot":"","sources":["../../src/internal/urls.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,65 @@
1
+ /** Runner-owned query polling, strictness, and action retry (spec 08-platforms.md). */
2
+ import { type TargetSession, type LocatorAction, type LocatorExpression, type NodeRef, type OperationContext, type SemanticNode } from '../backend/surface.ts';
3
+ import { E2EError } from '../internal/errors.ts';
4
+ import { Deadline } from '../internal/time.ts';
5
+ /** Canonical visibility predicate over a semantic node snapshot. */
6
+ export declare function isNodeVisible(node: SemanticNode | null): boolean;
7
+ interface EngineOptions {
8
+ readonly session: TargetSession;
9
+ readonly signal: AbortSignal;
10
+ readonly runId: string;
11
+ readonly attemptId: string;
12
+ readonly actionTimeout: number;
13
+ readonly assertionTimeout: number;
14
+ readonly testDeadline: Deadline;
15
+ }
16
+ /** Per-attempt locator execution engine. */
17
+ export declare class LocatorEngine {
18
+ private readonly options;
19
+ constructor(options: EngineOptions);
20
+ get session(): TargetSession;
21
+ get signal(): AbortSignal;
22
+ get assertionTimeout(): number;
23
+ /** Builds an operation context capped by the remaining test timeout. */
24
+ operation(timeoutMs?: number): OperationContext;
25
+ /** Deadline for one action-family operation, capped by the test deadline. */
26
+ deadline(timeoutMs?: number): Deadline;
27
+ private operationWithin;
28
+ /** One immediate backend resolve, retrying retryable frame misses within the deadline. */
29
+ private resolveOnce;
30
+ /**
31
+ * Resolves exactly one match. Zero matches poll until the deadline;
32
+ * multiple matches fail immediately with LOCATOR_AMBIGUOUS.
33
+ */
34
+ resolveExactlyOne(expression: LocatorExpression, deadline: Deadline): Promise<NodeRef>;
35
+ /** Immediate single resolve for direct reads: zero or multiple matches fail immediately. */
36
+ resolveForRead(expression: LocatorExpression): Promise<NodeRef>;
37
+ /**
38
+ * Resolves all current matches once without waiting. The caller's deadline,
39
+ * when given, bounds internal retries of retryable backend errors; it
40
+ * defaults to the action timeout.
41
+ */
42
+ resolveAll(expression: LocatorExpression, deadline?: Deadline): Promise<readonly NodeRef[]>;
43
+ /**
44
+ * Reads one node snapshot. A concurrent locator can supersede the ref
45
+ * between resolve and read; that is a repeatable race, so it re-resolves
46
+ * while the deadline remains instead of failing the test.
47
+ */
48
+ read(expression: LocatorExpression): Promise<SemanticNode>;
49
+ /** Reads one node for polling surfaces; returns null while zero matches. */
50
+ tryRead(expression: LocatorExpression, deadline: Deadline): Promise<{
51
+ node: SemanticNode | null;
52
+ count: number;
53
+ }>;
54
+ /**
55
+ * Performs exactly one action against exactly one match. Stale nodes are
56
+ * re-resolved while the deadline remains; a possibly committed action is
57
+ * never repeated. An action that itself names other nodes (dragTo) is built
58
+ * per attempt, so its refs are re-resolved together with the source.
59
+ */
60
+ perform(expression: LocatorExpression, action: LocatorAction | ((deadline: Deadline) => Promise<LocatorAction>), timeoutMs?: number): Promise<void>;
61
+ }
62
+ /** Translates a backend error into the runner-owned public taxonomy. */
63
+ export declare function translateLocatorError(cause: unknown, expression?: LocatorExpression): E2EError;
64
+ export {};
65
+ //# sourceMappingURL=engine.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../../src/locator/engine.ts"],"names":[],"mappings":"AAAA,uFAAuF;AAEvF,OAAO,EACL,KAAK,aAAa,EAClB,KAAK,aAAa,EAClB,KAAK,iBAAiB,EACtB,KAAK,OAAO,EACZ,KAAK,gBAAgB,EACrB,KAAK,YAAY,EAClB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAEL,QAAQ,EAGT,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EAAE,QAAQ,EAA2B,MAAM,qBAAqB,CAAC;AAExE,oEAAoE;AACpE,wBAAgB,aAAa,CAAC,IAAI,EAAE,YAAY,GAAG,IAAI,GAAG,OAAO,CAEhE;AAED,UAAU,aAAa;IACrB,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAC;IAChC,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC;IAC7B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,YAAY,EAAE,QAAQ,CAAC;CACjC;AAED,4CAA4C;AAC5C,qBAAa,aAAa;IACZ,OAAO,CAAC,QAAQ,CAAC,OAAO;IAApC,YAA6B,OAAO,EAAE,aAAa,EAAI;IAEvD,IAAI,OAAO,IAAI,aAAa,CAE3B;IAED,IAAI,MAAM,IAAI,WAAW,CAExB;IAED,IAAI,gBAAgB,IAAI,MAAM,CAE7B;IAED,wEAAwE;IACxE,SAAS,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,gBAAgB,CAE9C;IAED,6EAA6E;IAC7E,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,QAAQ,CAKrC;IAED,OAAO,CAAC,eAAe;IASvB,0FAA0F;YAC5E,WAAW;IAiBzB;;;OAGG;IACG,iBAAiB,CAAC,UAAU,EAAE,iBAAiB,EAAE,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC,CAY3F;IAED,4FAA4F;IACtF,cAAc,CAAC,UAAU,EAAE,iBAAiB,GAAG,OAAO,CAAC,OAAO,CAAC,CAUpE;IAED;;;;OAIG;IACG,UAAU,CACd,UAAU,EAAE,iBAAiB,EAC7B,QAAQ,GAAE,QAAoD,GAC7D,OAAO,CAAC,SAAS,OAAO,EAAE,CAAC,CAE7B;IAED;;;;OAIG;IACG,IAAI,CAAC,UAAU,EAAE,iBAAiB,GAAG,OAAO,CAAC,YAAY,CAAC,CAc/D;IAED,4EAA4E;IACtE,OAAO,CACX,UAAU,EAAE,iBAAiB,EAC7B,QAAQ,EAAE,QAAQ,GACjB,OAAO,CAAC;QAAE,IAAI,EAAE,YAAY,GAAG,IAAI,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAYvD;IAED;;;;;OAKG;IACG,OAAO,CACX,UAAU,EAAE,iBAAiB,EAC7B,MAAM,EAAE,aAAa,GAAG,CAAC,CAAC,QAAQ,EAAE,QAAQ,KAAK,OAAO,CAAC,aAAa,CAAC,CAAC,EACxE,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,IAAI,CAAC,CAoBf;CACF;AAaD,wEAAwE;AACxE,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,OAAO,EAAE,UAAU,CAAC,EAAE,iBAAiB,GAAG,QAAQ,CAG9F"}
@@ -0,0 +1,164 @@
1
+ /** Runner-owned query polling, strictness, and action retry (spec 08-platforms.md). */
2
+ import {} from '../backend/surface.js';
3
+ import { asBackendError, E2EError, TestError, translateBackendError, } from '../internal/errors.js';
4
+ import { describeExpression } from './expression.js';
5
+ import { Deadline, POLL_INTERVAL_MS, sleep } from '../internal/time.js';
6
+ /** Canonical visibility predicate over a semantic node snapshot. */
7
+ export function isNodeVisible(node) {
8
+ return node !== null && node.states?.hidden !== true;
9
+ }
10
+ /** Per-attempt locator execution engine. */
11
+ export class LocatorEngine {
12
+ options;
13
+ constructor(options) {
14
+ this.options = options;
15
+ }
16
+ get session() {
17
+ return this.options.session;
18
+ }
19
+ get signal() {
20
+ return this.options.signal;
21
+ }
22
+ get assertionTimeout() {
23
+ return this.options.assertionTimeout;
24
+ }
25
+ /** Builds an operation context capped by the remaining test timeout. */
26
+ operation(timeoutMs) {
27
+ return this.operationWithin(this.deadline(timeoutMs));
28
+ }
29
+ /** Deadline for one action-family operation, capped by the test deadline. */
30
+ deadline(timeoutMs) {
31
+ return Deadline.min(new Deadline(timeoutMs ?? this.options.actionTimeout), this.options.testDeadline);
32
+ }
33
+ operationWithin(deadline) {
34
+ return {
35
+ signal: this.options.signal,
36
+ timeoutMs: Math.max(1, deadline.remaining()),
37
+ runId: this.options.runId,
38
+ attemptId: this.options.attemptId,
39
+ };
40
+ }
41
+ /** One immediate backend resolve, retrying retryable frame misses within the deadline. */
42
+ async resolveOnce(expression, deadline) {
43
+ for (;;) {
44
+ try {
45
+ return await this.session.locate(expression, this.operationWithin(deadline));
46
+ }
47
+ catch (cause) {
48
+ if (asBackendError(cause)?.retryable === true && !deadline.expired()) {
49
+ await sleep(POLL_INTERVAL_MS, this.options.signal);
50
+ continue;
51
+ }
52
+ throw translateLocatorError(cause, expression);
53
+ }
54
+ }
55
+ }
56
+ /**
57
+ * Resolves exactly one match. Zero matches poll until the deadline;
58
+ * multiple matches fail immediately with LOCATOR_AMBIGUOUS.
59
+ */
60
+ async resolveExactlyOne(expression, deadline) {
61
+ for (;;) {
62
+ const ref = assertSingle(await this.resolveOnce(expression, deadline), expression);
63
+ if (ref !== null)
64
+ return ref;
65
+ if (deadline.expired()) {
66
+ throw new TestError('LOCATOR_NOT_FOUND', `locator matched no nodes within ${describeExpression(expression)}`);
67
+ }
68
+ await sleep(POLL_INTERVAL_MS, this.options.signal);
69
+ }
70
+ }
71
+ /** Immediate single resolve for direct reads: zero or multiple matches fail immediately. */
72
+ async resolveForRead(expression) {
73
+ const deadline = this.deadline(this.options.actionTimeout);
74
+ const ref = assertSingle(await this.resolveOnce(expression, deadline), expression);
75
+ if (ref === null) {
76
+ throw new TestError('LOCATOR_NOT_FOUND', `locator matched no nodes: ${describeExpression(expression)}`);
77
+ }
78
+ return ref;
79
+ }
80
+ /**
81
+ * Resolves all current matches once without waiting. The caller's deadline,
82
+ * when given, bounds internal retries of retryable backend errors; it
83
+ * defaults to the action timeout.
84
+ */
85
+ async resolveAll(expression, deadline = this.deadline(this.options.actionTimeout)) {
86
+ return this.resolveOnce(expression, deadline);
87
+ }
88
+ /**
89
+ * Reads one node snapshot. A concurrent locator can supersede the ref
90
+ * between resolve and read; that is a repeatable race, so it re-resolves
91
+ * while the deadline remains instead of failing the test.
92
+ */
93
+ async read(expression) {
94
+ const deadline = this.deadline(this.options.actionTimeout);
95
+ for (;;) {
96
+ const ref = await this.resolveForRead(expression);
97
+ try {
98
+ return await this.session.read(ref, this.operationWithin(deadline));
99
+ }
100
+ catch (cause) {
101
+ const backendError = asBackendError(cause);
102
+ if (backendError?.code === 'NODE_STALE' && backendError.retryable && !deadline.expired()) {
103
+ continue;
104
+ }
105
+ throw translateLocatorError(cause, expression);
106
+ }
107
+ }
108
+ }
109
+ /** Reads one node for polling surfaces; returns null while zero matches. */
110
+ async tryRead(expression, deadline) {
111
+ const ref = assertSingle(await this.resolveOnce(expression, deadline), expression);
112
+ if (ref === null)
113
+ return { node: null, count: 0 };
114
+ try {
115
+ const node = await this.session.read(ref, this.operationWithin(deadline));
116
+ return { node, count: 1 };
117
+ }
118
+ catch (cause) {
119
+ if (asBackendError(cause)?.code === 'NODE_STALE') {
120
+ return { node: null, count: 0 };
121
+ }
122
+ throw translateLocatorError(cause, expression);
123
+ }
124
+ }
125
+ /**
126
+ * Performs exactly one action against exactly one match. Stale nodes are
127
+ * re-resolved while the deadline remains; a possibly committed action is
128
+ * never repeated. An action that itself names other nodes (dragTo) is built
129
+ * per attempt, so its refs are re-resolved together with the source.
130
+ */
131
+ async perform(expression, action, timeoutMs) {
132
+ const deadline = this.deadline(timeoutMs);
133
+ for (;;) {
134
+ const ref = await this.resolveExactlyOne(expression, deadline);
135
+ const resolved = typeof action === 'function' ? await action(deadline) : action;
136
+ try {
137
+ await this.session.perform(ref, resolved, this.operationWithin(deadline));
138
+ return;
139
+ }
140
+ catch (cause) {
141
+ const backendError = asBackendError(cause);
142
+ if (backendError?.code === 'NODE_STALE' &&
143
+ backendError.retryable &&
144
+ !deadline.expired()) {
145
+ continue;
146
+ }
147
+ throw translateLocatorError(cause, expression);
148
+ }
149
+ }
150
+ }
151
+ }
152
+ /** Zero matches -> null; one -> the ref; many -> LOCATOR_AMBIGUOUS. */
153
+ function assertSingle(refs, expression) {
154
+ if (refs.length > 1) {
155
+ throw new TestError('LOCATOR_AMBIGUOUS', `locator matched ${refs.length} nodes, expected exactly one: ${describeExpression(expression)}`);
156
+ }
157
+ return refs[0] ?? null;
158
+ }
159
+ /** Translates a backend error into the runner-owned public taxonomy. */
160
+ export function translateLocatorError(cause, expression) {
161
+ const suffix = expression === undefined ? '' : `: ${describeExpression(expression)}`;
162
+ return translateBackendError(cause, suffix);
163
+ }
164
+ //# sourceMappingURL=engine.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"engine.js","sourceRoot":"","sources":["../../src/locator/engine.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ /** Immutable locator expression construction (spec 08-platforms.md). */
2
+ import type { LocatorExpression } from '../backend/surface.ts';
3
+ import type { Role, RoleOptions, TextMatch, TextMatchOptions } from '../types.ts';
4
+ /** Builds a role query expression. */
5
+ export declare function roleQuery(role: Role, options: RoleOptions | undefined, scope: LocatorExpression | undefined): LocatorExpression;
6
+ /** Builds a text-family query expression (label, placeholder, text, displayValue). */
7
+ export declare function textQuery(kind: 'label' | 'placeholder' | 'text' | 'displayValue', text: TextMatch, options: TextMatchOptions | undefined, scope: LocatorExpression | undefined): LocatorExpression;
8
+ /** Builds a test-id query expression. */
9
+ export declare function testIdQuery(id: string, scope: LocatorExpression | undefined): LocatorExpression;
10
+ /** Builds a filter expression; an empty filter object is an immediate error. */
11
+ export declare function filterExpression(source: LocatorExpression, options: {
12
+ hasText?: TextMatch;
13
+ has?: LocatorExpression;
14
+ }): LocatorExpression;
15
+ /** Builds an index expression; negative indices are errors. */
16
+ export declare function indexExpression(source: LocatorExpression, index: number | 'first' | 'last'): LocatorExpression;
17
+ /** Renders an expression for diagnostics. */
18
+ export declare function describeExpression(expression: LocatorExpression): string;
19
+ //# sourceMappingURL=expression.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"expression.d.ts","sourceRoot":"","sources":["../../src/locator/expression.ts"],"names":[],"mappings":"AAAA,wEAAwE;AAExE,OAAO,KAAK,EAAE,iBAAiB,EAAiB,MAAM,uBAAuB,CAAC;AAG9E,OAAO,KAAK,EAAE,IAAI,EAAE,WAAW,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAElF,sCAAsC;AACtC,wBAAgB,SAAS,CACvB,IAAI,EAAE,IAAI,EACV,OAAO,EAAE,WAAW,GAAG,SAAS,EAChC,KAAK,EAAE,iBAAiB,GAAG,SAAS,GACnC,iBAAiB,CAenB;AAED,sFAAsF;AACtF,wBAAgB,SAAS,CACvB,IAAI,EAAE,OAAO,GAAG,aAAa,GAAG,MAAM,GAAG,cAAc,EACvD,IAAI,EAAE,SAAS,EACf,OAAO,EAAE,gBAAgB,GAAG,SAAS,EACrC,KAAK,EAAE,iBAAiB,GAAG,SAAS,GACnC,iBAAiB,CAKnB;AAED,yCAAyC;AACzC,wBAAgB,WAAW,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,iBAAiB,GAAG,SAAS,GAAG,iBAAiB,CAK/F;AAUD,gFAAgF;AAChF,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,iBAAiB,EACzB,OAAO,EAAE;IAAE,OAAO,CAAC,EAAE,SAAS,CAAC;IAAC,GAAG,CAAC,EAAE,iBAAiB,CAAA;CAAE,GACxD,iBAAiB,CAUnB;AAED,+DAA+D;AAC/D,wBAAgB,eAAe,CAC7B,MAAM,EAAE,iBAAiB,EACzB,KAAK,EAAE,MAAM,GAAG,OAAO,GAAG,MAAM,GAC/B,iBAAiB,CAKnB;AAED,6CAA6C;AAC7C,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,iBAAiB,GAAG,MAAM,CAgCxE"}
@@ -0,0 +1,85 @@
1
+ /** Immutable locator expression construction (spec 08-platforms.md). */
2
+ import { toTextPattern } from '../internal/text.js';
3
+ import { TestError } from '../internal/errors.js';
4
+ /** Builds a role query expression. */
5
+ export function roleQuery(role, options, scope) {
6
+ const states = {};
7
+ for (const key of ['checked', 'disabled', 'selected', 'expanded', 'hidden']) {
8
+ const value = options?.[key];
9
+ if (value !== undefined)
10
+ states[key] = value;
11
+ }
12
+ const query = {
13
+ kind: 'role',
14
+ value: { kind: 'string', value: role, exact: true },
15
+ ...(options?.name !== undefined
16
+ ? { name: toTextPattern(options.name, { exact: options.exact ?? true }) }
17
+ : {}),
18
+ ...(Object.keys(states).length > 0 ? { states } : {}),
19
+ };
20
+ return scoped({ kind: 'query', query }, scope);
21
+ }
22
+ /** Builds a text-family query expression (label, placeholder, text, displayValue). */
23
+ export function textQuery(kind, text, options, scope) {
24
+ return scoped({ kind: 'query', query: { kind, value: toTextPattern(text, { exact: options?.exact ?? true }) } }, scope);
25
+ }
26
+ /** Builds a test-id query expression. */
27
+ export function testIdQuery(id, scope) {
28
+ return scoped({ kind: 'query', query: { kind: 'testId', value: { kind: 'string', value: id, exact: true } } }, scope);
29
+ }
30
+ function scoped(expression, scope) {
31
+ if (scope === undefined)
32
+ return expression;
33
+ return { ...expression, scope };
34
+ }
35
+ /** Builds a filter expression; an empty filter object is an immediate error. */
36
+ export function filterExpression(source, options) {
37
+ if (options.hasText === undefined && options.has === undefined) {
38
+ throw new TestError('INVALID_LOCATOR', 'filter() requires hasText and/or has');
39
+ }
40
+ return {
41
+ kind: 'filter',
42
+ source,
43
+ ...(options.hasText !== undefined ? { hasText: toTextPattern(options.hasText, { exact: false }) } : {}),
44
+ ...(options.has !== undefined ? { has: options.has } : {}),
45
+ };
46
+ }
47
+ /** Builds an index expression; negative indices are errors. */
48
+ export function indexExpression(source, index) {
49
+ if (typeof index === 'number' && (!Number.isInteger(index) || index < 0)) {
50
+ throw new TestError('INVALID_LOCATOR', `nth() index must be a nonnegative integer, got ${index}`);
51
+ }
52
+ return { kind: 'index', source, index };
53
+ }
54
+ /** Renders an expression for diagnostics. */
55
+ export function describeExpression(expression) {
56
+ switch (expression.kind) {
57
+ case 'query': {
58
+ const query = expression.query;
59
+ const value = query.value.kind === 'string' ? JSON.stringify(query.value.value) : `/${query.value.source}/${query.value.flags}`;
60
+ const name = query.name === undefined
61
+ ? ''
62
+ : `, name: ${query.name.kind === 'string' ? JSON.stringify(query.name.value) : `/${query.name.source}/${query.name.flags}`}`;
63
+ const scope = expression.scope === undefined ? '' : `${describeExpression(expression.scope)} >> `;
64
+ return `${scope}getBy${query.kind[0].toUpperCase()}${query.kind.slice(1)}(${value}${name})`;
65
+ }
66
+ case 'filter': {
67
+ const parts = [];
68
+ if (expression.hasText !== undefined) {
69
+ parts.push(`hasText: ${expression.hasText.kind === 'string' ? JSON.stringify(expression.hasText.value) : `/${expression.hasText.source}/${expression.hasText.flags}`}`);
70
+ }
71
+ if (expression.has !== undefined)
72
+ parts.push(`has: ${describeExpression(expression.has)}`);
73
+ return `${describeExpression(expression.source)}.filter({ ${parts.join(', ')} })`;
74
+ }
75
+ case 'index':
76
+ return typeof expression.index === 'number'
77
+ ? `${describeExpression(expression.source)}.nth(${expression.index})`
78
+ : `${describeExpression(expression.source)}.${expression.index}()`;
79
+ case 'selector':
80
+ return `locator(${JSON.stringify(expression.selector)})`;
81
+ case 'frame':
82
+ return `frameLocator(${JSON.stringify(expression.selector)}) >> ${describeExpression(expression.source)}`;
83
+ }
84
+ }
85
+ //# sourceMappingURL=expression.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"expression.js","sourceRoot":"","sources":["../../src/locator/expression.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,36 @@
1
+ /** Public Screen and Locator surfaces bound to one attempt. */
2
+ import type { LocatorExpression } from '../backend/surface.ts';
3
+ import type { Locator, Screen, Secret } from '../types.ts';
4
+ import type { StepRecorder } from '../run/steps.ts';
5
+ import { type LocatorEngine } from './engine.ts';
6
+ export interface SecretResolver {
7
+ /**
8
+ * Resolves an opaque Secret to its plaintext for a closed input sink, at
9
+ * fill time — a provider-backed credential may compute it fresh per fill.
10
+ */
11
+ resolve(secret: Secret): Promise<string>;
12
+ }
13
+ export interface ScreenContext {
14
+ readonly engine: LocatorEngine;
15
+ readonly steps: StepRecorder;
16
+ readonly secrets: SecretResolver;
17
+ /** Base directory for resolving relative file paths, e.g. uploads. */
18
+ readonly projectRoot?: string;
19
+ }
20
+ export declare function isSecret(value: unknown): value is Secret;
21
+ /** Internal accessor used by expect() to reach a locator's expression/engine. */
22
+ export interface LocatorInternals {
23
+ readonly expression: LocatorExpression;
24
+ readonly context: ScreenContext;
25
+ }
26
+ export declare function locatorInternals(locator: unknown): LocatorInternals | undefined;
27
+ /** Creates the screen fixture for one attempt. */
28
+ export declare function createScreen(context: ScreenContext): Screen;
29
+ /**
30
+ * Creates a screen scope whose every query is wrapped by `wrap` - a
31
+ * contributed fixture scoping queries into a nested document, for example.
32
+ */
33
+ export declare function createScopedScreen(context: ScreenContext, wrap: (expression: LocatorExpression) => LocatorExpression): Screen;
34
+ /** Creates a public locator from a raw expression (a contributed fixture's platform selector). */
35
+ export declare function createLocator(context: ScreenContext, expression: LocatorExpression): Locator;
36
+ //# sourceMappingURL=screen.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"screen.d.ts","sourceRoot":"","sources":["../../src/locator/screen.ts"],"names":[],"mappings":"AAAA,+DAA+D;AAG/D,OAAO,KAAK,EAAE,iBAAiB,EAAgB,MAAM,uBAAuB,CAAC;AAK7E,OAAO,KAAK,EAEV,OAAO,EAGP,MAAM,EACN,MAAM,EAKP,MAAM,aAAa,CAAC;AACrB,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAAiB,KAAK,aAAa,EAAE,MAAM,aAAa,CAAC;AAWhE,MAAM,WAAW,cAAc;IAC7B;;;OAGG;IACH,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CAC1C;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAC;IAC/B,QAAQ,CAAC,KAAK,EAAE,YAAY,CAAC;IAC7B,QAAQ,CAAC,OAAO,EAAE,cAAc,CAAC;IACjC,sEAAsE;IACtE,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;CAC/B;AAED,wBAAgB,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAMxD;AAED,iFAAiF;AACjF,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,UAAU,EAAE,iBAAiB,CAAC;IACvC,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAC;CACjC;AAQD,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,OAAO,GAAG,gBAAgB,GAAG,SAAS,CAI/E;AAED,kDAAkD;AAClD,wBAAgB,YAAY,CAAC,OAAO,EAAE,aAAa,GAAG,MAAM,CAE3D;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,aAAa,EACtB,IAAI,EAAE,CAAC,UAAU,EAAE,iBAAiB,KAAK,iBAAiB,GACzD,MAAM,CAER;AAED,kGAAkG;AAClG,wBAAgB,aAAa,CAAC,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,iBAAiB,GAAG,OAAO,CAE5F"}