@smoothdeploy/playwright 1.57.1 → 1.58.1-beta-1770383926000

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.

Potentially problematic release.


This version of @smoothdeploy/playwright might be problematic. Click here for more details.

Files changed (264) hide show
  1. package/ThirdPartyNotices.txt +1188 -65
  2. package/lib/agents/agentParser.js +89 -0
  3. package/lib/agents/generateAgents.js +27 -74
  4. package/lib/agents/generateAgents.js.map +7 -0
  5. package/lib/agents/playwright-test-planner.agent.md +1 -0
  6. package/lib/common/config.js +6 -4
  7. package/lib/common/config.js.map +7 -0
  8. package/lib/common/configLoader.js.map +7 -0
  9. package/lib/common/esmLoaderHost.js +2 -0
  10. package/lib/common/esmLoaderHost.js.map +7 -0
  11. package/lib/common/expectBundle.js +2 -17
  12. package/lib/common/expectBundle.js.map +7 -0
  13. package/lib/common/expectBundleImpl.js +132 -132
  14. package/lib/common/expectBundleImpl.js.map +7 -0
  15. package/lib/common/fixtures.js.map +7 -0
  16. package/lib/common/globals.js.map +7 -0
  17. package/lib/common/ipc.js.map +7 -0
  18. package/lib/common/poolBuilder.js.map +7 -0
  19. package/lib/common/process.js +28 -0
  20. package/lib/common/process.js.map +7 -0
  21. package/lib/common/suiteUtils.js.map +7 -0
  22. package/lib/common/test.js.map +7 -0
  23. package/lib/common/testLoader.js.map +7 -0
  24. package/lib/common/testType.js.map +7 -0
  25. package/lib/common/validators.js +10 -10
  26. package/lib/common/validators.js.map +7 -0
  27. package/lib/fsWatcher.js.map +7 -0
  28. package/lib/index.js +205 -12
  29. package/lib/index.js.map +7 -0
  30. package/lib/internalsForTest.js.map +7 -0
  31. package/lib/isomorphic/events.js.map +7 -0
  32. package/lib/isomorphic/folders.js.map +7 -0
  33. package/lib/isomorphic/stringInternPool.js.map +7 -0
  34. package/lib/isomorphic/teleReceiver.js +15 -2
  35. package/lib/isomorphic/teleReceiver.js.map +7 -0
  36. package/lib/isomorphic/teleSuiteUpdater.js +24 -4
  37. package/lib/isomorphic/teleSuiteUpdater.js.map +7 -0
  38. package/lib/isomorphic/testServerConnection.js.map +7 -0
  39. package/lib/isomorphic/testServerInterface.js.map +7 -0
  40. package/lib/isomorphic/testTree.js +13 -18
  41. package/lib/isomorphic/testTree.js.map +7 -0
  42. package/lib/isomorphic/types.d.js.map +7 -0
  43. package/lib/loader/loaderMain.js.map +7 -0
  44. package/lib/matchers/expect.js +2 -15
  45. package/lib/matchers/expect.js.map +7 -0
  46. package/lib/matchers/matcherHint.js +1 -44
  47. package/lib/matchers/matcherHint.js.map +7 -0
  48. package/lib/matchers/matchers.js +3 -2
  49. package/lib/matchers/matchers.js.map +7 -0
  50. package/lib/matchers/toBeTruthy.js +5 -3
  51. package/lib/matchers/toBeTruthy.js.map +7 -0
  52. package/lib/matchers/toEqual.js +4 -3
  53. package/lib/matchers/toEqual.js.map +7 -0
  54. package/lib/matchers/toHaveURL.js +5 -6
  55. package/lib/matchers/toHaveURL.js.map +7 -0
  56. package/lib/matchers/toMatchAriaSnapshot.js +5 -5
  57. package/lib/matchers/toMatchAriaSnapshot.js.map +7 -0
  58. package/lib/matchers/toMatchSnapshot.js +9 -8
  59. package/lib/matchers/toMatchSnapshot.js.map +7 -0
  60. package/lib/matchers/toMatchText.js +9 -9
  61. package/lib/matchers/toMatchText.js.map +7 -0
  62. package/lib/mcp/browser/actions.d.js.map +7 -0
  63. package/lib/mcp/browser/browserContextFactory.js +62 -29
  64. package/lib/mcp/browser/browserContextFactory.js.map +7 -0
  65. package/lib/mcp/browser/browserServerBackend.js +17 -9
  66. package/lib/mcp/browser/browserServerBackend.js.map +7 -0
  67. package/lib/mcp/browser/codegen.js.map +7 -0
  68. package/lib/mcp/browser/config.js +65 -12
  69. package/lib/mcp/browser/config.js.map +7 -0
  70. package/lib/mcp/browser/context.js +71 -94
  71. package/lib/mcp/browser/context.js.map +7 -0
  72. package/lib/mcp/browser/response.js +172 -131
  73. package/lib/mcp/browser/response.js.map +7 -0
  74. package/lib/mcp/browser/sessionLog.js +19 -104
  75. package/lib/mcp/browser/sessionLog.js.map +7 -0
  76. package/lib/mcp/browser/tab.js +92 -41
  77. package/lib/mcp/browser/tab.js.map +7 -0
  78. package/lib/mcp/browser/tools/common.js +8 -6
  79. package/lib/mcp/browser/tools/common.js.map +7 -0
  80. package/lib/mcp/browser/tools/console.js +7 -5
  81. package/lib/mcp/browser/tools/console.js.map +7 -0
  82. package/lib/mcp/browser/tools/dialogs.js +4 -4
  83. package/lib/mcp/browser/tools/dialogs.js.map +7 -0
  84. package/lib/mcp/browser/tools/evaluate.js +11 -19
  85. package/lib/mcp/browser/tools/evaluate.js.map +7 -0
  86. package/lib/mcp/browser/tools/files.js +3 -3
  87. package/lib/mcp/browser/tools/files.js.map +7 -0
  88. package/lib/mcp/browser/tools/form.js +9 -19
  89. package/lib/mcp/browser/tools/form.js.map +7 -0
  90. package/lib/mcp/browser/tools/install.js +6 -3
  91. package/lib/mcp/browser/tools/install.js.map +7 -0
  92. package/lib/mcp/browser/tools/keyboard.js +34 -11
  93. package/lib/mcp/browser/tools/keyboard.js.map +7 -0
  94. package/lib/mcp/browser/tools/mouse.js +11 -11
  95. package/lib/mcp/browser/tools/mouse.js.map +7 -0
  96. package/lib/mcp/browser/tools/navigate.js +14 -5
  97. package/lib/mcp/browser/tools/navigate.js.map +7 -0
  98. package/lib/mcp/browser/tools/network.js +20 -11
  99. package/lib/mcp/browser/tools/network.js.map +7 -0
  100. package/lib/mcp/browser/tools/open.js +57 -0
  101. package/lib/mcp/browser/tools/pdf.js +9 -19
  102. package/lib/mcp/browser/tools/pdf.js.map +7 -0
  103. package/lib/mcp/browser/tools/runCode.js +11 -8
  104. package/lib/mcp/browser/tools/runCode.js.map +7 -0
  105. package/lib/mcp/browser/tools/screenshot.js +16 -29
  106. package/lib/mcp/browser/tools/screenshot.js.map +7 -0
  107. package/lib/mcp/browser/tools/snapshot.js +21 -29
  108. package/lib/mcp/browser/tools/snapshot.js.map +7 -0
  109. package/lib/mcp/browser/tools/tabs.js +12 -12
  110. package/lib/mcp/browser/tools/tabs.js.map +7 -0
  111. package/lib/mcp/browser/tools/tool.js +2 -4
  112. package/lib/mcp/browser/tools/tool.js.map +7 -0
  113. package/lib/mcp/browser/tools/tracing.js +6 -6
  114. package/lib/mcp/browser/tools/tracing.js.map +7 -0
  115. package/lib/mcp/browser/tools/utils.js +49 -44
  116. package/lib/mcp/browser/tools/utils.js.map +7 -0
  117. package/lib/mcp/browser/tools/verify.js +24 -34
  118. package/lib/mcp/browser/tools/verify.js.map +7 -0
  119. package/lib/mcp/browser/tools/wait.js +6 -6
  120. package/lib/mcp/browser/tools/wait.js.map +7 -0
  121. package/lib/mcp/browser/tools.js +3 -1
  122. package/lib/mcp/browser/tools.js.map +7 -0
  123. package/lib/mcp/browser/watchdog.js.map +7 -0
  124. package/lib/mcp/config.d.js.map +7 -0
  125. package/lib/mcp/extension/cdpRelay.js +1 -1
  126. package/lib/mcp/extension/cdpRelay.js.map +7 -0
  127. package/lib/mcp/extension/extensionContextFactory.js +6 -5
  128. package/lib/mcp/extension/extensionContextFactory.js.map +7 -0
  129. package/lib/mcp/extension/protocol.js.map +7 -0
  130. package/lib/mcp/index.js.map +7 -0
  131. package/lib/mcp/log.js.map +7 -0
  132. package/lib/mcp/program.js +15 -20
  133. package/lib/mcp/program.js.map +7 -0
  134. package/lib/mcp/sdk/bundle.js.map +7 -0
  135. package/lib/mcp/sdk/exports.js +0 -2
  136. package/lib/mcp/sdk/exports.js.map +7 -0
  137. package/lib/mcp/sdk/http.js +20 -55
  138. package/lib/mcp/sdk/http.js.map +7 -0
  139. package/lib/mcp/sdk/inProcessTransport.js.map +7 -0
  140. package/lib/mcp/sdk/proxyBackend.js.map +7 -0
  141. package/lib/mcp/sdk/server.js +29 -4
  142. package/lib/mcp/sdk/server.js.map +7 -0
  143. package/lib/mcp/sdk/tool.js +2 -2
  144. package/lib/mcp/sdk/tool.js.map +7 -0
  145. package/lib/mcp/terminal/cli.js +296 -0
  146. package/lib/mcp/terminal/command.js +56 -0
  147. package/lib/mcp/terminal/commands.js +333 -0
  148. package/lib/mcp/terminal/daemon.js +129 -0
  149. package/lib/mcp/terminal/help.json +32 -0
  150. package/lib/mcp/terminal/helpGenerator.js +88 -0
  151. package/lib/mcp/terminal/socketConnection.js +80 -0
  152. package/lib/mcp/test/browserBackend.js +3 -13
  153. package/lib/mcp/test/browserBackend.js.map +7 -0
  154. package/lib/mcp/test/generatorTools.js +9 -9
  155. package/lib/mcp/test/generatorTools.js.map +7 -0
  156. package/lib/mcp/test/plannerTools.js +23 -22
  157. package/lib/mcp/test/plannerTools.js.map +7 -0
  158. package/lib/mcp/test/seed.js.map +7 -0
  159. package/lib/mcp/test/streams.js.map +7 -0
  160. package/lib/mcp/test/testBackend.js +6 -6
  161. package/lib/mcp/test/testBackend.js.map +7 -0
  162. package/lib/mcp/test/testContext.js +9 -3
  163. package/lib/mcp/test/testContext.js.map +7 -0
  164. package/lib/mcp/test/testTool.js.map +7 -0
  165. package/lib/mcp/test/testTools.js +12 -10
  166. package/lib/mcp/test/testTools.js.map +7 -0
  167. package/lib/mcpBundleImpl.js.map +7 -0
  168. package/lib/plugins/gitCommitInfoPlugin.js.map +7 -0
  169. package/lib/plugins/index.js.map +7 -0
  170. package/lib/plugins/webServerPlugin.js.map +7 -0
  171. package/lib/program.js +18 -4
  172. package/lib/program.js.map +7 -0
  173. package/lib/reporters/base.js +29 -4
  174. package/lib/reporters/base.js.map +7 -0
  175. package/lib/reporters/blob.js +3 -0
  176. package/lib/reporters/blob.js.map +7 -0
  177. package/lib/reporters/dot.js +17 -0
  178. package/lib/reporters/dot.js.map +7 -0
  179. package/lib/reporters/empty.js.map +7 -0
  180. package/lib/reporters/github.js.map +7 -0
  181. package/lib/reporters/html.js +13 -3
  182. package/lib/reporters/html.js.map +7 -0
  183. package/lib/reporters/internalReporter.js +6 -0
  184. package/lib/reporters/internalReporter.js.map +7 -0
  185. package/lib/reporters/json.js.map +7 -0
  186. package/lib/reporters/junit.js.map +7 -0
  187. package/lib/reporters/line.js +18 -0
  188. package/lib/reporters/line.js.map +7 -0
  189. package/lib/reporters/list.js +22 -0
  190. package/lib/reporters/list.js.map +7 -0
  191. package/lib/reporters/listModeReporter.js.map +7 -0
  192. package/lib/reporters/markdown.js.map +7 -0
  193. package/lib/reporters/merge.js +25 -8
  194. package/lib/reporters/merge.js.map +7 -0
  195. package/lib/reporters/multiplexer.js +8 -0
  196. package/lib/reporters/multiplexer.js.map +7 -0
  197. package/lib/reporters/reporterV2.js.map +7 -0
  198. package/lib/reporters/smoothdeploy.js +191 -0
  199. package/lib/reporters/teleEmitter.js +22 -4
  200. package/lib/reporters/teleEmitter.js.map +7 -0
  201. package/lib/reporters/versions/blobV1.js.map +7 -0
  202. package/lib/runner/dispatcher.js +20 -4
  203. package/lib/runner/dispatcher.js.map +7 -0
  204. package/lib/runner/failureTracker.js.map +7 -0
  205. package/lib/runner/lastRun.js.map +7 -0
  206. package/lib/runner/loadUtils.js +2 -2
  207. package/lib/runner/loadUtils.js.map +7 -0
  208. package/lib/runner/loaderHost.js.map +7 -0
  209. package/lib/runner/processHost.js +19 -0
  210. package/lib/runner/processHost.js.map +7 -0
  211. package/lib/runner/projectUtils.js +1 -1
  212. package/lib/runner/projectUtils.js.map +7 -0
  213. package/lib/runner/rebase.js.map +7 -0
  214. package/lib/runner/reporters.js +3 -1
  215. package/lib/runner/reporters.js.map +7 -0
  216. package/lib/runner/sigIntWatcher.js.map +7 -0
  217. package/lib/runner/storage.js +91 -0
  218. package/lib/runner/taskRunner.js.map +7 -0
  219. package/lib/runner/tasks.js.map +7 -0
  220. package/lib/runner/testGroups.js +14 -6
  221. package/lib/runner/testGroups.js.map +7 -0
  222. package/lib/runner/testRunner.js +13 -4
  223. package/lib/runner/testRunner.js.map +7 -0
  224. package/lib/runner/testServer.js +2 -2
  225. package/lib/runner/testServer.js.map +7 -0
  226. package/lib/runner/uiModeReporter.js.map +7 -0
  227. package/lib/runner/vcs.js.map +7 -0
  228. package/lib/runner/watchMode.js +2 -1
  229. package/lib/runner/watchMode.js.map +7 -0
  230. package/lib/runner/workerHost.js +6 -0
  231. package/lib/runner/workerHost.js.map +7 -0
  232. package/lib/third_party/pirates.js.map +7 -0
  233. package/lib/third_party/tsconfig-loader.js.map +7 -0
  234. package/lib/transform/babelBundle.js +3 -0
  235. package/lib/transform/babelBundle.js.map +7 -0
  236. package/lib/transform/babelBundleImpl.js +134 -134
  237. package/lib/transform/babelBundleImpl.js.map +7 -0
  238. package/lib/transform/compilationCache.js +2 -0
  239. package/lib/transform/compilationCache.js.map +7 -0
  240. package/lib/transform/esmLoader.js +10 -11
  241. package/lib/transform/esmLoader.js.map +7 -0
  242. package/lib/transform/md.js +221 -0
  243. package/lib/transform/portTransport.js.map +7 -0
  244. package/lib/transform/transform.js +18 -8
  245. package/lib/transform/transform.js.map +7 -0
  246. package/lib/util.js +3 -6
  247. package/lib/util.js.map +7 -0
  248. package/lib/utilsBundle.js +7 -0
  249. package/lib/utilsBundle.js.map +7 -0
  250. package/lib/utilsBundleImpl.js +51 -48
  251. package/lib/utilsBundleImpl.js.map +7 -0
  252. package/lib/worker/fixtureRunner.js +6 -2
  253. package/lib/worker/fixtureRunner.js.map +7 -0
  254. package/lib/worker/testInfo.js +39 -19
  255. package/lib/worker/testInfo.js.map +7 -0
  256. package/lib/worker/testTracing.js.map +7 -0
  257. package/lib/worker/timeoutManager.js.map +7 -0
  258. package/lib/worker/util.js.map +7 -0
  259. package/lib/worker/workerMain.js +17 -16
  260. package/lib/worker/workerMain.js.map +7 -0
  261. package/package.json +2 -2
  262. package/test.mjs +1 -0
  263. package/types/test.d.ts +26 -6
  264. package/types/testReporter.d.ts +1 -0
@@ -48,10 +48,18 @@ class Multiplexer {
48
48
  for (const reporter of this._reporters)
49
49
  wrap(() => reporter.onStdErr?.(chunk, test, result));
50
50
  }
51
+ async onTestPaused(test, result) {
52
+ for (const reporter of this._reporters)
53
+ await wrapAsync(() => reporter.onTestPaused?.(test, result));
54
+ }
51
55
  onTestEnd(test, result) {
52
56
  for (const reporter of this._reporters)
53
57
  wrap(() => reporter.onTestEnd?.(test, result));
54
58
  }
59
+ onMachineEnd(result) {
60
+ for (const reporter of this._reporters)
61
+ wrap(() => reporter.onMachineEnd?.(result));
62
+ }
55
63
  async onEnd(result) {
56
64
  for (const reporter of this._reporters) {
57
65
  const outResult = await wrapAsync(() => reporter.onEnd?.(result));
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/reporters/multiplexer.ts"],
4
+ "sourcesContent": ["/**\n * Copyright (c) Microsoft Corporation.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type { ReporterV2 } from './reporterV2';\nimport type { FullConfig, FullResult, TestCase, TestError, TestResult, TestStep } from '../../types/testReporter';\nimport type { Suite } from '../common/test';\n\nexport class Multiplexer implements ReporterV2 {\n private _reporters: ReporterV2[];\n\n constructor(reporters: ReporterV2[]) {\n this._reporters = reporters;\n }\n\n version(): 'v2' {\n return 'v2';\n }\n\n onConfigure(config: FullConfig) {\n for (const reporter of this._reporters)\n wrap(() => reporter.onConfigure?.(config));\n }\n\n onBegin(suite: Suite) {\n for (const reporter of this._reporters)\n wrap(() => reporter.onBegin?.(suite));\n }\n\n onTestBegin(test: TestCase, result: TestResult) {\n for (const reporter of this._reporters)\n wrap(() => reporter.onTestBegin?.(test, result));\n }\n\n onStdOut(chunk: string | Buffer, test?: TestCase, result?: TestResult) {\n for (const reporter of this._reporters)\n wrap(() => reporter.onStdOut?.(chunk, test, result));\n }\n\n onStdErr(chunk: string | Buffer, test?: TestCase, result?: TestResult) {\n for (const reporter of this._reporters)\n wrap(() => reporter.onStdErr?.(chunk, test, result));\n }\n\n onTestEnd(test: TestCase, result: TestResult) {\n for (const reporter of this._reporters)\n wrap(() => reporter.onTestEnd?.(test, result));\n }\n\n async onEnd(result: FullResult) {\n for (const reporter of this._reporters) {\n const outResult = await wrapAsync(() => reporter.onEnd?.(result));\n if (outResult?.status)\n result.status = outResult.status;\n }\n return result;\n }\n\n async onExit() {\n for (const reporter of this._reporters)\n await wrapAsync(() => reporter.onExit?.());\n }\n\n onError(error: TestError) {\n for (const reporter of this._reporters)\n wrap(() => reporter.onError?.(error));\n }\n\n onStepBegin(test: TestCase, result: TestResult, step: TestStep) {\n for (const reporter of this._reporters)\n wrap(() => reporter.onStepBegin?.(test, result, step));\n }\n\n onStepEnd(test: TestCase, result: TestResult, step: TestStep) {\n for (const reporter of this._reporters)\n wrap(() => reporter.onStepEnd?.(test, result, step));\n }\n\n printsToStdio(): boolean {\n return this._reporters.some(r => {\n let prints = false;\n wrap(() => prints = r.printsToStdio ? r.printsToStdio() : true);\n return prints;\n });\n }\n}\n\nasync function wrapAsync<T>(callback: () => T | Promise<T>) {\n try {\n return await callback();\n } catch (e) {\n // eslint-disable-next-line no-console\n console.error('Error in reporter', e);\n }\n}\n\nfunction wrap(callback: () => void) {\n try {\n callback();\n } catch (e) {\n // eslint-disable-next-line no-console\n console.error('Error in reporter', e);\n }\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAoBO,MAAM,YAAkC;AAAA,EAG7C,YAAY,WAAyB;AACnC,SAAK,aAAa;AAAA,EACpB;AAAA,EAEA,UAAgB;AACd,WAAO;AAAA,EACT;AAAA,EAEA,YAAY,QAAoB;AAC9B,eAAW,YAAY,KAAK;AAC1B,WAAK,MAAM,SAAS,cAAc,MAAM,CAAC;AAAA,EAC7C;AAAA,EAEA,QAAQ,OAAc;AACpB,eAAW,YAAY,KAAK;AAC1B,WAAK,MAAM,SAAS,UAAU,KAAK,CAAC;AAAA,EACxC;AAAA,EAEA,YAAY,MAAgB,QAAoB;AAC9C,eAAW,YAAY,KAAK;AAC1B,WAAK,MAAM,SAAS,cAAc,MAAM,MAAM,CAAC;AAAA,EACnD;AAAA,EAEA,SAAS,OAAwB,MAAiB,QAAqB;AACrE,eAAW,YAAY,KAAK;AAC1B,WAAK,MAAM,SAAS,WAAW,OAAO,MAAM,MAAM,CAAC;AAAA,EACvD;AAAA,EAEA,SAAS,OAAwB,MAAiB,QAAqB;AACrE,eAAW,YAAY,KAAK;AAC1B,WAAK,MAAM,SAAS,WAAW,OAAO,MAAM,MAAM,CAAC;AAAA,EACvD;AAAA,EAEA,UAAU,MAAgB,QAAoB;AAC5C,eAAW,YAAY,KAAK;AAC1B,WAAK,MAAM,SAAS,YAAY,MAAM,MAAM,CAAC;AAAA,EACjD;AAAA,EAEA,MAAM,MAAM,QAAoB;AAC9B,eAAW,YAAY,KAAK,YAAY;AACtC,YAAM,YAAY,MAAM,UAAU,MAAM,SAAS,QAAQ,MAAM,CAAC;AAChE,UAAI,WAAW;AACb,eAAO,SAAS,UAAU;AAAA,IAC9B;AACA,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,SAAS;AACb,eAAW,YAAY,KAAK;AAC1B,YAAM,UAAU,MAAM,SAAS,SAAS,CAAC;AAAA,EAC7C;AAAA,EAEA,QAAQ,OAAkB;AACxB,eAAW,YAAY,KAAK;AAC1B,WAAK,MAAM,SAAS,UAAU,KAAK,CAAC;AAAA,EACxC;AAAA,EAEA,YAAY,MAAgB,QAAoB,MAAgB;AAC9D,eAAW,YAAY,KAAK;AAC1B,WAAK,MAAM,SAAS,cAAc,MAAM,QAAQ,IAAI,CAAC;AAAA,EACzD;AAAA,EAEA,UAAU,MAAgB,QAAoB,MAAgB;AAC5D,eAAW,YAAY,KAAK;AAC1B,WAAK,MAAM,SAAS,YAAY,MAAM,QAAQ,IAAI,CAAC;AAAA,EACvD;AAAA,EAEA,gBAAyB;AACvB,WAAO,KAAK,WAAW,KAAK,OAAK;AAC/B,UAAI,SAAS;AACb,WAAK,MAAM,SAAS,EAAE,gBAAgB,EAAE,cAAc,IAAI,IAAI;AAC9D,aAAO;AAAA,IACT,CAAC;AAAA,EACH;AACF;AAEA,eAAe,UAAa,UAAgC;AAC1D,MAAI;AACF,WAAO,MAAM,SAAS;AAAA,EACxB,SAAS,GAAG;AAEV,YAAQ,MAAM,qBAAqB,CAAC;AAAA,EACtC;AACF;AAEA,SAAS,KAAK,UAAsB;AAClC,MAAI;AACF,aAAS;AAAA,EACX,SAAS,GAAG;AAEV,YAAQ,MAAM,qBAAqB,CAAC;AAAA,EACtC;AACF;",
6
+ "names": []
7
+ }
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/reporters/reporterV2.ts"],
4
+ "sourcesContent": ["/**\n * Copyright (c) Microsoft Corporation.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type { FullConfig, FullResult, Reporter, Suite, TestCase, TestError, TestResult, TestStep } from '../../types/testReporter';\n\nexport interface ReporterV2 {\n onConfigure?(config: FullConfig): void;\n onBegin?(suite: Suite): void;\n onTestBegin?(test: TestCase, result: TestResult): void;\n onStdOut?(chunk: string | Buffer, test?: TestCase, result?: TestResult): void;\n onStdErr?(chunk: string | Buffer, test?: TestCase, result?: TestResult): void;\n onTestEnd?(test: TestCase, result: TestResult): void;\n onEnd?(result: FullResult): Promise<{ status?: FullResult['status'] } | undefined | void> | void;\n onExit?(): void | Promise<void>;\n onError?(error: TestError): void;\n onStepBegin?(test: TestCase, result: TestResult, step: TestStep): void;\n onStepEnd?(test: TestCase, result: TestResult, step: TestStep): void;\n printsToStdio?(): boolean;\n version(): 'v2';\n}\n\nexport type AnyReporter = ReporterV2 | Reporter;\n\ntype StdIOChunk = {\n chunk: string | Buffer;\n test?: TestCase;\n result?: TestResult;\n};\n\nexport function wrapReporterAsV2(reporter: Reporter | ReporterV2): ReporterV2 {\n try {\n if ('version' in reporter && reporter.version() === 'v2')\n return reporter as ReporterV2;\n } catch (e) {\n }\n return new ReporterV2Wrapper(reporter as Reporter);\n}\n\nclass ReporterV2Wrapper implements ReporterV2 {\n private _reporter: Reporter;\n private _deferred: { error?: TestError, stdout?: StdIOChunk, stderr?: StdIOChunk }[] | null = [];\n private _config!: FullConfig;\n\n constructor(reporter: Reporter) {\n this._reporter = reporter;\n }\n\n version(): 'v2' {\n return 'v2';\n }\n\n onConfigure(config: FullConfig) {\n this._config = config;\n }\n\n onBegin(suite: Suite) {\n this._reporter.onBegin?.(this._config, suite);\n\n const deferred = this._deferred!;\n this._deferred = null;\n for (const item of deferred) {\n if (item.error)\n this.onError(item.error);\n if (item.stdout)\n this.onStdOut(item.stdout.chunk, item.stdout.test, item.stdout.result);\n if (item.stderr)\n this.onStdErr(item.stderr.chunk, item.stderr.test, item.stderr.result);\n }\n }\n\n onTestBegin(test: TestCase, result: TestResult) {\n this._reporter.onTestBegin?.(test, result);\n }\n\n onStdOut(chunk: string | Buffer, test?: TestCase, result?: TestResult) {\n if (this._deferred) {\n this._deferred.push({ stdout: { chunk, test, result } });\n return;\n }\n this._reporter.onStdOut?.(chunk, test, result);\n }\n\n onStdErr(chunk: string | Buffer, test?: TestCase, result?: TestResult) {\n if (this._deferred) {\n this._deferred.push({ stderr: { chunk, test, result } });\n return;\n }\n this._reporter.onStdErr?.(chunk, test, result);\n }\n\n onTestEnd(test: TestCase, result: TestResult) {\n this._reporter.onTestEnd?.(test, result);\n }\n\n async onEnd(result: FullResult) {\n return await this._reporter.onEnd?.(result);\n }\n\n async onExit() {\n await this._reporter.onExit?.();\n }\n\n onError(error: TestError) {\n if (this._deferred) {\n this._deferred.push({ error });\n return;\n }\n this._reporter.onError?.(error);\n }\n\n onStepBegin(test: TestCase, result: TestResult, step: TestStep) {\n this._reporter.onStepBegin?.(test, result, step);\n }\n\n onStepEnd(test: TestCase, result: TestResult, step: TestStep) {\n this._reporter.onStepEnd?.(test, result, step);\n }\n\n printsToStdio() {\n return this._reporter.printsToStdio ? this._reporter.printsToStdio() : true;\n }\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AA0CO,SAAS,iBAAiB,UAA6C;AAC5E,MAAI;AACF,QAAI,aAAa,YAAY,SAAS,QAAQ,MAAM;AAClD,aAAO;AAAA,EACX,SAAS,GAAG;AAAA,EACZ;AACA,SAAO,IAAI,kBAAkB,QAAoB;AACnD;AAEA,MAAM,kBAAwC;AAAA,EAK5C,YAAY,UAAoB;AAHhC,SAAQ,YAAsF,CAAC;AAI7F,SAAK,YAAY;AAAA,EACnB;AAAA,EAEA,UAAgB;AACd,WAAO;AAAA,EACT;AAAA,EAEA,YAAY,QAAoB;AAC9B,SAAK,UAAU;AAAA,EACjB;AAAA,EAEA,QAAQ,OAAc;AACpB,SAAK,UAAU,UAAU,KAAK,SAAS,KAAK;AAE5C,UAAM,WAAW,KAAK;AACtB,SAAK,YAAY;AACjB,eAAW,QAAQ,UAAU;AAC3B,UAAI,KAAK;AACP,aAAK,QAAQ,KAAK,KAAK;AACzB,UAAI,KAAK;AACP,aAAK,SAAS,KAAK,OAAO,OAAO,KAAK,OAAO,MAAM,KAAK,OAAO,MAAM;AACvE,UAAI,KAAK;AACP,aAAK,SAAS,KAAK,OAAO,OAAO,KAAK,OAAO,MAAM,KAAK,OAAO,MAAM;AAAA,IACzE;AAAA,EACF;AAAA,EAEA,YAAY,MAAgB,QAAoB;AAC9C,SAAK,UAAU,cAAc,MAAM,MAAM;AAAA,EAC3C;AAAA,EAEA,SAAS,OAAwB,MAAiB,QAAqB;AACrE,QAAI,KAAK,WAAW;AAClB,WAAK,UAAU,KAAK,EAAE,QAAQ,EAAE,OAAO,MAAM,OAAO,EAAE,CAAC;AACvD;AAAA,IACF;AACA,SAAK,UAAU,WAAW,OAAO,MAAM,MAAM;AAAA,EAC/C;AAAA,EAEA,SAAS,OAAwB,MAAiB,QAAqB;AACrE,QAAI,KAAK,WAAW;AAClB,WAAK,UAAU,KAAK,EAAE,QAAQ,EAAE,OAAO,MAAM,OAAO,EAAE,CAAC;AACvD;AAAA,IACF;AACA,SAAK,UAAU,WAAW,OAAO,MAAM,MAAM;AAAA,EAC/C;AAAA,EAEA,UAAU,MAAgB,QAAoB;AAC5C,SAAK,UAAU,YAAY,MAAM,MAAM;AAAA,EACzC;AAAA,EAEA,MAAM,MAAM,QAAoB;AAC9B,WAAO,MAAM,KAAK,UAAU,QAAQ,MAAM;AAAA,EAC5C;AAAA,EAEA,MAAM,SAAS;AACb,UAAM,KAAK,UAAU,SAAS;AAAA,EAChC;AAAA,EAEA,QAAQ,OAAkB;AACxB,QAAI,KAAK,WAAW;AAClB,WAAK,UAAU,KAAK,EAAE,MAAM,CAAC;AAC7B;AAAA,IACF;AACA,SAAK,UAAU,UAAU,KAAK;AAAA,EAChC;AAAA,EAEA,YAAY,MAAgB,QAAoB,MAAgB;AAC9D,SAAK,UAAU,cAAc,MAAM,QAAQ,IAAI;AAAA,EACjD;AAAA,EAEA,UAAU,MAAgB,QAAoB,MAAgB;AAC5D,SAAK,UAAU,YAAY,MAAM,QAAQ,IAAI;AAAA,EAC/C;AAAA,EAEA,gBAAgB;AACd,WAAO,KAAK,UAAU,gBAAgB,KAAK,UAAU,cAAc,IAAI;AAAA,EACzE;AACF;",
6
+ "names": []
7
+ }
@@ -0,0 +1,191 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+ var smoothdeploy_exports = {};
30
+ __export(smoothdeploy_exports, {
31
+ default: () => smoothdeploy_default
32
+ });
33
+ module.exports = __toCommonJS(smoothdeploy_exports);
34
+ var fs = __toESM(require("fs"));
35
+ var path = __toESM(require("path"));
36
+ class SmoothDeployReporter {
37
+ constructor() {
38
+ // Track sequential step index per test
39
+ this._stepIndices = /* @__PURE__ */ new Map();
40
+ // Map internal stepId to stepIndex for matching begin/end
41
+ this._stepIdToIndex = /* @__PURE__ */ new Map();
42
+ // Accumulate step data per test for manifest
43
+ this._testSteps = /* @__PURE__ */ new Map();
44
+ }
45
+ version() {
46
+ return "v2";
47
+ }
48
+ printsToStdio() {
49
+ return false;
50
+ }
51
+ _emit(event) {
52
+ process.stdout.write(`[SMOOTHDEPLOY_EVENT]${JSON.stringify(event)}
53
+ `);
54
+ }
55
+ // Check if this is a user-facing step (not internal browser operations)
56
+ _isUserStep(step) {
57
+ const title = step.title;
58
+ if (title === "Before Hooks" || title === "After Hooks")
59
+ return false;
60
+ if (title.startsWith('Fixture "'))
61
+ return false;
62
+ const internalSteps = [
63
+ "Launch browser",
64
+ "Launch persistent context",
65
+ "Connect over CDP",
66
+ "Close browser",
67
+ "Create context",
68
+ "Close context",
69
+ "Create page",
70
+ "Close page",
71
+ "Create CDP session"
72
+ ];
73
+ if (internalSteps.includes(title))
74
+ return false;
75
+ return true;
76
+ }
77
+ onTestBegin(test, result) {
78
+ this._stepIndices.set(test.id, 0);
79
+ this._emit({
80
+ event: "testBegin",
81
+ testId: test.id,
82
+ testTitle: test.title,
83
+ timestamp: Date.now()
84
+ });
85
+ }
86
+ onTestEnd(test, result) {
87
+ this._stepIndices.delete(test.id);
88
+ this._emit({
89
+ event: "testEnd",
90
+ testId: test.id,
91
+ testTitle: test.title,
92
+ status: result.status,
93
+ duration: result.duration,
94
+ timestamp: Date.now()
95
+ });
96
+ }
97
+ onEnd(result) {
98
+ const manifest = {};
99
+ for (const [testId, steps] of this._testSteps) {
100
+ manifest[testId] = { steps };
101
+ }
102
+ const outputDir = path.join(process.cwd(), "_internal_output");
103
+ fs.mkdirSync(outputDir, { recursive: true });
104
+ fs.writeFileSync(
105
+ path.join(outputDir, "manifest.json"),
106
+ JSON.stringify(manifest, null, 2)
107
+ );
108
+ this._emit({
109
+ event: "runEnd",
110
+ status: result.status,
111
+ timestamp: Date.now()
112
+ });
113
+ }
114
+ onStepBegin(test, result, step) {
115
+ if (!this._isUserStep(step))
116
+ return;
117
+ const internalStepId = step._stepId ?? step.title;
118
+ const stepIndex = this._stepIndices.get(test.id) ?? 0;
119
+ this._stepIndices.set(test.id, stepIndex + 1);
120
+ this._stepIdToIndex.set(`${test.id}:${internalStepId}`, stepIndex);
121
+ this._emit({
122
+ event: "stepBegin",
123
+ testId: test.id,
124
+ testTitle: test.title,
125
+ stepIndex,
126
+ stepId: internalStepId,
127
+ title: step.title,
128
+ category: step.category,
129
+ timestamp: Date.now()
130
+ });
131
+ }
132
+ onStepEnd(test, result, step) {
133
+ if (!this._isUserStep(step))
134
+ return;
135
+ const internalStepId = step._stepId ?? step.title;
136
+ const mapKey = `${test.id}:${internalStepId}`;
137
+ const stepIndex = this._stepIdToIndex.get(mapKey);
138
+ if (stepIndex === void 0)
139
+ return;
140
+ this._stepIdToIndex.delete(mapKey);
141
+ const safeTestId = test.id.replace(/[^a-zA-Z0-9_-]/g, "-");
142
+ const noScreenshotPrefixes = [
143
+ "Navigate",
144
+ // page.goto
145
+ "Expect",
146
+ // assertions
147
+ "Go back",
148
+ // page.goBack
149
+ "Go forward",
150
+ // page.goForward
151
+ "Reload",
152
+ // page.reload
153
+ "Screenshot",
154
+ // page.screenshot
155
+ "Wait for",
156
+ // waitFor* events
157
+ "Pause",
158
+ // pause
159
+ "Evaluate"
160
+ // page.evaluate
161
+ ];
162
+ const hasScreenshot = step.category === "pw:api" && !noScreenshotPrefixes.some((prefix) => step.title.startsWith(prefix));
163
+ const safeStepId = internalStepId.replace(/[^a-zA-Z0-9_-]/g, "-");
164
+ const screenshots = hasScreenshot ? {
165
+ page: `_internal_output/screenshots/${safeTestId}/${safeStepId}-page.png`,
166
+ element: `_internal_output/screenshots/${safeTestId}/${safeStepId}-element.png`
167
+ } : null;
168
+ const steps = this._testSteps.get(test.id) || [];
169
+ steps.push({
170
+ stepIndex,
171
+ stepId: internalStepId,
172
+ title: step.title,
173
+ category: step.category,
174
+ duration: step.duration,
175
+ error: step.error ? { message: step.error.message } : null,
176
+ screenshots
177
+ });
178
+ this._testSteps.set(test.id, steps);
179
+ this._emit({
180
+ event: "stepEnd",
181
+ testId: test.id,
182
+ stepIndex,
183
+ stepId: internalStepId,
184
+ title: step.title,
185
+ duration: step.duration,
186
+ error: step.error ? { message: step.error.message } : null,
187
+ timestamp: Date.now()
188
+ });
189
+ }
190
+ }
191
+ var smoothdeploy_default = SmoothDeployReporter;
@@ -37,7 +37,8 @@ var import_teleReceiver = require("../isomorphic/teleReceiver");
37
37
  class TeleReporterEmitter {
38
38
  constructor(messageSink, options = {}) {
39
39
  this._resultKnownAttachmentCounts = /* @__PURE__ */ new Map();
40
- // In case there is blob reporter and UI mode, make sure one does override
40
+ this._resultKnownErrorCounts = /* @__PURE__ */ new Map();
41
+ // In case there is blob reporter and UI mode, make sure one doesn't override
41
42
  // the id assigned by the other.
42
43
  this._idSymbol = Symbol("id");
43
44
  this._messageSink = messageSink;
@@ -66,6 +67,20 @@ class TeleReporterEmitter {
66
67
  }
67
68
  });
68
69
  }
70
+ async onTestPaused(test, result) {
71
+ const resultId = result[this._idSymbol];
72
+ this._resultKnownErrorCounts.set(resultId, result.errors.length);
73
+ this._messageSink({
74
+ method: "onTestPaused",
75
+ params: {
76
+ testId: test.id,
77
+ resultId,
78
+ errors: result.errors
79
+ }
80
+ });
81
+ await new Promise(() => {
82
+ });
83
+ }
69
84
  onTestEnd(test, result) {
70
85
  const testEnd = {
71
86
  testId: test.id,
@@ -81,7 +96,9 @@ class TeleReporterEmitter {
81
96
  result: this._serializeResultEnd(result)
82
97
  }
83
98
  });
84
- this._resultKnownAttachmentCounts.delete(result[this._idSymbol]);
99
+ const resultId = result[this._idSymbol];
100
+ this._resultKnownAttachmentCounts.delete(resultId);
101
+ this._resultKnownErrorCounts.delete(resultId);
85
102
  }
86
103
  onStepBegin(test, result, step) {
87
104
  step[this._idSymbol] = (0, import_utils.createGuid)();
@@ -221,11 +238,12 @@ class TeleReporterEmitter {
221
238
  };
222
239
  }
223
240
  _serializeResultEnd(result) {
241
+ const id = result[this._idSymbol];
224
242
  return {
225
- id: result[this._idSymbol],
243
+ id,
226
244
  duration: result.duration,
227
245
  status: result.status,
228
- errors: result.errors,
246
+ errors: this._resultKnownErrorCounts.has(id) ? result.errors.slice(this._resultKnownAttachmentCounts.get(id)) : result.errors,
229
247
  annotations: result.annotations?.length ? this._relativeAnnotationLocations(result.annotations) : void 0
230
248
  };
231
249
  }
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/reporters/teleEmitter.ts"],
4
+ "sourcesContent": ["/**\n * Copyright (c) Microsoft Corporation.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport path from 'path';\n\nimport { createGuid } from 'playwright-core/lib/utils';\n\nimport { serializeRegexPatterns } from '../isomorphic/teleReceiver';\n\nimport type { ReporterV2 } from './reporterV2';\nimport type * as reporterTypes from '../../types/testReporter';\nimport type { TestAnnotation } from '../../types/test';\nimport type * as teleReceiver from '../isomorphic/teleReceiver';\n\nexport type TeleReporterEmitterOptions = {\n omitOutput?: boolean;\n omitBuffers?: boolean;\n};\n\nexport class TeleReporterEmitter implements ReporterV2 {\n private _messageSink: (message: teleReceiver.JsonEvent) => void;\n private _rootDir!: string;\n private _emitterOptions: TeleReporterEmitterOptions;\n private _resultKnownAttachmentCounts = new Map<string, number>();\n // In case there is blob reporter and UI mode, make sure one does override\n // the id assigned by the other.\n private readonly _idSymbol = Symbol('id');\n\n constructor(messageSink: (message: teleReceiver.JsonEvent) => void, options: TeleReporterEmitterOptions = {}) {\n this._messageSink = messageSink;\n this._emitterOptions = options;\n }\n\n version(): 'v2' {\n return 'v2';\n }\n\n onConfigure(config: reporterTypes.FullConfig) {\n this._rootDir = config.rootDir;\n this._messageSink({ method: 'onConfigure', params: { config: this._serializeConfig(config) } });\n }\n\n onBegin(suite: reporterTypes.Suite) {\n const projects = suite.suites.map(projectSuite => this._serializeProject(projectSuite));\n for (const project of projects)\n this._messageSink({ method: 'onProject', params: { project } });\n this._messageSink({ method: 'onBegin', params: undefined });\n }\n\n onTestBegin(test: reporterTypes.TestCase, result: reporterTypes.TestResult): void {\n (result as any)[this._idSymbol] = createGuid();\n this._messageSink({\n method: 'onTestBegin',\n params: {\n testId: test.id,\n result: this._serializeResultStart(result)\n }\n });\n }\n\n onTestEnd(test: reporterTypes.TestCase, result: reporterTypes.TestResult): void {\n const testEnd: teleReceiver.JsonTestEnd = {\n testId: test.id,\n expectedStatus: test.expectedStatus,\n timeout: test.timeout,\n annotations: []\n };\n this._sendNewAttachments(result, test.id);\n this._messageSink({\n method: 'onTestEnd',\n params: {\n test: testEnd,\n result: this._serializeResultEnd(result),\n }\n });\n\n this._resultKnownAttachmentCounts.delete((result as any)[this._idSymbol]);\n }\n\n onStepBegin(test: reporterTypes.TestCase, result: reporterTypes.TestResult, step: reporterTypes.TestStep): void {\n (step as any)[this._idSymbol] = createGuid();\n this._messageSink({\n method: 'onStepBegin',\n params: {\n testId: test.id,\n resultId: (result as any)[this._idSymbol],\n step: this._serializeStepStart(step)\n }\n });\n }\n\n onStepEnd(test: reporterTypes.TestCase, result: reporterTypes.TestResult, step: reporterTypes.TestStep): void {\n // Create synthetic onAttach event so we serialize the entire attachment along with the step\n const resultId = (result as any)[this._idSymbol] as string;\n this._sendNewAttachments(result, test.id);\n\n this._messageSink({\n method: 'onStepEnd',\n params: {\n testId: test.id,\n resultId,\n step: this._serializeStepEnd(step, result)\n }\n });\n }\n\n onError(error: reporterTypes.TestError): void {\n this._messageSink({\n method: 'onError',\n params: { error }\n });\n }\n\n onStdOut(chunk: string | Buffer, test?: reporterTypes.TestCase, result?: reporterTypes.TestResult): void {\n this._onStdIO('stdout', chunk, test, result);\n }\n\n onStdErr(chunk: string | Buffer, test?: reporterTypes.TestCase, result?: reporterTypes.TestResult): void {\n this._onStdIO('stderr', chunk, test, result);\n }\n\n private _onStdIO(type: teleReceiver.JsonStdIOType, chunk: string | Buffer, test: void | reporterTypes.TestCase, result: void | reporterTypes.TestResult): void {\n if (this._emitterOptions.omitOutput)\n return;\n const isBase64 = typeof chunk !== 'string';\n const data = isBase64 ? chunk.toString('base64') : chunk;\n this._messageSink({\n method: 'onStdIO',\n params: { testId: test?.id, resultId: result ? (result as any)[this._idSymbol] : undefined, type, data, isBase64 }\n });\n }\n\n async onEnd(result: reporterTypes.FullResult) {\n const resultPayload: teleReceiver.JsonFullResult = {\n status: result.status,\n startTime: result.startTime.getTime(),\n duration: result.duration,\n };\n this._messageSink({\n method: 'onEnd',\n params: {\n result: resultPayload\n }\n });\n }\n\n printsToStdio() {\n return false;\n }\n\n private _serializeConfig(config: reporterTypes.FullConfig): teleReceiver.JsonConfig {\n return {\n configFile: this._relativePath(config.configFile),\n globalTimeout: config.globalTimeout,\n maxFailures: config.maxFailures,\n metadata: config.metadata,\n rootDir: config.rootDir,\n version: config.version,\n workers: config.workers,\n globalSetup: config.globalSetup,\n globalTeardown: config.globalTeardown,\n tags: config.tags,\n webServer: config.webServer,\n };\n }\n\n private _serializeProject(suite: reporterTypes.Suite): teleReceiver.JsonProject {\n const project = suite.project()!;\n const report: teleReceiver.JsonProject = {\n metadata: project.metadata,\n name: project.name,\n outputDir: this._relativePath(project.outputDir),\n repeatEach: project.repeatEach,\n retries: project.retries,\n testDir: this._relativePath(project.testDir),\n testIgnore: serializeRegexPatterns(project.testIgnore),\n testMatch: serializeRegexPatterns(project.testMatch),\n timeout: project.timeout,\n suites: suite.suites.map(fileSuite => {\n return this._serializeSuite(fileSuite);\n }),\n grep: serializeRegexPatterns(project.grep),\n grepInvert: serializeRegexPatterns(project.grepInvert || []),\n dependencies: project.dependencies,\n snapshotDir: this._relativePath(project.snapshotDir),\n teardown: project.teardown,\n use: this._serializeProjectUseOptions(project.use),\n };\n return report;\n }\n\n private _serializeProjectUseOptions(use: reporterTypes.FullProject['use']): Record<string, any> {\n return {\n testIdAttribute: use.testIdAttribute,\n };\n }\n\n private _serializeSuite(suite: reporterTypes.Suite): teleReceiver.JsonSuite {\n const result = {\n title: suite.title,\n location: this._relativeLocation(suite.location),\n entries: suite.entries().map(e => {\n if (e.type === 'test')\n return this._serializeTest(e);\n return this._serializeSuite(e);\n })\n };\n return result;\n }\n\n private _serializeTest(test: reporterTypes.TestCase): teleReceiver.JsonTestCase {\n return {\n testId: test.id,\n title: test.title,\n location: this._relativeLocation(test.location),\n retries: test.retries,\n tags: test.tags,\n repeatEachIndex: test.repeatEachIndex,\n annotations: this._relativeAnnotationLocations(test.annotations),\n };\n }\n\n private _serializeResultStart(result: reporterTypes.TestResult): teleReceiver.JsonTestResultStart {\n return {\n id: (result as any)[this._idSymbol],\n retry: result.retry,\n workerIndex: result.workerIndex,\n parallelIndex: result.parallelIndex,\n startTime: +result.startTime,\n };\n }\n\n private _serializeResultEnd(result: reporterTypes.TestResult): teleReceiver.JsonTestResultEnd {\n return {\n id: (result as any)[this._idSymbol],\n duration: result.duration,\n status: result.status,\n errors: result.errors,\n annotations: result.annotations?.length ? this._relativeAnnotationLocations(result.annotations) : undefined,\n };\n }\n\n private _sendNewAttachments(result: reporterTypes.TestResult, testId: string) {\n const resultId = (result as any)[this._idSymbol] as string;\n // Track whether this step (or something else since the last step) has added attachments and send them\n const knownAttachmentCount = this._resultKnownAttachmentCounts.get(resultId) ?? 0;\n if (result.attachments.length > knownAttachmentCount) {\n this._messageSink({\n method: 'onAttach',\n params: {\n testId,\n resultId,\n attachments: this._serializeAttachments((result.attachments.slice(knownAttachmentCount))),\n }\n });\n }\n\n this._resultKnownAttachmentCounts.set(resultId, result.attachments.length);\n }\n\n _serializeAttachments(attachments: reporterTypes.TestResult['attachments']): teleReceiver.JsonAttachment[] {\n return attachments.map(a => {\n const { body, ...rest } = a;\n return {\n ...rest,\n // There is no Buffer in the browser, so there is no point in sending the data there.\n base64: (body && !this._emitterOptions.omitBuffers) ? body.toString('base64') : undefined,\n };\n });\n }\n\n private _serializeStepStart(step: reporterTypes.TestStep): teleReceiver.JsonTestStepStart {\n return {\n id: (step as any)[this._idSymbol],\n parentStepId: (step.parent as any)?.[this._idSymbol],\n title: step.title,\n category: step.category,\n startTime: +step.startTime,\n location: this._relativeLocation(step.location),\n };\n }\n\n private _serializeStepEnd(step: reporterTypes.TestStep, result: reporterTypes.TestResult): teleReceiver.JsonTestStepEnd {\n return {\n id: (step as any)[this._idSymbol],\n duration: step.duration,\n error: step.error,\n attachments: step.attachments.length ? step.attachments.map(a => result.attachments.indexOf(a)) : undefined,\n annotations: step.annotations.length ? this._relativeAnnotationLocations(step.annotations) : undefined,\n };\n }\n\n private _relativeAnnotationLocations(annotations: TestAnnotation[]): TestAnnotation[] {\n return annotations.map(annotation => ({\n ...annotation,\n location: annotation.location ? this._relativeLocation(annotation.location) : undefined,\n }));\n }\n\n private _relativeLocation(location: reporterTypes.Location): reporterTypes.Location;\n private _relativeLocation(location?: reporterTypes.Location): reporterTypes.Location | undefined;\n private _relativeLocation(location: reporterTypes.Location | undefined): reporterTypes.Location | undefined {\n if (!location)\n return location;\n return {\n ...location,\n file: this._relativePath(location.file),\n };\n }\n\n private _relativePath(absolutePath: string): string;\n private _relativePath(absolutePath?: string): string | undefined;\n private _relativePath(absolutePath?: string): string | undefined {\n if (!absolutePath)\n return absolutePath;\n return path.relative(this._rootDir, absolutePath);\n }\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["path"]
7
+ }
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/reporters/versions/blobV1.ts"],
4
+ "sourcesContent": ["/**\n * Copyright (c) Microsoft Corporation.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type { Metadata } from '../../../types/test';\nimport type * as reporterTypes from '../../../types/testReporter';\n\nexport type JsonLocation = reporterTypes.Location;\nexport type JsonError = string;\nexport type JsonStackFrame = { file: string, line: number, column: number };\n\nexport type JsonStdIOType = 'stdout' | 'stderr';\n\nexport type JsonConfig = Pick<reporterTypes.FullConfig, 'configFile' | 'globalTimeout' | 'maxFailures' | 'metadata' | 'rootDir' | 'version' | 'workers'>;\n\nexport type JsonPattern = {\n s?: string;\n r?: { source: string, flags: string };\n};\n\nexport type JsonProject = {\n grep: JsonPattern[];\n grepInvert: JsonPattern[];\n metadata: Metadata;\n name: string;\n dependencies: string[];\n // This is relative to root dir.\n snapshotDir: string;\n // This is relative to root dir.\n outputDir: string;\n repeatEach: number;\n retries: number;\n suites: JsonSuite[];\n teardown?: string;\n // This is relative to root dir.\n testDir: string;\n testIgnore: JsonPattern[];\n testMatch: JsonPattern[];\n timeout: number;\n};\n\nexport type JsonSuite = {\n title: string;\n location?: JsonLocation;\n suites: JsonSuite[];\n tests: JsonTestCase[];\n};\n\nexport type JsonTestCase = {\n testId: string;\n title: string;\n location: JsonLocation;\n retries: number;\n tags?: string[];\n repeatEachIndex: number;\n};\n\nexport type JsonTestEnd = {\n testId: string;\n expectedStatus: reporterTypes.TestStatus;\n timeout: number;\n annotations: { type: string, description?: string }[];\n};\n\nexport type JsonTestResultStart = {\n id: string;\n retry: number;\n workerIndex: number;\n parallelIndex: number;\n startTime: number;\n};\n\nexport type JsonAttachment = Omit<reporterTypes.TestResult['attachments'][0], 'body'> & { base64?: string };\n\nexport type JsonTestResultEnd = {\n id: string;\n duration: number;\n status: reporterTypes.TestStatus;\n errors: reporterTypes.TestError[];\n attachments: JsonAttachment[];\n};\n\nexport type JsonTestStepStart = {\n id: string;\n parentStepId?: string;\n title: string;\n category: string,\n startTime: number;\n location?: reporterTypes.Location;\n};\n\nexport type JsonTestStepEnd = {\n id: string;\n duration: number;\n error?: reporterTypes.TestError;\n};\n\nexport type JsonFullResult = {\n status: reporterTypes.FullResult['status'];\n startTime: number;\n duration: number;\n};\n\nexport type JsonEvent = {\n method: string;\n params: any\n};\n\nexport type BlobReportMetadata = {\n version: number;\n userAgent: string;\n name?: string;\n shard?: { total: number, current: number };\n pathSeparator?: string;\n};\n"],
5
+ "mappings": ";;;;;;;;;;;;;;AAAA;AAAA;",
6
+ "names": []
7
+ }
@@ -28,6 +28,7 @@ var import_workerHost = require("./workerHost");
28
28
  var import_ipc = require("../common/ipc");
29
29
  var import_internalReporter = require("../reporters/internalReporter");
30
30
  var import_util = require("../util");
31
+ var import_storage = require("./storage");
31
32
  class Dispatcher {
32
33
  constructor(config, reporter, failureTracker) {
33
34
  this._workerSlots = [];
@@ -197,6 +198,12 @@ class Dispatcher {
197
198
  const producedEnv = this._producedEnvByProjectId.get(testGroup.projectId) || {};
198
199
  this._producedEnvByProjectId.set(testGroup.projectId, { ...producedEnv, ...worker.producedEnv() });
199
200
  });
201
+ worker.onRequest("cloneStorage", async (params) => {
202
+ return await import_storage.Storage.clone(params.storageFile, outputDir);
203
+ });
204
+ worker.onRequest("upstreamStorage", async (params) => {
205
+ await import_storage.Storage.upstream(params.storageFile, params.storageOutFile);
206
+ });
200
207
  return worker;
201
208
  }
202
209
  producedEnvByProjectId() {
@@ -295,7 +302,8 @@ class JobDispatcher {
295
302
  steps: [],
296
303
  attachments: [],
297
304
  annotations: [],
298
- location: params.location
305
+ location: params.location,
306
+ _stepId: params.stepId
299
307
  };
300
308
  steps.set(params.stepId, step);
301
309
  (parentStep || result).steps.push(step);
@@ -458,11 +466,15 @@ class JobDispatcher {
458
466
  ];
459
467
  }
460
468
  _onTestPaused(worker, params) {
469
+ const data = this._dataByTestId.get(params.testId);
470
+ if (!data)
471
+ return;
472
+ const { result, test } = data;
461
473
  const sendMessage = async (message) => {
462
474
  try {
463
475
  if (this.jobResult.isDone())
464
476
  throw new Error("Test has already stopped");
465
- const response = await worker.sendCustomMessage({ testId: params.testId, request: message.request });
477
+ const response = await worker.sendCustomMessage({ testId: test.id, request: message.request });
466
478
  if (response.error)
467
479
  (0, import_internalReporter.addLocationAndSnippetToError)(this._config.config, response.error);
468
480
  return response;
@@ -472,8 +484,12 @@ class JobDispatcher {
472
484
  return { response: void 0, error };
473
485
  }
474
486
  };
475
- for (const error of params.errors)
476
- (0, import_internalReporter.addLocationAndSnippetToError)(this._config.config, error);
487
+ result.status = params.status;
488
+ result.errors = params.errors;
489
+ result.error = result.errors[0];
490
+ void this._reporter.onTestPaused?.(test, result).then(() => {
491
+ worker.sendResume({});
492
+ });
477
493
  this._failureTracker.onTestPaused?.({ ...params, sendMessage });
478
494
  }
479
495
  skipWholeJob() {
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/runner/dispatcher.ts"],
4
+ "sourcesContent": ["/**\n * Copyright Microsoft Corporation. All rights reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { ManualPromise, eventsHelper } from 'playwright-core/lib/utils';\nimport { colors } from 'playwright-core/lib/utils';\n\nimport { addSuggestedRebaseline } from './rebase';\nimport { WorkerHost } from './workerHost';\nimport { serializeConfig } from '../common/ipc';\nimport { addLocationAndSnippetToError } from '../reporters/internalReporter';\nimport { serializeError } from '../util';\n\nimport type { FailureTracker } from './failureTracker';\nimport type { ProcessExitData } from './processHost';\nimport type { TestGroup } from './testGroups';\nimport type { TestError, TestResult, TestStep } from '../../types/testReporter';\nimport type { FullConfigInternal } from '../common/config';\nimport type { AttachmentPayload, DonePayload, RunPayload, SerializedConfig, StepBeginPayload, StepEndPayload, TeardownErrorsPayload, TestBeginPayload, TestEndPayload, TestOutputPayload, TestPausedPayload } from '../common/ipc';\nimport type { Suite } from '../common/test';\nimport type { TestCase } from '../common/test';\nimport type { ReporterV2 } from '../reporters/reporterV2';\nimport type { RegisteredListener } from 'playwright-core/lib/utils';\n\n\nexport type EnvByProjectId = Map<string, Record<string, string | undefined>>;\n\nexport class Dispatcher {\n private _workerSlots: { busy: boolean, worker?: WorkerHost, jobDispatcher?: JobDispatcher }[] = [];\n private _queue: TestGroup[] = [];\n private _workerLimitPerProjectId = new Map<string, number>();\n private _queuedOrRunningHashCount = new Map<string, number>();\n private _finished = new ManualPromise<void>();\n private _isStopped = true;\n\n private _config: FullConfigInternal;\n private _reporter: ReporterV2;\n private _failureTracker: FailureTracker;\n\n private _extraEnvByProjectId: EnvByProjectId = new Map();\n private _producedEnvByProjectId: EnvByProjectId = new Map();\n\n constructor(config: FullConfigInternal, reporter: ReporterV2, failureTracker: FailureTracker) {\n this._config = config;\n this._reporter = reporter;\n this._failureTracker = failureTracker;\n for (const project of config.projects) {\n if (project.workers)\n this._workerLimitPerProjectId.set(project.id, project.workers);\n }\n }\n\n private _findFirstJobToRun() {\n // Always pick the first job that can be run while respecting the project worker limit.\n for (let index = 0; index < this._queue.length; index++) {\n const job = this._queue[index];\n const projectIdWorkerLimit = this._workerLimitPerProjectId.get(job.projectId);\n if (!projectIdWorkerLimit)\n return index;\n const runningWorkersWithSameProjectId = this._workerSlots.filter(w => w.busy && w.worker && w.worker.projectId() === job.projectId).length;\n if (runningWorkersWithSameProjectId < projectIdWorkerLimit)\n return index;\n }\n return -1;\n }\n\n private _scheduleJob() {\n // NOTE: keep this method synchronous for easier reasoning.\n\n // 0. No more running jobs after stop.\n if (this._isStopped)\n return;\n\n // 1. Find a job to run.\n const jobIndex = this._findFirstJobToRun();\n if (jobIndex === -1)\n return;\n const job = this._queue[jobIndex];\n\n // 2. Find a worker with the same hash, or just some free worker.\n let workerIndex = this._workerSlots.findIndex(w => !w.busy && w.worker && w.worker.hash() === job.workerHash && !w.worker.didSendStop());\n if (workerIndex === -1)\n workerIndex = this._workerSlots.findIndex(w => !w.busy);\n if (workerIndex === -1) {\n // No workers available, bail out.\n return;\n }\n\n // 3. Claim both the job and the worker slot.\n this._queue.splice(jobIndex, 1);\n const jobDispatcher = new JobDispatcher(job, this._config, this._reporter, this._failureTracker, () => this.stop().catch(() => {}));\n this._workerSlots[workerIndex].busy = true;\n this._workerSlots[workerIndex].jobDispatcher = jobDispatcher;\n\n // 4. Run the job. This is the only async operation.\n void this._runJobInWorker(workerIndex, jobDispatcher).then(() => {\n\n // 5. Release the worker slot.\n this._workerSlots[workerIndex].jobDispatcher = undefined;\n this._workerSlots[workerIndex].busy = false;\n\n // 6. Check whether we are done or should schedule another job.\n this._checkFinished();\n this._scheduleJob();\n });\n }\n\n private async _runJobInWorker(index: number, jobDispatcher: JobDispatcher) {\n const job = jobDispatcher.job;\n\n // 0. Perhaps skip the whole job?\n if (jobDispatcher.skipWholeJob())\n return;\n\n let worker = this._workerSlots[index].worker;\n\n // 1. Restart the worker if it has the wrong hash or is being stopped already.\n if (worker && (worker.hash() !== job.workerHash || worker.didSendStop())) {\n await worker.stop();\n worker = undefined;\n if (this._isStopped) // Check stopped signal after async hop.\n return;\n }\n\n // 2. Start the worker if it is down.\n let startError;\n if (!worker) {\n worker = this._createWorker(job, index, serializeConfig(this._config, true));\n this._workerSlots[index].worker = worker;\n worker.on('exit', () => this._workerSlots[index].worker = undefined);\n startError = await worker.start();\n if (this._isStopped) // Check stopped signal after async hop.\n return;\n }\n\n // 3. Finally, run some tests in the worker! Or fail all of them because of startup error...\n if (startError)\n jobDispatcher.onExit(startError);\n else\n jobDispatcher.runInWorker(worker);\n const result = await jobDispatcher.jobResult;\n this._updateCounterForWorkerHash(job.workerHash, -1);\n\n // 4. When worker encounters error, we stop it and create a new one.\n // We also do not keep the worker alive if it cannot serve any more jobs.\n if (result.didFail)\n void worker.stop(true /* didFail */);\n else if (this._isWorkerRedundant(worker))\n void worker.stop();\n\n // 5. Possibly queue a new job with leftover tests and/or retries.\n if (!this._isStopped && result.newJob) {\n this._queue.unshift(result.newJob);\n this._updateCounterForWorkerHash(result.newJob.workerHash, +1);\n }\n }\n\n private _checkFinished() {\n if (this._finished.isDone())\n return;\n\n // Check that we have no more work to do.\n if (this._queue.length && !this._isStopped)\n return;\n\n // Make sure all workers have finished the current job.\n if (this._workerSlots.some(w => w.busy))\n return;\n\n this._finished.resolve();\n }\n\n private _isWorkerRedundant(worker: WorkerHost) {\n let workersWithSameHash = 0;\n for (const slot of this._workerSlots) {\n if (slot.worker && !slot.worker.didSendStop() && slot.worker.hash() === worker.hash())\n workersWithSameHash++;\n }\n return workersWithSameHash > this._queuedOrRunningHashCount.get(worker.hash())!;\n }\n\n private _updateCounterForWorkerHash(hash: string, delta: number) {\n this._queuedOrRunningHashCount.set(hash, delta + (this._queuedOrRunningHashCount.get(hash) || 0));\n }\n\n async run(testGroups: TestGroup[], extraEnvByProjectId: EnvByProjectId) {\n this._extraEnvByProjectId = extraEnvByProjectId;\n this._queue = testGroups;\n for (const group of testGroups)\n this._updateCounterForWorkerHash(group.workerHash, +1);\n this._isStopped = false;\n this._workerSlots = [];\n // 0. Stop right away if we have reached max failures.\n if (this._failureTracker.hasReachedMaxFailures())\n void this.stop();\n // 1. Allocate workers.\n for (let i = 0; i < this._config.config.workers; i++)\n this._workerSlots.push({ busy: false });\n // 2. Schedule enough jobs.\n for (let i = 0; i < this._workerSlots.length; i++)\n this._scheduleJob();\n this._checkFinished();\n // 3. More jobs are scheduled when the worker becomes free.\n // 4. Wait for all jobs to finish.\n await this._finished;\n }\n\n _createWorker(testGroup: TestGroup, parallelIndex: number, loaderData: SerializedConfig) {\n const projectConfig = this._config.projects.find(p => p.id === testGroup.projectId)!;\n const outputDir = projectConfig.project.outputDir;\n const worker = new WorkerHost(testGroup, {\n parallelIndex,\n config: loaderData,\n extraEnv: this._extraEnvByProjectId.get(testGroup.projectId) || {},\n outputDir,\n pauseOnError: this._failureTracker.pauseOnError(),\n pauseAtEnd: this._failureTracker.pauseAtEnd(projectConfig),\n });\n const handleOutput = (params: TestOutputPayload) => {\n const chunk = chunkFromParams(params);\n if (worker.didFail()) {\n // Note: we keep reading stdio from workers that are currently stopping after failure,\n // to debug teardown issues. However, we avoid spoiling the test result from\n // the next retry.\n return { chunk };\n }\n const currentlyRunning = this._workerSlots[parallelIndex].jobDispatcher?.currentlyRunning();\n if (!currentlyRunning)\n return { chunk };\n return { chunk, test: currentlyRunning.test, result: currentlyRunning.result };\n };\n worker.on('stdOut', (params: TestOutputPayload) => {\n const { chunk, test, result } = handleOutput(params);\n result?.stdout.push(chunk);\n this._reporter.onStdOut?.(chunk, test, result);\n });\n worker.on('stdErr', (params: TestOutputPayload) => {\n const { chunk, test, result } = handleOutput(params);\n result?.stderr.push(chunk);\n this._reporter.onStdErr?.(chunk, test, result);\n });\n worker.on('teardownErrors', (params: TeardownErrorsPayload) => {\n this._failureTracker.onWorkerError();\n for (const error of params.fatalErrors)\n this._reporter.onError?.(error);\n });\n worker.on('exit', () => {\n const producedEnv = this._producedEnvByProjectId.get(testGroup.projectId) || {};\n this._producedEnvByProjectId.set(testGroup.projectId, { ...producedEnv, ...worker.producedEnv() });\n });\n return worker;\n }\n\n producedEnvByProjectId() {\n return this._producedEnvByProjectId;\n }\n\n async stop() {\n if (this._isStopped)\n return;\n this._isStopped = true;\n await Promise.all(this._workerSlots.map(({ worker }) => worker?.stop()));\n this._checkFinished();\n }\n}\n\nclass JobDispatcher {\n jobResult = new ManualPromise<{ newJob?: TestGroup, didFail: boolean }>();\n\n readonly job: TestGroup;\n private _config: FullConfigInternal;\n private _reporter: ReporterV2;\n private _failureTracker: FailureTracker;\n private _stopCallback: () => void;\n private _listeners: RegisteredListener[] = [];\n private _failedTests = new Set<TestCase>();\n private _failedWithNonRetriableError = new Set<TestCase|Suite>();\n private _remainingByTestId = new Map<string, TestCase>();\n private _dataByTestId = new Map<string, { test: TestCase, result: TestResult, steps: Map<string, TestStep> }>();\n private _parallelIndex = 0;\n private _workerIndex = 0;\n private _currentlyRunning: { test: TestCase, result: TestResult } | undefined;\n\n constructor(job: TestGroup, config: FullConfigInternal, reporter: ReporterV2, failureTracker: FailureTracker, stopCallback: () => void) {\n this.job = job;\n this._config = config;\n this._reporter = reporter;\n this._failureTracker = failureTracker;\n this._stopCallback = stopCallback;\n this._remainingByTestId = new Map(this.job.tests.map(e => [e.id, e]));\n }\n\n private _onTestBegin(params: TestBeginPayload) {\n const test = this._remainingByTestId.get(params.testId);\n if (!test) {\n // TODO: this should never be the case, report an internal error?\n return;\n }\n const result = test._appendTestResult();\n this._dataByTestId.set(test.id, { test, result, steps: new Map() });\n result.parallelIndex = this._parallelIndex;\n result.workerIndex = this._workerIndex;\n result.startTime = new Date(params.startWallTime);\n this._reporter.onTestBegin?.(test, result);\n this._currentlyRunning = { test, result };\n }\n\n private _onTestEnd(params: TestEndPayload) {\n if (this._failureTracker.hasReachedMaxFailures()) {\n // Do not show more than one error to avoid confusion, but report\n // as interrupted to indicate that we did actually start the test.\n params.status = 'interrupted';\n params.errors = [];\n }\n const data = this._dataByTestId.get(params.testId);\n if (!data) {\n // TODO: this should never be the case, report an internal error?\n return;\n }\n this._dataByTestId.delete(params.testId);\n this._remainingByTestId.delete(params.testId);\n const { result, test } = data;\n result.duration = params.duration;\n result.errors = params.errors;\n result.error = result.errors[0];\n result.status = params.status;\n result.annotations = params.annotations;\n test.annotations = [...params.annotations]; // last test result wins\n test.expectedStatus = params.expectedStatus;\n test.timeout = params.timeout;\n const isFailure = result.status !== 'skipped' && result.status !== test.expectedStatus;\n if (isFailure)\n this._failedTests.add(test);\n if (params.hasNonRetriableError)\n this._addNonretriableTestAndSerialModeParents(test);\n this._reportTestEnd(test, result);\n this._currentlyRunning = undefined;\n }\n\n private _addNonretriableTestAndSerialModeParents(test: TestCase) {\n this._failedWithNonRetriableError.add(test);\n for (let parent: Suite | undefined = test.parent; parent; parent = parent.parent) {\n if (parent._parallelMode === 'serial')\n this._failedWithNonRetriableError.add(parent);\n }\n }\n\n private _onStepBegin(params: StepBeginPayload) {\n const data = this._dataByTestId.get(params.testId);\n if (!data) {\n // The test has finished, but steps are still coming. Just ignore them.\n return;\n }\n const { result, steps, test } = data;\n const parentStep = params.parentStepId ? steps.get(params.parentStepId) : undefined;\n const step: TestStep = {\n title: params.title,\n titlePath: () => {\n const parentPath = parentStep?.titlePath() || [];\n return [...parentPath, params.title];\n },\n parent: parentStep,\n category: params.category,\n startTime: new Date(params.wallTime),\n duration: -1,\n steps: [],\n attachments: [],\n annotations: [],\n location: params.location,\n };\n steps.set(params.stepId, step);\n (parentStep || result).steps.push(step);\n this._reporter.onStepBegin?.(test, result, step);\n }\n\n private _onStepEnd(params: StepEndPayload) {\n const data = this._dataByTestId.get(params.testId);\n if (!data) {\n // The test has finished, but steps are still coming. Just ignore them.\n return;\n }\n const { result, steps, test } = data;\n const step = steps.get(params.stepId);\n if (!step) {\n this._reporter.onStdErr?.('Internal error: step end without step begin: ' + params.stepId, test, result);\n return;\n }\n step.duration = params.wallTime - step.startTime.getTime();\n if (params.error)\n step.error = params.error;\n if (params.suggestedRebaseline)\n addSuggestedRebaseline(step.location!, params.suggestedRebaseline);\n step.annotations = params.annotations;\n steps.delete(params.stepId);\n this._reporter.onStepEnd?.(test, result, step);\n }\n\n private _onAttach(params: AttachmentPayload) {\n const data = this._dataByTestId.get(params.testId)!;\n if (!data) {\n // The test has finished, but attachments are still coming. Just ignore them.\n return;\n }\n const attachment = {\n name: params.name,\n path: params.path,\n contentType: params.contentType,\n body: params.body !== undefined ? Buffer.from(params.body, 'base64') : undefined\n };\n data.result.attachments.push(attachment);\n if (params.stepId) {\n const step = data.steps.get(params.stepId);\n if (step)\n step.attachments.push(attachment);\n else\n this._reporter.onStdErr?.('Internal error: step id not found: ' + params.stepId);\n }\n }\n\n private _failTestWithErrors(test: TestCase, errors: TestError[]) {\n const runData = this._dataByTestId.get(test.id);\n // There might be a single test that has started but has not finished yet.\n let result: TestResult;\n if (runData) {\n result = runData.result;\n } else {\n result = test._appendTestResult();\n this._reporter.onTestBegin?.(test, result);\n }\n result.errors = [...errors];\n result.error = result.errors[0];\n result.status = errors.length ? 'failed' : 'skipped';\n this._reportTestEnd(test, result);\n this._failedTests.add(test);\n }\n\n private _massSkipTestsFromRemaining(testIds: Set<string>, errors: TestError[]) {\n for (const test of this._remainingByTestId.values()) {\n if (!testIds.has(test.id))\n continue;\n if (!this._failureTracker.hasReachedMaxFailures()) {\n this._failTestWithErrors(test, errors);\n errors = []; // Only report errors for the first test.\n }\n this._remainingByTestId.delete(test.id);\n }\n if (errors.length) {\n // We had fatal errors after all tests have passed - most likely in some teardown.\n // Let's just fail the test run.\n this._failureTracker.onWorkerError();\n for (const error of errors)\n this._reporter.onError?.(error);\n }\n }\n\n private _onDone(params: DonePayload & { unexpectedExitError?: TestError }) {\n // We won't file remaining if:\n // - there are no remaining\n // - we are here not because something failed\n // - no unrecoverable worker error\n if (!this._remainingByTestId.size && !this._failedTests.size && !params.fatalErrors.length && !params.skipTestsDueToSetupFailure.length && !params.fatalUnknownTestIds && !params.unexpectedExitError && !params.stoppedDueToUnhandledErrorInTestFail) {\n this._finished({ didFail: false });\n return;\n }\n\n for (const testId of params.fatalUnknownTestIds || []) {\n const test = this._remainingByTestId.get(testId);\n if (test) {\n this._remainingByTestId.delete(testId);\n this._failTestWithErrors(test, [{ message: `Test not found in the worker process. Make sure test title does not change.` }]);\n }\n }\n\n if (params.fatalErrors.length) {\n // In case of fatal errors, report first remaining test as failing with these errors,\n // and all others as skipped.\n this._massSkipTestsFromRemaining(new Set(this._remainingByTestId.keys()), params.fatalErrors);\n }\n // Handle tests that should be skipped because of the setup failure.\n this._massSkipTestsFromRemaining(new Set(params.skipTestsDueToSetupFailure), []);\n\n if (params.unexpectedExitError) {\n // When worker exits during a test, we blame the test itself.\n //\n // The most common situation when worker exits while not running a test is:\n // worker failed to require the test file (at the start) because of an exception in one of imports.\n // In this case, \"skip\" all remaining tests, to avoid running into the same exception over and over.\n if (this._currentlyRunning)\n this._massSkipTestsFromRemaining(new Set([this._currentlyRunning.test.id]), [params.unexpectedExitError]);\n else\n this._massSkipTestsFromRemaining(new Set(this._remainingByTestId.keys()), [params.unexpectedExitError]);\n }\n\n const retryCandidates = new Set<TestCase>();\n const serialSuitesWithFailures = new Set<Suite>();\n\n for (const failedTest of this._failedTests) {\n if (this._failedWithNonRetriableError.has(failedTest))\n continue;\n retryCandidates.add(failedTest);\n\n let outermostSerialSuite: Suite | undefined;\n for (let parent: Suite | undefined = failedTest.parent; parent; parent = parent.parent) {\n if (parent._parallelMode === 'serial')\n outermostSerialSuite = parent;\n }\n if (outermostSerialSuite && !this._failedWithNonRetriableError.has(outermostSerialSuite))\n serialSuitesWithFailures.add(outermostSerialSuite);\n }\n\n // If we have failed tests that belong to a serial suite,\n // we should skip all future tests from the same serial suite.\n const testsBelongingToSomeSerialSuiteWithFailures = [...this._remainingByTestId.values()].filter(test => {\n let parent: Suite | undefined = test.parent;\n while (parent && !serialSuitesWithFailures.has(parent))\n parent = parent.parent;\n return !!parent;\n });\n this._massSkipTestsFromRemaining(new Set(testsBelongingToSomeSerialSuiteWithFailures.map(test => test.id)), []);\n\n for (const serialSuite of serialSuitesWithFailures) {\n // Add all tests from failed serial suites for possible retry.\n // These will only be retried together, because they have the same\n // \"retries\" setting and the same number of previous runs.\n serialSuite.allTests().forEach(test => retryCandidates.add(test));\n }\n\n const remaining = [...this._remainingByTestId.values()];\n for (const test of retryCandidates) {\n if (test.results.length < test.retries + 1)\n remaining.push(test);\n }\n\n // This job is over, we will schedule another one.\n const newJob = remaining.length ? { ...this.job, tests: remaining } : undefined;\n this._finished({ didFail: true, newJob });\n }\n\n onExit(data: ProcessExitData) {\n const unexpectedExitError: TestError | undefined = data.unexpectedly ? {\n message: `Error: worker process exited unexpectedly (code=${data.code}, signal=${data.signal})`\n } : undefined;\n this._onDone({ skipTestsDueToSetupFailure: [], fatalErrors: [], unexpectedExitError });\n }\n\n private _finished(result: { newJob?: TestGroup, didFail: boolean }) {\n eventsHelper.removeEventListeners(this._listeners);\n this.jobResult.resolve(result);\n }\n\n runInWorker(worker: WorkerHost) {\n this._parallelIndex = worker.parallelIndex;\n this._workerIndex = worker.workerIndex;\n\n const runPayload: RunPayload = {\n file: this.job.requireFile,\n entries: this.job.tests.map(test => {\n return { testId: test.id, retry: test.results.length };\n }),\n };\n worker.runTestGroup(runPayload);\n\n this._listeners = [\n eventsHelper.addEventListener(worker, 'testBegin', this._onTestBegin.bind(this)),\n eventsHelper.addEventListener(worker, 'testEnd', this._onTestEnd.bind(this)),\n eventsHelper.addEventListener(worker, 'stepBegin', this._onStepBegin.bind(this)),\n eventsHelper.addEventListener(worker, 'stepEnd', this._onStepEnd.bind(this)),\n eventsHelper.addEventListener(worker, 'attach', this._onAttach.bind(this)),\n eventsHelper.addEventListener(worker, 'testPaused', this._onTestPaused.bind(this, worker)),\n eventsHelper.addEventListener(worker, 'done', this._onDone.bind(this)),\n eventsHelper.addEventListener(worker, 'exit', this.onExit.bind(this)),\n ];\n }\n\n private _onTestPaused(worker: WorkerHost, params: TestPausedPayload) {\n const sendMessage = async (message: { request: any }) => {\n try {\n if (this.jobResult.isDone())\n throw new Error('Test has already stopped');\n const response = await worker.sendCustomMessage({ testId: params.testId, request: message.request });\n if (response.error)\n addLocationAndSnippetToError(this._config.config, response.error);\n return response;\n } catch (e) {\n const error = serializeError(e);\n addLocationAndSnippetToError(this._config.config, error);\n return { response: undefined, error };\n }\n };\n\n for (const error of params.errors)\n addLocationAndSnippetToError(this._config.config, error);\n this._failureTracker.onTestPaused?.({ ...params, sendMessage });\n }\n\n skipWholeJob(): boolean {\n // If all the tests in a group are skipped, we report them immediately\n // without sending anything to a worker. This avoids creating unnecessary worker processes.\n //\n // However, if there is at least one non-skipped test in a group, we'll send\n // the whole group to the worker process and report tests in the natural order,\n // with skipped tests mixed in-between non-skipped. This makes\n // for a better reporter experience.\n const allTestsSkipped = this.job.tests.every(test => test.expectedStatus === 'skipped');\n if (allTestsSkipped && !this._failureTracker.hasReachedMaxFailures()) {\n for (const test of this.job.tests) {\n const result = test._appendTestResult();\n this._reporter.onTestBegin?.(test, result);\n result.status = 'skipped';\n // This must mirror _onTestEnd() above\n result.annotations = [...test.annotations];\n this._reportTestEnd(test, result);\n }\n return true;\n }\n return false;\n }\n\n currentlyRunning() {\n return this._currentlyRunning;\n }\n\n private _reportTestEnd(test: TestCase, result: TestResult) {\n this._reporter.onTestEnd?.(test, result);\n const hadMaxFailures = this._failureTracker.hasReachedMaxFailures();\n this._failureTracker.onTestEnd(test, result);\n if (this._failureTracker.hasReachedMaxFailures()) {\n this._stopCallback();\n if (!hadMaxFailures)\n this._reporter.onError?.({ message: colors.red(`Testing stopped early after ${this._failureTracker.maxFailures()} maximum allowed failures.`) });\n }\n }\n}\n\nfunction chunkFromParams(params: TestOutputPayload): string | Buffer {\n if (typeof params.text === 'string')\n return params.text;\n return Buffer.from(params.buffer!, 'base64');\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["import_utils"]
7
+ }
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/runner/failureTracker.ts"],
4
+ "sourcesContent": ["/**\n * Copyright Microsoft Corporation. All rights reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type { TestResult, TestError } from '../../types/testReporter';\nimport type { FullConfigInternal, FullProjectInternal } from '../common/config';\nimport type { Suite, TestCase } from '../common/test';\n\nexport type TestPausedParams = {\n errors: TestError[];\n sendMessage: (params: { request: any }) => Promise<{ response: any, error?: TestError }>;\n};\n\nexport class FailureTracker {\n private _config: FullConfigInternal;\n private _failureCount = 0;\n private _hasWorkerErrors = false;\n private _rootSuite: Suite | undefined;\n private _topLevelProjects: FullProjectInternal[] = [];\n private _pauseOnError: boolean;\n private _pauseAtEnd: boolean;\n onTestPaused?: (params: TestPausedParams) => void;\n\n constructor(config: FullConfigInternal, options?: { pauseOnError?: boolean, pauseAtEnd?: boolean }) {\n this._config = config;\n this._pauseOnError = !!options?.pauseOnError;\n this._pauseAtEnd = !!options?.pauseAtEnd;\n }\n\n onRootSuite(rootSuite: Suite, topLevelProjects: FullProjectInternal[]) {\n this._rootSuite = rootSuite;\n this._topLevelProjects = topLevelProjects;\n }\n\n onTestEnd(test: TestCase, result: TestResult) {\n // Test is considered failing after the last retry.\n if (test.outcome() === 'unexpected' && test.results.length > test.retries)\n ++this._failureCount;\n }\n\n onWorkerError() {\n this._hasWorkerErrors = true;\n }\n\n pauseOnError() {\n return this._pauseOnError;\n }\n\n pauseAtEnd(inProject: FullProjectInternal) {\n return this._topLevelProjects.includes(inProject) && this._pauseAtEnd;\n }\n\n hasReachedMaxFailures() {\n return this.maxFailures() > 0 && this._failureCount >= this.maxFailures();\n }\n\n hasWorkerErrors() {\n return this._hasWorkerErrors;\n }\n\n result(): 'failed' | 'passed' {\n return this._hasWorkerErrors || this.hasReachedMaxFailures() || this.hasFailedTests() || (this._config.failOnFlakyTests && this.hasFlakyTests()) ? 'failed' : 'passed';\n }\n\n hasFailedTests() {\n return this._rootSuite?.allTests().some(test => !test.ok());\n }\n\n hasFlakyTests() {\n return this._rootSuite?.allTests().some(test => (test.outcome() === 'flaky'));\n }\n\n maxFailures() {\n return this._config.config.maxFailures;\n }\n\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAyBO,MAAM,eAAe;AAAA,EAU1B,YAAY,QAA4B,SAA4D;AARpG,SAAQ,gBAAgB;AACxB,SAAQ,mBAAmB;AAE3B,SAAQ,oBAA2C,CAAC;AAMlD,SAAK,UAAU;AACf,SAAK,gBAAgB,CAAC,CAAC,SAAS;AAChC,SAAK,cAAc,CAAC,CAAC,SAAS;AAAA,EAChC;AAAA,EAEA,YAAY,WAAkB,kBAAyC;AACrE,SAAK,aAAa;AAClB,SAAK,oBAAoB;AAAA,EAC3B;AAAA,EAEA,UAAU,MAAgB,QAAoB;AAE5C,QAAI,KAAK,QAAQ,MAAM,gBAAgB,KAAK,QAAQ,SAAS,KAAK;AAChE,QAAE,KAAK;AAAA,EACX;AAAA,EAEA,gBAAgB;AACd,SAAK,mBAAmB;AAAA,EAC1B;AAAA,EAEA,eAAe;AACb,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,WAAW,WAAgC;AACzC,WAAO,KAAK,kBAAkB,SAAS,SAAS,KAAK,KAAK;AAAA,EAC5D;AAAA,EAEA,wBAAwB;AACtB,WAAO,KAAK,YAAY,IAAI,KAAK,KAAK,iBAAiB,KAAK,YAAY;AAAA,EAC1E;AAAA,EAEA,kBAAkB;AAChB,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,SAA8B;AAC5B,WAAO,KAAK,oBAAoB,KAAK,sBAAsB,KAAK,KAAK,eAAe,KAAM,KAAK,QAAQ,oBAAoB,KAAK,cAAc,IAAK,WAAW;AAAA,EAChK;AAAA,EAEA,iBAAiB;AACf,WAAO,KAAK,YAAY,SAAS,EAAE,KAAK,UAAQ,CAAC,KAAK,GAAG,CAAC;AAAA,EAC5D;AAAA,EAEA,gBAAgB;AACd,WAAO,KAAK,YAAY,SAAS,EAAE,KAAK,UAAS,KAAK,QAAQ,MAAM,OAAQ;AAAA,EAC9E;AAAA,EAEA,cAAc;AACZ,WAAO,KAAK,QAAQ,OAAO;AAAA,EAC7B;AAEF;",
6
+ "names": []
7
+ }
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/runner/lastRun.ts"],
4
+ "sourcesContent": ["/**\n * Copyright Microsoft Corporation. All rights reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport fs from 'fs';\nimport path from 'path';\n\nimport { filterProjects } from './projectUtils';\n\nimport type { FullResult, Suite } from '../../types/testReporter';\nimport type { FullConfigInternal } from '../common/config';\nimport type { ReporterV2 } from '../reporters/reporterV2';\n\ntype LastRunInfo = {\n status: FullResult['status'];\n failedTests: string[];\n};\n\nexport class LastRunReporter implements ReporterV2 {\n private _config: FullConfigInternal;\n private _lastRunFile: string | undefined;\n private _suite: Suite | undefined;\n\n constructor(config: FullConfigInternal) {\n this._config = config;\n const [project] = filterProjects(config.projects, config.cliProjectFilter);\n if (project)\n this._lastRunFile = path.join(project.project.outputDir, '.last-run.json');\n }\n\n async filterLastFailed() {\n if (!this._lastRunFile)\n return;\n try {\n const lastRunInfo = JSON.parse(await fs.promises.readFile(this._lastRunFile, 'utf8')) as LastRunInfo;\n const failedTestIds = new Set(lastRunInfo.failedTests);\n // Explicitly apply --last-failed filter after sharding.\n this._config.postShardTestFilters.push(test => failedTestIds.has(test.id));\n } catch {\n }\n }\n\n version(): 'v2' {\n return 'v2';\n }\n\n printsToStdio() {\n return false;\n }\n\n onBegin(suite: Suite) {\n this._suite = suite;\n }\n\n async onEnd(result: FullResult) {\n if (!this._lastRunFile || this._config.cliListOnly)\n return;\n const lastRunInfo: LastRunInfo = {\n status: result.status,\n failedTests: this._suite?.allTests().filter(t => !t.ok()).map(t => t.id) || [],\n };\n await fs.promises.mkdir(path.dirname(this._lastRunFile), { recursive: true });\n await fs.promises.writeFile(this._lastRunFile, JSON.stringify(lastRunInfo, undefined, 2));\n }\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAgBA,gBAAe;AACf,kBAAiB;AAEjB,0BAA+B;AAWxB,MAAM,gBAAsC;AAAA,EAKjD,YAAY,QAA4B;AACtC,SAAK,UAAU;AACf,UAAM,CAAC,OAAO,QAAI,oCAAe,OAAO,UAAU,OAAO,gBAAgB;AACzE,QAAI;AACF,WAAK,eAAe,YAAAA,QAAK,KAAK,QAAQ,QAAQ,WAAW,gBAAgB;AAAA,EAC7E;AAAA,EAEA,MAAM,mBAAmB;AACvB,QAAI,CAAC,KAAK;AACR;AACF,QAAI;AACF,YAAM,cAAc,KAAK,MAAM,MAAM,UAAAC,QAAG,SAAS,SAAS,KAAK,cAAc,MAAM,CAAC;AACpF,YAAM,gBAAgB,IAAI,IAAI,YAAY,WAAW;AAErD,WAAK,QAAQ,qBAAqB,KAAK,UAAQ,cAAc,IAAI,KAAK,EAAE,CAAC;AAAA,IAC3E,QAAQ;AAAA,IACR;AAAA,EACF;AAAA,EAEA,UAAgB;AACd,WAAO;AAAA,EACT;AAAA,EAEA,gBAAgB;AACd,WAAO;AAAA,EACT;AAAA,EAEA,QAAQ,OAAc;AACpB,SAAK,SAAS;AAAA,EAChB;AAAA,EAEA,MAAM,MAAM,QAAoB;AAC9B,QAAI,CAAC,KAAK,gBAAgB,KAAK,QAAQ;AACrC;AACF,UAAM,cAA2B;AAAA,MAC/B,QAAQ,OAAO;AAAA,MACf,aAAa,KAAK,QAAQ,SAAS,EAAE,OAAO,OAAK,CAAC,EAAE,GAAG,CAAC,EAAE,IAAI,OAAK,EAAE,EAAE,KAAK,CAAC;AAAA,IAC/E;AACA,UAAM,UAAAA,QAAG,SAAS,MAAM,YAAAD,QAAK,QAAQ,KAAK,YAAY,GAAG,EAAE,WAAW,KAAK,CAAC;AAC5E,UAAM,UAAAC,QAAG,SAAS,UAAU,KAAK,cAAc,KAAK,UAAU,aAAa,QAAW,CAAC,CAAC;AAAA,EAC1F;AACF;",
6
+ "names": ["path", "fs"]
7
+ }
@@ -162,7 +162,7 @@ async function createRootSuite(testRun, errors, shouldFilterOnly) {
162
162
  for (const group of (0, import_testGroups.createTestGroups)(projectSuite, config.config.shard.total))
163
163
  testGroups.push(group);
164
164
  }
165
- const testGroupsInThisShard = (0, import_testGroups.filterForShard)(config.config.shard, testGroups);
165
+ const testGroupsInThisShard = (0, import_testGroups.filterForShard)(config.config.shard, config.configCLIOverrides.shardWeights, testGroups);
166
166
  const testsInThisShard = /* @__PURE__ */ new Set();
167
167
  for (const group of testGroupsInThisShard) {
168
168
  for (const test of group.tests)
@@ -317,7 +317,7 @@ async function loadTestList(config, filePath) {
317
317
  const relativeFile = (0, import_utils.toPosixPath)(import_path.default.relative(config.config.rootDir, test.location.file));
318
318
  if (relativeFile !== d.file)
319
319
  return false;
320
- return d.titlePath.length === titles.length && d.titlePath.every((_, index) => titles[index] === d.titlePath[index]);
320
+ return d.titlePath.length <= titles.length && d.titlePath.every((_, index) => titles[index] === d.titlePath[index]);
321
321
  });
322
322
  } catch (e) {
323
323
  throw (0, import_util.errorWithFile)(filePath, "Cannot read test list file: " + e.message);