expect-sdk 0.0.24

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 (324) hide show
  1. package/.claude/settings.local.json +48 -0
  2. package/.expect/replays/08a6cacb-cdfb-47ba-9cf7-41a13ac07a36.html +286 -0
  3. package/.expect/replays/08a6cacb-cdfb-47ba-9cf7-41a13ac07a36.ndjson +2 -0
  4. package/.expect/replays/08a6cacb-cdfb-47ba-9cf7-41a13ac07a36.ndjson.js +2 -0
  5. package/.expect/replays/0abc2d0c-30d4-405b-8f6a-ad55eab10797.html +286 -0
  6. package/.expect/replays/0abc2d0c-30d4-405b-8f6a-ad55eab10797.ndjson +2 -0
  7. package/.expect/replays/0abc2d0c-30d4-405b-8f6a-ad55eab10797.ndjson.js +2 -0
  8. package/.expect/replays/0be009ad-fc3d-4aa8-81e2-2473dddf876a.html +286 -0
  9. package/.expect/replays/0be009ad-fc3d-4aa8-81e2-2473dddf876a.ndjson +7 -0
  10. package/.expect/replays/0be009ad-fc3d-4aa8-81e2-2473dddf876a.ndjson.js +2 -0
  11. package/.expect/replays/0bf0f4f1-9c7d-4dac-ae8f-6990ec08b82b.html +286 -0
  12. package/.expect/replays/0bf0f4f1-9c7d-4dac-ae8f-6990ec08b82b.ndjson +10 -0
  13. package/.expect/replays/0bf0f4f1-9c7d-4dac-ae8f-6990ec08b82b.ndjson.js +2 -0
  14. package/.expect/replays/0cdb0236-3fdf-4c48-8ef1-fbc8539a8d32.html +286 -0
  15. package/.expect/replays/0cdb0236-3fdf-4c48-8ef1-fbc8539a8d32.ndjson +49 -0
  16. package/.expect/replays/0cdb0236-3fdf-4c48-8ef1-fbc8539a8d32.ndjson.js +2 -0
  17. package/.expect/replays/0dbbf37b-6749-4973-ae20-b37b9b734ce6.html +286 -0
  18. package/.expect/replays/0dbbf37b-6749-4973-ae20-b37b9b734ce6.ndjson +44 -0
  19. package/.expect/replays/0dbbf37b-6749-4973-ae20-b37b9b734ce6.ndjson.js +2 -0
  20. package/.expect/replays/15009a95-16f4-4f14-9f52-a2a650b6de23.html +286 -0
  21. package/.expect/replays/15009a95-16f4-4f14-9f52-a2a650b6de23.ndjson +23 -0
  22. package/.expect/replays/15009a95-16f4-4f14-9f52-a2a650b6de23.ndjson.js +2 -0
  23. package/.expect/replays/2095af47-e1dc-444b-ab84-f614d755fd04.html +286 -0
  24. package/.expect/replays/2095af47-e1dc-444b-ab84-f614d755fd04.ndjson +10 -0
  25. package/.expect/replays/2095af47-e1dc-444b-ab84-f614d755fd04.ndjson.js +2 -0
  26. package/.expect/replays/26962ef6-a3ac-4033-aee6-d09414c2232d.html +286 -0
  27. package/.expect/replays/26962ef6-a3ac-4033-aee6-d09414c2232d.ndjson +8 -0
  28. package/.expect/replays/26962ef6-a3ac-4033-aee6-d09414c2232d.ndjson.js +2 -0
  29. package/.expect/replays/28d1ed69-05c0-44dc-a369-77b0d37b64c8.html +286 -0
  30. package/.expect/replays/28d1ed69-05c0-44dc-a369-77b0d37b64c8.ndjson +12 -0
  31. package/.expect/replays/28d1ed69-05c0-44dc-a369-77b0d37b64c8.ndjson.js +2 -0
  32. package/.expect/replays/2ece9734-85bf-4d45-9738-7e3c7a4b6c9e.html +286 -0
  33. package/.expect/replays/2ece9734-85bf-4d45-9738-7e3c7a4b6c9e.ndjson +20 -0
  34. package/.expect/replays/2ece9734-85bf-4d45-9738-7e3c7a4b6c9e.ndjson.js +2 -0
  35. package/.expect/replays/301ecd28-499b-4367-80c8-8f5c740a4011.html +286 -0
  36. package/.expect/replays/301ecd28-499b-4367-80c8-8f5c740a4011.ndjson +6 -0
  37. package/.expect/replays/301ecd28-499b-4367-80c8-8f5c740a4011.ndjson.js +2 -0
  38. package/.expect/replays/323fdb67-102e-45c2-a6ae-2ed78e590928.html +286 -0
  39. package/.expect/replays/323fdb67-102e-45c2-a6ae-2ed78e590928.ndjson +7 -0
  40. package/.expect/replays/323fdb67-102e-45c2-a6ae-2ed78e590928.ndjson.js +2 -0
  41. package/.expect/replays/338b9a53-a211-448a-99cd-a95873edef79.html +286 -0
  42. package/.expect/replays/338b9a53-a211-448a-99cd-a95873edef79.ndjson +7 -0
  43. package/.expect/replays/338b9a53-a211-448a-99cd-a95873edef79.ndjson.js +2 -0
  44. package/.expect/replays/33bfd732-9116-4200-b732-41faba42ae75.html +286 -0
  45. package/.expect/replays/33bfd732-9116-4200-b732-41faba42ae75.ndjson +10 -0
  46. package/.expect/replays/33bfd732-9116-4200-b732-41faba42ae75.ndjson.js +2 -0
  47. package/.expect/replays/33eb7162-e0c8-40ae-8e72-8ad273b0fca7.html +286 -0
  48. package/.expect/replays/33eb7162-e0c8-40ae-8e72-8ad273b0fca7.ndjson +7 -0
  49. package/.expect/replays/33eb7162-e0c8-40ae-8e72-8ad273b0fca7.ndjson.js +2 -0
  50. package/.expect/replays/365939fb-9693-4219-b5f5-0bafef524617.html +286 -0
  51. package/.expect/replays/365939fb-9693-4219-b5f5-0bafef524617.ndjson +2 -0
  52. package/.expect/replays/365939fb-9693-4219-b5f5-0bafef524617.ndjson.js +2 -0
  53. package/.expect/replays/383ea7a8-0ff8-4958-a148-3032f0a52eab.html +286 -0
  54. package/.expect/replays/383ea7a8-0ff8-4958-a148-3032f0a52eab.ndjson +54 -0
  55. package/.expect/replays/383ea7a8-0ff8-4958-a148-3032f0a52eab.ndjson.js +2 -0
  56. package/.expect/replays/397a5665-4344-441b-a424-2ac53df712a1.html +286 -0
  57. package/.expect/replays/397a5665-4344-441b-a424-2ac53df712a1.ndjson +14 -0
  58. package/.expect/replays/397a5665-4344-441b-a424-2ac53df712a1.ndjson.js +2 -0
  59. package/.expect/replays/39a5d9cc-72d0-483d-bfcc-506a6fc85f13.html +286 -0
  60. package/.expect/replays/39a5d9cc-72d0-483d-bfcc-506a6fc85f13.ndjson +10 -0
  61. package/.expect/replays/39a5d9cc-72d0-483d-bfcc-506a6fc85f13.ndjson.js +2 -0
  62. package/.expect/replays/39ccd62e-2f4c-4a4a-9b43-40524b7a945b.html +286 -0
  63. package/.expect/replays/39ccd62e-2f4c-4a4a-9b43-40524b7a945b.ndjson +14 -0
  64. package/.expect/replays/39ccd62e-2f4c-4a4a-9b43-40524b7a945b.ndjson.js +2 -0
  65. package/.expect/replays/3eff073f-7e14-49d8-a2e2-1b7634a117cd.html +286 -0
  66. package/.expect/replays/3eff073f-7e14-49d8-a2e2-1b7634a117cd.ndjson +45 -0
  67. package/.expect/replays/3eff073f-7e14-49d8-a2e2-1b7634a117cd.ndjson.js +2 -0
  68. package/.expect/replays/3f144b2f-78ce-4d23-bd96-99994bf07edd.html +286 -0
  69. package/.expect/replays/3f144b2f-78ce-4d23-bd96-99994bf07edd.ndjson +34 -0
  70. package/.expect/replays/3f144b2f-78ce-4d23-bd96-99994bf07edd.ndjson.js +2 -0
  71. package/.expect/replays/436e0182-8590-4520-97b5-d62b08ebe822.html +286 -0
  72. package/.expect/replays/436e0182-8590-4520-97b5-d62b08ebe822.ndjson +15 -0
  73. package/.expect/replays/436e0182-8590-4520-97b5-d62b08ebe822.ndjson.js +2 -0
  74. package/.expect/replays/43e9a6e6-ce7d-4ed4-b593-f07ce6d53009.html +286 -0
  75. package/.expect/replays/43e9a6e6-ce7d-4ed4-b593-f07ce6d53009.ndjson +85 -0
  76. package/.expect/replays/43e9a6e6-ce7d-4ed4-b593-f07ce6d53009.ndjson.js +2 -0
  77. package/.expect/replays/4568fc07-ea40-4740-be6f-0f6a8e632175.html +286 -0
  78. package/.expect/replays/4568fc07-ea40-4740-be6f-0f6a8e632175.ndjson +53 -0
  79. package/.expect/replays/4568fc07-ea40-4740-be6f-0f6a8e632175.ndjson.js +2 -0
  80. package/.expect/replays/47b43574-9b41-44be-af9c-fb7c0a81196f.html +286 -0
  81. package/.expect/replays/47b43574-9b41-44be-af9c-fb7c0a81196f.ndjson +2 -0
  82. package/.expect/replays/47b43574-9b41-44be-af9c-fb7c0a81196f.ndjson.js +2 -0
  83. package/.expect/replays/47d846d6-f86e-46e4-94d7-f0abff232b20.html +286 -0
  84. package/.expect/replays/47d846d6-f86e-46e4-94d7-f0abff232b20.ndjson +10 -0
  85. package/.expect/replays/47d846d6-f86e-46e4-94d7-f0abff232b20.ndjson.js +2 -0
  86. package/.expect/replays/486cd227-9d22-49cf-b050-cb546d374206.html +286 -0
  87. package/.expect/replays/486cd227-9d22-49cf-b050-cb546d374206.ndjson +2 -0
  88. package/.expect/replays/486cd227-9d22-49cf-b050-cb546d374206.ndjson.js +2 -0
  89. package/.expect/replays/4c53e4c2-ece4-4767-87fe-394fe0ab4300.html +286 -0
  90. package/.expect/replays/4c53e4c2-ece4-4767-87fe-394fe0ab4300.ndjson +33 -0
  91. package/.expect/replays/4c53e4c2-ece4-4767-87fe-394fe0ab4300.ndjson.js +2 -0
  92. package/.expect/replays/4d1c0166-77e7-49ee-9bdc-9e3382e7f60c.html +286 -0
  93. package/.expect/replays/4d1c0166-77e7-49ee-9bdc-9e3382e7f60c.ndjson +58 -0
  94. package/.expect/replays/4d1c0166-77e7-49ee-9bdc-9e3382e7f60c.ndjson.js +2 -0
  95. package/.expect/replays/4ee7ecf6-20ce-42c3-8ed6-9476e74498eb.html +286 -0
  96. package/.expect/replays/4ee7ecf6-20ce-42c3-8ed6-9476e74498eb.ndjson +10 -0
  97. package/.expect/replays/4ee7ecf6-20ce-42c3-8ed6-9476e74498eb.ndjson.js +2 -0
  98. package/.expect/replays/5438a8a6-ef42-42e2-8764-fde7c6529d95.html +286 -0
  99. package/.expect/replays/5438a8a6-ef42-42e2-8764-fde7c6529d95.ndjson +33 -0
  100. package/.expect/replays/5438a8a6-ef42-42e2-8764-fde7c6529d95.ndjson.js +2 -0
  101. package/.expect/replays/5709193a-1153-46b2-b19c-736e4bda525d.html +286 -0
  102. package/.expect/replays/5709193a-1153-46b2-b19c-736e4bda525d.ndjson +16 -0
  103. package/.expect/replays/5709193a-1153-46b2-b19c-736e4bda525d.ndjson.js +2 -0
  104. package/.expect/replays/5eee229c-5e60-4cb2-a1c2-f7720a94ea1c.html +286 -0
  105. package/.expect/replays/5eee229c-5e60-4cb2-a1c2-f7720a94ea1c.ndjson +2 -0
  106. package/.expect/replays/5eee229c-5e60-4cb2-a1c2-f7720a94ea1c.ndjson.js +2 -0
  107. package/.expect/replays/63657ec6-87d8-4250-a0db-05d12fa2983e.html +286 -0
  108. package/.expect/replays/63657ec6-87d8-4250-a0db-05d12fa2983e.ndjson +48 -0
  109. package/.expect/replays/63657ec6-87d8-4250-a0db-05d12fa2983e.ndjson.js +2 -0
  110. package/.expect/replays/6623c0d4-cfcf-461a-8029-0f157ff21080.html +286 -0
  111. package/.expect/replays/6623c0d4-cfcf-461a-8029-0f157ff21080.ndjson +8 -0
  112. package/.expect/replays/6623c0d4-cfcf-461a-8029-0f157ff21080.ndjson.js +2 -0
  113. package/.expect/replays/69a4dab6-06ad-4d54-99c9-1113d6f5a033.html +286 -0
  114. package/.expect/replays/69a4dab6-06ad-4d54-99c9-1113d6f5a033.ndjson +7 -0
  115. package/.expect/replays/69a4dab6-06ad-4d54-99c9-1113d6f5a033.ndjson.js +2 -0
  116. package/.expect/replays/6b3fae01-5e61-48e3-b675-334572bdaf67.html +286 -0
  117. package/.expect/replays/6b3fae01-5e61-48e3-b675-334572bdaf67.ndjson +14 -0
  118. package/.expect/replays/6b3fae01-5e61-48e3-b675-334572bdaf67.ndjson.js +2 -0
  119. package/.expect/replays/709859dd-cd9d-4f4a-93f3-0185631feaf5.html +286 -0
  120. package/.expect/replays/709859dd-cd9d-4f4a-93f3-0185631feaf5.ndjson +2 -0
  121. package/.expect/replays/709859dd-cd9d-4f4a-93f3-0185631feaf5.ndjson.js +2 -0
  122. package/.expect/replays/76b454d4-ba48-47a0-9336-486a7b106322.html +286 -0
  123. package/.expect/replays/76b454d4-ba48-47a0-9336-486a7b106322.ndjson +37 -0
  124. package/.expect/replays/76b454d4-ba48-47a0-9336-486a7b106322.ndjson.js +2 -0
  125. package/.expect/replays/76c75bfa-d266-487e-a4d2-54d6f64760b5.html +286 -0
  126. package/.expect/replays/76c75bfa-d266-487e-a4d2-54d6f64760b5.ndjson +18 -0
  127. package/.expect/replays/76c75bfa-d266-487e-a4d2-54d6f64760b5.ndjson.js +2 -0
  128. package/.expect/replays/78333bb7-5172-4839-98a0-745372a1032b.html +286 -0
  129. package/.expect/replays/78333bb7-5172-4839-98a0-745372a1032b.ndjson +65 -0
  130. package/.expect/replays/78333bb7-5172-4839-98a0-745372a1032b.ndjson.js +2 -0
  131. package/.expect/replays/7be24ce2-8544-492e-9b66-b56c0c1e027b.html +286 -0
  132. package/.expect/replays/7be24ce2-8544-492e-9b66-b56c0c1e027b.ndjson +10 -0
  133. package/.expect/replays/7be24ce2-8544-492e-9b66-b56c0c1e027b.ndjson.js +2 -0
  134. package/.expect/replays/825423b3-7e83-4037-b0b7-c4eafe6282b8.html +286 -0
  135. package/.expect/replays/825423b3-7e83-4037-b0b7-c4eafe6282b8.ndjson +54 -0
  136. package/.expect/replays/825423b3-7e83-4037-b0b7-c4eafe6282b8.ndjson.js +2 -0
  137. package/.expect/replays/83641ba6-ccfa-4400-88ee-b8e4a1775c12.html +286 -0
  138. package/.expect/replays/83641ba6-ccfa-4400-88ee-b8e4a1775c12.ndjson +18 -0
  139. package/.expect/replays/83641ba6-ccfa-4400-88ee-b8e4a1775c12.ndjson.js +2 -0
  140. package/.expect/replays/87af45a5-dd8f-433a-8e5d-5ab136d653b9.html +286 -0
  141. package/.expect/replays/87af45a5-dd8f-433a-8e5d-5ab136d653b9.ndjson +3 -0
  142. package/.expect/replays/87af45a5-dd8f-433a-8e5d-5ab136d653b9.ndjson.js +2 -0
  143. package/.expect/replays/882a48e3-15b5-47fb-9f96-3e63c282557c.html +286 -0
  144. package/.expect/replays/882a48e3-15b5-47fb-9f96-3e63c282557c.ndjson +44 -0
  145. package/.expect/replays/882a48e3-15b5-47fb-9f96-3e63c282557c.ndjson.js +2 -0
  146. package/.expect/replays/8efca11f-3649-4433-a61c-f3b844aaa0b9.html +286 -0
  147. package/.expect/replays/8efca11f-3649-4433-a61c-f3b844aaa0b9.ndjson +33 -0
  148. package/.expect/replays/8efca11f-3649-4433-a61c-f3b844aaa0b9.ndjson.js +2 -0
  149. package/.expect/replays/8f563116-c926-4de3-9d16-3dfe33dd52b6.html +286 -0
  150. package/.expect/replays/8f563116-c926-4de3-9d16-3dfe33dd52b6.ndjson +12 -0
  151. package/.expect/replays/8f563116-c926-4de3-9d16-3dfe33dd52b6.ndjson.js +2 -0
  152. package/.expect/replays/9321eb59-9587-4819-80b0-b387c50aaaf4.html +286 -0
  153. package/.expect/replays/9321eb59-9587-4819-80b0-b387c50aaaf4.ndjson +10 -0
  154. package/.expect/replays/9321eb59-9587-4819-80b0-b387c50aaaf4.ndjson.js +2 -0
  155. package/.expect/replays/94cb0431-e2a6-4a8d-800a-6918adb25660.html +286 -0
  156. package/.expect/replays/94cb0431-e2a6-4a8d-800a-6918adb25660.ndjson +10 -0
  157. package/.expect/replays/94cb0431-e2a6-4a8d-800a-6918adb25660.ndjson.js +2 -0
  158. package/.expect/replays/94d30b76-3fb0-476a-93c5-c9acb88eb45a.html +286 -0
  159. package/.expect/replays/94d30b76-3fb0-476a-93c5-c9acb88eb45a.ndjson +43 -0
  160. package/.expect/replays/94d30b76-3fb0-476a-93c5-c9acb88eb45a.ndjson.js +2 -0
  161. package/.expect/replays/94da15c7-217f-4167-aad9-0ed7d69fb1a9.html +286 -0
  162. package/.expect/replays/94da15c7-217f-4167-aad9-0ed7d69fb1a9.ndjson +2 -0
  163. package/.expect/replays/94da15c7-217f-4167-aad9-0ed7d69fb1a9.ndjson.js +2 -0
  164. package/.expect/replays/9998db1c-b008-497f-8a13-1fc0eb6a8845.html +286 -0
  165. package/.expect/replays/9998db1c-b008-497f-8a13-1fc0eb6a8845.ndjson +31 -0
  166. package/.expect/replays/9998db1c-b008-497f-8a13-1fc0eb6a8845.ndjson.js +2 -0
  167. package/.expect/replays/9c54b7fe-d113-4d99-9df9-42af0779a176.html +286 -0
  168. package/.expect/replays/9c54b7fe-d113-4d99-9df9-42af0779a176.ndjson +52 -0
  169. package/.expect/replays/9c54b7fe-d113-4d99-9df9-42af0779a176.ndjson.js +2 -0
  170. package/.expect/replays/9d8b9d7f-2fad-44c8-92bc-5377adb4ca1b.html +286 -0
  171. package/.expect/replays/9d8b9d7f-2fad-44c8-92bc-5377adb4ca1b.ndjson +24 -0
  172. package/.expect/replays/9d8b9d7f-2fad-44c8-92bc-5377adb4ca1b.ndjson.js +2 -0
  173. package/.expect/replays/9f6d215a-17bd-44f8-be75-4f21c36cb7a5.html +286 -0
  174. package/.expect/replays/9f6d215a-17bd-44f8-be75-4f21c36cb7a5.ndjson +14 -0
  175. package/.expect/replays/9f6d215a-17bd-44f8-be75-4f21c36cb7a5.ndjson.js +2 -0
  176. package/.expect/replays/9fddc5ad-02e8-4f8e-96cf-c249444bf123.html +286 -0
  177. package/.expect/replays/9fddc5ad-02e8-4f8e-96cf-c249444bf123.ndjson +2 -0
  178. package/.expect/replays/9fddc5ad-02e8-4f8e-96cf-c249444bf123.ndjson.js +2 -0
  179. package/.expect/replays/a1e5b091-888f-43c5-95c3-c25f91f8925a.html +286 -0
  180. package/.expect/replays/a1e5b091-888f-43c5-95c3-c25f91f8925a.ndjson +12 -0
  181. package/.expect/replays/a1e5b091-888f-43c5-95c3-c25f91f8925a.ndjson.js +2 -0
  182. package/.expect/replays/a2e5372c-e459-4c47-8133-921303e7c74d.html +286 -0
  183. package/.expect/replays/a2e5372c-e459-4c47-8133-921303e7c74d.ndjson +2 -0
  184. package/.expect/replays/a2e5372c-e459-4c47-8133-921303e7c74d.ndjson.js +2 -0
  185. package/.expect/replays/a41a8fe3-4abc-4bde-bea0-526ef9d5c16f.html +286 -0
  186. package/.expect/replays/a41a8fe3-4abc-4bde-bea0-526ef9d5c16f.ndjson +16 -0
  187. package/.expect/replays/a41a8fe3-4abc-4bde-bea0-526ef9d5c16f.ndjson.js +2 -0
  188. package/.expect/replays/a726e14d-080c-4b30-b413-fcf6d14d0daf.html +286 -0
  189. package/.expect/replays/a726e14d-080c-4b30-b413-fcf6d14d0daf.ndjson +8 -0
  190. package/.expect/replays/a726e14d-080c-4b30-b413-fcf6d14d0daf.ndjson.js +2 -0
  191. package/.expect/replays/ab5651bb-3528-4b4b-809d-1e6d1fef2ade.html +286 -0
  192. package/.expect/replays/ab5651bb-3528-4b4b-809d-1e6d1fef2ade.ndjson +52 -0
  193. package/.expect/replays/ab5651bb-3528-4b4b-809d-1e6d1fef2ade.ndjson.js +2 -0
  194. package/.expect/replays/ac83d5ac-73c5-48f0-8d73-53f50151e4bf.html +286 -0
  195. package/.expect/replays/ac83d5ac-73c5-48f0-8d73-53f50151e4bf.ndjson +2 -0
  196. package/.expect/replays/ac83d5ac-73c5-48f0-8d73-53f50151e4bf.ndjson.js +2 -0
  197. package/.expect/replays/afeb4664-90ba-4525-9f4e-54349c5254f4.html +286 -0
  198. package/.expect/replays/afeb4664-90ba-4525-9f4e-54349c5254f4.ndjson +8 -0
  199. package/.expect/replays/afeb4664-90ba-4525-9f4e-54349c5254f4.ndjson.js +2 -0
  200. package/.expect/replays/b205a14f-ea04-41f7-b3f6-6a24881a4907.html +286 -0
  201. package/.expect/replays/b205a14f-ea04-41f7-b3f6-6a24881a4907.ndjson +44 -0
  202. package/.expect/replays/b205a14f-ea04-41f7-b3f6-6a24881a4907.ndjson.js +2 -0
  203. package/.expect/replays/b23eafd9-c876-4a66-a5e6-8d560672d5a8.html +286 -0
  204. package/.expect/replays/b23eafd9-c876-4a66-a5e6-8d560672d5a8.ndjson +84 -0
  205. package/.expect/replays/b23eafd9-c876-4a66-a5e6-8d560672d5a8.ndjson.js +2 -0
  206. package/.expect/replays/b4116451-32d0-4b85-a404-503bb4123815.html +286 -0
  207. package/.expect/replays/b4116451-32d0-4b85-a404-503bb4123815.ndjson +10 -0
  208. package/.expect/replays/b4116451-32d0-4b85-a404-503bb4123815.ndjson.js +2 -0
  209. package/.expect/replays/b649a6ef-45e3-49c2-bd02-284deb7ea9b1.html +286 -0
  210. package/.expect/replays/b649a6ef-45e3-49c2-bd02-284deb7ea9b1.ndjson +32 -0
  211. package/.expect/replays/b649a6ef-45e3-49c2-bd02-284deb7ea9b1.ndjson.js +2 -0
  212. package/.expect/replays/b8487d6d-87db-4453-9a87-f3ef57b9596a.html +286 -0
  213. package/.expect/replays/b8487d6d-87db-4453-9a87-f3ef57b9596a.ndjson +12 -0
  214. package/.expect/replays/b8487d6d-87db-4453-9a87-f3ef57b9596a.ndjson.js +2 -0
  215. package/.expect/replays/b9126d9e-93e9-44d1-901b-f4e4700a2ac7.html +286 -0
  216. package/.expect/replays/b9126d9e-93e9-44d1-901b-f4e4700a2ac7.ndjson +16 -0
  217. package/.expect/replays/b9126d9e-93e9-44d1-901b-f4e4700a2ac7.ndjson.js +2 -0
  218. package/.expect/replays/bc9ac26e-6915-466d-a250-61679c7d8785.html +286 -0
  219. package/.expect/replays/bc9ac26e-6915-466d-a250-61679c7d8785.ndjson +58 -0
  220. package/.expect/replays/bc9ac26e-6915-466d-a250-61679c7d8785.ndjson.js +2 -0
  221. package/.expect/replays/bf71f292-d0fa-4b38-88d2-838d631b4fd3.html +286 -0
  222. package/.expect/replays/bf71f292-d0fa-4b38-88d2-838d631b4fd3.ndjson +18 -0
  223. package/.expect/replays/bf71f292-d0fa-4b38-88d2-838d631b4fd3.ndjson.js +2 -0
  224. package/.expect/replays/c064a436-aa74-411c-b4ff-228e6016748c.html +286 -0
  225. package/.expect/replays/c064a436-aa74-411c-b4ff-228e6016748c.ndjson +14 -0
  226. package/.expect/replays/c064a436-aa74-411c-b4ff-228e6016748c.ndjson.js +2 -0
  227. package/.expect/replays/c293319a-56fc-47c2-be0a-efebab7e5547.html +286 -0
  228. package/.expect/replays/c293319a-56fc-47c2-be0a-efebab7e5547.ndjson +10 -0
  229. package/.expect/replays/c293319a-56fc-47c2-be0a-efebab7e5547.ndjson.js +2 -0
  230. package/.expect/replays/c48e7ccb-f40a-4d86-9ada-f9ac0f174809.html +286 -0
  231. package/.expect/replays/c48e7ccb-f40a-4d86-9ada-f9ac0f174809.ndjson +18 -0
  232. package/.expect/replays/c48e7ccb-f40a-4d86-9ada-f9ac0f174809.ndjson.js +2 -0
  233. package/.expect/replays/c4ec751f-4c2f-4ac4-83e1-9d53ebd275b0.html +286 -0
  234. package/.expect/replays/c4ec751f-4c2f-4ac4-83e1-9d53ebd275b0.ndjson +12 -0
  235. package/.expect/replays/c4ec751f-4c2f-4ac4-83e1-9d53ebd275b0.ndjson.js +2 -0
  236. package/.expect/replays/c5f8f2de-415c-4605-90e9-8a31286c1d33.html +286 -0
  237. package/.expect/replays/c5f8f2de-415c-4605-90e9-8a31286c1d33.ndjson +36 -0
  238. package/.expect/replays/c5f8f2de-415c-4605-90e9-8a31286c1d33.ndjson.js +2 -0
  239. package/.expect/replays/c92defec-c6f7-4334-89f4-d3b1010a592b.html +286 -0
  240. package/.expect/replays/c92defec-c6f7-4334-89f4-d3b1010a592b.ndjson +97 -0
  241. package/.expect/replays/c92defec-c6f7-4334-89f4-d3b1010a592b.ndjson.js +2 -0
  242. package/.expect/replays/ce024389-749b-4d9f-9cbe-d2add9b5d506.html +286 -0
  243. package/.expect/replays/ce024389-749b-4d9f-9cbe-d2add9b5d506.ndjson +8 -0
  244. package/.expect/replays/ce024389-749b-4d9f-9cbe-d2add9b5d506.ndjson.js +2 -0
  245. package/.expect/replays/d0106187-b170-4208-b6e2-1652906fb952.html +286 -0
  246. package/.expect/replays/d0106187-b170-4208-b6e2-1652906fb952.ndjson +52 -0
  247. package/.expect/replays/d0106187-b170-4208-b6e2-1652906fb952.ndjson.js +2 -0
  248. package/.expect/replays/d4aa55a2-9b5f-4eb5-b795-5324e5c5d7db.html +286 -0
  249. package/.expect/replays/d4aa55a2-9b5f-4eb5-b795-5324e5c5d7db.ndjson +84 -0
  250. package/.expect/replays/d4aa55a2-9b5f-4eb5-b795-5324e5c5d7db.ndjson.js +2 -0
  251. package/.expect/replays/d4fc939c-c97d-4125-95dc-a8745709e879.html +286 -0
  252. package/.expect/replays/d4fc939c-c97d-4125-95dc-a8745709e879.ndjson +2 -0
  253. package/.expect/replays/d4fc939c-c97d-4125-95dc-a8745709e879.ndjson.js +2 -0
  254. package/.expect/replays/d59474f3-6eee-4145-9252-ac56d7d634d1.html +286 -0
  255. package/.expect/replays/d59474f3-6eee-4145-9252-ac56d7d634d1.ndjson +46 -0
  256. package/.expect/replays/d59474f3-6eee-4145-9252-ac56d7d634d1.ndjson.js +2 -0
  257. package/.expect/replays/d842aee0-a2e0-45a4-84bb-02571ea704ef.html +286 -0
  258. package/.expect/replays/d842aee0-a2e0-45a4-84bb-02571ea704ef.ndjson +10 -0
  259. package/.expect/replays/d842aee0-a2e0-45a4-84bb-02571ea704ef.ndjson.js +2 -0
  260. package/.expect/replays/dbacab2e-6e47-4c2e-861b-881a3439cc61.html +286 -0
  261. package/.expect/replays/dbacab2e-6e47-4c2e-861b-881a3439cc61.ndjson +40 -0
  262. package/.expect/replays/dbacab2e-6e47-4c2e-861b-881a3439cc61.ndjson.js +2 -0
  263. package/.expect/replays/e47ad94c-1326-4e5f-9e36-9187b2475dc4.html +286 -0
  264. package/.expect/replays/e47ad94c-1326-4e5f-9e36-9187b2475dc4.ndjson +10 -0
  265. package/.expect/replays/e47ad94c-1326-4e5f-9e36-9187b2475dc4.ndjson.js +2 -0
  266. package/.expect/replays/e4e7c05e-0def-4eb4-80de-5c0abc6e9707.html +286 -0
  267. package/.expect/replays/e4e7c05e-0def-4eb4-80de-5c0abc6e9707.ndjson +32 -0
  268. package/.expect/replays/e4e7c05e-0def-4eb4-80de-5c0abc6e9707.ndjson.js +2 -0
  269. package/.expect/replays/e7fbb2f5-f5be-430f-b9d8-e9b5980c4e25.html +286 -0
  270. package/.expect/replays/e7fbb2f5-f5be-430f-b9d8-e9b5980c4e25.ndjson +30 -0
  271. package/.expect/replays/e7fbb2f5-f5be-430f-b9d8-e9b5980c4e25.ndjson.js +2 -0
  272. package/.expect/replays/ef25484d-6e02-4cde-bf19-7251a9ada2b3.html +286 -0
  273. package/.expect/replays/ef25484d-6e02-4cde-bf19-7251a9ada2b3.ndjson +37 -0
  274. package/.expect/replays/ef25484d-6e02-4cde-bf19-7251a9ada2b3.ndjson.js +2 -0
  275. package/.expect/replays/f114ddaa-f891-4be1-b626-eaeeba692e0f.html +286 -0
  276. package/.expect/replays/f114ddaa-f891-4be1-b626-eaeeba692e0f.ndjson +12 -0
  277. package/.expect/replays/f114ddaa-f891-4be1-b626-eaeeba692e0f.ndjson.js +2 -0
  278. package/.expect/replays/f39c87c6-34c7-4b81-8350-a644e309430f.html +286 -0
  279. package/.expect/replays/f39c87c6-34c7-4b81-8350-a644e309430f.ndjson +8 -0
  280. package/.expect/replays/f39c87c6-34c7-4b81-8350-a644e309430f.ndjson.js +2 -0
  281. package/.expect/replays/f6484a4f-c647-4f78-9a2e-f41f00683c15.html +286 -0
  282. package/.expect/replays/f6484a4f-c647-4f78-9a2e-f41f00683c15.ndjson +14 -0
  283. package/.expect/replays/f6484a4f-c647-4f78-9a2e-f41f00683c15.ndjson.js +2 -0
  284. package/.turbo/turbo-build.log +22 -0
  285. package/.turbo/turbo-check.log +6 -0
  286. package/.turbo/turbo-typecheck.log +4 -0
  287. package/CHANGELOG.md +12 -0
  288. package/LICENSE +110 -0
  289. package/README.md +536 -0
  290. package/dist/constants-DFJAD4-F.mjs +152 -0
  291. package/dist/constants-DFJAD4-F.mjs.map +1 -0
  292. package/dist/effect.d.mts +30 -0
  293. package/dist/effect.d.mts.map +1 -0
  294. package/dist/effect.mjs +2 -0
  295. package/dist/index.d.mts +20 -0
  296. package/dist/index.d.mts.map +1 -0
  297. package/dist/index.mjs +279 -0
  298. package/dist/index.mjs.map +1 -0
  299. package/dist/types-0J0EwTM4.d.mts +124 -0
  300. package/dist/types-0J0EwTM4.d.mts.map +1 -0
  301. package/package.json +46 -0
  302. package/src/build-instruction.ts +35 -0
  303. package/src/config.ts +15 -0
  304. package/src/constants.ts +2 -0
  305. package/src/effect.ts +14 -0
  306. package/src/errors.ts +17 -0
  307. package/src/expect.ts +432 -0
  308. package/src/index.ts +23 -0
  309. package/src/layers.ts +14 -0
  310. package/src/result-builder.ts +184 -0
  311. package/src/test-run.ts +19 -0
  312. package/src/tool.ts +26 -0
  313. package/src/types.ts +98 -0
  314. package/tests/build-instruction.test.ts +62 -0
  315. package/tests/config.test.ts +44 -0
  316. package/tests/e2e.ts +81 -0
  317. package/tests/examples.test.ts +44 -0
  318. package/tests/expect.test.ts +143 -0
  319. package/tests/fixtures/fixture-server.ts +111 -0
  320. package/tests/result-builder.test.ts +292 -0
  321. package/tests/test-run.test.ts +95 -0
  322. package/tests/tool.test.ts +60 -0
  323. package/tsconfig.json +9 -0
  324. package/vite.config.ts +13 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants-DFJAD4-F.mjs","names":[],"sources":["../src/errors.ts","../src/build-instruction.ts","../src/layers.ts","../src/result-builder.ts","../src/constants.ts"],"sourcesContent":["import { Schema } from \"effect\";\n\nexport class ExpectTimeoutError extends Schema.ErrorClass<ExpectTimeoutError>(\"ExpectTimeoutError\")(\n {\n _tag: Schema.tag(\"ExpectTimeoutError\"),\n timeoutMs: Schema.Number,\n },\n) {\n message = `expect execution timed out after ${this.timeoutMs}ms`;\n}\n\nexport class ExpectConfigError extends Error {\n constructor(message: string, fix: string) {\n super(`${message}\\n\\nFix: ${fix}`);\n this.name = \"ExpectConfigError\";\n }\n}\n","import { ExpectConfigError } from \"./errors\";\n\nexport const resolveUrl = (url: unknown, baseUrl: string | undefined): string => {\n if (typeof url !== \"string\") {\n throw new ExpectConfigError(\n `Expected a URL string, got ${typeof url}.`,\n `Expect.test({ url: \"http://localhost:3000/login\", tests: [...] })`,\n );\n }\n\n try {\n return new URL(url).href;\n } catch {\n /* relative URL — falls through to baseUrl resolution */\n }\n\n if (!baseUrl) {\n throw new ExpectConfigError(\n `No baseUrl configured and URL \"${url}\" is relative.`,\n `configure({ baseUrl: \"http://localhost:3000\" })\\nOr use a full URL: Expect.test({ url: \"http://localhost:3000${url}\", tests: [...] })`,\n );\n }\n\n return new URL(url, baseUrl).href;\n};\n\nexport const buildInstruction = (url: string, tests: readonly string[]): string => {\n const lines = [`Navigate to ${url} and verify the following requirements:`, \"\"];\n\n for (const [index, title] of tests.entries()) {\n lines.push(`${index + 1}. ${title}`);\n }\n\n return lines.join(\"\\n\");\n};\n","import { Layer, References } from \"effect\";\nimport { Executor, Git } from \"@expect/supervisor\";\nimport { Agent, type AgentBackend } from \"@expect/agent\";\n\nexport const layerSdk = (agentBackend: AgentBackend, rootDir: string) => {\n const gitLayer = Git.withRepoRoot(rootDir);\n const agentLayer = Agent.layerFor(agentBackend);\n const executorLayer = Executor.layer.pipe(Layer.provide(gitLayer));\n\n return Layer.mergeAll(executorLayer, gitLayer).pipe(\n Layer.provideMerge(agentLayer),\n Layer.provideMerge(Layer.succeed(References.MinimumLogLevel, \"Error\")),\n );\n};\n","import { DateTime, Option } from \"effect\";\nimport type { ExecutedTestPlan, TestPlanStep, ExecutionEvent } from \"@expect/shared/models\";\nimport type { Status, StepResult, TestResult, TestEvent } from \"./types\";\n\nconst REPLAY_SESSION_PREFIX = \"rrweb replay:\";\nconst SCREENSHOT_PREFIX = \"Screenshot:\";\n\nconst stepDurationMs = (step: TestPlanStep): number => {\n if (Option.isNone(step.startedAt)) return 0;\n if (Option.isNone(step.endedAt))\n return Date.now() - Number(DateTime.toEpochMillis(step.startedAt.value));\n return (\n Number(DateTime.toEpochMillis(step.endedAt.value)) -\n Number(DateTime.toEpochMillis(step.startedAt.value))\n );\n};\n\nconst stepStatusToResultStatus = (status: string): Status => {\n if (status === \"passed\") return \"passed\";\n if (status === \"failed\" || status === \"skipped\") return \"failed\";\n return \"pending\";\n};\n\nexport interface ExecutionArtifacts {\n readonly recordingPath: string | undefined;\n readonly screenshotPaths: readonly string[];\n}\n\nexport const extractArtifacts = (events: readonly ExecutionEvent[]): ExecutionArtifacts => {\n const closeResult = events\n .slice()\n .reverse()\n .find(\n (event) =>\n event._tag === \"ToolResult\" &&\n event.toolName === \"close\" &&\n !event.isError &&\n event.result.length > 0,\n );\n\n if (!closeResult || closeResult._tag !== \"ToolResult\") {\n return { recordingPath: undefined, screenshotPaths: [] };\n }\n\n const lines = closeResult.result\n .split(\"\\n\")\n .map((line) => line.trim())\n .filter((line) => line.length > 0);\n\n const replayLine = lines.find((line) => line.startsWith(REPLAY_SESSION_PREFIX));\n const recordingPath = replayLine?.replace(REPLAY_SESSION_PREFIX, \"\").trim() || undefined;\n\n const screenshotPaths = lines\n .filter((line) => line.startsWith(SCREENSHOT_PREFIX))\n .map((line) => line.replace(SCREENSHOT_PREFIX, \"\").trim())\n .filter((value) => value.length > 0);\n\n return { recordingPath, screenshotPaths };\n};\n\nexport const buildStepResult = (\n step: TestPlanStep,\n screenshotPaths: readonly string[],\n stepIndex: number,\n): StepResult => ({\n title: step.title,\n status: stepStatusToResultStatus(step.status),\n summary: Option.getOrElse(step.summary, () => \"\"),\n screenshotPath: screenshotPaths[stepIndex],\n duration: stepDurationMs(step),\n});\n\nexport const buildTestResult = (\n executed: ExecutedTestPlan,\n url: string,\n startedAt: number,\n artifacts: ExecutionArtifacts,\n): TestResult => {\n const steps = executed.steps.map((step, index) =>\n buildStepResult(step, artifacts.screenshotPaths, index),\n );\n const errors = steps.filter((step) => step.status === \"failed\");\n const hasFailure = errors.length > 0;\n const hasPending = steps.some((step) => step.status === \"pending\");\n\n let status: Status = \"passed\";\n if (hasFailure) status = \"failed\";\n else if (hasPending || steps.length === 0) status = \"pending\";\n\n return {\n status,\n url,\n duration: Date.now() - startedAt,\n recordingPath: artifacts.recordingPath,\n steps,\n errors,\n };\n};\n\ninterface DiffContext {\n readonly stepMap: ReadonlyMap<string, TestPlanStep>;\n readonly stepIndexMap: ReadonlyMap<string, number>;\n readonly artifacts: ExecutionArtifacts;\n readonly executed: ExecutedTestPlan;\n readonly url: string;\n readonly startedAt: number;\n}\n\nconst mapExecutionEvent = (event: ExecutionEvent, context: DiffContext): TestEvent | undefined => {\n switch (event._tag) {\n case \"RunStarted\":\n return {\n type: \"run:started\",\n title: event.plan.title,\n baseUrl: Option.getOrUndefined(event.plan.baseUrl),\n };\n case \"StepStarted\":\n return { type: \"step:started\", title: event.title };\n case \"StepCompleted\": {\n const step = context.stepMap.get(event.stepId);\n const index = context.stepIndexMap.get(event.stepId) ?? -1;\n return step\n ? {\n type: \"step:passed\",\n step: buildStepResult(step, context.artifacts.screenshotPaths, index),\n }\n : undefined;\n }\n case \"StepFailed\": {\n const step = context.stepMap.get(event.stepId);\n const index = context.stepIndexMap.get(event.stepId) ?? -1;\n return step\n ? {\n type: \"step:failed\",\n step: buildStepResult(step, context.artifacts.screenshotPaths, index),\n }\n : undefined;\n }\n case \"StepSkipped\":\n return {\n type: \"step:skipped\",\n title: context.stepMap.get(event.stepId)?.title ?? event.stepId,\n reason: event.reason,\n };\n case \"ToolResult\":\n return event.toolName.endsWith(\"__screenshot\") && !event.isError\n ? { type: \"screenshot\", title: event.toolName, path: event.result }\n : undefined;\n case \"RunFinished\":\n return {\n type: \"completed\",\n result: buildTestResult(\n context.executed,\n context.url,\n context.startedAt,\n context.artifacts,\n ),\n };\n default:\n return undefined;\n }\n};\n\nexport const diffEvents = (\n previous: readonly ExecutionEvent[],\n current: readonly ExecutionEvent[],\n executed: ExecutedTestPlan,\n url: string,\n startedAt: number,\n): TestEvent[] => {\n const context: DiffContext = {\n stepMap: new Map(executed.steps.map((step) => [step.id, step])),\n stepIndexMap: new Map(executed.steps.map((step, index) => [step.id, index])),\n artifacts: extractArtifacts(executed.events),\n executed,\n url,\n startedAt,\n };\n\n return current\n .slice(previous.length)\n .map((event) => mapExecutionEvent(event, context))\n .filter((event): event is TestEvent => event !== undefined);\n};\n","export const DEFAULT_TIMEOUT_MS = 5 * 60 * 1000;\nexport const DEFAULT_AGENT_BACKEND = \"claude\" as const;\n"],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ import { _ as DEFAULT_AGENT_BACKEND, b as ExpectTimeoutError, f as TestEvent, i as CookieInput, m as TestResult, n as BrowserName, r as Cookie, t as Action, u as StepResult, v as DEFAULT_TIMEOUT_MS, y as ExpectConfigError } from "./types-0J0EwTM4.mjs";
2
+ import { Layer } from "effect";
3
+ import * as _expect_supervisor0 from "@expect/supervisor";
4
+ import { Executor, Git } from "@expect/supervisor";
5
+ import { ExecutedTestPlan, ExecutionEvent, TestPlanStep } from "@expect/shared/models";
6
+ import * as _expect_agent0 from "@expect/agent";
7
+ import { Agent, AgentBackend } from "@expect/agent";
8
+ import * as effect_PlatformError0 from "effect/PlatformError";
9
+ import * as effect_Config0 from "effect/Config";
10
+ import * as effect_Schema0 from "effect/Schema";
11
+
12
+ //#region src/build-instruction.d.ts
13
+ declare const resolveUrl: (url: unknown, baseUrl: string | undefined) => string;
14
+ declare const buildInstruction: (url: string, tests: readonly string[]) => string;
15
+ //#endregion
16
+ //#region src/layers.d.ts
17
+ declare const layerSdk: (agentBackend: AgentBackend, rootDir: string) => Layer.Layer<Executor | Agent | Git | _expect_supervisor0.GitRepoRoot, _expect_supervisor0.FindRepoRootError | (_expect_agent0.AcpProviderUnauthenticatedError | effect_PlatformError0.PlatformError | effect_Config0.ConfigError | effect_Schema0.SchemaError | _expect_agent0.AcpProviderNotInstalledError | _expect_agent0.AcpConnectionInitError | _expect_agent0.AcpAdapterNotFoundError), never>;
18
+ //#endregion
19
+ //#region src/result-builder.d.ts
20
+ interface ExecutionArtifacts {
21
+ readonly recordingPath: string | undefined;
22
+ readonly screenshotPaths: readonly string[];
23
+ }
24
+ declare const extractArtifacts: (events: readonly ExecutionEvent[]) => ExecutionArtifacts;
25
+ declare const buildStepResult: (step: TestPlanStep, screenshotPaths: readonly string[], stepIndex: number) => StepResult;
26
+ declare const buildTestResult: (executed: ExecutedTestPlan, url: string, startedAt: number, artifacts: ExecutionArtifacts) => TestResult;
27
+ declare const diffEvents: (previous: readonly ExecutionEvent[], current: readonly ExecutionEvent[], executed: ExecutedTestPlan, url: string, startedAt: number) => TestEvent[];
28
+ //#endregion
29
+ export { type Action, type BrowserName, type Cookie, type CookieInput, DEFAULT_AGENT_BACKEND, DEFAULT_TIMEOUT_MS, ExpectConfigError, ExpectTimeoutError, type StepResult, type TestEvent, type TestResult, buildInstruction, buildStepResult, buildTestResult, diffEvents, extractArtifacts, layerSdk, resolveUrl };
30
+ //# sourceMappingURL=effect.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"effect.d.mts","names":[],"sources":["../src/build-instruction.ts","../src/layers.ts","../src/result-builder.ts"],"mappings":";;;;;;;;;;;;cAEa,UAAA,GAAc,GAAA,WAAc,OAAA;AAAA,cAwB5B,gBAAA,GAAoB,GAAA,UAAa,KAAA;;;cCtBjC,QAAA,GAAY,YAAA,EAAc,YAAA,EAAc,OAAA,aAAe,KAAA,CAAA,KAAA,CAAA,QAAA,GAAA,KAAA,GAAA,GAAA,GAAA,mBAAA,CAAA,WAAA,EAAA,mBAAA,CAAA,iBAAA,IAAA,cAAA,CAAA,+BAAA,GAAA,qBAAA,CAAA,aAAA,GAAA,cAAA,CAAA,WAAA,GAAA,cAAA,CAAA,WAAA,GAAA,cAAA,CAAA,4BAAA,GAAA,cAAA,CAAA,sBAAA,GAAA,cAAA,CAAA,uBAAA;;;UCmBnD,kBAAA;EAAA,SACN,aAAA;EAAA,SACA,eAAA;AAAA;AAAA,cAGE,gBAAA,GAAoB,MAAA,WAAiB,cAAA,OAAmB,kBAAA;AAAA,cAgCxD,eAAA,GACX,IAAA,EAAM,YAAA,EACN,eAAA,qBACA,SAAA,aACC,UAAA;AAAA,cAQU,eAAA,GACX,QAAA,EAAU,gBAAA,EACV,GAAA,UACA,SAAA,UACA,SAAA,EAAW,kBAAA,KACV,UAAA;AAAA,cAsFU,UAAA,GACX,QAAA,WAAmB,cAAA,IACnB,OAAA,WAAkB,cAAA,IAClB,QAAA,EAAU,gBAAA,EACV,GAAA,UACA,SAAA,aACC,SAAA"}
@@ -0,0 +1,2 @@
1
+ import { a as diffEvents, c as buildInstruction, d as ExpectTimeoutError, i as buildTestResult, l as resolveUrl, n as DEFAULT_TIMEOUT_MS, o as extractArtifacts, r as buildStepResult, s as layerSdk, t as DEFAULT_AGENT_BACKEND, u as ExpectConfigError } from "./constants-DFJAD4-F.mjs";
2
+ export { DEFAULT_AGENT_BACKEND, DEFAULT_TIMEOUT_MS, ExpectConfigError, ExpectTimeoutError, buildInstruction, buildStepResult, buildTestResult, diffEvents, extractArtifacts, layerSdk, resolveUrl };
@@ -0,0 +1,20 @@
1
+ import { a as ExpectConfig, c as SessionTestInput, d as Test, f as TestEvent, g as Tool, h as TestRun, i as CookieInput, l as Status, m as TestResult, n as BrowserName, o as ExpectSession, p as TestInput, r as Cookie, s as SessionConfig, t as Action, u as StepResult, v as DEFAULT_TIMEOUT_MS, y as ExpectConfigError } from "./types-0J0EwTM4.mjs";
2
+ import { StandardJSONSchemaV1 } from "@standard-schema/spec";
3
+
4
+ //#region src/expect.d.ts
5
+ declare const Expect: {
6
+ readonly test: (input: TestInput) => TestRun;
7
+ readonly session: (config: SessionConfig) => ExpectSession;
8
+ readonly cookies: (browser: true | BrowserName | BrowserName[]) => Promise<Cookie[]>;
9
+ };
10
+ //#endregion
11
+ //#region src/tool.d.ts
12
+ type SchemaInput = StandardJSONSchemaV1 | Record<string, unknown>;
13
+ declare const tool: (name: string, description: string, schema: SchemaInput, handler: (input: Record<string, unknown>) => Promise<string>) => Tool;
14
+ //#endregion
15
+ //#region src/config.d.ts
16
+ declare const defineConfig: (config: ExpectConfig) => ExpectConfig;
17
+ declare const configure: (config: Partial<ExpectConfig>) => void;
18
+ //#endregion
19
+ export { type Action, type BrowserName, type Cookie, type CookieInput, DEFAULT_TIMEOUT_MS, Expect, Expect as default, type ExpectConfig, ExpectConfigError, type ExpectSession, type SessionConfig, type SessionTestInput, type Status, type StepResult, type Test, type TestEvent, type TestInput, type TestResult, type TestRun, type Tool, configure, defineConfig, tool };
20
+ //# sourceMappingURL=index.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../src/expect.ts","../src/tool.ts","../src/config.ts"],"mappings":";;;;cA+aa,MAAA;EAAA,uBAjEQ,SAAA,KAAY,OAAA;EAAA,2BAOR,aAAA,KAAgB,aAAA;EAAA,mCA6CR,WAAA,GAAc,WAAA,OAAgB,OAAA,CAAQ,MAAA;AAAA;;;KC/ZlE,WAAA,GAAc,oBAAA,GAAuB,MAAA;AAAA,cAY7B,IAAA,GACX,IAAA,UACA,WAAA,UACA,MAAA,EAAQ,WAAA,EACR,OAAA,GAAU,KAAA,EAAO,MAAA,sBAA4B,OAAA,aAC5C,IAAA;;;cChBU,YAAA,GAAgB,MAAA,EAAQ,YAAA,KAAe,YAAA;AAAA,cAEvC,SAAA,GAAa,MAAA,EAAQ,OAAA,CAAQ,YAAA"}
package/dist/index.mjs ADDED
@@ -0,0 +1,279 @@
1
+ import { a as diffEvents, c as buildInstruction, d as ExpectTimeoutError, i as buildTestResult, l as resolveUrl, n as DEFAULT_TIMEOUT_MS, o as extractArtifacts, s as layerSdk, t as DEFAULT_AGENT_BACKEND, u as ExpectConfigError } from "./constants-DFJAD4-F.mjs";
2
+ import { Effect, Option, Stream } from "effect";
3
+ import * as NodeServices from "@effect/platform-node/NodeServices";
4
+ import { Executor } from "@expect/supervisor";
5
+ import { ChangesFor } from "@expect/shared/models";
6
+ import { Browsers, Cookies, layerLive } from "@expect/cookies";
7
+ //#region src/config.ts
8
+ let globalConfig = {};
9
+ const defineConfig = (config) => config;
10
+ const configure = (config) => {
11
+ globalConfig = {
12
+ ...globalConfig,
13
+ ...config
14
+ };
15
+ };
16
+ const getGlobalConfig = () => globalConfig;
17
+ //#endregion
18
+ //#region src/test-run.ts
19
+ const createTestRun = (callbacks) => ({
20
+ then(onfulfilled, onrejected) {
21
+ return callbacks.promise.then(onfulfilled, onrejected);
22
+ },
23
+ [Symbol.asyncIterator]() {
24
+ return callbacks.subscribe();
25
+ }
26
+ });
27
+ //#endregion
28
+ //#region src/expect.ts
29
+ const normalizeTestPrompts = (tests) => tests.map((test) => typeof test === "string" ? test : test.prompt);
30
+ const resolveInputUrl = (input) => {
31
+ const config = getGlobalConfig();
32
+ if (input.page) return input.page.url();
33
+ if (input.url !== void 0) return resolveUrl(input.url, config.baseUrl);
34
+ if (config.baseUrl) return config.baseUrl;
35
+ throw new ExpectConfigError("No URL provided and no baseUrl configured.", `Expect.test({ url: "http://localhost:3000", tests: [...] })\nOr: configure({ baseUrl: "http://localhost:3000" })`);
36
+ };
37
+ const validateTests = (tests) => {
38
+ if (tests.length === 0) throw new ExpectConfigError("tests array is empty.", `Expect.test({ url: "...", tests: ["at least one test"] })`);
39
+ };
40
+ const validateTestInput = (input) => {
41
+ validateTests(input.tests);
42
+ if (input.tools && input.tools.length > 0) throw new ExpectConfigError("Custom tools are not yet supported.", `Remove the tools field for now. Tool support is coming in a future release.`);
43
+ if (typeof input.before === "function" && !input.page) throw new ExpectConfigError("Function before requires a page.", `Pass a Playwright Page: Expect.test({ page, before: async (page) => { ... }, tests: [...] })`);
44
+ if (typeof input.after === "function" && !input.page) throw new ExpectConfigError("Function after requires a page.", `Pass a Playwright Page: Expect.test({ page, after: async (page) => { ... }, tests: [...] })`);
45
+ };
46
+ const validateSessionConfig = (config) => {
47
+ if (config.browserContext) throw new ExpectConfigError("External browserContext is not yet supported.", `Remove the browserContext field. The SDK manages browser lifecycle internally.`);
48
+ if (config.tools && config.tools.length > 0) throw new ExpectConfigError("Custom tools are not yet supported.", `Remove the tools field for now. Tool support is coming in a future release.`);
49
+ };
50
+ const isBrowserNameArray = (cookies) => cookies.length > 0 && typeof cookies[0] === "string";
51
+ const resolveCookies = (cookies) => {
52
+ if (cookies === void 0) return {
53
+ browserKeys: [],
54
+ explicitCookies: []
55
+ };
56
+ if (cookies === true) return {
57
+ browserKeys: ["chrome"],
58
+ explicitCookies: []
59
+ };
60
+ if (typeof cookies === "string") return {
61
+ browserKeys: [cookies],
62
+ explicitCookies: []
63
+ };
64
+ if (Array.isArray(cookies)) {
65
+ if (isBrowserNameArray(cookies)) return {
66
+ browserKeys: cookies,
67
+ explicitCookies: []
68
+ };
69
+ return {
70
+ browserKeys: [],
71
+ explicitCookies: cookies
72
+ };
73
+ }
74
+ return {
75
+ browserKeys: [],
76
+ explicitCookies: []
77
+ };
78
+ };
79
+ const buildInstructionWithActions = (url, tests, before, beforeContext, after) => {
80
+ let instruction = buildInstruction(url, normalizeTestPrompts(tests));
81
+ if (typeof before === "string") instruction = `Before: ${before}\n\n${instruction}`;
82
+ if (beforeContext) instruction = `Context from before: ${beforeContext}\n\n${instruction}`;
83
+ if (typeof after === "string") instruction = `${instruction}\n\nAfter: ${after}`;
84
+ return instruction;
85
+ };
86
+ const executeTests = Effect.fn("Sdk.executeTests")(function* (executeOptions, context) {
87
+ yield* Effect.annotateCurrentSpan({
88
+ url: context.url,
89
+ isHeadless: executeOptions.isHeadless
90
+ });
91
+ const executor = yield* Executor;
92
+ let previousEvents = [];
93
+ const finalExecuted = yield* executor.execute(executeOptions).pipe(Stream.tap((executed) => Effect.sync(() => {
94
+ const newEvents = diffEvents(previousEvents, executed.events, executed, context.url, context.startedAt);
95
+ previousEvents = executed.events;
96
+ for (const event of newEvents) context.eventBuffer.push(event);
97
+ context.resolveWaiter.current?.();
98
+ })), Stream.runLast, Effect.flatMap((option) => Option.match(option, {
99
+ onNone: () => Effect.fail(new ExpectTimeoutError({ timeoutMs: 0 })),
100
+ onSome: (executed) => Effect.succeed(executed.finalizeTextBlock().synthesizeRunFinished())
101
+ })));
102
+ const artifacts = extractArtifacts(finalExecuted.events);
103
+ const result = buildTestResult(finalExecuted, context.url, context.startedAt, artifacts);
104
+ if (!context.eventBuffer.some((event) => event.type === "completed")) context.eventBuffer.push({
105
+ type: "completed",
106
+ result
107
+ });
108
+ context.resolveWaiter.current?.();
109
+ return result;
110
+ });
111
+ const extractCookies = Effect.fn("Sdk.extractCookies")(function* (keys) {
112
+ yield* Effect.annotateCurrentSpan({ browserKeys: keys.join(",") });
113
+ const cookiesService = yield* Cookies;
114
+ const matchingBrowsers = (yield* (yield* Browsers).list).filter((browser) => keys.some((key) => {
115
+ if (browser._tag === "ChromiumBrowser") return browser.key === key;
116
+ if (browser._tag === "FirefoxBrowser") return key === "firefox";
117
+ if (browser._tag === "SafariBrowser") return key === "safari";
118
+ return false;
119
+ }));
120
+ return (yield* Effect.forEach(matchingBrowsers, (browser) => cookiesService.extract(browser), { concurrency: "unbounded" })).flat().map((cookie) => {
121
+ const formatted = cookie.playwrightFormat;
122
+ return {
123
+ ...formatted,
124
+ sameSite: formatted.sameSite ?? "Lax"
125
+ };
126
+ });
127
+ });
128
+ const createAsyncIterator = (eventBuffer, resolveWaiter, getFinished, getError) => {
129
+ return () => {
130
+ let cursor = 0;
131
+ return {
132
+ async next() {
133
+ while (true) {
134
+ if (cursor < eventBuffer.length) {
135
+ const event = eventBuffer[cursor];
136
+ cursor++;
137
+ if (event.type === "completed") return {
138
+ done: true,
139
+ value: void 0
140
+ };
141
+ return {
142
+ done: false,
143
+ value: event
144
+ };
145
+ }
146
+ if (getFinished()) {
147
+ const error = getError();
148
+ if (error) throw error;
149
+ return {
150
+ done: true,
151
+ value: void 0
152
+ };
153
+ }
154
+ await new Promise((resolve) => {
155
+ resolveWaiter.current = resolve;
156
+ });
157
+ }
158
+ },
159
+ [Symbol.asyncIterator]() {
160
+ return this;
161
+ }
162
+ };
163
+ };
164
+ };
165
+ const runExecution = (url, tests, input) => {
166
+ const config = getGlobalConfig();
167
+ const timeoutMs = input.timeout ?? config.timeout ?? 3e5;
168
+ const isHeadless = (input.mode ?? config.mode ?? "headless") === "headless";
169
+ const resolved = resolveCookies(input.cookies ?? config.cookies);
170
+ const rootDir = config.rootDir ?? process.cwd();
171
+ const eventBuffer = [];
172
+ const resolveWaiter = { current: void 0 };
173
+ let finished = false;
174
+ let executionError;
175
+ const startExecution = async () => {
176
+ let beforeContext;
177
+ if (typeof input.before === "function" && input.page) {
178
+ const beforeResult = await input.before(input.page);
179
+ if (typeof beforeResult === "string") beforeContext = beforeResult;
180
+ }
181
+ const instruction = buildInstructionWithActions(url, tests, input.before, beforeContext, input.after);
182
+ const program = executeTests({
183
+ changesFor: ChangesFor.makeUnsafe({ _tag: "WorkingTree" }),
184
+ instruction,
185
+ isHeadless,
186
+ cookieBrowserKeys: [...resolved.browserKeys],
187
+ baseUrl: url
188
+ }, {
189
+ url,
190
+ startedAt: Date.now(),
191
+ eventBuffer,
192
+ resolveWaiter
193
+ }).pipe(Effect.timeoutOrElse({
194
+ duration: `${timeoutMs} millis`,
195
+ onTimeout: () => Effect.fail(new ExpectTimeoutError({ timeoutMs }))
196
+ }), Effect.provide(layerSdk(DEFAULT_AGENT_BACKEND, rootDir)), Effect.provide(NodeServices.layer));
197
+ const result = await Effect.runPromise(program);
198
+ if (typeof input.after === "function" && input.page) await input.after(input.page);
199
+ return result;
200
+ };
201
+ return {
202
+ promise: startExecution().then((result) => {
203
+ finished = true;
204
+ resolveWaiter.current?.();
205
+ return result;
206
+ }, (error) => {
207
+ executionError = error;
208
+ finished = true;
209
+ resolveWaiter.current?.();
210
+ throw error;
211
+ }),
212
+ subscribe: createAsyncIterator(eventBuffer, resolveWaiter, () => finished, () => executionError)
213
+ };
214
+ };
215
+ const test = (input) => {
216
+ validateTestInput(input);
217
+ const { promise, subscribe } = runExecution(resolveInputUrl(input), input.tests, input);
218
+ return createTestRun({
219
+ promise,
220
+ subscribe
221
+ });
222
+ };
223
+ const session = (config) => {
224
+ validateSessionConfig(config);
225
+ const sessionTest = (input) => {
226
+ validateTests(input.tests);
227
+ const testUrl = input.url ?? config.url;
228
+ const globalCfg = getGlobalConfig();
229
+ let resolvedUrl;
230
+ if (testUrl !== void 0) resolvedUrl = resolveUrl(testUrl, globalCfg.baseUrl ?? config.url);
231
+ else if (config.url) resolvedUrl = config.url;
232
+ else if (globalCfg.baseUrl) resolvedUrl = globalCfg.baseUrl;
233
+ else throw new ExpectConfigError("No URL provided for session test and no baseUrl configured.", `session.test({ url: "/page", tests: [...] })`);
234
+ const { promise, subscribe } = runExecution(resolvedUrl, input.tests, {
235
+ cookies: config.cookies,
236
+ mode: input.mode ?? config.mode,
237
+ timeout: input.timeout ?? config.timeout,
238
+ isRecording: input.isRecording ?? config.isRecording,
239
+ before: input.before,
240
+ after: input.after
241
+ });
242
+ return createTestRun({
243
+ promise,
244
+ subscribe
245
+ });
246
+ };
247
+ const close = async () => {};
248
+ return {
249
+ test: sessionTest,
250
+ close,
251
+ [Symbol.asyncDispose]: close
252
+ };
253
+ };
254
+ const cookies = (browser) => {
255
+ const keys = browser === true ? ["chrome"] : typeof browser === "string" ? [browser] : browser;
256
+ return Effect.runPromise(Effect.scoped(extractCookies(keys)).pipe(Effect.provide(Cookies.layer), Effect.provide(layerLive), Effect.provide(NodeServices.layer)));
257
+ };
258
+ const Expect = {
259
+ test,
260
+ session,
261
+ cookies
262
+ };
263
+ //#endregion
264
+ //#region src/tool.ts
265
+ const isStandardSchema = (schema) => "~standard" in schema && typeof schema["~standard"] === "object";
266
+ const toInputSchema = (schema) => {
267
+ if (isStandardSchema(schema)) return schema["~standard"].jsonSchema.input({ target: "draft-07" });
268
+ return schema;
269
+ };
270
+ const tool = (name, description, schema, handler) => ({
271
+ name,
272
+ description,
273
+ inputSchema: toInputSchema(schema),
274
+ handler
275
+ });
276
+ //#endregion
277
+ export { DEFAULT_TIMEOUT_MS, Expect, Expect as default, ExpectConfigError, configure, defineConfig, tool };
278
+
279
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.mjs","names":["CookiesService","cookiesLayerLive"],"sources":["../src/config.ts","../src/test-run.ts","../src/expect.ts","../src/tool.ts"],"sourcesContent":["import type { ExpectConfig } from \"./types\";\n\nlet globalConfig: ExpectConfig = {};\n\nexport const defineConfig = (config: ExpectConfig): ExpectConfig => config;\n\nexport const configure = (config: Partial<ExpectConfig>): void => {\n globalConfig = { ...globalConfig, ...config };\n};\n\nexport const getGlobalConfig = (): ExpectConfig => globalConfig;\n\nexport const resetGlobalConfig = (): void => {\n globalConfig = {};\n};\n","import type { TestResult, TestEvent, TestRun } from \"./types\";\n\ninterface TestRunCallbacks {\n readonly promise: Promise<TestResult>;\n readonly subscribe: () => AsyncIterableIterator<TestEvent>;\n}\n\nexport const createTestRun = (callbacks: TestRunCallbacks): TestRun => ({\n then<TResult1 = TestResult, TResult2 = never>(\n onfulfilled?: ((value: TestResult) => TResult1 | PromiseLike<TResult1>) | undefined | null,\n onrejected?: ((reason: unknown) => TResult2 | PromiseLike<TResult2>) | undefined | null,\n ): PromiseLike<TResult1 | TResult2> {\n return callbacks.promise.then(onfulfilled, onrejected);\n },\n\n [Symbol.asyncIterator](): AsyncIterator<TestEvent> {\n return callbacks.subscribe();\n },\n});\n","import { Effect, Option, Stream } from \"effect\";\nimport * as NodeServices from \"@effect/platform-node/NodeServices\";\nimport { Executor, type ExecuteOptions } from \"@expect/supervisor\";\nimport { type ExecutedTestPlan, type ExecutionEvent, ChangesFor } from \"@expect/shared/models\";\nimport {\n Cookies as CookiesService,\n Browsers,\n layerLive as cookiesLayerLive,\n} from \"@expect/cookies\";\nimport { ExpectConfigError, ExpectTimeoutError } from \"./errors\";\nimport { resolveUrl, buildInstruction } from \"./build-instruction\";\nimport { getGlobalConfig } from \"./config\";\nimport { layerSdk } from \"./layers\";\nimport { createTestRun } from \"./test-run\";\nimport { buildTestResult, diffEvents, extractArtifacts } from \"./result-builder\";\nimport { DEFAULT_TIMEOUT_MS, DEFAULT_AGENT_BACKEND } from \"./constants\";\nimport type { Page } from \"playwright\";\nimport type {\n TestInput,\n TestRun,\n TestResult,\n TestEvent,\n SessionConfig,\n SessionTestInput,\n ExpectSession,\n Cookie,\n BrowserName,\n Test,\n} from \"./types\";\n\nconst normalizeTestPrompts = (tests: readonly Test[]): readonly string[] =>\n tests.map((test) => (typeof test === \"string\" ? test : test.prompt));\n\nconst resolveInputUrl = (input: { url?: string; page?: Page }): string => {\n const config = getGlobalConfig();\n\n if (input.page) {\n return input.page.url();\n }\n\n if (input.url !== undefined) {\n return resolveUrl(input.url, config.baseUrl);\n }\n\n if (config.baseUrl) {\n return config.baseUrl;\n }\n\n throw new ExpectConfigError(\n \"No URL provided and no baseUrl configured.\",\n `Expect.test({ url: \"http://localhost:3000\", tests: [...] })\\nOr: configure({ baseUrl: \"http://localhost:3000\" })`,\n );\n};\n\nconst validateTests = (tests: readonly Test[]): void => {\n if (tests.length === 0) {\n throw new ExpectConfigError(\n \"tests array is empty.\",\n `Expect.test({ url: \"...\", tests: [\"at least one test\"] })`,\n );\n }\n};\n\nconst validateTestInput = (input: TestInput): void => {\n validateTests(input.tests);\n if (input.tools && input.tools.length > 0) {\n throw new ExpectConfigError(\n \"Custom tools are not yet supported.\",\n `Remove the tools field for now. Tool support is coming in a future release.`,\n );\n }\n if (typeof input.before === \"function\" && !input.page) {\n throw new ExpectConfigError(\n \"Function before requires a page.\",\n `Pass a Playwright Page: Expect.test({ page, before: async (page) => { ... }, tests: [...] })`,\n );\n }\n if (typeof input.after === \"function\" && !input.page) {\n throw new ExpectConfigError(\n \"Function after requires a page.\",\n `Pass a Playwright Page: Expect.test({ page, after: async (page) => { ... }, tests: [...] })`,\n );\n }\n};\n\nconst validateSessionConfig = (config: SessionConfig): void => {\n if (config.browserContext) {\n throw new ExpectConfigError(\n \"External browserContext is not yet supported.\",\n `Remove the browserContext field. The SDK manages browser lifecycle internally.`,\n );\n }\n if (config.tools && config.tools.length > 0) {\n throw new ExpectConfigError(\n \"Custom tools are not yet supported.\",\n `Remove the tools field for now. Tool support is coming in a future release.`,\n );\n }\n};\n\ninterface ResolvedCookies {\n readonly browserKeys: readonly string[];\n readonly explicitCookies: readonly Cookie[];\n}\n\nconst isBrowserNameArray = (cookies: readonly unknown[]): cookies is readonly string[] =>\n cookies.length > 0 && typeof cookies[0] === \"string\";\n\nconst resolveCookies = (cookies: TestInput[\"cookies\"]): ResolvedCookies => {\n if (cookies === undefined) return { browserKeys: [], explicitCookies: [] };\n if (cookies === true) return { browserKeys: [\"chrome\"], explicitCookies: [] };\n if (typeof cookies === \"string\") return { browserKeys: [cookies], explicitCookies: [] };\n if (Array.isArray(cookies)) {\n if (isBrowserNameArray(cookies)) {\n return { browserKeys: cookies, explicitCookies: [] };\n }\n return { browserKeys: [], explicitCookies: cookies };\n }\n return { browserKeys: [], explicitCookies: [] };\n};\n\nconst buildInstructionWithActions = (\n url: string,\n tests: readonly Test[],\n before: TestInput[\"before\"],\n beforeContext: string | undefined,\n after: TestInput[\"after\"],\n): string => {\n const prompts = normalizeTestPrompts(tests);\n let instruction = buildInstruction(url, prompts);\n\n if (typeof before === \"string\") {\n instruction = `Before: ${before}\\n\\n${instruction}`;\n }\n if (beforeContext) {\n instruction = `Context from before: ${beforeContext}\\n\\n${instruction}`;\n }\n if (typeof after === \"string\") {\n instruction = `${instruction}\\n\\nAfter: ${after}`;\n }\n\n return instruction;\n};\n\ninterface ExecutionContext {\n readonly url: string;\n readonly startedAt: number;\n readonly eventBuffer: TestEvent[];\n readonly resolveWaiter: { current: (() => void) | undefined };\n}\n\nconst executeTests = Effect.fn(\"Sdk.executeTests\")(function* (\n executeOptions: ExecuteOptions,\n context: ExecutionContext,\n) {\n yield* Effect.annotateCurrentSpan({\n url: context.url,\n isHeadless: executeOptions.isHeadless,\n });\n\n const executor = yield* Executor;\n let previousEvents: readonly ExecutionEvent[] = [];\n\n const finalExecuted = yield* executor.execute(executeOptions).pipe(\n Stream.tap((executed: ExecutedTestPlan) =>\n Effect.sync(() => {\n const newEvents = diffEvents(\n previousEvents,\n executed.events,\n executed,\n context.url,\n context.startedAt,\n );\n previousEvents = executed.events;\n for (const event of newEvents) {\n context.eventBuffer.push(event);\n }\n context.resolveWaiter.current?.();\n }),\n ),\n Stream.runLast,\n Effect.flatMap((option) =>\n Option.match(option, {\n onNone: () => Effect.fail(new ExpectTimeoutError({ timeoutMs: 0 })),\n onSome: (executed) => Effect.succeed(executed.finalizeTextBlock().synthesizeRunFinished()),\n }),\n ),\n );\n\n const artifacts = extractArtifacts(finalExecuted.events);\n const result = buildTestResult(finalExecuted, context.url, context.startedAt, artifacts);\n\n if (!context.eventBuffer.some((event) => event.type === \"completed\")) {\n context.eventBuffer.push({ type: \"completed\", result });\n }\n\n context.resolveWaiter.current?.();\n return result;\n});\n\nconst extractCookies = Effect.fn(\"Sdk.extractCookies\")(function* (keys: readonly string[]) {\n yield* Effect.annotateCurrentSpan({ browserKeys: keys.join(\",\") });\n\n const cookiesService = yield* CookiesService;\n const browsers = yield* Browsers;\n const allBrowsers = yield* browsers.list;\n\n const matchingBrowsers = allBrowsers.filter((browser) =>\n keys.some((key) => {\n if (browser._tag === \"ChromiumBrowser\") return browser.key === key;\n if (browser._tag === \"FirefoxBrowser\") return key === \"firefox\";\n if (browser._tag === \"SafariBrowser\") return key === \"safari\";\n return false;\n }),\n );\n\n const results = yield* Effect.forEach(\n matchingBrowsers,\n (browser) => cookiesService.extract(browser),\n { concurrency: \"unbounded\" },\n );\n\n return results.flat().map((cookie): Cookie => {\n const formatted = cookie.playwrightFormat;\n return { ...formatted, sameSite: formatted.sameSite ?? \"Lax\" };\n });\n});\n\nconst createAsyncIterator = (\n eventBuffer: TestEvent[],\n resolveWaiter: { current: (() => void) | undefined },\n getFinished: () => boolean,\n getError: () => unknown,\n): (() => AsyncIterableIterator<TestEvent>) => {\n return () => {\n let cursor = 0;\n\n return {\n async next(): Promise<IteratorResult<TestEvent>> {\n while (true) {\n if (cursor < eventBuffer.length) {\n const event = eventBuffer[cursor];\n cursor++;\n if (event.type === \"completed\") {\n return { done: true, value: undefined };\n }\n return { done: false, value: event };\n }\n\n if (getFinished()) {\n const error = getError();\n if (error) throw error;\n return { done: true, value: undefined };\n }\n\n await new Promise<void>((resolve) => {\n resolveWaiter.current = resolve;\n });\n }\n },\n\n [Symbol.asyncIterator]() {\n return this;\n },\n };\n };\n};\n\nconst runExecution = (\n url: string,\n tests: readonly Test[],\n input: {\n cookies?: TestInput[\"cookies\"];\n mode?: \"headed\" | \"headless\";\n timeout?: number;\n isRecording?: boolean;\n before?: TestInput[\"before\"];\n after?: TestInput[\"after\"];\n page?: Page;\n },\n): { promise: Promise<TestResult>; subscribe: () => AsyncIterableIterator<TestEvent> } => {\n const config = getGlobalConfig();\n const timeoutMs = input.timeout ?? config.timeout ?? DEFAULT_TIMEOUT_MS;\n const isHeadless = (input.mode ?? config.mode ?? \"headless\") === \"headless\";\n const resolved = resolveCookies(input.cookies ?? config.cookies);\n const rootDir = config.rootDir ?? process.cwd();\n\n const eventBuffer: TestEvent[] = [];\n const resolveWaiter: { current: (() => void) | undefined } = { current: undefined };\n let finished = false;\n let executionError: unknown;\n\n const startExecution = async (): Promise<TestResult> => {\n let beforeContext: string | undefined;\n if (typeof input.before === \"function\" && input.page) {\n const beforeResult = await input.before(input.page);\n if (typeof beforeResult === \"string\") {\n beforeContext = beforeResult;\n }\n }\n\n const instruction = buildInstructionWithActions(\n url,\n tests,\n input.before,\n beforeContext,\n input.after,\n );\n\n const executeOptions: ExecuteOptions = {\n changesFor: ChangesFor.makeUnsafe({ _tag: \"WorkingTree\" }),\n instruction,\n isHeadless,\n cookieBrowserKeys: [...resolved.browserKeys],\n baseUrl: url,\n };\n\n const context: ExecutionContext = {\n url,\n startedAt: Date.now(),\n eventBuffer,\n resolveWaiter,\n };\n\n const program = executeTests(executeOptions, context).pipe(\n Effect.timeoutOrElse({\n duration: `${timeoutMs} millis`,\n onTimeout: () => Effect.fail(new ExpectTimeoutError({ timeoutMs })),\n }),\n Effect.provide(layerSdk(DEFAULT_AGENT_BACKEND, rootDir)),\n Effect.provide(NodeServices.layer),\n );\n\n const result = await Effect.runPromise(program);\n\n if (typeof input.after === \"function\" && input.page) {\n await input.after(input.page);\n }\n\n return result;\n };\n\n const promise = startExecution().then(\n (result) => {\n finished = true;\n resolveWaiter.current?.();\n return result;\n },\n (error) => {\n executionError = error;\n finished = true;\n resolveWaiter.current?.();\n throw error;\n },\n );\n\n const subscribe = createAsyncIterator(\n eventBuffer,\n resolveWaiter,\n () => finished,\n () => executionError,\n );\n\n return { promise, subscribe };\n};\n\nconst test = (input: TestInput): TestRun => {\n validateTestInput(input);\n const url = resolveInputUrl(input);\n const { promise, subscribe } = runExecution(url, input.tests, input);\n return createTestRun({ promise, subscribe });\n};\n\nconst session = (config: SessionConfig): ExpectSession => {\n validateSessionConfig(config);\n\n const sessionTest = (input: SessionTestInput): TestRun => {\n validateTests(input.tests);\n const testUrl = input.url ?? config.url;\n const globalCfg = getGlobalConfig();\n\n let resolvedUrl: string;\n if (testUrl !== undefined) {\n resolvedUrl = resolveUrl(testUrl, globalCfg.baseUrl ?? config.url);\n } else if (config.url) {\n resolvedUrl = config.url;\n } else if (globalCfg.baseUrl) {\n resolvedUrl = globalCfg.baseUrl;\n } else {\n throw new ExpectConfigError(\n \"No URL provided for session test and no baseUrl configured.\",\n `session.test({ url: \"/page\", tests: [...] })`,\n );\n }\n\n const { promise, subscribe } = runExecution(resolvedUrl, input.tests, {\n cookies: config.cookies,\n mode: input.mode ?? config.mode,\n timeout: input.timeout ?? config.timeout,\n isRecording: input.isRecording ?? config.isRecording,\n before: input.before,\n after: input.after,\n });\n\n return createTestRun({ promise, subscribe });\n };\n\n const close = async (): Promise<void> => {\n // HACK: browser lifecycle is managed by the executor internally for now\n };\n\n return {\n test: sessionTest,\n close,\n [Symbol.asyncDispose]: close,\n };\n};\n\nconst cookies = (browser: true | BrowserName | BrowserName[]): Promise<Cookie[]> => {\n const keys: string[] =\n browser === true ? [\"chrome\"] : typeof browser === \"string\" ? [browser] : browser;\n\n return Effect.runPromise(\n Effect.scoped(extractCookies(keys)).pipe(\n Effect.provide(CookiesService.layer),\n Effect.provide(cookiesLayerLive),\n Effect.provide(NodeServices.layer),\n ),\n );\n};\n\nexport const Expect = { test, session, cookies } as const;\n","import type { StandardJSONSchemaV1 } from \"@standard-schema/spec\";\nimport type { Tool } from \"./types\";\n\ntype SchemaInput = StandardJSONSchemaV1 | Record<string, unknown>;\n\nconst isStandardSchema = (schema: SchemaInput): schema is StandardJSONSchemaV1 =>\n \"~standard\" in schema && typeof (schema as Record<string, unknown>)[\"~standard\"] === \"object\";\n\nconst toInputSchema = (schema: SchemaInput): Tool[\"inputSchema\"] => {\n if (isStandardSchema(schema)) {\n return schema[\"~standard\"].jsonSchema.input({ target: \"draft-07\" }) as Tool[\"inputSchema\"];\n }\n return schema as Tool[\"inputSchema\"];\n};\n\nexport const tool = (\n name: string,\n description: string,\n schema: SchemaInput,\n handler: (input: Record<string, unknown>) => Promise<string>,\n): Tool => ({\n name,\n description,\n inputSchema: toInputSchema(schema),\n handler,\n});\n"],"mappings":"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"}
@@ -0,0 +1,124 @@
1
+ import { Schema } from "effect";
2
+ import * as effect_Cause0 from "effect/Cause";
3
+ import { BrowserContext, Cookie, Page } from "playwright";
4
+ import { Tool } from "@modelcontextprotocol/sdk/types.js";
5
+
6
+ //#region src/errors.d.ts
7
+ declare const ExpectTimeoutError_base: Schema.ErrorClass<ExpectTimeoutError, Schema.Struct<{
8
+ readonly _tag: Schema.tag<"ExpectTimeoutError">;
9
+ readonly timeoutMs: Schema.Number;
10
+ }>, effect_Cause0.YieldableError>;
11
+ declare class ExpectTimeoutError extends ExpectTimeoutError_base {
12
+ message: string;
13
+ }
14
+ declare class ExpectConfigError extends Error {
15
+ constructor(message: string, fix: string);
16
+ }
17
+ //#endregion
18
+ //#region src/constants.d.ts
19
+ declare const DEFAULT_TIMEOUT_MS: number;
20
+ declare const DEFAULT_AGENT_BACKEND: "claude";
21
+ //#endregion
22
+ //#region src/types.d.ts
23
+ type Action = string | ((page: Page) => Promise<void | string>);
24
+ type BrowserName = "chrome" | "firefox" | "safari" | "edge" | "brave" | "arc";
25
+ type CookieInput = true | BrowserName | BrowserName[] | Cookie[];
26
+ type Test = string | {
27
+ title?: string;
28
+ prompt: string;
29
+ };
30
+ type Status = "pending" | "passed" | "failed";
31
+ interface Tool$1 extends Pick<Tool, "name" | "description" | "inputSchema"> {
32
+ readonly handler: (input: Record<string, unknown>) => Promise<string>;
33
+ }
34
+ interface StepResult {
35
+ readonly title: string;
36
+ readonly status: Status;
37
+ readonly summary: string;
38
+ readonly screenshotPath?: string;
39
+ readonly duration: number;
40
+ }
41
+ interface TestResult {
42
+ readonly status: Status;
43
+ readonly url: string;
44
+ readonly duration: number;
45
+ readonly recordingPath?: string;
46
+ readonly steps: StepResult[];
47
+ readonly errors: StepResult[];
48
+ }
49
+ type TestEvent = {
50
+ readonly type: "run:started";
51
+ readonly title: string;
52
+ readonly baseUrl?: string;
53
+ } | {
54
+ readonly type: "step:started";
55
+ readonly title: string;
56
+ } | {
57
+ readonly type: "step:passed";
58
+ readonly step: StepResult;
59
+ } | {
60
+ readonly type: "step:failed";
61
+ readonly step: StepResult;
62
+ } | {
63
+ readonly type: "step:skipped";
64
+ readonly title: string;
65
+ readonly reason: string;
66
+ } | {
67
+ readonly type: "screenshot";
68
+ readonly title: string;
69
+ readonly path: string;
70
+ } | {
71
+ readonly type: "completed";
72
+ readonly result: TestResult;
73
+ };
74
+ interface TestRun extends PromiseLike<TestResult> {
75
+ [Symbol.asyncIterator](): AsyncIterator<TestEvent>;
76
+ }
77
+ interface TestInput {
78
+ readonly url?: string;
79
+ readonly page?: Page;
80
+ readonly cookies?: CookieInput;
81
+ readonly tools?: Tool$1[];
82
+ readonly tests: Test[];
83
+ readonly before?: Action;
84
+ readonly after?: Action;
85
+ readonly mode?: "headed" | "headless";
86
+ readonly timeout?: number;
87
+ readonly isRecording?: boolean;
88
+ }
89
+ interface SessionConfig {
90
+ readonly url?: string;
91
+ readonly browserContext?: BrowserContext;
92
+ readonly cookies?: CookieInput;
93
+ readonly tools?: Tool$1[];
94
+ readonly mode?: "headed" | "headless";
95
+ readonly timeout?: number;
96
+ readonly isRecording?: boolean;
97
+ }
98
+ interface SessionTestInput {
99
+ readonly url?: string;
100
+ readonly tests: Test[];
101
+ readonly before?: Action;
102
+ readonly after?: Action;
103
+ readonly mode?: "headed" | "headless";
104
+ readonly timeout?: number;
105
+ readonly isRecording?: boolean;
106
+ }
107
+ interface ExpectSession {
108
+ test(input: SessionTestInput): TestRun;
109
+ close(): Promise<void>;
110
+ [Symbol.asyncDispose](): Promise<void>;
111
+ }
112
+ interface ExpectConfig {
113
+ readonly baseUrl?: string;
114
+ readonly browser?: BrowserName;
115
+ readonly mode?: "headed" | "headless";
116
+ readonly cookies?: CookieInput;
117
+ readonly timeout?: number;
118
+ readonly model?: string;
119
+ readonly apiKey?: string;
120
+ readonly rootDir?: string;
121
+ }
122
+ //#endregion
123
+ export { DEFAULT_AGENT_BACKEND as _, ExpectConfig as a, ExpectTimeoutError as b, SessionTestInput as c, Test as d, TestEvent as f, Tool$1 as g, TestRun as h, CookieInput as i, Status as l, TestResult as m, BrowserName as n, ExpectSession as o, TestInput as p, Cookie as r, SessionConfig as s, Action as t, StepResult as u, DEFAULT_TIMEOUT_MS as v, ExpectConfigError as y };
124
+ //# sourceMappingURL=types-0J0EwTM4.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types-0J0EwTM4.d.mts","names":[],"sources":["../src/errors.ts","../src/constants.ts","../src/types.ts"],"mappings":";;;;;;cAAgC,uBAAA;;;;cAEnB,kBAAA,SAA2B,uBAAA;EAMtC,OAAA;AAAA;AAAA,cAGW,iBAAA,SAA0B,KAAA;cACzB,OAAA,UAAiB,GAAA;AAAA;;;cCZlB,kBAAA;AAAA,cACA,qBAAA;;;KCID,MAAA,cAAoB,IAAA,EAAM,IAAA,KAAS,OAAA;AAAA,KAEnC,WAAA;AAAA,KAEA,WAAA,UAAqB,WAAA,GAAc,WAAA,KAAgB,MAAA;AAAA,KAEnD,IAAA;EAAkB,KAAA;EAAgB,MAAA;AAAA;AAAA,KAElC,MAAA;AAAA,UAEK,MAAA,SAAa,IAAA,CAAK,IAAA;EAAA,SACxB,OAAA,GAAU,KAAA,EAAO,MAAA,sBAA4B,OAAA;AAAA;AAAA,UAGvC,UAAA;EAAA,SACN,KAAA;EAAA,SACA,MAAA,EAAQ,MAAA;EAAA,SACR,OAAA;EAAA,SACA,cAAA;EAAA,SACA,QAAA;AAAA;AAAA,UAGM,UAAA;EAAA,SACN,MAAA,EAAQ,MAAA;EAAA,SACR,GAAA;EAAA,SACA,QAAA;EAAA,SACA,aAAA;EAAA,SACA,KAAA,EAAO,UAAA;EAAA,SACP,MAAA,EAAQ,UAAA;AAAA;AAAA,KAGP,SAAA;EAAA,SACG,IAAA;EAAA,SAA8B,KAAA;EAAA,SAAwB,OAAA;AAAA;EAAA,SACtD,IAAA;EAAA,SAA+B,KAAA;AAAA;EAAA,SAC/B,IAAA;EAAA,SAA8B,IAAA,EAAM,UAAA;AAAA;EAAA,SACpC,IAAA;EAAA,SAA8B,IAAA,EAAM,UAAA;AAAA;EAAA,SACpC,IAAA;EAAA,SAA+B,KAAA;EAAA,SAAwB,MAAA;AAAA;EAAA,SACvD,IAAA;EAAA,SAA6B,KAAA;EAAA,SAAwB,IAAA;AAAA;EAAA,SACrD,IAAA;EAAA,SAA4B,MAAA,EAAQ,UAAA;AAAA;AAAA,UAElC,OAAA,SAAgB,WAAA,CAAY,UAAA;EAAA,CAC1C,MAAA,CAAO,aAAP,KAAyB,aAAA,CAAc,SAAA;AAAA;AAAA,UAGzB,SAAA;EAAA,SACN,GAAA;EAAA,SACA,IAAA,GAAO,IAAA;EAAA,SACP,OAAA,GAAU,WAAA;EAAA,SACV,KAAA,GAAQ,MAAA;EAAA,SACR,KAAA,EAAO,IAAA;EAAA,SACP,MAAA,GAAS,MAAA;EAAA,SACT,KAAA,GAAQ,MAAA;EAAA,SACR,IAAA;EAAA,SACA,OAAA;EAAA,SACA,WAAA;AAAA;AAAA,UAGM,aAAA;EAAA,SACN,GAAA;EAAA,SACA,cAAA,GAAiB,cAAA;EAAA,SACjB,OAAA,GAAU,WAAA;EAAA,SACV,KAAA,GAAQ,MAAA;EAAA,SACR,IAAA;EAAA,SACA,OAAA;EAAA,SACA,WAAA;AAAA;AAAA,UAGM,gBAAA;EAAA,SACN,GAAA;EAAA,SACA,KAAA,EAAO,IAAA;EAAA,SACP,MAAA,GAAS,MAAA;EAAA,SACT,KAAA,GAAQ,MAAA;EAAA,SACR,IAAA;EAAA,SACA,OAAA;EAAA,SACA,WAAA;AAAA;AAAA,UAGM,aAAA;EACf,IAAA,CAAK,KAAA,EAAO,gBAAA,GAAmB,OAAA;EAC/B,KAAA,IAAS,OAAA;EAAA,CACR,MAAA,CAAO,YAAP,KAAwB,OAAA;AAAA;AAAA,UAGV,YAAA;EAAA,SACN,OAAA;EAAA,SACA,OAAA,GAAU,WAAA;EAAA,SACV,IAAA;EAAA,SACA,OAAA,GAAU,WAAA;EAAA,SACV,OAAA;EAAA,SACA,KAAA;EAAA,SACA,MAAA;EAAA,SACA,OAAA;AAAA"}
package/package.json ADDED
@@ -0,0 +1,46 @@
1
+ {
2
+ "name": "expect-sdk",
3
+ "version": "0.0.24",
4
+ "publishConfig": {
5
+ "tag": "alpha"
6
+ },
7
+ "type": "module",
8
+ "exports": {
9
+ ".": "./src/index.ts",
10
+ "./effect": "./src/effect.ts"
11
+ },
12
+ "dependencies": {
13
+ "@effect/platform-node": "4.0.0-beta.35",
14
+ "@modelcontextprotocol/sdk": "^1.27.1",
15
+ "@standard-schema/spec": "^1.1.0",
16
+ "effect": "4.0.0-beta.35",
17
+ "@expect/agent": "0.0.24",
18
+ "@expect/shared": "0.0.24",
19
+ "@expect/supervisor": "0.0.24",
20
+ "@expect/cookies": "0.0.24"
21
+ },
22
+ "devDependencies": {
23
+ "@types/bun": "^1.3.11",
24
+ "@types/node": "^22.15.0",
25
+ "typescript": "^5.7.0"
26
+ },
27
+ "peerDependencies": {
28
+ "playwright": ">=1.50.0"
29
+ },
30
+ "peerDependenciesMeta": {
31
+ "playwright": {
32
+ "optional": true
33
+ }
34
+ },
35
+ "scripts": {
36
+ "lint": "vp lint && tsc --noEmit",
37
+ "format": "vp fmt",
38
+ "format:check": "vp fmt --check",
39
+ "build": "vp pack",
40
+ "check": "vp check",
41
+ "test": "vp test run",
42
+ "test:e2e": "~/.bun/bin/bun tests/e2e.ts",
43
+ "test:watch": "vp test",
44
+ "typecheck": "tsgo --noEmit"
45
+ }
46
+ }
@@ -0,0 +1,35 @@
1
+ import { ExpectConfigError } from "./errors";
2
+
3
+ export const resolveUrl = (url: unknown, baseUrl: string | undefined): string => {
4
+ if (typeof url !== "string") {
5
+ throw new ExpectConfigError(
6
+ `Expected a URL string, got ${typeof url}.`,
7
+ `Expect.test({ url: "http://localhost:3000/login", tests: [...] })`,
8
+ );
9
+ }
10
+
11
+ try {
12
+ return new URL(url).href;
13
+ } catch {
14
+ /* relative URL — falls through to baseUrl resolution */
15
+ }
16
+
17
+ if (!baseUrl) {
18
+ throw new ExpectConfigError(
19
+ `No baseUrl configured and URL "${url}" is relative.`,
20
+ `configure({ baseUrl: "http://localhost:3000" })\nOr use a full URL: Expect.test({ url: "http://localhost:3000${url}", tests: [...] })`,
21
+ );
22
+ }
23
+
24
+ return new URL(url, baseUrl).href;
25
+ };
26
+
27
+ export const buildInstruction = (url: string, tests: readonly string[]): string => {
28
+ const lines = [`Navigate to ${url} and verify the following requirements:`, ""];
29
+
30
+ for (const [index, title] of tests.entries()) {
31
+ lines.push(`${index + 1}. ${title}`);
32
+ }
33
+
34
+ return lines.join("\n");
35
+ };
package/src/config.ts ADDED
@@ -0,0 +1,15 @@
1
+ import type { ExpectConfig } from "./types";
2
+
3
+ let globalConfig: ExpectConfig = {};
4
+
5
+ export const defineConfig = (config: ExpectConfig): ExpectConfig => config;
6
+
7
+ export const configure = (config: Partial<ExpectConfig>): void => {
8
+ globalConfig = { ...globalConfig, ...config };
9
+ };
10
+
11
+ export const getGlobalConfig = (): ExpectConfig => globalConfig;
12
+
13
+ export const resetGlobalConfig = (): void => {
14
+ globalConfig = {};
15
+ };