@stablyai/internal-playwright 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (297) hide show
  1. package/LICENSE +202 -0
  2. package/NOTICE +5 -0
  3. package/README.md +168 -0
  4. package/ThirdPartyNotices.txt +6277 -0
  5. package/cli.js +19 -0
  6. package/index.d.ts +17 -0
  7. package/index.js +17 -0
  8. package/index.mjs +18 -0
  9. package/jsx-runtime.js +42 -0
  10. package/jsx-runtime.mjs +21 -0
  11. package/lib/agents/generateAgents.js +265 -0
  12. package/lib/agents/generator.md +102 -0
  13. package/lib/agents/healer.md +78 -0
  14. package/lib/agents/planner.md +135 -0
  15. package/lib/cli.js +274 -0
  16. package/lib/common/config.js +274 -0
  17. package/lib/common/config.js.map +7 -0
  18. package/lib/common/configLoader.js +377 -0
  19. package/lib/common/configLoader.js.map +7 -0
  20. package/lib/common/esmLoaderHost.js +102 -0
  21. package/lib/common/esmLoaderHost.js.map +7 -0
  22. package/lib/common/expectBundle.js +52 -0
  23. package/lib/common/expectBundle.js.map +7 -0
  24. package/lib/common/expectBundleImpl.js +389 -0
  25. package/lib/common/expectBundleImpl.js.map +7 -0
  26. package/lib/common/fixtures.js +302 -0
  27. package/lib/common/fixtures.js.map +7 -0
  28. package/lib/common/globals.js +58 -0
  29. package/lib/common/globals.js.map +7 -0
  30. package/lib/common/ipc.js +60 -0
  31. package/lib/common/ipc.js.map +7 -0
  32. package/lib/common/poolBuilder.js +85 -0
  33. package/lib/common/poolBuilder.js.map +7 -0
  34. package/lib/common/process.js +104 -0
  35. package/lib/common/process.js.map +7 -0
  36. package/lib/common/suiteUtils.js +140 -0
  37. package/lib/common/suiteUtils.js.map +7 -0
  38. package/lib/common/test.js +321 -0
  39. package/lib/common/test.js.map +7 -0
  40. package/lib/common/testLoader.js +100 -0
  41. package/lib/common/testLoader.js.map +7 -0
  42. package/lib/common/testType.js +310 -0
  43. package/lib/common/testType.js.map +7 -0
  44. package/lib/fsWatcher.js +67 -0
  45. package/lib/fsWatcher.js.map +7 -0
  46. package/lib/index.js +696 -0
  47. package/lib/index.js.map +7 -0
  48. package/lib/internalsForTest.js +42 -0
  49. package/lib/internalsForTest.js.map +7 -0
  50. package/lib/isomorphic/events.js +77 -0
  51. package/lib/isomorphic/events.js.map +7 -0
  52. package/lib/isomorphic/folders.js +30 -0
  53. package/lib/isomorphic/folders.js.map +7 -0
  54. package/lib/isomorphic/stringInternPool.js +69 -0
  55. package/lib/isomorphic/stringInternPool.js.map +7 -0
  56. package/lib/isomorphic/teleReceiver.js +507 -0
  57. package/lib/isomorphic/teleReceiver.js.map +7 -0
  58. package/lib/isomorphic/teleSuiteUpdater.js +137 -0
  59. package/lib/isomorphic/teleSuiteUpdater.js.map +7 -0
  60. package/lib/isomorphic/testServerConnection.js +211 -0
  61. package/lib/isomorphic/testServerConnection.js.map +7 -0
  62. package/lib/isomorphic/testServerInterface.js +16 -0
  63. package/lib/isomorphic/testServerInterface.js.map +7 -0
  64. package/lib/isomorphic/testTree.js +334 -0
  65. package/lib/isomorphic/testTree.js.map +7 -0
  66. package/lib/isomorphic/types.d.js +16 -0
  67. package/lib/isomorphic/types.d.js.map +7 -0
  68. package/lib/loader/loaderMain.js +59 -0
  69. package/lib/loader/loaderMain.js.map +7 -0
  70. package/lib/matchers/expect.js +325 -0
  71. package/lib/matchers/expect.js.map +7 -0
  72. package/lib/matchers/matcherHint.js +87 -0
  73. package/lib/matchers/matcherHint.js.map +7 -0
  74. package/lib/matchers/matchers.js +366 -0
  75. package/lib/matchers/matchers.js.map +7 -0
  76. package/lib/matchers/toBeTruthy.js +73 -0
  77. package/lib/matchers/toBeTruthy.js.map +7 -0
  78. package/lib/matchers/toEqual.js +99 -0
  79. package/lib/matchers/toEqual.js.map +7 -0
  80. package/lib/matchers/toHaveURL.js +102 -0
  81. package/lib/matchers/toHaveURL.js.map +7 -0
  82. package/lib/matchers/toMatchAriaSnapshot.js +159 -0
  83. package/lib/matchers/toMatchAriaSnapshot.js.map +7 -0
  84. package/lib/matchers/toMatchSnapshot.js +359 -0
  85. package/lib/matchers/toMatchSnapshot.js.map +7 -0
  86. package/lib/matchers/toMatchText.js +99 -0
  87. package/lib/matchers/toMatchText.js.map +7 -0
  88. package/lib/mcp/browser/actions.d.js +16 -0
  89. package/lib/mcp/browser/backend.js +93 -0
  90. package/lib/mcp/browser/backend.js.map +7 -0
  91. package/lib/mcp/browser/browserContextFactory.js +296 -0
  92. package/lib/mcp/browser/browserServerBackend.js +76 -0
  93. package/lib/mcp/browser/codegen.js +66 -0
  94. package/lib/mcp/browser/config.js +385 -0
  95. package/lib/mcp/browser/context.js +287 -0
  96. package/lib/mcp/browser/response.js +228 -0
  97. package/lib/mcp/browser/sessionLog.js +160 -0
  98. package/lib/mcp/browser/tab.js +277 -0
  99. package/lib/mcp/browser/tool.js +30 -0
  100. package/lib/mcp/browser/tool.js.map +7 -0
  101. package/lib/mcp/browser/tools/common.js +63 -0
  102. package/lib/mcp/browser/tools/console.js +44 -0
  103. package/lib/mcp/browser/tools/dialogs.js +60 -0
  104. package/lib/mcp/browser/tools/evaluate.js +70 -0
  105. package/lib/mcp/browser/tools/files.js +58 -0
  106. package/lib/mcp/browser/tools/form.js +74 -0
  107. package/lib/mcp/browser/tools/install.js +69 -0
  108. package/lib/mcp/browser/tools/keyboard.js +85 -0
  109. package/lib/mcp/browser/tools/mouse.js +107 -0
  110. package/lib/mcp/browser/tools/navigate.js +62 -0
  111. package/lib/mcp/browser/tools/network.js +54 -0
  112. package/lib/mcp/browser/tools/pdf.js +59 -0
  113. package/lib/mcp/browser/tools/screenshot.js +88 -0
  114. package/lib/mcp/browser/tools/snapshot.js +182 -0
  115. package/lib/mcp/browser/tools/tabs.js +67 -0
  116. package/lib/mcp/browser/tools/tool.js +49 -0
  117. package/lib/mcp/browser/tools/tracing.js +74 -0
  118. package/lib/mcp/browser/tools/utils.js +100 -0
  119. package/lib/mcp/browser/tools/verify.js +154 -0
  120. package/lib/mcp/browser/tools/wait.js +63 -0
  121. package/lib/mcp/browser/tools.js +80 -0
  122. package/lib/mcp/browser/tools.js.map +7 -0
  123. package/lib/mcp/browser/watchdog.js +44 -0
  124. package/lib/mcp/config.d.js +16 -0
  125. package/lib/mcp/extension/cdpRelay.js +351 -0
  126. package/lib/mcp/extension/extensionContextFactory.js +75 -0
  127. package/lib/mcp/extension/protocol.js +28 -0
  128. package/lib/mcp/index.js +61 -0
  129. package/lib/mcp/log.js +35 -0
  130. package/lib/mcp/program.js +96 -0
  131. package/lib/mcp/sdk/bundle.js +81 -0
  132. package/lib/mcp/sdk/bundle.js.map +7 -0
  133. package/lib/mcp/sdk/call.js +49 -0
  134. package/lib/mcp/sdk/call.js.map +7 -0
  135. package/lib/mcp/sdk/exports.js +32 -0
  136. package/lib/mcp/sdk/exports.js.map +7 -0
  137. package/lib/mcp/sdk/http.js +187 -0
  138. package/lib/mcp/sdk/http.js.map +7 -0
  139. package/lib/mcp/sdk/inProcessTransport.js +71 -0
  140. package/lib/mcp/sdk/inProcessTransport.js.map +7 -0
  141. package/lib/mcp/sdk/mdb.js +206 -0
  142. package/lib/mcp/sdk/mdb.js.map +7 -0
  143. package/lib/mcp/sdk/proxyBackend.js +128 -0
  144. package/lib/mcp/sdk/proxyBackend.js.map +7 -0
  145. package/lib/mcp/sdk/server.js +189 -0
  146. package/lib/mcp/sdk/server.js.map +7 -0
  147. package/lib/mcp/sdk/tool.js +51 -0
  148. package/lib/mcp/sdk/tool.js.map +7 -0
  149. package/lib/mcp/test/backend.js +67 -0
  150. package/lib/mcp/test/backend.js.map +7 -0
  151. package/lib/mcp/test/browserBackend.js +98 -0
  152. package/lib/mcp/test/context.js +48 -0
  153. package/lib/mcp/test/context.js.map +7 -0
  154. package/lib/mcp/test/generatorTools.js +122 -0
  155. package/lib/mcp/test/plannerTools.js +46 -0
  156. package/lib/mcp/test/seed.js +72 -0
  157. package/lib/mcp/test/streams.js +39 -0
  158. package/lib/mcp/test/streams.js.map +7 -0
  159. package/lib/mcp/test/testBackend.js +97 -0
  160. package/lib/mcp/test/testContext.js +176 -0
  161. package/lib/mcp/test/testTool.js +30 -0
  162. package/lib/mcp/test/testTools.js +115 -0
  163. package/lib/mcp/test/tool.js +30 -0
  164. package/lib/mcp/test/tool.js.map +7 -0
  165. package/lib/mcp/test/tools.js +150 -0
  166. package/lib/mcp/test/tools.js.map +7 -0
  167. package/lib/mcp/vscode/host.js +187 -0
  168. package/lib/mcp/vscode/main.js +77 -0
  169. package/lib/mcpBundleImpl.js +41 -0
  170. package/lib/mcpBundleImpl.js.map +7 -0
  171. package/lib/plugins/gitCommitInfoPlugin.js +198 -0
  172. package/lib/plugins/gitCommitInfoPlugin.js.map +7 -0
  173. package/lib/plugins/index.js +28 -0
  174. package/lib/plugins/index.js.map +7 -0
  175. package/lib/plugins/webServerPlugin.js +209 -0
  176. package/lib/plugins/webServerPlugin.js.map +7 -0
  177. package/lib/program.js +412 -0
  178. package/lib/program.js.map +7 -0
  179. package/lib/reporters/base.js +609 -0
  180. package/lib/reporters/base.js.map +7 -0
  181. package/lib/reporters/blob.js +135 -0
  182. package/lib/reporters/blob.js.map +7 -0
  183. package/lib/reporters/dot.js +82 -0
  184. package/lib/reporters/dot.js.map +7 -0
  185. package/lib/reporters/empty.js +32 -0
  186. package/lib/reporters/empty.js.map +7 -0
  187. package/lib/reporters/github.js +128 -0
  188. package/lib/reporters/github.js.map +7 -0
  189. package/lib/reporters/html.js +644 -0
  190. package/lib/reporters/html.js.map +7 -0
  191. package/lib/reporters/internalReporter.js +130 -0
  192. package/lib/reporters/internalReporter.js.map +7 -0
  193. package/lib/reporters/json.js +254 -0
  194. package/lib/reporters/json.js.map +7 -0
  195. package/lib/reporters/junit.js +230 -0
  196. package/lib/reporters/junit.js.map +7 -0
  197. package/lib/reporters/line.js +113 -0
  198. package/lib/reporters/line.js.map +7 -0
  199. package/lib/reporters/list.js +235 -0
  200. package/lib/reporters/list.js.map +7 -0
  201. package/lib/reporters/listModeReporter.js +69 -0
  202. package/lib/reporters/listModeReporter.js.map +7 -0
  203. package/lib/reporters/markdown.js +144 -0
  204. package/lib/reporters/markdown.js.map +7 -0
  205. package/lib/reporters/merge.js +535 -0
  206. package/lib/reporters/merge.js.map +7 -0
  207. package/lib/reporters/multiplexer.js +104 -0
  208. package/lib/reporters/multiplexer.js.map +7 -0
  209. package/lib/reporters/reporterV2.js +102 -0
  210. package/lib/reporters/reporterV2.js.map +7 -0
  211. package/lib/reporters/teleEmitter.js +297 -0
  212. package/lib/reporters/teleEmitter.js.map +7 -0
  213. package/lib/reporters/versions/blobV1.js +16 -0
  214. package/lib/reporters/versions/blobV1.js.map +7 -0
  215. package/lib/runner/dispatcher.js +491 -0
  216. package/lib/runner/dispatcher.js.map +7 -0
  217. package/lib/runner/failureTracker.js +72 -0
  218. package/lib/runner/failureTracker.js.map +7 -0
  219. package/lib/runner/lastRun.js +77 -0
  220. package/lib/runner/lastRun.js.map +7 -0
  221. package/lib/runner/loadUtils.js +333 -0
  222. package/lib/runner/loadUtils.js.map +7 -0
  223. package/lib/runner/loaderHost.js +89 -0
  224. package/lib/runner/loaderHost.js.map +7 -0
  225. package/lib/runner/processHost.js +161 -0
  226. package/lib/runner/processHost.js.map +7 -0
  227. package/lib/runner/projectUtils.js +241 -0
  228. package/lib/runner/projectUtils.js.map +7 -0
  229. package/lib/runner/rebase.js +189 -0
  230. package/lib/runner/rebase.js.map +7 -0
  231. package/lib/runner/reporters.js +137 -0
  232. package/lib/runner/reporters.js.map +7 -0
  233. package/lib/runner/runner.js +173 -0
  234. package/lib/runner/sigIntWatcher.js +96 -0
  235. package/lib/runner/sigIntWatcher.js.map +7 -0
  236. package/lib/runner/taskRunner.js +127 -0
  237. package/lib/runner/taskRunner.js.map +7 -0
  238. package/lib/runner/tasks.js +410 -0
  239. package/lib/runner/tasks.js.map +7 -0
  240. package/lib/runner/testGroups.js +117 -0
  241. package/lib/runner/testGroups.js.map +7 -0
  242. package/lib/runner/testRunner.js +390 -0
  243. package/lib/runner/testRunner.js.map +7 -0
  244. package/lib/runner/testServer.js +264 -0
  245. package/lib/runner/testServer.js.map +7 -0
  246. package/lib/runner/uiMode.js +271 -0
  247. package/lib/runner/uiModeReporter.js +30 -0
  248. package/lib/runner/uiModeReporter.js.map +7 -0
  249. package/lib/runner/vcs.js +72 -0
  250. package/lib/runner/vcs.js.map +7 -0
  251. package/lib/runner/watchMode.js +395 -0
  252. package/lib/runner/watchMode.js.map +7 -0
  253. package/lib/runner/workerHost.js +95 -0
  254. package/lib/runner/workerHost.js.map +7 -0
  255. package/lib/store.js +98 -0
  256. package/lib/third_party/pirates.js +62 -0
  257. package/lib/third_party/pirates.js.map +7 -0
  258. package/lib/third_party/tsconfig-loader.js +103 -0
  259. package/lib/third_party/tsconfig-loader.js.map +7 -0
  260. package/lib/transform/babelBundle.js +43 -0
  261. package/lib/transform/babelBundle.js.map +7 -0
  262. package/lib/transform/babelBundleImpl.js +461 -0
  263. package/lib/transform/babelBundleImpl.js.map +7 -0
  264. package/lib/transform/compilationCache.js +272 -0
  265. package/lib/transform/compilationCache.js.map +7 -0
  266. package/lib/transform/esmLoader.js +104 -0
  267. package/lib/transform/esmLoader.js.map +7 -0
  268. package/lib/transform/esmUtils.js +32 -0
  269. package/lib/transform/portTransport.js +67 -0
  270. package/lib/transform/portTransport.js.map +7 -0
  271. package/lib/transform/transform.js +293 -0
  272. package/lib/transform/transform.js.map +7 -0
  273. package/lib/util.js +403 -0
  274. package/lib/util.js.map +7 -0
  275. package/lib/utilsBundle.js +43 -0
  276. package/lib/utilsBundle.js.map +7 -0
  277. package/lib/utilsBundleImpl.js +100 -0
  278. package/lib/utilsBundleImpl.js.map +7 -0
  279. package/lib/worker/fixtureRunner.js +258 -0
  280. package/lib/worker/fixtureRunner.js.map +7 -0
  281. package/lib/worker/stepContext.js +34 -0
  282. package/lib/worker/testInfo.js +508 -0
  283. package/lib/worker/testInfo.js.map +7 -0
  284. package/lib/worker/testTracing.js +344 -0
  285. package/lib/worker/testTracing.js.map +7 -0
  286. package/lib/worker/timeoutManager.js +174 -0
  287. package/lib/worker/timeoutManager.js.map +7 -0
  288. package/lib/worker/util.js +31 -0
  289. package/lib/worker/util.js.map +7 -0
  290. package/lib/worker/workerMain.js +520 -0
  291. package/lib/worker/workerMain.js.map +7 -0
  292. package/package.json +74 -0
  293. package/test.d.ts +18 -0
  294. package/test.js +24 -0
  295. package/test.mjs +33 -0
  296. package/types/test.d.ts +10217 -0
  297. package/types/testReporter.d.ts +816 -0
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/runner/rebase.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 fs from 'fs';\nimport path from 'path';\n\n\nimport { MultiMap } from 'playwright-core/lib/utils';\nimport { colors } from 'playwright-core/lib/utils';\nimport { diff } from 'playwright-core/lib/utilsBundle';\n\nimport { filterProjects } from './projectUtils';\nimport { babelParse, traverse, types } from '../transform/babelBundle';\n\nimport type { FullConfigInternal } from '../common/config';\nimport type { InternalReporter } from '../reporters/internalReporter';\nimport type { T } from '../transform/babelBundle';\nconst t: typeof T = types;\n\ntype Location = {\n file: string;\n line: number;\n column: number;\n};\n\ntype Replacement = {\n // Points to the call expression.\n location: Location;\n code: string;\n};\n\nconst suggestedRebaselines = new MultiMap<string, Replacement>();\n\nexport function addSuggestedRebaseline(location: Location, suggestedRebaseline: string) {\n suggestedRebaselines.set(location.file, { location, code: suggestedRebaseline });\n}\n\nexport function clearSuggestedRebaselines() {\n suggestedRebaselines.clear();\n}\n\nexport async function applySuggestedRebaselines(config: FullConfigInternal, reporter: InternalReporter) {\n if (config.config.updateSnapshots === 'none')\n return;\n if (!suggestedRebaselines.size)\n return;\n const [project] = filterProjects(config.projects, config.cliProjectFilter);\n if (!project)\n return;\n\n const patches: string[] = [];\n const files: string[] = [];\n const gitCache = new Map<string, string | null>();\n\n const patchFile = path.join(project.project.outputDir, 'rebaselines.patch');\n\n for (const fileName of [...suggestedRebaselines.keys()].sort()) {\n const source = await fs.promises.readFile(fileName, 'utf8');\n const lines = source.split('\\n');\n const replacements = suggestedRebaselines.get(fileName);\n const fileNode = babelParse(source, fileName, true);\n const ranges: { start: number, end: number, oldText: string, newText: string }[] = [];\n\n traverse(fileNode, {\n CallExpression: path => {\n const node = path.node;\n if (node.arguments.length < 1)\n return;\n if (!t.isMemberExpression(node.callee))\n return;\n const argument = node.arguments[0];\n if (!t.isStringLiteral(argument) && !t.isTemplateLiteral(argument))\n return;\n const prop = node.callee.property;\n if (!prop.loc || !argument.start || !argument.end)\n return;\n // Replacements are anchored by the location of the call expression.\n // However, replacement text is meant to only replace the first argument.\n for (const replacement of replacements) {\n // In Babel, rows are 1-based, columns are 0-based.\n if (prop.loc.start.line !== replacement.location.line)\n continue;\n if (prop.loc.start.column + 1 !== replacement.location.column)\n continue;\n const indent = lines[prop.loc.start.line - 1].match(/^\\s*/)![0];\n const newText = replacement.code.replace(/\\{indent\\}/g, indent);\n ranges.push({ start: argument.start, end: argument.end, oldText: source.substring(argument.start, argument.end), newText });\n // We can have multiple, hopefully equal, replacements for the same location,\n // for example when a single test runs multiple times because of projects or retries.\n // Do not apply multiple replacements for the same assertion.\n break;\n }\n }\n });\n\n ranges.sort((a, b) => b.start - a.start);\n let result = source;\n for (const range of ranges)\n result = result.substring(0, range.start) + range.newText + result.substring(range.end);\n\n const relativeName = path.relative(process.cwd(), fileName);\n files.push(relativeName);\n\n if (config.config.updateSourceMethod === 'overwrite') {\n await fs.promises.writeFile(fileName, result);\n } else if (config.config.updateSourceMethod === '3way') {\n await fs.promises.writeFile(fileName, applyPatchWithConflictMarkers(source, result));\n } else {\n const gitFolder = findGitRoot(path.dirname(fileName), gitCache);\n const relativeToGit = path.relative(gitFolder || process.cwd(), fileName);\n patches.push(createPatch(relativeToGit, source, result));\n }\n }\n\n const fileList = files.map(file => ' ' + colors.dim(file)).join('\\n');\n reporter.onStdErr(`\\nNew baselines created for:\\n\\n${fileList}\\n`);\n if (config.config.updateSourceMethod === 'patch') {\n await fs.promises.mkdir(path.dirname(patchFile), { recursive: true });\n await fs.promises.writeFile(patchFile, patches.join('\\n'));\n reporter.onStdErr(`\\n ` + colors.cyan('git apply ' + path.relative(process.cwd(), patchFile)) + '\\n');\n }\n}\n\nfunction createPatch(fileName: string, before: string, after: string) {\n const file = fileName.replace(/\\\\/g, '/');\n const text = diff.createPatch(file, before, after, undefined, undefined, { context: 3 });\n return [\n 'diff --git a/' + file + ' b/' + file,\n '--- a/' + file,\n '+++ b/' + file,\n ...text.split('\\n').slice(4)\n ].join('\\n');\n}\n\nfunction findGitRoot(dir: string, cache: Map<string, string | null>): string | null {\n const result = cache.get(dir);\n if (result !== undefined)\n return result;\n\n const gitPath = path.join(dir, '.git');\n if (fs.existsSync(gitPath) && fs.lstatSync(gitPath).isDirectory()) {\n cache.set(dir, dir);\n return dir;\n }\n\n const parentDir = path.dirname(dir);\n if (dir === parentDir) {\n cache.set(dir, null);\n return null;\n }\n\n const parentResult = findGitRoot(parentDir, cache);\n cache.set(dir, parentResult);\n return parentResult;\n}\n\nfunction applyPatchWithConflictMarkers(oldText: string, newText: string) {\n const diffResult = diff.diffLines(oldText, newText);\n\n let result = '';\n let conflict = false;\n\n diffResult.forEach(part => {\n if (part.added) {\n if (conflict) {\n result += part.value;\n result += '>>>>>>> SNAPSHOT\\n';\n conflict = false;\n } else {\n result += '<<<<<<< HEAD\\n';\n result += part.value;\n result += '=======\\n';\n conflict = true;\n }\n } else if (part.removed) {\n result += '<<<<<<< HEAD\\n';\n result += part.value;\n result += '=======\\n';\n conflict = true;\n } else {\n if (conflict) {\n result += '>>>>>>> SNAPSHOT\\n';\n conflict = false;\n }\n result += part.value;\n }\n });\n\n if (conflict)\n result += '>>>>>>> SNAPSHOT\\n';\n return result;\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["import_utils", "path", "fs"]
7
+ }
@@ -0,0 +1,137 @@
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 reporters_exports = {};
30
+ __export(reporters_exports, {
31
+ createErrorCollectingReporter: () => createErrorCollectingReporter,
32
+ createReporterForTestServer: () => createReporterForTestServer,
33
+ createReporters: () => createReporters
34
+ });
35
+ module.exports = __toCommonJS(reporters_exports);
36
+ var import_utils = require("playwright-core/lib/utils");
37
+ var import_loadUtils = require("./loadUtils");
38
+ var import_base = require("../reporters/base");
39
+ var import_blob = require("../reporters/blob");
40
+ var import_dot = __toESM(require("../reporters/dot"));
41
+ var import_empty = __toESM(require("../reporters/empty"));
42
+ var import_github = __toESM(require("../reporters/github"));
43
+ var import_html = __toESM(require("../reporters/html"));
44
+ var import_json = __toESM(require("../reporters/json"));
45
+ var import_junit = __toESM(require("../reporters/junit"));
46
+ var import_line = __toESM(require("../reporters/line"));
47
+ var import_list = __toESM(require("../reporters/list"));
48
+ var import_listModeReporter = __toESM(require("../reporters/listModeReporter"));
49
+ var import_reporterV2 = require("../reporters/reporterV2");
50
+ async function createReporters(config, mode, isTestServer, descriptions) {
51
+ const defaultReporters = {
52
+ blob: import_blob.BlobReporter,
53
+ dot: mode === "list" ? import_listModeReporter.default : import_dot.default,
54
+ line: mode === "list" ? import_listModeReporter.default : import_line.default,
55
+ list: mode === "list" ? import_listModeReporter.default : import_list.default,
56
+ github: import_github.default,
57
+ json: import_json.default,
58
+ junit: import_junit.default,
59
+ null: import_empty.default,
60
+ html: import_html.default
61
+ };
62
+ const reporters = [];
63
+ descriptions ??= config.config.reporter;
64
+ if (config.configCLIOverrides.additionalReporters)
65
+ descriptions = [...descriptions, ...config.configCLIOverrides.additionalReporters];
66
+ const runOptions = reporterOptions(config, mode, isTestServer);
67
+ for (const r of descriptions) {
68
+ const [name, arg] = r;
69
+ const options = { ...runOptions, ...arg };
70
+ if (name in defaultReporters) {
71
+ reporters.push(new defaultReporters[name](options));
72
+ } else {
73
+ const reporterConstructor = await (0, import_loadUtils.loadReporter)(config, name);
74
+ reporters.push((0, import_reporterV2.wrapReporterAsV2)(new reporterConstructor(options)));
75
+ }
76
+ }
77
+ if (process.env.PW_TEST_REPORTER) {
78
+ const reporterConstructor = await (0, import_loadUtils.loadReporter)(config, process.env.PW_TEST_REPORTER);
79
+ reporters.push((0, import_reporterV2.wrapReporterAsV2)(new reporterConstructor(runOptions)));
80
+ }
81
+ const someReporterPrintsToStdio = reporters.some((r) => r.printsToStdio ? r.printsToStdio() : true);
82
+ if (reporters.length && !someReporterPrintsToStdio) {
83
+ if (mode === "list")
84
+ reporters.unshift(new import_listModeReporter.default());
85
+ else if (mode !== "merge")
86
+ reporters.unshift(!process.env.CI ? new import_line.default() : new import_dot.default());
87
+ }
88
+ return reporters;
89
+ }
90
+ async function createReporterForTestServer(file, messageSink) {
91
+ const reporterConstructor = await (0, import_loadUtils.loadReporter)(null, file);
92
+ return (0, import_reporterV2.wrapReporterAsV2)(new reporterConstructor({
93
+ _send: messageSink
94
+ }));
95
+ }
96
+ function createErrorCollectingReporter(screen) {
97
+ const errors = [];
98
+ return {
99
+ version: () => "v2",
100
+ onError(error) {
101
+ errors.push(error);
102
+ screen.stderr?.write((0, import_base.formatError)(screen, error).message + "\n");
103
+ },
104
+ errors: () => errors
105
+ };
106
+ }
107
+ function reporterOptions(config, mode, isTestServer) {
108
+ return {
109
+ configDir: config.configDir,
110
+ _mode: mode,
111
+ _isTestServer: isTestServer,
112
+ _commandHash: computeCommandHash(config)
113
+ };
114
+ }
115
+ function computeCommandHash(config) {
116
+ const parts = [];
117
+ if (config.cliProjectFilter)
118
+ parts.push(...config.cliProjectFilter);
119
+ const command = {};
120
+ if (config.cliArgs.length)
121
+ command.cliArgs = config.cliArgs;
122
+ if (config.cliGrep)
123
+ command.cliGrep = config.cliGrep;
124
+ if (config.cliGrepInvert)
125
+ command.cliGrepInvert = config.cliGrepInvert;
126
+ if (config.cliOnlyChanged)
127
+ command.cliOnlyChanged = config.cliOnlyChanged;
128
+ if (Object.keys(command).length)
129
+ parts.push((0, import_utils.calculateSha1)(JSON.stringify(command)).substring(0, 7));
130
+ return parts.join("-");
131
+ }
132
+ // Annotate the CommonJS export names for ESM import in node:
133
+ 0 && (module.exports = {
134
+ createErrorCollectingReporter,
135
+ createReporterForTestServer,
136
+ createReporters
137
+ });
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/runner/reporters.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 { calculateSha1 } from 'playwright-core/lib/utils';\n\nimport { loadReporter } from './loadUtils';\nimport { formatError } from '../reporters/base';\nimport { BlobReporter } from '../reporters/blob';\nimport DotReporter from '../reporters/dot';\nimport EmptyReporter from '../reporters/empty';\nimport GitHubReporter from '../reporters/github';\nimport HtmlReporter from '../reporters/html';\nimport JSONReporter from '../reporters/json';\nimport JUnitReporter from '../reporters/junit';\nimport LineReporter from '../reporters/line';\nimport ListReporter from '../reporters/list';\nimport ListModeReporter from '../reporters/listModeReporter';\nimport { wrapReporterAsV2 } from '../reporters/reporterV2';\n\nimport type { ReporterDescription } from '../../types/test';\nimport type { TestError } from '../../types/testReporter';\nimport type { BuiltInReporter, FullConfigInternal } from '../common/config';\nimport type { CommonReporterOptions, Screen } from '../reporters/base';\nimport type { ReporterV2 } from '../reporters/reporterV2';\n\nexport async function createReporters(config: FullConfigInternal, mode: 'list' | 'test' | 'merge', isTestServer: boolean, descriptions?: ReporterDescription[]): Promise<ReporterV2[]> {\n const defaultReporters: { [key in BuiltInReporter]: new(arg: any) => ReporterV2 } = {\n blob: BlobReporter,\n dot: mode === 'list' ? ListModeReporter : DotReporter,\n line: mode === 'list' ? ListModeReporter : LineReporter,\n list: mode === 'list' ? ListModeReporter : ListReporter,\n github: GitHubReporter,\n json: JSONReporter,\n junit: JUnitReporter,\n null: EmptyReporter,\n html: HtmlReporter,\n };\n const reporters: ReporterV2[] = [];\n descriptions ??= config.config.reporter;\n if (config.configCLIOverrides.additionalReporters)\n descriptions = [...descriptions, ...config.configCLIOverrides.additionalReporters];\n const runOptions = reporterOptions(config, mode, isTestServer);\n for (const r of descriptions) {\n const [name, arg] = r;\n const options = { ...runOptions, ...arg };\n if (name in defaultReporters) {\n reporters.push(new defaultReporters[name as keyof typeof defaultReporters](options));\n } else {\n const reporterConstructor = await loadReporter(config, name);\n reporters.push(wrapReporterAsV2(new reporterConstructor(options)));\n }\n }\n if (process.env.PW_TEST_REPORTER) {\n const reporterConstructor = await loadReporter(config, process.env.PW_TEST_REPORTER);\n reporters.push(wrapReporterAsV2(new reporterConstructor(runOptions)));\n }\n\n const someReporterPrintsToStdio = reporters.some(r => r.printsToStdio ? r.printsToStdio() : true);\n if (reporters.length && !someReporterPrintsToStdio) {\n // Add a line/dot/list-mode reporter for convenience.\n // Important to put it first, just in case some other reporter stalls onEnd.\n if (mode === 'list')\n reporters.unshift(new ListModeReporter());\n else if (mode !== 'merge')\n reporters.unshift(!process.env.CI ? new LineReporter() : new DotReporter());\n }\n return reporters;\n}\n\nexport async function createReporterForTestServer(file: string, messageSink: (message: any) => void): Promise<ReporterV2> {\n const reporterConstructor = await loadReporter(null, file);\n return wrapReporterAsV2(new reporterConstructor({\n _send: messageSink,\n }));\n}\n\ninterface ErrorCollectingReporter extends ReporterV2 {\n errors(): TestError[];\n}\n\nexport function createErrorCollectingReporter(screen: Screen): ErrorCollectingReporter {\n const errors: TestError[] = [];\n return {\n version: () => 'v2',\n onError(error: TestError) {\n errors.push(error);\n screen.stderr?.write(formatError(screen, error).message + '\\n');\n },\n errors: () => errors,\n };\n}\n\nfunction reporterOptions(config: FullConfigInternal, mode: 'list' | 'test' | 'merge', isTestServer: boolean): CommonReporterOptions {\n return {\n configDir: config.configDir,\n _mode: mode,\n _isTestServer: isTestServer,\n _commandHash: computeCommandHash(config),\n };\n}\n\nfunction computeCommandHash(config: FullConfigInternal) {\n const parts = [];\n // Include project names for readability.\n if (config.cliProjectFilter)\n parts.push(...config.cliProjectFilter);\n const command = {} as any;\n if (config.cliArgs.length)\n command.cliArgs = config.cliArgs;\n if (config.cliGrep)\n command.cliGrep = config.cliGrep;\n if (config.cliGrepInvert)\n command.cliGrepInvert = config.cliGrepInvert;\n if (config.cliOnlyChanged)\n command.cliOnlyChanged = config.cliOnlyChanged;\n if (Object.keys(command).length)\n parts.push(calculateSha1(JSON.stringify(command)).substring(0, 7));\n return parts.join('-');\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["ListModeReporter", "DotReporter", "LineReporter", "ListReporter", "GitHubReporter", "JSONReporter", "JUnitReporter", "EmptyReporter", "HtmlReporter"]
7
+ }
@@ -0,0 +1,173 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.Runner = void 0;
7
+ exports.readLastRunInfo = readLastRunInfo;
8
+ var _fs = _interopRequireDefault(require("fs"));
9
+ var _path = _interopRequireDefault(require("path"));
10
+ var _utils = require("playwright-core/lib/utils");
11
+ var _webServerPlugin = require("../plugins/webServerPlugin");
12
+ var _projectUtils = require("./projectUtils");
13
+ var _reporters = require("./reporters");
14
+ var _tasks = require("./tasks");
15
+ var _watchMode = require("./watchMode");
16
+ var _internalReporter = require("../reporters/internalReporter");
17
+ var _multiplexer = require("../reporters/multiplexer");
18
+ var _reporterV = require("../reporters/reporterV2");
19
+ var _compilationCache = require("../transform/compilationCache");
20
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
21
+ /**
22
+ * Copyright 2019 Google Inc. All rights reserved.
23
+ * Modifications copyright (c) Microsoft Corporation.
24
+ *
25
+ * Licensed under the Apache License, Version 2.0 (the "License");
26
+ * you may not use this file except in compliance with the License.
27
+ * You may obtain a copy of the License at
28
+ *
29
+ * http://www.apache.org/licenses/LICENSE-2.0
30
+ *
31
+ * Unless required by applicable law or agreed to in writing, software
32
+ * distributed under the License is distributed on an "AS IS" BASIS,
33
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
34
+ * See the License for the specific language governing permissions and
35
+ * limitations under the License.
36
+ */
37
+
38
+ class Runner {
39
+ constructor(config) {
40
+ this._config = void 0;
41
+ this._config = config;
42
+ }
43
+ async listTestFiles(projectNames) {
44
+ const projects = (0, _projectUtils.filterProjects)(this._config.projects, projectNames);
45
+ const report = {
46
+ projects: []
47
+ };
48
+ for (const project of projects) {
49
+ report.projects.push({
50
+ name: project.project.name,
51
+ testDir: project.project.testDir,
52
+ use: {
53
+ testIdAttribute: project.project.use.testIdAttribute
54
+ },
55
+ files: await (0, _projectUtils.collectFilesForProject)(project)
56
+ });
57
+ }
58
+ return report;
59
+ }
60
+ async runAllTests() {
61
+ const config = this._config;
62
+ const listOnly = config.cliListOnly;
63
+ const deadline = config.config.globalTimeout ? (0, _utils.monotonicTime)() + config.config.globalTimeout : 0;
64
+
65
+ // Legacy webServer support.
66
+ (0, _webServerPlugin.webServerPluginsForConfig)(config).forEach(p => config.plugins.push({
67
+ factory: p
68
+ }));
69
+ const reporter = new _internalReporter.InternalReporter(new _multiplexer.Multiplexer(await (0, _reporters.createReporters)(config, listOnly ? 'list' : 'test', false)));
70
+ const taskRunner = listOnly ? (0, _tasks.createTaskRunnerForList)(config, reporter, 'in-process', {
71
+ failOnLoadErrors: true
72
+ }) : (0, _tasks.createTaskRunner)(config, reporter);
73
+ const testRun = new _tasks.TestRun(config, reporter);
74
+ reporter.onConfigure(config.config);
75
+ const taskStatus = await taskRunner.run(testRun, deadline);
76
+ let status = testRun.failureTracker.result();
77
+ if (status === 'passed' && taskStatus !== 'passed') status = taskStatus;
78
+ const modifiedResult = await reporter.onEnd({
79
+ status
80
+ });
81
+ if (modifiedResult && modifiedResult.status) status = modifiedResult.status;
82
+ if (!listOnly) await writeLastRunInfo(testRun, status);
83
+ await reporter.onExit();
84
+
85
+ // Calling process.exit() might truncate large stdout/stderr output.
86
+ // See https://github.com/nodejs/node/issues/6456.
87
+ // See https://github.com/nodejs/node/issues/12921
88
+ await new Promise(resolve => process.stdout.write('', () => resolve()));
89
+ await new Promise(resolve => process.stderr.write('', () => resolve()));
90
+ return status;
91
+ }
92
+ async loadAllTests(mode = 'in-process') {
93
+ const config = this._config;
94
+ const errors = [];
95
+ const reporter = new _internalReporter.InternalReporter(new _multiplexer.Multiplexer([(0, _reporterV.wrapReporterAsV2)({
96
+ onError(error) {
97
+ errors.push(error);
98
+ }
99
+ })]));
100
+ const taskRunner = (0, _tasks.createTaskRunnerForList)(config, reporter, mode, {
101
+ failOnLoadErrors: true
102
+ });
103
+ const testRun = new _tasks.TestRun(config, reporter);
104
+ reporter.onConfigure(config.config);
105
+ const taskStatus = await taskRunner.run(testRun, 0);
106
+ let status = testRun.failureTracker.result();
107
+ if (status === 'passed' && taskStatus !== 'passed') status = taskStatus;
108
+ const modifiedResult = await reporter.onEnd({
109
+ status
110
+ });
111
+ if (modifiedResult && modifiedResult.status) status = modifiedResult.status;
112
+ await reporter.onExit();
113
+ return {
114
+ status,
115
+ suite: testRun.rootSuite,
116
+ errors
117
+ };
118
+ }
119
+ async watchAllTests() {
120
+ const config = this._config;
121
+ (0, _webServerPlugin.webServerPluginsForConfig)(config).forEach(p => config.plugins.push({
122
+ factory: p
123
+ }));
124
+ return await (0, _watchMode.runWatchModeLoop)(config);
125
+ }
126
+ async findRelatedTestFiles(mode, files) {
127
+ var _playwrightTest;
128
+ const result = await this.loadAllTests(mode);
129
+ if (result.status !== 'passed' || !result.suite) return {
130
+ errors: result.errors,
131
+ testFiles: []
132
+ };
133
+ const resolvedFiles = files.map(file => _path.default.resolve(process.cwd(), file));
134
+ const override = (_playwrightTest = this._config.config['@playwright/test']) === null || _playwrightTest === void 0 || (_playwrightTest = _playwrightTest['cli']) === null || _playwrightTest === void 0 ? void 0 : _playwrightTest['find-related-test-files'];
135
+ if (override) return await override(resolvedFiles, this._config, result.suite);
136
+ return {
137
+ testFiles: (0, _compilationCache.affectedTestFiles)(resolvedFiles)
138
+ };
139
+ }
140
+ }
141
+ exports.Runner = Runner;
142
+ async function writeLastRunInfo(testRun, status) {
143
+ var _testRun$rootSuite;
144
+ const [project] = (0, _projectUtils.filterProjects)(testRun.config.projects, testRun.config.cliProjectFilter);
145
+ if (!project) return;
146
+ const outputDir = project.project.outputDir;
147
+ await _fs.default.promises.mkdir(outputDir, {
148
+ recursive: true
149
+ });
150
+ const lastRunReportFile = _path.default.join(outputDir, '.last-run.json');
151
+ const failedTests = (_testRun$rootSuite = testRun.rootSuite) === null || _testRun$rootSuite === void 0 ? void 0 : _testRun$rootSuite.allTests().filter(t => !t.ok()).map(t => t.id);
152
+ const lastRunReport = JSON.stringify({
153
+ status,
154
+ failedTests
155
+ }, undefined, 2);
156
+ await _fs.default.promises.writeFile(lastRunReportFile, lastRunReport);
157
+ }
158
+ async function readLastRunInfo(config) {
159
+ const [project] = (0, _projectUtils.filterProjects)(config.projects, config.cliProjectFilter);
160
+ if (!project) return {
161
+ status: 'passed',
162
+ failedTests: []
163
+ };
164
+ const outputDir = project.project.outputDir;
165
+ try {
166
+ const lastRunReportFile = _path.default.join(outputDir, '.last-run.json');
167
+ return JSON.parse(await _fs.default.promises.readFile(lastRunReportFile, 'utf8'));
168
+ } catch {}
169
+ return {
170
+ status: 'passed',
171
+ failedTests: []
172
+ };
173
+ }
@@ -0,0 +1,96 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var sigIntWatcher_exports = {};
20
+ __export(sigIntWatcher_exports, {
21
+ SigIntWatcher: () => SigIntWatcher
22
+ });
23
+ module.exports = __toCommonJS(sigIntWatcher_exports);
24
+ class SigIntWatcher {
25
+ constructor() {
26
+ this._hadSignal = false;
27
+ let sigintCallback;
28
+ this._sigintPromise = new Promise((f) => sigintCallback = f);
29
+ this._sigintHandler = () => {
30
+ FixedNodeSIGINTHandler.off(this._sigintHandler);
31
+ this._hadSignal = true;
32
+ sigintCallback();
33
+ };
34
+ FixedNodeSIGINTHandler.on(this._sigintHandler);
35
+ }
36
+ promise() {
37
+ return this._sigintPromise;
38
+ }
39
+ hadSignal() {
40
+ return this._hadSignal;
41
+ }
42
+ disarm() {
43
+ FixedNodeSIGINTHandler.off(this._sigintHandler);
44
+ }
45
+ }
46
+ class FixedNodeSIGINTHandler {
47
+ static {
48
+ this._handlers = [];
49
+ }
50
+ static {
51
+ this._ignoreNextSIGINTs = false;
52
+ }
53
+ static {
54
+ this._handlerInstalled = false;
55
+ }
56
+ static {
57
+ this._dispatch = () => {
58
+ if (this._ignoreNextSIGINTs)
59
+ return;
60
+ this._ignoreNextSIGINTs = true;
61
+ setTimeout(() => {
62
+ this._ignoreNextSIGINTs = false;
63
+ if (!this._handlers.length)
64
+ this._uninstall();
65
+ }, 1e3);
66
+ for (const handler of this._handlers)
67
+ handler();
68
+ };
69
+ }
70
+ static _install() {
71
+ if (!this._handlerInstalled) {
72
+ this._handlerInstalled = true;
73
+ process.on("SIGINT", this._dispatch);
74
+ }
75
+ }
76
+ static _uninstall() {
77
+ if (this._handlerInstalled) {
78
+ this._handlerInstalled = false;
79
+ process.off("SIGINT", this._dispatch);
80
+ }
81
+ }
82
+ static on(handler) {
83
+ this._handlers.push(handler);
84
+ if (this._handlers.length === 1)
85
+ this._install();
86
+ }
87
+ static off(handler) {
88
+ this._handlers = this._handlers.filter((h) => h !== handler);
89
+ if (!this._ignoreNextSIGINTs && !this._handlers.length)
90
+ this._uninstall();
91
+ }
92
+ }
93
+ // Annotate the CommonJS export names for ESM import in node:
94
+ 0 && (module.exports = {
95
+ SigIntWatcher
96
+ });
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/runner/sigIntWatcher.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\nexport class SigIntWatcher {\n private _hadSignal: boolean = false;\n private _sigintPromise: Promise<void>;\n private _sigintHandler: () => void;\n constructor() {\n let sigintCallback: () => void;\n this._sigintPromise = new Promise<void>(f => sigintCallback = f);\n this._sigintHandler = () => {\n FixedNodeSIGINTHandler.off(this._sigintHandler);\n this._hadSignal = true;\n sigintCallback();\n };\n FixedNodeSIGINTHandler.on(this._sigintHandler);\n }\n\n promise(): Promise<void> {\n return this._sigintPromise;\n }\n\n hadSignal(): boolean {\n return this._hadSignal;\n }\n\n disarm() {\n FixedNodeSIGINTHandler.off(this._sigintHandler);\n }\n}\n\n// NPM/NPX will send us duplicate SIGINT signals, so we need to ignore them.\nclass FixedNodeSIGINTHandler {\n private static _handlers: (() => void)[] = [];\n private static _ignoreNextSIGINTs = false;\n private static _handlerInstalled = false;\n\n static _dispatch = () => {\n if (this._ignoreNextSIGINTs)\n return;\n\n this._ignoreNextSIGINTs = true;\n setTimeout(() => {\n this._ignoreNextSIGINTs = false;\n // We remove the handler so that second Ctrl+C immediately kills the process\n // via the default sigint handler. This is handy in the case where our shutdown\n // takes a lot of time or is buggy.\n //\n // When running through NPM we might get multiple SIGINT signals\n // for a single Ctrl+C - this is an NPM bug present since NPM v6+.\n // https://github.com/npm/cli/issues/1591\n // https://github.com/npm/cli/issues/2124\n // https://github.com/npm/cli/issues/5021\n //\n // Therefore, removing the handler too soon will just kill the process\n // with default handler without printing the results.\n // We work around this by giving NPM 1000ms to send us duplicate signals.\n // The side effect is that slow shutdown or bug in our process will force\n // the user to hit Ctrl+C again after at least a second.\n if (!this._handlers.length)\n this._uninstall();\n }, 1000);\n for (const handler of this._handlers)\n handler();\n };\n\n static _install() {\n if (!this._handlerInstalled) {\n this._handlerInstalled = true;\n process.on('SIGINT', this._dispatch);\n }\n }\n\n static _uninstall() {\n if (this._handlerInstalled) {\n this._handlerInstalled = false;\n process.off('SIGINT', this._dispatch);\n }\n }\n\n static on(handler: () => void) {\n this._handlers.push(handler);\n if (this._handlers.length === 1)\n this._install();\n }\n\n static off(handler: () => void) {\n this._handlers = this._handlers.filter(h => h !== handler);\n if (!this._ignoreNextSIGINTs && !this._handlers.length)\n this._uninstall();\n }\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAgBO,MAAM,cAAc;AAAA,EAIzB,cAAc;AAHd,SAAQ,aAAsB;AAI5B,QAAI;AACJ,SAAK,iBAAiB,IAAI,QAAc,OAAK,iBAAiB,CAAC;AAC/D,SAAK,iBAAiB,MAAM;AAC1B,6BAAuB,IAAI,KAAK,cAAc;AAC9C,WAAK,aAAa;AAClB,qBAAe;AAAA,IACjB;AACA,2BAAuB,GAAG,KAAK,cAAc;AAAA,EAC/C;AAAA,EAEA,UAAyB;AACvB,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,YAAqB;AACnB,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,SAAS;AACP,2BAAuB,IAAI,KAAK,cAAc;AAAA,EAChD;AACF;AAGA,MAAM,uBAAuB;AAAA,EAC3B;AAAA,SAAe,YAA4B,CAAC;AAAA;AAAA,EAC5C;AAAA,SAAe,qBAAqB;AAAA;AAAA,EACpC;AAAA,SAAe,oBAAoB;AAAA;AAAA,EAEnC;AAAA,SAAO,YAAY,MAAM;AACvB,UAAI,KAAK;AACP;AAEF,WAAK,qBAAqB;AAC1B,iBAAW,MAAM;AACf,aAAK,qBAAqB;AAgB1B,YAAI,CAAC,KAAK,UAAU;AAClB,eAAK,WAAW;AAAA,MACpB,GAAG,GAAI;AACP,iBAAW,WAAW,KAAK;AACzB,gBAAQ;AAAA,IACZ;AAAA;AAAA,EAEA,OAAO,WAAW;AAChB,QAAI,CAAC,KAAK,mBAAmB;AAC3B,WAAK,oBAAoB;AACzB,cAAQ,GAAG,UAAU,KAAK,SAAS;AAAA,IACrC;AAAA,EACF;AAAA,EAEA,OAAO,aAAa;AAClB,QAAI,KAAK,mBAAmB;AAC1B,WAAK,oBAAoB;AACzB,cAAQ,IAAI,UAAU,KAAK,SAAS;AAAA,IACtC;AAAA,EACF;AAAA,EAEA,OAAO,GAAG,SAAqB;AAC7B,SAAK,UAAU,KAAK,OAAO;AAC3B,QAAI,KAAK,UAAU,WAAW;AAC5B,WAAK,SAAS;AAAA,EAClB;AAAA,EAEA,OAAO,IAAI,SAAqB;AAC9B,SAAK,YAAY,KAAK,UAAU,OAAO,OAAK,MAAM,OAAO;AACzD,QAAI,CAAC,KAAK,sBAAsB,CAAC,KAAK,UAAU;AAC9C,WAAK,WAAW;AAAA,EACpB;AACF;",
6
+ "names": []
7
+ }
@@ -0,0 +1,127 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var taskRunner_exports = {};
20
+ __export(taskRunner_exports, {
21
+ TaskRunner: () => TaskRunner
22
+ });
23
+ module.exports = __toCommonJS(taskRunner_exports);
24
+ var import_utils = require("playwright-core/lib/utils");
25
+ var import_utils2 = require("playwright-core/lib/utils");
26
+ var import_utilsBundle = require("playwright-core/lib/utilsBundle");
27
+ var import_sigIntWatcher = require("./sigIntWatcher");
28
+ var import_util = require("../util");
29
+ class TaskRunner {
30
+ constructor(reporter, globalTimeoutForError) {
31
+ this._tasks = [];
32
+ this._hasErrors = false;
33
+ this._interrupted = false;
34
+ this._isTearDown = false;
35
+ this._reporter = reporter;
36
+ this._globalTimeoutForError = globalTimeoutForError;
37
+ }
38
+ addTask(task) {
39
+ this._tasks.push(task);
40
+ }
41
+ async run(context, deadline, cancelPromise) {
42
+ const { status, cleanup } = await this.runDeferCleanup(context, deadline, cancelPromise);
43
+ const teardownStatus = await cleanup();
44
+ return status === "passed" ? teardownStatus : status;
45
+ }
46
+ async runDeferCleanup(context, deadline, cancelPromise = new import_utils.ManualPromise()) {
47
+ const sigintWatcher = new import_sigIntWatcher.SigIntWatcher();
48
+ const timeoutWatcher = new TimeoutWatcher(deadline);
49
+ const teardownRunner = new TaskRunner(this._reporter, this._globalTimeoutForError);
50
+ teardownRunner._isTearDown = true;
51
+ let currentTaskName;
52
+ const taskLoop = async () => {
53
+ for (const task of this._tasks) {
54
+ currentTaskName = task.title;
55
+ if (this._interrupted)
56
+ break;
57
+ (0, import_utilsBundle.debug)("pw:test:task")(`"${task.title}" started`);
58
+ const errors = [];
59
+ const softErrors = [];
60
+ try {
61
+ teardownRunner._tasks.unshift({ title: `teardown for ${task.title}`, setup: task.teardown });
62
+ await task.setup?.(context, errors, softErrors);
63
+ } catch (e) {
64
+ (0, import_utilsBundle.debug)("pw:test:task")(`error in "${task.title}": `, e);
65
+ errors.push((0, import_util.serializeError)(e));
66
+ } finally {
67
+ for (const error of [...softErrors, ...errors])
68
+ this._reporter.onError?.(error);
69
+ if (errors.length) {
70
+ if (!this._isTearDown)
71
+ this._interrupted = true;
72
+ this._hasErrors = true;
73
+ }
74
+ }
75
+ (0, import_utilsBundle.debug)("pw:test:task")(`"${task.title}" finished`);
76
+ }
77
+ };
78
+ await Promise.race([
79
+ taskLoop(),
80
+ cancelPromise,
81
+ sigintWatcher.promise(),
82
+ timeoutWatcher.promise
83
+ ]);
84
+ sigintWatcher.disarm();
85
+ timeoutWatcher.disarm();
86
+ this._interrupted = true;
87
+ let status = "passed";
88
+ if (sigintWatcher.hadSignal() || cancelPromise?.isDone()) {
89
+ status = "interrupted";
90
+ } else if (timeoutWatcher.timedOut()) {
91
+ this._reporter.onError?.({ message: import_utils2.colors.red(`Timed out waiting ${this._globalTimeoutForError / 1e3}s for the ${currentTaskName} to run`) });
92
+ status = "timedout";
93
+ } else if (this._hasErrors) {
94
+ status = "failed";
95
+ }
96
+ cancelPromise?.resolve();
97
+ const cleanup = () => teardownRunner.runDeferCleanup(context, deadline).then((r) => r.status);
98
+ return { status, cleanup };
99
+ }
100
+ }
101
+ class TimeoutWatcher {
102
+ constructor(deadline) {
103
+ this._timedOut = false;
104
+ this.promise = new import_utils.ManualPromise();
105
+ if (!deadline)
106
+ return;
107
+ if (deadline - (0, import_utils.monotonicTime)() <= 0) {
108
+ this._timedOut = true;
109
+ this.promise.resolve();
110
+ return;
111
+ }
112
+ this._timer = setTimeout(() => {
113
+ this._timedOut = true;
114
+ this.promise.resolve();
115
+ }, deadline - (0, import_utils.monotonicTime)());
116
+ }
117
+ timedOut() {
118
+ return this._timedOut;
119
+ }
120
+ disarm() {
121
+ clearTimeout(this._timer);
122
+ }
123
+ }
124
+ // Annotate the CommonJS export names for ESM import in node:
125
+ 0 && (module.exports = {
126
+ TaskRunner
127
+ });
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/runner/taskRunner.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 { ManualPromise, monotonicTime } from 'playwright-core/lib/utils';\nimport { colors } from 'playwright-core/lib/utils';\nimport { debug } from 'playwright-core/lib/utilsBundle';\n\n\nimport { SigIntWatcher } from './sigIntWatcher';\nimport { serializeError } from '../util';\n\nimport type { FullResult, TestError } from '../../types/testReporter';\nimport type { InternalReporter } from '../reporters/internalReporter';\n\ntype TaskPhase<Context> = (context: Context, errors: TestError[], softErrors: TestError[]) => Promise<void> | void;\nexport type Task<Context> = { title: string, setup?: TaskPhase<Context>, teardown?: TaskPhase<Context> };\n\nexport class TaskRunner<Context> {\n private _tasks: Task<Context>[] = [];\n private _reporter: InternalReporter;\n private _hasErrors = false;\n private _interrupted = false;\n private _isTearDown = false;\n private _globalTimeoutForError: number;\n\n constructor(reporter: InternalReporter, globalTimeoutForError: number) {\n this._reporter = reporter;\n this._globalTimeoutForError = globalTimeoutForError;\n }\n\n addTask(task: Task<Context>) {\n this._tasks.push(task);\n }\n\n async run(context: Context, deadline: number, cancelPromise?: ManualPromise<void>): Promise<FullResult['status']> {\n const { status, cleanup } = await this.runDeferCleanup(context, deadline, cancelPromise);\n const teardownStatus = await cleanup();\n return status === 'passed' ? teardownStatus : status;\n }\n\n async runDeferCleanup(context: Context, deadline: number, cancelPromise = new ManualPromise<void>()): Promise<{ status: FullResult['status'], cleanup: () => Promise<FullResult['status']> }> {\n const sigintWatcher = new SigIntWatcher();\n const timeoutWatcher = new TimeoutWatcher(deadline);\n const teardownRunner = new TaskRunner<Context>(this._reporter, this._globalTimeoutForError);\n teardownRunner._isTearDown = true;\n\n let currentTaskName: string | undefined;\n\n const taskLoop = async () => {\n for (const task of this._tasks) {\n currentTaskName = task.title;\n if (this._interrupted)\n break;\n debug('pw:test:task')(`\"${task.title}\" started`);\n const errors: TestError[] = [];\n const softErrors: TestError[] = [];\n try {\n teardownRunner._tasks.unshift({ title: `teardown for ${task.title}`, setup: task.teardown });\n await task.setup?.(context, errors, softErrors);\n } catch (e) {\n debug('pw:test:task')(`error in \"${task.title}\": `, e);\n errors.push(serializeError(e));\n } finally {\n for (const error of [...softErrors, ...errors])\n this._reporter.onError?.(error);\n if (errors.length) {\n if (!this._isTearDown)\n this._interrupted = true;\n this._hasErrors = true;\n }\n }\n debug('pw:test:task')(`\"${task.title}\" finished`);\n }\n };\n\n await Promise.race([\n taskLoop(),\n cancelPromise,\n sigintWatcher.promise(),\n timeoutWatcher.promise,\n ]);\n\n sigintWatcher.disarm();\n timeoutWatcher.disarm();\n\n // Prevent subsequent tasks from running.\n this._interrupted = true;\n\n let status: FullResult['status'] = 'passed';\n if (sigintWatcher.hadSignal() || cancelPromise?.isDone()) {\n status = 'interrupted';\n } else if (timeoutWatcher.timedOut()) {\n this._reporter.onError?.({ message: colors.red(`Timed out waiting ${this._globalTimeoutForError / 1000}s for the ${currentTaskName} to run`) });\n status = 'timedout';\n } else if (this._hasErrors) {\n status = 'failed';\n }\n cancelPromise?.resolve();\n // Note that upon hitting deadline, we \"run cleanup\", but it exits immediately\n // because of the same deadline. Essentially, we're not performing any cleanup.\n const cleanup = () => teardownRunner.runDeferCleanup(context, deadline).then(r => r.status);\n return { status, cleanup };\n }\n}\n\nclass TimeoutWatcher {\n private _timedOut = false;\n readonly promise = new ManualPromise();\n private _timer: NodeJS.Timeout | undefined;\n\n constructor(deadline: number) {\n if (!deadline)\n return;\n\n if (deadline - monotonicTime() <= 0) {\n this._timedOut = true;\n this.promise.resolve();\n return;\n }\n this._timer = setTimeout(() => {\n this._timedOut = true;\n this.promise.resolve();\n }, deadline - monotonicTime());\n }\n\n timedOut(): boolean {\n return this._timedOut;\n }\n\n disarm() {\n clearTimeout(this._timer);\n }\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["import_utils"]
7
+ }