@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,135 @@
1
+ ---
2
+ name: planner
3
+ description: Use this agent when you need to create comprehensive test plan for a web application or website
4
+ model: sonnet
5
+ color: green
6
+ tools:
7
+ - ls
8
+ - grep
9
+ - read
10
+ - write
11
+ - playwright-test/browser_click
12
+ - playwright-test/browser_close
13
+ - playwright-test/browser_console_messages
14
+ - playwright-test/browser_drag
15
+ - playwright-test/browser_evaluate
16
+ - playwright-test/browser_file_upload
17
+ - playwright-test/browser_handle_dialog
18
+ - playwright-test/browser_hover
19
+ - playwright-test/browser_navigate
20
+ - playwright-test/browser_navigate_back
21
+ - playwright-test/browser_network_requests
22
+ - playwright-test/browser_press_key
23
+ - playwright-test/browser_select_option
24
+ - playwright-test/browser_snapshot
25
+ - playwright-test/browser_take_screenshot
26
+ - playwright-test/browser_type
27
+ - playwright-test/browser_wait_for
28
+ - playwright-test/planner_setup_page
29
+ ---
30
+
31
+ You are an expert web test planner with extensive experience in quality assurance, user experience testing, and test
32
+ scenario design. Your expertise includes functional testing, edge case identification, and comprehensive test coverage
33
+ planning.
34
+
35
+ You will:
36
+
37
+ 1. **Navigate and Explore**
38
+ - Invoke the `planner_setup_page` tool once to set up page before using any other tools
39
+ - Explore the browser snapshot
40
+ - Do not take screenshots unless absolutely necessary
41
+ - Use browser_* tools to navigate and discover interface
42
+ - Thoroughly explore the interface, identifying all interactive elements, forms, navigation paths, and functionality
43
+
44
+ 2. **Analyze User Flows**
45
+ - Map out the primary user journeys and identify critical paths through the application
46
+ - Consider different user types and their typical behaviors
47
+
48
+ 3. **Design Comprehensive Scenarios**
49
+
50
+ Create detailed test scenarios that cover:
51
+ - Happy path scenarios (normal user behavior)
52
+ - Edge cases and boundary conditions
53
+ - Error handling and validation
54
+
55
+ 4. **Structure Test Plans**
56
+
57
+ Each scenario must include:
58
+ - Clear, descriptive title
59
+ - Detailed step-by-step instructions
60
+ - Expected outcomes where appropriate
61
+ - Assumptions about starting state (always assume blank/fresh state)
62
+ - Success criteria and failure conditions
63
+
64
+ 5. **Create Documentation**
65
+
66
+ Save your test plan as requested:
67
+ - Executive summary of the tested page/application
68
+ - Individual scenarios as separate sections
69
+ - Each scenario formatted with numbered steps
70
+ - Clear expected results for verification
71
+
72
+ <example-spec>
73
+ # TodoMVC Application - Comprehensive Test Plan
74
+
75
+ ## Application Overview
76
+
77
+ The TodoMVC application is a React-based todo list manager that provides core task management functionality. The
78
+ application features:
79
+
80
+ - **Task Management**: Add, edit, complete, and delete individual todos
81
+ - **Bulk Operations**: Mark all todos as complete/incomplete and clear all completed todos
82
+ - **Filtering**: View todos by All, Active, or Completed status
83
+ - **URL Routing**: Support for direct navigation to filtered views via URLs
84
+ - **Counter Display**: Real-time count of active (incomplete) todos
85
+ - **Persistence**: State maintained during session (browser refresh behavior not tested)
86
+
87
+ ## Test Scenarios
88
+
89
+ ### 1. Adding New Todos
90
+
91
+ **Seed:** `tests/seed.spec.ts`
92
+
93
+ #### 1.1 Add Valid Todo
94
+ **Steps:**
95
+ 1. Click in the "What needs to be done?" input field
96
+ 2. Type "Buy groceries"
97
+ 3. Press Enter key
98
+
99
+ **Expected Results:**
100
+ - Todo appears in the list with unchecked checkbox
101
+ - Counter shows "1 item left"
102
+ - Input field is cleared and ready for next entry
103
+ - Todo list controls become visible (Mark all as complete checkbox)
104
+
105
+ #### 1.2
106
+ ...
107
+ </example-spec>
108
+
109
+ **Quality Standards**:
110
+ - Write steps that are specific enough for any tester to follow
111
+ - Include negative testing scenarios
112
+ - Ensure scenarios are independent and can be run in any order
113
+
114
+ **Output Format**: Always save the complete test plan as a markdown file with clear headings, numbered steps, and
115
+ professional formatting suitable for sharing with development and QA teams.
116
+
117
+ <example>
118
+ Context: User wants to test a new e-commerce checkout flow.
119
+ user: 'I need test scenarios for our new checkout process at https://mystore.com/checkout'
120
+ assistant: 'I'll use the planner agent to navigate to your checkout page and create comprehensive test
121
+ scenarios.'
122
+ <commentary>
123
+ The user needs test planning for a specific web page, so use the planner agent to explore and create
124
+ test scenarios.
125
+ </commentary>
126
+ </example>
127
+ <example>
128
+ Context: User has deployed a new feature and wants thorough testing coverage.
129
+ user: 'Can you help me test our new user dashboard at https://app.example.com/dashboard?'
130
+ assistant: 'I'll launch the planner agent to explore your dashboard and develop detailed test
131
+ scenarios.'
132
+ <commentary>
133
+ This requires web exploration and test scenario creation, perfect for the planner agent.
134
+ </commentary>
135
+ </example>
package/lib/cli.js ADDED
@@ -0,0 +1,274 @@
1
+ "use strict";
2
+
3
+ var _fs = _interopRequireDefault(require("fs"));
4
+ var _path = _interopRequireDefault(require("path"));
5
+ var _runner = require("./runner/runner");
6
+ var _utils = require("playwright-core/lib/utils");
7
+ var _util = require("./util");
8
+ var _html = require("./reporters/html");
9
+ var _merge = require("./reporters/merge");
10
+ var _configLoader = require("./common/configLoader");
11
+ var _config = require("./common/config");
12
+ var _program = _interopRequireDefault(require("playwright-core/lib/cli/program"));
13
+ var _base = require("./reporters/base");
14
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
15
+ /**
16
+ * Copyright (c) Microsoft Corporation.
17
+ *
18
+ * Licensed under the Apache License, Version 2.0 (the 'License");
19
+ * you may not use this file except in compliance with the License.
20
+ * You may obtain a copy of the License at
21
+ *
22
+ * http://www.apache.org/licenses/LICENSE-2.0
23
+ *
24
+ * Unless required by applicable law or agreed to in writing, software
25
+ * distributed under the License is distributed on an "AS IS" BASIS,
26
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
27
+ * See the License for the specific language governing permissions and
28
+ * limitations under the License.
29
+ */
30
+
31
+ /* eslint-disable no-console */
32
+
33
+ function addTestCommand(program) {
34
+ const command = program.command('test [test-filter...]');
35
+ command.description('run tests with Playwright Test');
36
+ const options = testOptions.sort((a, b) => a[0].replace(/-/g, '').localeCompare(b[0].replace(/-/g, '')));
37
+ options.forEach(([name, description]) => command.option(name, description));
38
+ command.action(async (args, opts) => {
39
+ try {
40
+ await runTests(args, opts);
41
+ } catch (e) {
42
+ console.error(e);
43
+ (0, _utils.gracefullyProcessExitDoNotHang)(1);
44
+ }
45
+ });
46
+ command.addHelpText('afterAll', `
47
+ Arguments [test-filter...]:
48
+ Pass arguments to filter test files. Each argument is treated as a regular expression. Matching is performed against the absolute file paths.
49
+
50
+ Examples:
51
+ $ npx playwright test my.spec.ts
52
+ $ npx playwright test some.spec.ts:42
53
+ $ npx playwright test --headed
54
+ $ npx playwright test --project=webkit`);
55
+ }
56
+ function addListFilesCommand(program) {
57
+ const command = program.command('list-files [file-filter...]', {
58
+ hidden: true
59
+ });
60
+ command.description('List files with Playwright Test tests');
61
+ command.option('-c, --config <file>', `Configuration file, or a test directory with optional "playwright.config.{m,c}?{js,ts}"`);
62
+ command.option('--project <project-name...>', `Only run tests from the specified list of projects (default: list all projects)`);
63
+ command.action(async (args, opts) => {
64
+ try {
65
+ await listTestFiles(opts);
66
+ } catch (e) {
67
+ console.error(e);
68
+ (0, _utils.gracefullyProcessExitDoNotHang)(1);
69
+ }
70
+ });
71
+ }
72
+ function addShowReportCommand(program) {
73
+ const command = program.command('show-report [report]');
74
+ command.description('show HTML report');
75
+ command.action((report, options) => (0, _html.showHTMLReport)(report, options.host, +options.port));
76
+ command.option('--host <host>', 'Host to serve report on', 'localhost');
77
+ command.option('--port <port>', 'Port to serve report on', '9323');
78
+ command.addHelpText('afterAll', `
79
+ Arguments [report]:
80
+ When specified, opens given report, otherwise opens last generated report.
81
+
82
+ Examples:
83
+ $ npx playwright show-report
84
+ $ npx playwright show-report playwright-report`);
85
+ }
86
+ function addMergeReportsCommand(program) {
87
+ const command = program.command('merge-reports [dir]', {
88
+ hidden: true
89
+ });
90
+ command.description('merge multiple blob reports (for sharded tests) into a single report');
91
+ command.action(async (dir, options) => {
92
+ try {
93
+ await mergeReports(dir, options);
94
+ } catch (e) {
95
+ console.error(e);
96
+ (0, _utils.gracefullyProcessExitDoNotHang)(1);
97
+ }
98
+ });
99
+ command.option('-c, --config <file>', `Configuration file. Can be used to specify additional configuration for the output report.`);
100
+ command.option('--reporter <reporter>', `Reporter to use, comma-separated, can be ${_config.builtInReporters.map(name => `"${name}"`).join(', ')} (default: "${_config.defaultReporter}")`);
101
+ command.addHelpText('afterAll', `
102
+ Arguments [dir]:
103
+ Directory containing blob reports.
104
+
105
+ Examples:
106
+ $ npx playwright merge-reports playwright-report`);
107
+ }
108
+ async function runTests(args, opts) {
109
+ await (0, _utils.startProfiling)();
110
+
111
+ // When no --config option is passed, let's look for the config file in the current directory.
112
+ const configFileOrDirectory = opts.config ? _path.default.resolve(process.cwd(), opts.config) : process.cwd();
113
+ const resolvedConfigFile = (0, _configLoader.resolveConfigFile)(configFileOrDirectory);
114
+ if (restartWithExperimentalTsEsm(resolvedConfigFile)) return;
115
+ const overrides = overridesFromOptions(opts);
116
+ const configLoader = new _configLoader.ConfigLoader(overrides);
117
+ let config;
118
+ if (resolvedConfigFile) config = await configLoader.loadConfigFile(resolvedConfigFile, opts.deps === false);else config = await configLoader.loadEmptyConfig(configFileOrDirectory);
119
+ config.cliArgs = args;
120
+ config.cliGrep = opts.grep;
121
+ config.cliGrepInvert = opts.grepInvert;
122
+ config.cliListOnly = !!opts.list;
123
+ config.cliProjectFilter = opts.project || undefined;
124
+ config.cliPassWithNoTests = !!opts.passWithNoTests;
125
+ const runner = new _runner.Runner(config);
126
+ let status;
127
+ if (opts.ui || opts.uiHost || opts.uiPort) status = await runner.uiAllTests({
128
+ host: opts.uiHost,
129
+ port: opts.uiPort ? +opts.uiPort : undefined
130
+ });else if (process.env.PWTEST_WATCH) status = await runner.watchAllTests();else status = await runner.runAllTests();
131
+ await (0, _utils.stopProfiling)('runner');
132
+ const exitCode = status === 'interrupted' ? 130 : status === 'passed' ? 0 : 1;
133
+ (0, _utils.gracefullyProcessExitDoNotHang)(exitCode);
134
+ }
135
+ async function listTestFiles(opts) {
136
+ // Redefine process.stdout.write in case config decides to pollute stdio.
137
+ const stdoutWrite = process.stdout.write.bind(process.stdout);
138
+ process.stdout.write = () => {};
139
+ process.stderr.write = () => {};
140
+ const configFileOrDirectory = opts.config ? _path.default.resolve(process.cwd(), opts.config) : process.cwd();
141
+ const resolvedConfigFile = (0, _configLoader.resolveConfigFile)(configFileOrDirectory);
142
+ if (restartWithExperimentalTsEsm(resolvedConfigFile)) return;
143
+ try {
144
+ const configLoader = new _configLoader.ConfigLoader();
145
+ const config = await configLoader.loadConfigFile(resolvedConfigFile);
146
+ const runner = new _runner.Runner(config);
147
+ const report = await runner.listTestFiles(opts.project);
148
+ stdoutWrite(JSON.stringify(report), () => {
149
+ (0, _utils.gracefullyProcessExitDoNotHang)(0);
150
+ });
151
+ } catch (e) {
152
+ const error = (0, _util.serializeError)(e);
153
+ error.location = (0, _base.prepareErrorStack)(e.stack).location;
154
+ stdoutWrite(JSON.stringify({
155
+ error
156
+ }), () => {
157
+ (0, _utils.gracefullyProcessExitDoNotHang)(0);
158
+ });
159
+ }
160
+ }
161
+ async function mergeReports(reportDir, opts) {
162
+ let configFile = opts.config;
163
+ if (configFile) {
164
+ configFile = _path.default.resolve(process.cwd(), configFile);
165
+ if (!_fs.default.existsSync(configFile)) throw new Error(`${configFile} does not exist`);
166
+ if (!_fs.default.statSync(configFile).isFile()) throw new Error(`${configFile} is not a file`);
167
+ }
168
+ if (restartWithExperimentalTsEsm(configFile)) return;
169
+ const configLoader = new _configLoader.ConfigLoader();
170
+ const config = await (configFile ? configLoader.loadConfigFile(configFile) : configLoader.loadEmptyConfig(process.cwd()));
171
+ const dir = _path.default.resolve(process.cwd(), reportDir || '');
172
+ const dirStat = await _fs.default.promises.stat(dir).catch(e => null);
173
+ if (!dirStat) throw new Error('Directory does not exist: ' + dir);
174
+ if (!dirStat.isDirectory()) throw new Error(`"${dir}" is not a directory`);
175
+ let reporterDescriptions = resolveReporterOption(opts.reporter);
176
+ if (!reporterDescriptions && configFile) reporterDescriptions = config.config.reporter;
177
+ if (!reporterDescriptions) reporterDescriptions = [[_config.defaultReporter]];
178
+ const rootDirOverride = configFile ? config.config.rootDir : undefined;
179
+ await (0, _merge.createMergedReport)(config, dir, reporterDescriptions, rootDirOverride);
180
+ (0, _utils.gracefullyProcessExitDoNotHang)(0);
181
+ }
182
+ function overridesFromOptions(options) {
183
+ const shardPair = options.shard ? options.shard.split('/').map(t => parseInt(t, 10)) : undefined;
184
+ const overrides = {
185
+ forbidOnly: options.forbidOnly ? true : undefined,
186
+ fullyParallel: options.fullyParallel ? true : undefined,
187
+ globalTimeout: options.globalTimeout ? parseInt(options.globalTimeout, 10) : undefined,
188
+ maxFailures: options.x ? 1 : options.maxFailures ? parseInt(options.maxFailures, 10) : undefined,
189
+ outputDir: options.output ? _path.default.resolve(process.cwd(), options.output) : undefined,
190
+ quiet: options.quiet ? options.quiet : undefined,
191
+ repeatEach: options.repeatEach ? parseInt(options.repeatEach, 10) : undefined,
192
+ retries: options.retries ? parseInt(options.retries, 10) : undefined,
193
+ reporter: resolveReporterOption(options.reporter),
194
+ shard: shardPair ? {
195
+ current: shardPair[0],
196
+ total: shardPair[1]
197
+ } : undefined,
198
+ timeout: options.timeout ? parseInt(options.timeout, 10) : undefined,
199
+ ignoreSnapshots: options.ignoreSnapshots ? !!options.ignoreSnapshots : undefined,
200
+ updateSnapshots: options.updateSnapshots ? 'all' : undefined,
201
+ workers: options.workers
202
+ };
203
+ if (options.browser) {
204
+ const browserOpt = options.browser.toLowerCase();
205
+ if (!['all', 'chromium', 'firefox', 'webkit'].includes(browserOpt)) throw new Error(`Unsupported browser "${options.browser}", must be one of "all", "chromium", "firefox" or "webkit"`);
206
+ const browserNames = browserOpt === 'all' ? ['chromium', 'firefox', 'webkit'] : [browserOpt];
207
+ overrides.projects = browserNames.map(browserName => {
208
+ return {
209
+ name: browserName,
210
+ use: {
211
+ browserName
212
+ }
213
+ };
214
+ });
215
+ }
216
+ if (options.headed || options.debug) overrides.use = {
217
+ headless: false
218
+ };
219
+ if (!options.ui && options.debug) {
220
+ overrides.maxFailures = 1;
221
+ overrides.timeout = 0;
222
+ overrides.workers = 1;
223
+ process.env.PWDEBUG = '1';
224
+ }
225
+ if (!options.ui && options.trace) {
226
+ if (!kTraceModes.includes(options.trace)) throw new Error(`Unsupported trace mode "${options.trace}", must be one of ${kTraceModes.map(mode => `"${mode}"`).join(', ')}`);
227
+ overrides.use = overrides.use || {};
228
+ overrides.use.trace = options.trace;
229
+ }
230
+ return overrides;
231
+ }
232
+ function resolveReporterOption(reporter) {
233
+ if (!reporter || !reporter.length) return undefined;
234
+ return reporter.split(',').map(r => [resolveReporter(r)]);
235
+ }
236
+ function resolveReporter(id) {
237
+ if (_config.builtInReporters.includes(id)) return id;
238
+ const localPath = _path.default.resolve(process.cwd(), id);
239
+ if (_fs.default.existsSync(localPath)) return localPath;
240
+ return require.resolve(id, {
241
+ paths: [process.cwd()]
242
+ });
243
+ }
244
+ function restartWithExperimentalTsEsm(configFile) {
245
+ const nodeVersion = +process.versions.node.split('.')[0];
246
+ // New experimental loader is only supported on Node 16+.
247
+ if (nodeVersion < 16) return false;
248
+ if (!configFile) return false;
249
+ if (process.env.PW_DISABLE_TS_ESM) return false;
250
+ if (process.env.PW_TS_ESM_ON) {
251
+ // clear execArgv after restart, so that childProcess.fork in user code does not inherit our loader.
252
+ process.execArgv = (0, _util.execArgvWithoutExperimentalLoaderOptions)();
253
+ return false;
254
+ }
255
+ if (!(0, _util.fileIsModule)(configFile)) return false;
256
+ const innerProcess = require('child_process').fork(require.resolve('./cli'), process.argv.slice(2), {
257
+ env: {
258
+ ...process.env,
259
+ PW_TS_ESM_ON: '1'
260
+ },
261
+ execArgv: (0, _util.execArgvWithExperimentalLoaderOptions)()
262
+ });
263
+ innerProcess.on('close', code => {
264
+ if (code !== 0 && code !== null) (0, _utils.gracefullyProcessExitDoNotHang)(code);
265
+ });
266
+ return true;
267
+ }
268
+ const kTraceModes = ['on', 'off', 'on-first-retry', 'on-all-retries', 'retain-on-failure'];
269
+ const testOptions = [['--browser <browser>', `Browser to use for tests, one of "all", "chromium", "firefox" or "webkit" (default: "chromium")`], ['-c, --config <file>', `Configuration file, or a test directory with optional "playwright.config.{m,c}?{js,ts}"`], ['--debug', `Run tests with Playwright Inspector. Shortcut for "PWDEBUG=1" environment variable and "--timeout=0 --max-failures=1 --headed --workers=1" options`], ['--forbid-only', `Fail if test.only is called (default: false)`], ['--fully-parallel', `Run all tests in parallel (default: false)`], ['--global-timeout <timeout>', `Maximum time this test suite can run in milliseconds (default: unlimited)`], ['-g, --grep <grep>', `Only run tests matching this regular expression (default: ".*")`], ['-gv, --grep-invert <grep>', `Only run tests that do not match this regular expression`], ['--headed', `Run tests in headed browsers (default: headless)`], ['--ignore-snapshots', `Ignore screenshot and snapshot expectations`], ['--list', `Collect all the tests and report them, but do not run`], ['--max-failures <N>', `Stop after the first N failures`], ['--no-deps', 'Do not run project dependencies'], ['--output <dir>', `Folder for output artifacts (default: "test-results")`], ['--pass-with-no-tests', `Makes test run succeed even if no tests were found`], ['--project <project-name...>', `Only run tests from the specified list of projects (default: run all projects)`], ['--quiet', `Suppress stdio`], ['--repeat-each <N>', `Run each test N times (default: 1)`], ['--reporter <reporter>', `Reporter to use, comma-separated, can be ${_config.builtInReporters.map(name => `"${name}"`).join(', ')} (default: "${_config.defaultReporter}")`], ['--retries <retries>', `Maximum retry count for flaky tests, zero for no retries (default: no retries)`], ['--shard <shard>', `Shard tests and execute only the selected shard, specify in the form "current/all", 1-based, for example "3/5"`], ['--timeout <timeout>', `Specify test timeout threshold in milliseconds, zero for unlimited (default: ${_config.defaultTimeout})`], ['--trace <mode>', `Force tracing mode, can be ${kTraceModes.map(mode => `"${mode}"`).join(', ')}`], ['--ui', `Run tests in interactive UI mode`], ['--ui-host <host>', 'Host to serve UI on; specifying this option opens UI in a browser tab'], ['--ui-port <port>', 'Port to serve UI on, 0 for any free port; specifying this option opens UI in a browser tab'], ['-u, --update-snapshots', `Update snapshots with actual results (default: only create missing snapshots)`], ['-j, --workers <workers>', `Number of concurrent workers or percentage of logical CPU cores, use 1 to run in a single worker (default: 50%)`], ['-x', `Stop after the first failure`]];
270
+ addTestCommand(_program.default);
271
+ addShowReportCommand(_program.default);
272
+ addListFilesCommand(_program.default);
273
+ addMergeReportsCommand(_program.default);
274
+ _program.default.parse(process.argv);