@one2x/playwright 1.57.0-alpha.1

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 (331) 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/copilot-setup-steps.yml +34 -0
  12. package/lib/agents/generateAgents.js +394 -0
  13. package/lib/agents/generateAgents.js.map +7 -0
  14. package/lib/agents/playwright-test-coverage.prompt.md +31 -0
  15. package/lib/agents/playwright-test-generate.prompt.md +8 -0
  16. package/lib/agents/playwright-test-generator.agent.md +88 -0
  17. package/lib/agents/playwright-test-heal.prompt.md +6 -0
  18. package/lib/agents/playwright-test-healer.agent.md +55 -0
  19. package/lib/agents/playwright-test-plan.prompt.md +9 -0
  20. package/lib/agents/playwright-test-planner.agent.md +117 -0
  21. package/lib/common/config.js +280 -0
  22. package/lib/common/config.js.map +7 -0
  23. package/lib/common/configLoader.js +344 -0
  24. package/lib/common/configLoader.js.map +7 -0
  25. package/lib/common/esmLoaderHost.js +102 -0
  26. package/lib/common/esmLoaderHost.js.map +7 -0
  27. package/lib/common/expectBundle.js +52 -0
  28. package/lib/common/expectBundle.js.map +7 -0
  29. package/lib/common/expectBundleImpl.js +389 -0
  30. package/lib/common/expectBundleImpl.js.map +7 -0
  31. package/lib/common/fixtures.js +302 -0
  32. package/lib/common/fixtures.js.map +7 -0
  33. package/lib/common/globals.js +58 -0
  34. package/lib/common/globals.js.map +7 -0
  35. package/lib/common/ipc.js +60 -0
  36. package/lib/common/ipc.js.map +7 -0
  37. package/lib/common/poolBuilder.js +85 -0
  38. package/lib/common/poolBuilder.js.map +7 -0
  39. package/lib/common/process.js +104 -0
  40. package/lib/common/process.js.map +7 -0
  41. package/lib/common/suiteUtils.js +140 -0
  42. package/lib/common/suiteUtils.js.map +7 -0
  43. package/lib/common/test.js +321 -0
  44. package/lib/common/test.js.map +7 -0
  45. package/lib/common/testLoader.js +101 -0
  46. package/lib/common/testLoader.js.map +7 -0
  47. package/lib/common/testType.js +298 -0
  48. package/lib/common/testType.js.map +7 -0
  49. package/lib/common/validators.js +68 -0
  50. package/lib/common/validators.js.map +7 -0
  51. package/lib/fsWatcher.js +67 -0
  52. package/lib/fsWatcher.js.map +7 -0
  53. package/lib/index.js +682 -0
  54. package/lib/index.js.map +7 -0
  55. package/lib/internalsForTest.js +42 -0
  56. package/lib/internalsForTest.js.map +7 -0
  57. package/lib/isomorphic/events.js +77 -0
  58. package/lib/isomorphic/events.js.map +7 -0
  59. package/lib/isomorphic/folders.js +30 -0
  60. package/lib/isomorphic/folders.js.map +7 -0
  61. package/lib/isomorphic/stringInternPool.js +69 -0
  62. package/lib/isomorphic/stringInternPool.js.map +7 -0
  63. package/lib/isomorphic/teleReceiver.js +508 -0
  64. package/lib/isomorphic/teleReceiver.js.map +7 -0
  65. package/lib/isomorphic/teleSuiteUpdater.js +137 -0
  66. package/lib/isomorphic/teleSuiteUpdater.js.map +7 -0
  67. package/lib/isomorphic/testServerConnection.js +211 -0
  68. package/lib/isomorphic/testServerConnection.js.map +7 -0
  69. package/lib/isomorphic/testServerInterface.js +16 -0
  70. package/lib/isomorphic/testServerInterface.js.map +7 -0
  71. package/lib/isomorphic/testTree.js +334 -0
  72. package/lib/isomorphic/testTree.js.map +7 -0
  73. package/lib/isomorphic/types.d.js +16 -0
  74. package/lib/isomorphic/types.d.js.map +7 -0
  75. package/lib/loader/loaderMain.js +59 -0
  76. package/lib/loader/loaderMain.js.map +7 -0
  77. package/lib/matchers/expect.js +325 -0
  78. package/lib/matchers/expect.js.map +7 -0
  79. package/lib/matchers/matcherHint.js +87 -0
  80. package/lib/matchers/matcherHint.js.map +7 -0
  81. package/lib/matchers/matchers.js +366 -0
  82. package/lib/matchers/matchers.js.map +7 -0
  83. package/lib/matchers/toBeTruthy.js +73 -0
  84. package/lib/matchers/toBeTruthy.js.map +7 -0
  85. package/lib/matchers/toEqual.js +99 -0
  86. package/lib/matchers/toEqual.js.map +7 -0
  87. package/lib/matchers/toHaveURL.js +102 -0
  88. package/lib/matchers/toHaveURL.js.map +7 -0
  89. package/lib/matchers/toMatchAriaSnapshot.js +159 -0
  90. package/lib/matchers/toMatchAriaSnapshot.js.map +7 -0
  91. package/lib/matchers/toMatchSnapshot.js +341 -0
  92. package/lib/matchers/toMatchSnapshot.js.map +7 -0
  93. package/lib/matchers/toMatchText.js +99 -0
  94. package/lib/matchers/toMatchText.js.map +7 -0
  95. package/lib/mcp/browser/actions.d.js +16 -0
  96. package/lib/mcp/browser/actions.d.js.map +7 -0
  97. package/lib/mcp/browser/browserContextFactory.js +357 -0
  98. package/lib/mcp/browser/browserContextFactory.js.map +7 -0
  99. package/lib/mcp/browser/browserServerBackend.js +76 -0
  100. package/lib/mcp/browser/browserServerBackend.js.map +7 -0
  101. package/lib/mcp/browser/codegen.js +66 -0
  102. package/lib/mcp/browser/codegen.js.map +7 -0
  103. package/lib/mcp/browser/config.js +425 -0
  104. package/lib/mcp/browser/config.js.map +7 -0
  105. package/lib/mcp/browser/context.js +287 -0
  106. package/lib/mcp/browser/context.js.map +7 -0
  107. package/lib/mcp/browser/response.js +228 -0
  108. package/lib/mcp/browser/response.js.map +7 -0
  109. package/lib/mcp/browser/sessionLog.js +160 -0
  110. package/lib/mcp/browser/sessionLog.js.map +7 -0
  111. package/lib/mcp/browser/tab.js +280 -0
  112. package/lib/mcp/browser/tab.js.map +7 -0
  113. package/lib/mcp/browser/tools/actionRetry.js +40 -0
  114. package/lib/mcp/browser/tools/actionRetry.js.map +7 -0
  115. package/lib/mcp/browser/tools/common.js +63 -0
  116. package/lib/mcp/browser/tools/common.js.map +7 -0
  117. package/lib/mcp/browser/tools/console.js +44 -0
  118. package/lib/mcp/browser/tools/console.js.map +7 -0
  119. package/lib/mcp/browser/tools/dialogs.js +60 -0
  120. package/lib/mcp/browser/tools/dialogs.js.map +7 -0
  121. package/lib/mcp/browser/tools/evaluate.js +69 -0
  122. package/lib/mcp/browser/tools/evaluate.js.map +7 -0
  123. package/lib/mcp/browser/tools/files.js +58 -0
  124. package/lib/mcp/browser/tools/files.js.map +7 -0
  125. package/lib/mcp/browser/tools/form.js +79 -0
  126. package/lib/mcp/browser/tools/form.js.map +7 -0
  127. package/lib/mcp/browser/tools/install.js +69 -0
  128. package/lib/mcp/browser/tools/install.js.map +7 -0
  129. package/lib/mcp/browser/tools/keyboard.js +84 -0
  130. package/lib/mcp/browser/tools/keyboard.js.map +7 -0
  131. package/lib/mcp/browser/tools/mouse.js +107 -0
  132. package/lib/mcp/browser/tools/mouse.js.map +7 -0
  133. package/lib/mcp/browser/tools/navigate.js +62 -0
  134. package/lib/mcp/browser/tools/navigate.js.map +7 -0
  135. package/lib/mcp/browser/tools/network.js +54 -0
  136. package/lib/mcp/browser/tools/network.js.map +7 -0
  137. package/lib/mcp/browser/tools/pdf.js +59 -0
  138. package/lib/mcp/browser/tools/pdf.js.map +7 -0
  139. package/lib/mcp/browser/tools/screenshot.js +106 -0
  140. package/lib/mcp/browser/tools/screenshot.js.map +7 -0
  141. package/lib/mcp/browser/tools/snapshot.js +312 -0
  142. package/lib/mcp/browser/tools/snapshot.js.map +7 -0
  143. package/lib/mcp/browser/tools/tabs.js +67 -0
  144. package/lib/mcp/browser/tools/tabs.js.map +7 -0
  145. package/lib/mcp/browser/tools/tool.js +49 -0
  146. package/lib/mcp/browser/tools/tool.js.map +7 -0
  147. package/lib/mcp/browser/tools/tracing.js +74 -0
  148. package/lib/mcp/browser/tools/tracing.js.map +7 -0
  149. package/lib/mcp/browser/tools/utils.js +96 -0
  150. package/lib/mcp/browser/tools/utils.js.map +7 -0
  151. package/lib/mcp/browser/tools/verify.js +153 -0
  152. package/lib/mcp/browser/tools/verify.js.map +7 -0
  153. package/lib/mcp/browser/tools/wait.js +63 -0
  154. package/lib/mcp/browser/tools/wait.js.map +7 -0
  155. package/lib/mcp/browser/tools.js +80 -0
  156. package/lib/mcp/browser/tools.js.map +7 -0
  157. package/lib/mcp/browser/watchdog.js +44 -0
  158. package/lib/mcp/browser/watchdog.js.map +7 -0
  159. package/lib/mcp/config.d.js +16 -0
  160. package/lib/mcp/config.d.js.map +7 -0
  161. package/lib/mcp/extension/cdpRelay.js +351 -0
  162. package/lib/mcp/extension/cdpRelay.js.map +7 -0
  163. package/lib/mcp/extension/extensionContextFactory.js +75 -0
  164. package/lib/mcp/extension/extensionContextFactory.js.map +7 -0
  165. package/lib/mcp/extension/protocol.js +28 -0
  166. package/lib/mcp/extension/protocol.js.map +7 -0
  167. package/lib/mcp/index.js +61 -0
  168. package/lib/mcp/index.js.map +7 -0
  169. package/lib/mcp/log.js +35 -0
  170. package/lib/mcp/log.js.map +7 -0
  171. package/lib/mcp/program.js +118 -0
  172. package/lib/mcp/program.js.map +7 -0
  173. package/lib/mcp/sdk/bundle.js +81 -0
  174. package/lib/mcp/sdk/bundle.js.map +7 -0
  175. package/lib/mcp/sdk/exports.js +32 -0
  176. package/lib/mcp/sdk/exports.js.map +7 -0
  177. package/lib/mcp/sdk/http.js +276 -0
  178. package/lib/mcp/sdk/http.js.map +7 -0
  179. package/lib/mcp/sdk/inProcessTransport.js +71 -0
  180. package/lib/mcp/sdk/inProcessTransport.js.map +7 -0
  181. package/lib/mcp/sdk/mdb.js +208 -0
  182. package/lib/mcp/sdk/mdb.js.map +7 -0
  183. package/lib/mcp/sdk/proxyBackend.js +128 -0
  184. package/lib/mcp/sdk/proxyBackend.js.map +7 -0
  185. package/lib/mcp/sdk/server.js +190 -0
  186. package/lib/mcp/sdk/server.js.map +7 -0
  187. package/lib/mcp/sdk/tool.js +51 -0
  188. package/lib/mcp/sdk/tool.js.map +7 -0
  189. package/lib/mcp/test/browserBackend.js +98 -0
  190. package/lib/mcp/test/browserBackend.js.map +7 -0
  191. package/lib/mcp/test/generatorTools.js +122 -0
  192. package/lib/mcp/test/generatorTools.js.map +7 -0
  193. package/lib/mcp/test/plannerTools.js +46 -0
  194. package/lib/mcp/test/plannerTools.js.map +7 -0
  195. package/lib/mcp/test/seed.js +82 -0
  196. package/lib/mcp/test/seed.js.map +7 -0
  197. package/lib/mcp/test/streams.js +41 -0
  198. package/lib/mcp/test/streams.js.map +7 -0
  199. package/lib/mcp/test/testBackend.js +97 -0
  200. package/lib/mcp/test/testBackend.js.map +7 -0
  201. package/lib/mcp/test/testContext.js +216 -0
  202. package/lib/mcp/test/testContext.js.map +7 -0
  203. package/lib/mcp/test/testTool.js +30 -0
  204. package/lib/mcp/test/testTool.js.map +7 -0
  205. package/lib/mcp/test/testTools.js +111 -0
  206. package/lib/mcp/test/testTools.js.map +7 -0
  207. package/lib/mcpBundleImpl.js +41 -0
  208. package/lib/mcpBundleImpl.js.map +7 -0
  209. package/lib/plugins/gitCommitInfoPlugin.js +198 -0
  210. package/lib/plugins/gitCommitInfoPlugin.js.map +7 -0
  211. package/lib/plugins/index.js +28 -0
  212. package/lib/plugins/index.js.map +7 -0
  213. package/lib/plugins/webServerPlugin.js +233 -0
  214. package/lib/plugins/webServerPlugin.js.map +7 -0
  215. package/lib/program.js +412 -0
  216. package/lib/program.js.map +7 -0
  217. package/lib/reporters/base.js +609 -0
  218. package/lib/reporters/base.js.map +7 -0
  219. package/lib/reporters/blob.js +135 -0
  220. package/lib/reporters/blob.js.map +7 -0
  221. package/lib/reporters/dot.js +82 -0
  222. package/lib/reporters/dot.js.map +7 -0
  223. package/lib/reporters/empty.js +32 -0
  224. package/lib/reporters/empty.js.map +7 -0
  225. package/lib/reporters/github.js +128 -0
  226. package/lib/reporters/github.js.map +7 -0
  227. package/lib/reporters/html.js +623 -0
  228. package/lib/reporters/html.js.map +7 -0
  229. package/lib/reporters/internalReporter.js +130 -0
  230. package/lib/reporters/internalReporter.js.map +7 -0
  231. package/lib/reporters/json.js +254 -0
  232. package/lib/reporters/json.js.map +7 -0
  233. package/lib/reporters/junit.js +232 -0
  234. package/lib/reporters/junit.js.map +7 -0
  235. package/lib/reporters/line.js +113 -0
  236. package/lib/reporters/line.js.map +7 -0
  237. package/lib/reporters/list.js +231 -0
  238. package/lib/reporters/list.js.map +7 -0
  239. package/lib/reporters/listModeReporter.js +69 -0
  240. package/lib/reporters/listModeReporter.js.map +7 -0
  241. package/lib/reporters/markdown.js +144 -0
  242. package/lib/reporters/markdown.js.map +7 -0
  243. package/lib/reporters/merge.js +541 -0
  244. package/lib/reporters/merge.js.map +7 -0
  245. package/lib/reporters/multiplexer.js +104 -0
  246. package/lib/reporters/multiplexer.js.map +7 -0
  247. package/lib/reporters/reporterV2.js +102 -0
  248. package/lib/reporters/reporterV2.js.map +7 -0
  249. package/lib/reporters/teleEmitter.js +298 -0
  250. package/lib/reporters/teleEmitter.js.map +7 -0
  251. package/lib/reporters/versions/blobV1.js +16 -0
  252. package/lib/reporters/versions/blobV1.js.map +7 -0
  253. package/lib/runner/dispatcher.js +491 -0
  254. package/lib/runner/dispatcher.js.map +7 -0
  255. package/lib/runner/failureTracker.js +72 -0
  256. package/lib/runner/failureTracker.js.map +7 -0
  257. package/lib/runner/lastRun.js +77 -0
  258. package/lib/runner/lastRun.js.map +7 -0
  259. package/lib/runner/loadUtils.js +334 -0
  260. package/lib/runner/loadUtils.js.map +7 -0
  261. package/lib/runner/loaderHost.js +89 -0
  262. package/lib/runner/loaderHost.js.map +7 -0
  263. package/lib/runner/processHost.js +161 -0
  264. package/lib/runner/processHost.js.map +7 -0
  265. package/lib/runner/projectUtils.js +241 -0
  266. package/lib/runner/projectUtils.js.map +7 -0
  267. package/lib/runner/rebase.js +189 -0
  268. package/lib/runner/rebase.js.map +7 -0
  269. package/lib/runner/reporters.js +138 -0
  270. package/lib/runner/reporters.js.map +7 -0
  271. package/lib/runner/runner.js +110 -0
  272. package/lib/runner/sigIntWatcher.js +96 -0
  273. package/lib/runner/sigIntWatcher.js.map +7 -0
  274. package/lib/runner/taskRunner.js +127 -0
  275. package/lib/runner/taskRunner.js.map +7 -0
  276. package/lib/runner/tasks.js +410 -0
  277. package/lib/runner/tasks.js.map +7 -0
  278. package/lib/runner/testGroups.js +117 -0
  279. package/lib/runner/testGroups.js.map +7 -0
  280. package/lib/runner/testRunner.js +390 -0
  281. package/lib/runner/testRunner.js.map +7 -0
  282. package/lib/runner/testServer.js +267 -0
  283. package/lib/runner/testServer.js.map +7 -0
  284. package/lib/runner/uiModeReporter.js +30 -0
  285. package/lib/runner/uiModeReporter.js.map +7 -0
  286. package/lib/runner/vcs.js +72 -0
  287. package/lib/runner/vcs.js.map +7 -0
  288. package/lib/runner/watchMode.js +395 -0
  289. package/lib/runner/watchMode.js.map +7 -0
  290. package/lib/runner/workerHost.js +95 -0
  291. package/lib/runner/workerHost.js.map +7 -0
  292. package/lib/third_party/pirates.js +62 -0
  293. package/lib/third_party/pirates.js.map +7 -0
  294. package/lib/third_party/tsconfig-loader.js +103 -0
  295. package/lib/third_party/tsconfig-loader.js.map +7 -0
  296. package/lib/transform/babelBundle.js +43 -0
  297. package/lib/transform/babelBundle.js.map +7 -0
  298. package/lib/transform/babelBundleImpl.js +461 -0
  299. package/lib/transform/babelBundleImpl.js.map +7 -0
  300. package/lib/transform/compilationCache.js +272 -0
  301. package/lib/transform/compilationCache.js.map +7 -0
  302. package/lib/transform/esmLoader.js +104 -0
  303. package/lib/transform/esmLoader.js.map +7 -0
  304. package/lib/transform/portTransport.js +67 -0
  305. package/lib/transform/portTransport.js.map +7 -0
  306. package/lib/transform/transform.js +293 -0
  307. package/lib/transform/transform.js.map +7 -0
  308. package/lib/util.js +403 -0
  309. package/lib/util.js.map +7 -0
  310. package/lib/utilsBundle.js +43 -0
  311. package/lib/utilsBundle.js.map +7 -0
  312. package/lib/utilsBundleImpl.js +100 -0
  313. package/lib/utilsBundleImpl.js.map +7 -0
  314. package/lib/worker/fixtureRunner.js +258 -0
  315. package/lib/worker/fixtureRunner.js.map +7 -0
  316. package/lib/worker/testInfo.js +514 -0
  317. package/lib/worker/testInfo.js.map +7 -0
  318. package/lib/worker/testTracing.js +344 -0
  319. package/lib/worker/testTracing.js.map +7 -0
  320. package/lib/worker/timeoutManager.js +174 -0
  321. package/lib/worker/timeoutManager.js.map +7 -0
  322. package/lib/worker/util.js +31 -0
  323. package/lib/worker/util.js.map +7 -0
  324. package/lib/worker/workerMain.js +520 -0
  325. package/lib/worker/workerMain.js.map +7 -0
  326. package/package.json +74 -0
  327. package/test.d.ts +18 -0
  328. package/test.js +24 -0
  329. package/test.mjs +33 -0
  330. package/types/test.d.ts +10196 -0
  331. package/types/testReporter.d.ts +821 -0
package/cli.js ADDED
@@ -0,0 +1,19 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Copyright (c) Microsoft Corporation.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ const { program } = require('./lib/program');
19
+ program.parse(process.argv);
package/index.d.ts ADDED
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Copyright (c) Microsoft Corporation.
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+ export * from 'playwright-core';
package/index.js ADDED
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Copyright (c) Microsoft Corporation.
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+ module.exports = require('playwright-core');
package/index.mjs ADDED
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Copyright (c) Microsoft Corporation.
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+ export * from 'playwright-core';
17
+ import playwright from 'playwright-core';
18
+ export default playwright;
package/jsx-runtime.js ADDED
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Copyright (c) Microsoft Corporation.
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+ function jsx(type, props, key) {
18
+ return {
19
+ __pw_type: 'jsx',
20
+ type,
21
+ props,
22
+ key,
23
+ };
24
+ }
25
+
26
+ function jsxs(type, props, key) {
27
+ return {
28
+ __pw_type: 'jsx',
29
+ type,
30
+ props,
31
+ key,
32
+ };
33
+ }
34
+
35
+ // this is used in <></> notation
36
+ const Fragment = { __pw_jsx_fragment: true };
37
+
38
+ module.exports = {
39
+ Fragment,
40
+ jsx,
41
+ jsxs,
42
+ };
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Copyright (c) Microsoft Corporation.
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+ import jsxRuntime from './jsx-runtime.js';
18
+
19
+ export const jsx = jsxRuntime.jsx;
20
+ export const jsxs = jsxRuntime.jsxs;
21
+ export const Fragment = jsxRuntime.Fragment;
@@ -0,0 +1,34 @@
1
+ name: "Copilot Setup Steps"
2
+
3
+ on:
4
+ workflow_dispatch:
5
+ push:
6
+ paths:
7
+ - .github/workflows/copilot-setup-steps.yml
8
+ pull_request:
9
+ paths:
10
+ - .github/workflows/copilot-setup-steps.yml
11
+
12
+ jobs:
13
+ copilot-setup-steps:
14
+ runs-on: ubuntu-latest
15
+
16
+ permissions:
17
+ contents: read
18
+
19
+ steps:
20
+ - uses: actions/checkout@v4
21
+
22
+ - uses: actions/setup-node@v4
23
+ with:
24
+ node-version: lts/*
25
+
26
+ - name: Install dependencies
27
+ run: npm ci
28
+
29
+ - name: Install Playwright Browsers
30
+ run: npx playwright install --with-deps
31
+
32
+ # Customize this step as needed
33
+ - name: Build application
34
+ run: npx run build
@@ -0,0 +1,394 @@
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 generateAgents_exports = {};
30
+ __export(generateAgents_exports, {
31
+ ClaudeGenerator: () => ClaudeGenerator,
32
+ CopilotGenerator: () => CopilotGenerator,
33
+ OpencodeGenerator: () => OpencodeGenerator,
34
+ VSCodeGenerator: () => VSCodeGenerator
35
+ });
36
+ module.exports = __toCommonJS(generateAgents_exports);
37
+ var import_fs = __toESM(require("fs"));
38
+ var import_path = __toESM(require("path"));
39
+ var import_utilsBundle = require("playwright-core/lib/utilsBundle");
40
+ var import_utils = require("playwright-core/lib/utils");
41
+ var import_seed = require("../mcp/test/seed");
42
+ class AgentParser {
43
+ static async loadAgents() {
44
+ const files = await import_fs.default.promises.readdir(__dirname);
45
+ return Promise.all(files.filter((file) => file.endsWith(".agent.md")).map((file) => AgentParser.parseFile(import_path.default.join(__dirname, file))));
46
+ }
47
+ static async parseFile(filePath) {
48
+ const source = await import_fs.default.promises.readFile(filePath, "utf-8");
49
+ const { header, content } = this.extractYamlAndContent(source);
50
+ const { instructions, examples } = this.extractInstructionsAndExamples(content);
51
+ return { header, instructions, examples };
52
+ }
53
+ static extractYamlAndContent(markdown) {
54
+ const lines = markdown.split("\n");
55
+ if (lines[0] !== "---")
56
+ throw new Error("Markdown file must start with YAML front matter (---)");
57
+ let yamlEndIndex = -1;
58
+ for (let i = 1; i < lines.length; i++) {
59
+ if (lines[i] === "---") {
60
+ yamlEndIndex = i;
61
+ break;
62
+ }
63
+ }
64
+ if (yamlEndIndex === -1)
65
+ throw new Error("YAML front matter must be closed with ---");
66
+ const yamlLines = lines.slice(1, yamlEndIndex);
67
+ const yamlRaw = yamlLines.join("\n");
68
+ const contentLines = lines.slice(yamlEndIndex + 1);
69
+ const content = contentLines.join("\n");
70
+ let header;
71
+ try {
72
+ header = import_utilsBundle.yaml.parse(yamlRaw);
73
+ } catch (error) {
74
+ throw new Error(`Failed to parse YAML header: ${error.message}`);
75
+ }
76
+ if (!header.name)
77
+ throw new Error('YAML header must contain a "name" field');
78
+ if (!header.description)
79
+ throw new Error('YAML header must contain a "description" field');
80
+ return { header, content };
81
+ }
82
+ static extractInstructionsAndExamples(content) {
83
+ const examples = [];
84
+ const instructions = content.split("<example>")[0].trim();
85
+ const exampleRegex = /<example>([\s\S]*?)<\/example>/g;
86
+ let match;
87
+ while ((match = exampleRegex.exec(content)) !== null) {
88
+ const example = match[1].trim();
89
+ examples.push(example.replace(/[\n]/g, " ").replace(/ +/g, " "));
90
+ }
91
+ return { instructions, examples };
92
+ }
93
+ }
94
+ class ClaudeGenerator {
95
+ static async init(config, projectName, prompts) {
96
+ await initRepo(config, projectName, {
97
+ promptsFolder: prompts ? ".claude/prompts" : void 0
98
+ });
99
+ const agents = await AgentParser.loadAgents();
100
+ await import_fs.default.promises.mkdir(".claude/agents", { recursive: true });
101
+ for (const agent of agents)
102
+ await writeFile(`.claude/agents/${agent.header.name}.md`, ClaudeGenerator.agentSpec(agent), "\u{1F916}", "agent definition");
103
+ await writeFile(".mcp.json", JSON.stringify({
104
+ mcpServers: {
105
+ "playwright-test": {
106
+ command: "npx",
107
+ args: ["playwright", "run-test-mcp-server"]
108
+ }
109
+ }
110
+ }, null, 2), "\u{1F527}", "mcp configuration");
111
+ initRepoDone();
112
+ }
113
+ static agentSpec(agent) {
114
+ const claudeToolMap = /* @__PURE__ */ new Map([
115
+ ["search", ["Glob", "Grep", "Read", "LS"]],
116
+ ["edit", ["Edit", "MultiEdit", "Write"]]
117
+ ]);
118
+ function asClaudeTool(tool) {
119
+ const [first, second] = tool.split("/");
120
+ if (!second)
121
+ return (claudeToolMap.get(first) || [first]).join(", ");
122
+ return `mcp__${first}__${second}`;
123
+ }
124
+ const examples = agent.examples.length ? ` Examples: ${agent.examples.map((example) => `<example>${example}</example>`).join("")}` : "";
125
+ const lines = [];
126
+ const header = {
127
+ name: agent.header.name,
128
+ description: agent.header.description + examples,
129
+ tools: agent.header.tools.map((tool) => asClaudeTool(tool)).join(", "),
130
+ model: agent.header.model,
131
+ color: agent.header.color
132
+ };
133
+ lines.push(`---`);
134
+ lines.push(import_utilsBundle.yaml.stringify(header, { lineWidth: 1e5 }) + `---`);
135
+ lines.push("");
136
+ lines.push(agent.instructions);
137
+ return lines.join("\n");
138
+ }
139
+ }
140
+ class OpencodeGenerator {
141
+ static async init(config, projectName, prompts) {
142
+ await initRepo(config, projectName, {
143
+ defaultAgentName: "Build",
144
+ promptsFolder: prompts ? ".opencode/prompts" : void 0
145
+ });
146
+ const agents = await AgentParser.loadAgents();
147
+ for (const agent of agents) {
148
+ const prompt = [agent.instructions];
149
+ prompt.push("");
150
+ prompt.push(...agent.examples.map((example) => `<example>${example}</example>`));
151
+ await writeFile(`.opencode/prompts/${agent.header.name}.md`, prompt.join("\n"), "\u{1F916}", "agent definition");
152
+ }
153
+ await writeFile("opencode.json", OpencodeGenerator.configuration(agents), "\u{1F527}", "opencode configuration");
154
+ initRepoDone();
155
+ }
156
+ static configuration(agents) {
157
+ const opencodeToolMap = /* @__PURE__ */ new Map([
158
+ ["search", ["ls", "glob", "grep", "read"]],
159
+ ["edit", ["edit", "write"]]
160
+ ]);
161
+ const asOpencodeTool = (tools, tool) => {
162
+ const [first, second] = tool.split("/");
163
+ if (!second) {
164
+ for (const tool2 of opencodeToolMap.get(first) || [first])
165
+ tools[tool2] = true;
166
+ } else {
167
+ tools[`${first}*${second}`] = true;
168
+ }
169
+ };
170
+ const result = {};
171
+ result["$schema"] = "https://opencode.ai/config.json";
172
+ result["mcp"] = {};
173
+ result["tools"] = {
174
+ "playwright*": false
175
+ };
176
+ result["agent"] = {};
177
+ for (const agent of agents) {
178
+ const tools = {};
179
+ result["agent"][agent.header.name] = {
180
+ description: agent.header.description,
181
+ mode: "subagent",
182
+ prompt: `{file:.opencode/prompts/${agent.header.name}.md}`,
183
+ tools
184
+ };
185
+ for (const tool of agent.header.tools)
186
+ asOpencodeTool(tools, tool);
187
+ }
188
+ result["mcp"]["playwright-test"] = {
189
+ type: "local",
190
+ command: ["npx", "playwright", "run-test-mcp-server"],
191
+ enabled: true
192
+ };
193
+ return JSON.stringify(result, null, 2);
194
+ }
195
+ }
196
+ class CopilotGenerator {
197
+ static async init(config, projectName, prompts) {
198
+ await initRepo(config, projectName, {
199
+ defaultAgentName: "agent",
200
+ promptsFolder: prompts ? ".github/prompts" : void 0,
201
+ promptSuffix: "prompt"
202
+ });
203
+ const agents = await AgentParser.loadAgents();
204
+ await import_fs.default.promises.mkdir(".github/agents", { recursive: true });
205
+ for (const agent of agents)
206
+ await writeFile(`.github/agents/${agent.header.name}.agent.md`, CopilotGenerator.agentSpec(agent), "\u{1F916}", "agent definition");
207
+ await deleteFile(`.github/chatmodes/ \u{1F3AD} planner.chatmode.md`, "legacy planner chatmode");
208
+ await deleteFile(`.github/chatmodes/\u{1F3AD} generator.chatmode.md`, "legacy generator chatmode");
209
+ await deleteFile(`.github/chatmodes/\u{1F3AD} healer.chatmode.md`, "legacy healer chatmode");
210
+ await VSCodeGenerator.appendToMCPJson();
211
+ const cwdFolder = import_path.default.basename(process.cwd());
212
+ const mcpConfig = {
213
+ "mcpServers": {
214
+ "playwright-test": {
215
+ "type": "stdio",
216
+ "command": "npx",
217
+ "args": [
218
+ `--prefix=/home/runner/work/${cwdFolder}/${cwdFolder}`,
219
+ "playwright",
220
+ "run-test-mcp-server",
221
+ "--headless",
222
+ `--config=/home/runner/work/${cwdFolder}/${cwdFolder}`
223
+ ],
224
+ "tools": ["*"]
225
+ }
226
+ }
227
+ };
228
+ if (!import_fs.default.existsSync(".github/copilot-setup-steps.yml")) {
229
+ const yaml2 = import_fs.default.readFileSync(import_path.default.join(__dirname, "copilot-setup-steps.yml"), "utf-8");
230
+ await writeFile(".github/workflows/copilot-setup-steps.yml", yaml2, "\u{1F527}", "GitHub Copilot setup steps");
231
+ }
232
+ console.log("");
233
+ console.log("");
234
+ console.log(" \u{1F527} TODO: GitHub > Settings > Copilot > Coding agent > MCP configuration");
235
+ console.log("------------------------------------------------------------------");
236
+ console.log(JSON.stringify(mcpConfig, null, 2));
237
+ console.log("------------------------------------------------------------------");
238
+ initRepoDone();
239
+ }
240
+ static agentSpec(agent) {
241
+ const examples = agent.examples.length ? ` Examples: ${agent.examples.map((example) => `<example>${example}</example>`).join("")}` : "";
242
+ const lines = [];
243
+ const header = {
244
+ name: agent.header.name,
245
+ description: agent.header.description + examples,
246
+ tools: agent.header.tools,
247
+ model: "Claude Sonnet 4"
248
+ };
249
+ lines.push(`---`);
250
+ lines.push(import_utilsBundle.yaml.stringify(header) + `---`);
251
+ lines.push("");
252
+ lines.push(agent.instructions);
253
+ lines.push("");
254
+ return lines.join("\n");
255
+ }
256
+ }
257
+ class VSCodeGenerator {
258
+ static async init(config, projectName) {
259
+ await initRepo(config, projectName, {
260
+ promptsFolder: void 0
261
+ });
262
+ const agents = await AgentParser.loadAgents();
263
+ const nameMap = /* @__PURE__ */ new Map([
264
+ ["playwright-test-planner", " \u{1F3AD} planner"],
265
+ ["playwright-test-generator", "\u{1F3AD} generator"],
266
+ ["playwright-test-healer", "\u{1F3AD} healer"]
267
+ ]);
268
+ await import_fs.default.promises.mkdir(".github/chatmodes", { recursive: true });
269
+ for (const agent of agents)
270
+ await writeFile(`.github/chatmodes/${nameMap.get(agent.header.name)}.chatmode.md`, VSCodeGenerator.agentSpec(agent), "\u{1F916}", "chatmode definition");
271
+ await VSCodeGenerator.appendToMCPJson();
272
+ initRepoDone();
273
+ }
274
+ static async appendToMCPJson() {
275
+ await import_fs.default.promises.mkdir(".vscode", { recursive: true });
276
+ const mcpJsonPath = ".vscode/mcp.json";
277
+ let mcpJson = {
278
+ servers: {},
279
+ inputs: []
280
+ };
281
+ try {
282
+ mcpJson = JSON.parse(import_fs.default.readFileSync(mcpJsonPath, "utf8"));
283
+ } catch {
284
+ }
285
+ if (!mcpJson.servers)
286
+ mcpJson.servers = {};
287
+ mcpJson.servers["playwright-test"] = {
288
+ type: "stdio",
289
+ command: "npx",
290
+ args: ["playwright", "run-test-mcp-server"]
291
+ };
292
+ await writeFile(mcpJsonPath, JSON.stringify(mcpJson, null, 2), "\u{1F527}", "mcp configuration");
293
+ }
294
+ static agentSpec(agent) {
295
+ const vscodeToolMap = /* @__PURE__ */ new Map([
296
+ ["search", ["search/listDirectory", "search/fileSearch", "search/textSearch"]],
297
+ ["read", ["search/readFile"]],
298
+ ["edit", ["edit/editFiles"]],
299
+ ["write", ["edit/createFile", "edit/createDirectory"]]
300
+ ]);
301
+ const vscodeToolsOrder = ["edit/createFile", "edit/createDirectory", "edit/editFiles", "search/fileSearch", "search/textSearch", "search/listDirectory", "search/readFile"];
302
+ const vscodeMcpName = "playwright-test";
303
+ function asVscodeTool(tool) {
304
+ const [first, second] = tool.split("/");
305
+ if (second)
306
+ return `${vscodeMcpName}/${second}`;
307
+ return vscodeToolMap.get(first) || first;
308
+ }
309
+ const tools = agent.header.tools.map(asVscodeTool).flat().sort((a, b) => {
310
+ const indexA = vscodeToolsOrder.indexOf(a);
311
+ const indexB = vscodeToolsOrder.indexOf(b);
312
+ if (indexA === -1 && indexB === -1)
313
+ return a.localeCompare(b);
314
+ if (indexA === -1)
315
+ return 1;
316
+ if (indexB === -1)
317
+ return -1;
318
+ return indexA - indexB;
319
+ }).map((tool) => `'${tool}'`).join(", ");
320
+ const lines = [];
321
+ lines.push(`---`);
322
+ lines.push(`description: ${agent.header.description}.`);
323
+ lines.push(`tools: [${tools}]`);
324
+ lines.push(`---`);
325
+ lines.push("");
326
+ lines.push(agent.instructions);
327
+ for (const example of agent.examples)
328
+ lines.push(`<example>${example}</example>`);
329
+ lines.push("");
330
+ return lines.join("\n");
331
+ }
332
+ }
333
+ async function writeFile(filePath, content, icon, description) {
334
+ console.log(` ${icon} ${import_path.default.relative(process.cwd(), filePath)} ${import_utilsBundle.colors.dim("- " + description)}`);
335
+ await (0, import_utils.mkdirIfNeeded)(filePath);
336
+ await import_fs.default.promises.writeFile(filePath, content, "utf-8");
337
+ }
338
+ async function deleteFile(filePath, description) {
339
+ try {
340
+ if (!import_fs.default.existsSync(filePath))
341
+ return;
342
+ } catch {
343
+ return;
344
+ }
345
+ console.log(` \u2702\uFE0F ${import_path.default.relative(process.cwd(), filePath)} ${import_utilsBundle.colors.dim("- " + description)}`);
346
+ await import_fs.default.promises.unlink(filePath);
347
+ }
348
+ async function initRepo(config, projectName, options) {
349
+ const project = (0, import_seed.seedProject)(config, projectName);
350
+ console.log(` \u{1F3AD} Using project "${project.project.name}" as a primary project`);
351
+ if (!import_fs.default.existsSync("specs")) {
352
+ await import_fs.default.promises.mkdir("specs");
353
+ await writeFile(import_path.default.join("specs", "README.md"), `# Specs
354
+
355
+ This is a directory for test plans.
356
+ `, "\u{1F4DD}", "directory for test plans");
357
+ }
358
+ let seedFile = await (0, import_seed.findSeedFile)(project);
359
+ if (!seedFile) {
360
+ seedFile = (0, import_seed.defaultSeedFile)(project);
361
+ await writeFile(seedFile, import_seed.seedFileContent, "\u{1F331}", "default environment seed file");
362
+ }
363
+ if (options.promptsFolder) {
364
+ await import_fs.default.promises.mkdir(options.promptsFolder, { recursive: true });
365
+ for (const promptFile of await import_fs.default.promises.readdir(__dirname)) {
366
+ if (!promptFile.endsWith(".prompt.md"))
367
+ continue;
368
+ const shortName = promptFile.replace(".prompt.md", "");
369
+ const fileName = options.promptSuffix ? `${shortName}.${options.promptSuffix}.md` : `${shortName}.md`;
370
+ const content = await loadPrompt(promptFile, {
371
+ defaultAgentName: "default",
372
+ ...options,
373
+ seedFile: import_path.default.relative(process.cwd(), seedFile)
374
+ });
375
+ await writeFile(import_path.default.join(options.promptsFolder, fileName), content, "\u{1F4DD}", "prompt template");
376
+ }
377
+ }
378
+ }
379
+ function initRepoDone() {
380
+ console.log(" \u2705 Done.");
381
+ }
382
+ async function loadPrompt(file, params) {
383
+ const content = await import_fs.default.promises.readFile(import_path.default.join(__dirname, file), "utf-8");
384
+ return Object.entries(params).reduce((acc, [key, value]) => {
385
+ return acc.replace(new RegExp(`\\\${${key}}`, "g"), value);
386
+ }, content);
387
+ }
388
+ // Annotate the CommonJS export names for ESM import in node:
389
+ 0 && (module.exports = {
390
+ ClaudeGenerator,
391
+ CopilotGenerator,
392
+ OpencodeGenerator,
393
+ VSCodeGenerator
394
+ });
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/agents/generateAgents.ts"],
4
+ "sourcesContent": ["/**\n * Copyright Microsoft Corporation. All rights reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport fs from 'fs';\nimport path from 'path';\n\nimport { colors, yaml } from 'playwright-core/lib/utilsBundle';\nimport { mkdirIfNeeded } from 'playwright-core/lib/utils';\n\nimport { FullConfigInternal } from '../common/config';\nimport { defaultSeedFile, findSeedFile, seedFileContent, seedProject } from '../mcp/test/seed';\n\ninterface AgentHeader {\n name: string;\n description: string;\n model: string;\n color: string;\n tools: string[];\n}\n\ninterface Agent {\n header: AgentHeader;\n instructions: string;\n examples: string[];\n}\n\n/* eslint-disable no-console */\n\nclass AgentParser {\n static async loadAgents(): Promise<Agent[]> {\n const files = await fs.promises.readdir(__dirname);\n return Promise.all(files.filter(file => file.endsWith('.agent.md')).map(file => AgentParser.parseFile(path.join(__dirname, file))));\n }\n\n static async parseFile(filePath: string): Promise<Agent> {\n const source = await fs.promises.readFile(filePath, 'utf-8');\n const { header, content } = this.extractYamlAndContent(source);\n const { instructions, examples } = this.extractInstructionsAndExamples(content);\n return { header, instructions, examples };\n }\n\n static extractYamlAndContent(markdown: string): { header: AgentHeader; content: string } {\n const lines = markdown.split('\\n');\n\n if (lines[0] !== '---')\n throw new Error('Markdown file must start with YAML front matter (---)');\n\n let yamlEndIndex = -1;\n for (let i = 1; i < lines.length; i++) {\n if (lines[i] === '---') {\n yamlEndIndex = i;\n break;\n }\n }\n\n if (yamlEndIndex === -1)\n throw new Error('YAML front matter must be closed with ---');\n\n const yamlLines = lines.slice(1, yamlEndIndex);\n const yamlRaw = yamlLines.join('\\n');\n const contentLines = lines.slice(yamlEndIndex + 1);\n const content = contentLines.join('\\n');\n\n let header: AgentHeader;\n try {\n header = yaml.parse(yamlRaw) as AgentHeader;\n } catch (error: any) {\n throw new Error(`Failed to parse YAML header: ${error.message}`);\n }\n\n if (!header.name)\n throw new Error('YAML header must contain a \"name\" field');\n\n if (!header.description)\n throw new Error('YAML header must contain a \"description\" field');\n\n return { header, content };\n }\n\n static extractInstructionsAndExamples(content: string): { instructions: string; examples: string[] } {\n const examples: string[] = [];\n\n const instructions = content.split('<example>')[0].trim();\n const exampleRegex = /<example>([\\s\\S]*?)<\\/example>/g;\n let match: RegExpExecArray | null;\n\n while ((match = exampleRegex.exec(content)) !== null) {\n const example = match[1].trim();\n examples.push(example.replace(/[\\n]/g, ' ').replace(/ +/g, ' '));\n }\n\n return { instructions, examples };\n }\n}\n\nexport class ClaudeGenerator {\n static async init(config: FullConfigInternal, projectName: string, prompts: boolean) {\n await initRepo(config, projectName, {\n promptsFolder: prompts ? '.claude/prompts' : undefined,\n });\n\n const agents = await AgentParser.loadAgents();\n\n await fs.promises.mkdir('.claude/agents', { recursive: true });\n for (const agent of agents)\n await writeFile(`.claude/agents/${agent.header.name}.md`, ClaudeGenerator.agentSpec(agent), '\uD83E\uDD16', 'agent definition');\n\n await writeFile('.mcp.json', JSON.stringify({\n mcpServers: {\n 'playwright-test': {\n command: 'npx',\n args: ['playwright', 'run-test-mcp-server'],\n }\n }\n }, null, 2), '\uD83D\uDD27', 'mcp configuration');\n\n initRepoDone();\n }\n\n static agentSpec(agent: Agent): string {\n const claudeToolMap = new Map<string, string[]>([\n ['search', ['Glob', 'Grep', 'Read', 'LS']],\n ['edit', ['Edit', 'MultiEdit', 'Write']],\n ]);\n\n function asClaudeTool(tool: string): string {\n const [first, second] = tool.split('/');\n if (!second)\n return (claudeToolMap.get(first) || [first]).join(', ');\n return `mcp__${first}__${second}`;\n }\n\n const examples = agent.examples.length ? ` Examples: ${agent.examples.map(example => `<example>${example}</example>`).join('')}` : '';\n const lines: string[] = [];\n const header = {\n name: agent.header.name,\n description: agent.header.description + examples,\n tools: agent.header.tools.map(tool => asClaudeTool(tool)).join(', '),\n model: agent.header.model,\n color: agent.header.color,\n };\n lines.push(`---`);\n lines.push(yaml.stringify(header, { lineWidth: 100000 }) + `---`);\n lines.push('');\n lines.push(agent.instructions);\n return lines.join('\\n');\n }\n}\n\nexport class OpencodeGenerator {\n static async init(config: FullConfigInternal, projectName: string, prompts: boolean) {\n await initRepo(config, projectName, {\n defaultAgentName: 'Build',\n promptsFolder: prompts ? '.opencode/prompts' : undefined\n });\n\n const agents = await AgentParser.loadAgents();\n\n for (const agent of agents) {\n const prompt = [agent.instructions];\n prompt.push('');\n prompt.push(...agent.examples.map(example => `<example>${example}</example>`));\n await writeFile(`.opencode/prompts/${agent.header.name}.md`, prompt.join('\\n'), '\uD83E\uDD16', 'agent definition');\n }\n\n await writeFile('opencode.json', OpencodeGenerator.configuration(agents), '\uD83D\uDD27', 'opencode configuration');\n\n initRepoDone();\n }\n\n static configuration(agents: Agent[]): string {\n const opencodeToolMap = new Map<string, string[]>([\n ['search', ['ls', 'glob', 'grep', 'read']],\n ['edit', ['edit', 'write']],\n ]);\n\n const asOpencodeTool = (tools: Record<string, boolean>, tool: string) => {\n const [first, second] = tool.split('/');\n if (!second) {\n for (const tool of opencodeToolMap.get(first) || [first])\n tools[tool] = true;\n } else {\n tools[`${first}*${second}`] = true;\n }\n };\n\n const result: Record<string, any> = {};\n result['$schema'] = 'https://opencode.ai/config.json';\n result['mcp'] = {};\n result['tools'] = {\n 'playwright*': false,\n };\n result['agent'] = {};\n for (const agent of agents) {\n const tools: Record<string, boolean> = {};\n result['agent'][agent.header.name] = {\n description: agent.header.description,\n mode: 'subagent',\n prompt: `{file:.opencode/prompts/${agent.header.name}.md}`,\n tools,\n };\n for (const tool of agent.header.tools)\n asOpencodeTool(tools, tool);\n }\n\n result['mcp']['playwright-test'] = {\n type: 'local',\n command: ['npx', 'playwright', 'run-test-mcp-server'],\n enabled: true,\n };\n\n return JSON.stringify(result, null, 2);\n }\n}\nexport class CopilotGenerator {\n static async init(config: FullConfigInternal, projectName: string, prompts: boolean) {\n\n await initRepo(config, projectName, {\n defaultAgentName: 'agent',\n promptsFolder: prompts ? '.github/prompts' : undefined,\n promptSuffix: 'prompt'\n });\n\n const agents = await AgentParser.loadAgents();\n\n await fs.promises.mkdir('.github/agents', { recursive: true });\n for (const agent of agents)\n await writeFile(`.github/agents/${agent.header.name}.agent.md`, CopilotGenerator.agentSpec(agent), '\uD83E\uDD16', 'agent definition');\n\n await deleteFile(`.github/chatmodes/ \uD83C\uDFAD planner.chatmode.md`, 'legacy planner chatmode');\n await deleteFile(`.github/chatmodes/\uD83C\uDFAD generator.chatmode.md`, 'legacy generator chatmode');\n await deleteFile(`.github/chatmodes/\uD83C\uDFAD healer.chatmode.md`, 'legacy healer chatmode');\n\n await VSCodeGenerator.appendToMCPJson();\n const cwdFolder = path.basename(process.cwd());\n\n const mcpConfig = {\n 'mcpServers': {\n 'playwright-test': {\n 'type': 'stdio',\n 'command': 'npx',\n 'args': [\n `--prefix=/home/runner/work/${cwdFolder}/${cwdFolder}`,\n 'playwright',\n 'run-test-mcp-server',\n '--headless',\n `--config=/home/runner/work/${cwdFolder}/${cwdFolder}`\n ],\n 'tools': ['*']\n }\n }\n };\n\n if (!fs.existsSync('.github/copilot-setup-steps.yml')) {\n const yaml = fs.readFileSync(path.join(__dirname, 'copilot-setup-steps.yml'), 'utf-8');\n await writeFile('.github/workflows/copilot-setup-steps.yml', yaml, '\uD83D\uDD27', 'GitHub Copilot setup steps');\n }\n\n console.log('');\n console.log('');\n console.log(' \uD83D\uDD27 TODO: GitHub > Settings > Copilot > Coding agent > MCP configuration');\n console.log('------------------------------------------------------------------');\n console.log(JSON.stringify(mcpConfig, null, 2));\n console.log('------------------------------------------------------------------');\n\n initRepoDone();\n }\n\n static agentSpec(agent: Agent): string {\n const examples = agent.examples.length ? ` Examples: ${agent.examples.map(example => `<example>${example}</example>`).join('')}` : '';\n const lines: string[] = [];\n const header = {\n name: agent.header.name,\n description: agent.header.description + examples,\n tools: agent.header.tools,\n model: 'Claude Sonnet 4',\n };\n lines.push(`---`);\n lines.push(yaml.stringify(header) + `---`);\n lines.push('');\n lines.push(agent.instructions);\n lines.push('');\n return lines.join('\\n');\n }\n}\n\nexport class VSCodeGenerator {\n static async init(config: FullConfigInternal, projectName: string) {\n await initRepo(config, projectName, {\n promptsFolder: undefined\n });\n const agents = await AgentParser.loadAgents();\n\n const nameMap = new Map<string, string>([\n ['playwright-test-planner', ' \uD83C\uDFAD planner'],\n ['playwright-test-generator', '\uD83C\uDFAD generator'],\n ['playwright-test-healer', '\uD83C\uDFAD healer'],\n ]);\n\n await fs.promises.mkdir('.github/chatmodes', { recursive: true });\n for (const agent of agents)\n await writeFile(`.github/chatmodes/${nameMap.get(agent.header.name)}.chatmode.md`, VSCodeGenerator.agentSpec(agent), '\uD83E\uDD16', 'chatmode definition');\n\n await VSCodeGenerator.appendToMCPJson();\n\n initRepoDone();\n }\n\n static async appendToMCPJson() {\n await fs.promises.mkdir('.vscode', { recursive: true });\n\n const mcpJsonPath = '.vscode/mcp.json';\n let mcpJson: any = {\n servers: {},\n inputs: []\n };\n try {\n mcpJson = JSON.parse(fs.readFileSync(mcpJsonPath, 'utf8'));\n } catch {\n }\n\n if (!mcpJson.servers)\n mcpJson.servers = {};\n\n mcpJson.servers['playwright-test'] = {\n type: 'stdio',\n command: 'npx',\n args: ['playwright', 'run-test-mcp-server'],\n };\n await writeFile(mcpJsonPath, JSON.stringify(mcpJson, null, 2), '\uD83D\uDD27', 'mcp configuration');\n }\n\n static agentSpec(agent: Agent): string {\n const vscodeToolMap = new Map<string, string[]>([\n ['search', ['search/listDirectory', 'search/fileSearch', 'search/textSearch']],\n ['read', ['search/readFile']],\n ['edit', ['edit/editFiles']],\n ['write', ['edit/createFile', 'edit/createDirectory']],\n ]);\n const vscodeToolsOrder = ['edit/createFile', 'edit/createDirectory', 'edit/editFiles', 'search/fileSearch', 'search/textSearch', 'search/listDirectory', 'search/readFile'];\n const vscodeMcpName = 'playwright-test';\n\n function asVscodeTool(tool: string): string | string[] {\n const [first, second] = tool.split('/');\n if (second)\n return `${vscodeMcpName}/${second}`;\n return vscodeToolMap.get(first) || first;\n }\n const tools = agent.header.tools.map(asVscodeTool).flat().sort((a, b) => {\n // VSCode insists on the specific tools order when editing agent config.\n const indexA = vscodeToolsOrder.indexOf(a);\n const indexB = vscodeToolsOrder.indexOf(b);\n if (indexA === -1 && indexB === -1)\n return a.localeCompare(b);\n if (indexA === -1)\n return 1;\n if (indexB === -1)\n return -1;\n return indexA - indexB;\n }).map(tool => `'${tool}'`).join(', ');\n\n const lines: string[] = [];\n lines.push(`---`);\n lines.push(`description: ${agent.header.description}.`);\n lines.push(`tools: [${tools}]`);\n lines.push(`---`);\n lines.push('');\n lines.push(agent.instructions);\n for (const example of agent.examples)\n lines.push(`<example>${example}</example>`);\n\n lines.push('');\n return lines.join('\\n');\n }\n}\n\nasync function writeFile(filePath: string, content: string, icon: string, description: string) {\n console.log(` ${icon} ${path.relative(process.cwd(), filePath)} ${colors.dim('- ' + description)}`);\n await mkdirIfNeeded(filePath);\n await fs.promises.writeFile(filePath, content, 'utf-8');\n}\n\nasync function deleteFile(filePath: string, description: string) {\n try {\n if (!fs.existsSync(filePath))\n return;\n } catch {\n return;\n }\n\n console.log(` \u2702\uFE0F ${path.relative(process.cwd(), filePath)} ${colors.dim('- ' + description)}`);\n await fs.promises.unlink(filePath);\n}\n\ntype RepoParams = {\n promptsFolder?: string;\n promptSuffix?: string;\n defaultAgentName?: string;\n};\n\nasync function initRepo(config: FullConfigInternal, projectName: string, options: RepoParams) {\n const project = seedProject(config, projectName);\n console.log(` \uD83C\uDFAD Using project \"${project.project.name}\" as a primary project`);\n\n if (!fs.existsSync('specs')) {\n await fs.promises.mkdir('specs');\n await writeFile(path.join('specs', 'README.md'), `# Specs\n\nThis is a directory for test plans.\n`, '\uD83D\uDCDD', 'directory for test plans');\n }\n\n let seedFile = await findSeedFile(project);\n if (!seedFile) {\n seedFile = defaultSeedFile(project);\n await writeFile(seedFile, seedFileContent, '\uD83C\uDF31', 'default environment seed file');\n }\n\n if (options.promptsFolder) {\n await fs.promises.mkdir(options.promptsFolder, { recursive: true });\n\n for (const promptFile of await fs.promises.readdir(__dirname)) {\n if (!promptFile.endsWith('.prompt.md'))\n continue;\n const shortName = promptFile.replace('.prompt.md', '');\n const fileName = options.promptSuffix ? `${shortName}.${options.promptSuffix}.md` : `${shortName}.md`;\n const content = await loadPrompt(promptFile, {\n defaultAgentName: 'default',\n ...options,\n seedFile: path.relative(process.cwd(), seedFile)\n });\n await writeFile(path.join(options.promptsFolder, fileName), content, '\uD83D\uDCDD', 'prompt template');\n }\n }\n}\n\nfunction initRepoDone() {\n console.log(' \u2705 Done.');\n}\n\nasync function loadPrompt(file: string, params: Record<string, string>) {\n const content = await fs.promises.readFile(path.join(__dirname, file), 'utf-8');\n return Object.entries(params).reduce((acc, [key, value]) => {\n return acc.replace(new RegExp(`\\\\\\${${key}}`, 'g'), value);\n }, content);\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["fs", "path", "tool", "yaml"]
7
+ }
@@ -0,0 +1,31 @@
1
+ ---
2
+ agent: ${defaultAgentName}
3
+ description: Produce test coverage
4
+ ---
5
+
6
+ Parameters:
7
+ - Task: the task to perform
8
+ - Seed file (optional): the seed file to use, defaults to `${seedFile}`
9
+ - Test plan file (optional): the test plan file to write, under `specs/` folder.
10
+
11
+ 1. Call #playwright-test-planner subagent with prompt:
12
+
13
+ <plan>
14
+ <task-text><!-- the task --></task-text>
15
+ <seed-file><!-- path to seed file --></seed-file>
16
+ <plan-file><!-- path to test plan file to generate --></plan-file>
17
+ </plan>
18
+
19
+ 2. For each test case from the test plan file (1.1, 1.2, ...), one after another, not in parallel, call #playwright-test-generator subagent with prompt:
20
+
21
+ <generate>
22
+ <test-suite><!-- Verbatim name of the test spec group w/o ordinal like "Multiplication tests" --></test-suite>
23
+ <test-name><!-- Name of the test case without the ordinal like "should add two numbers" --></test-name>
24
+ <test-file><!-- Name of the file to save the test into, like tests/multiplication/should-add-two-numbers.spec.ts --></test-file>
25
+ <seed-file><!-- Seed file path from test plan --></seed-file>
26
+ <body><!-- Test case content including steps and expectations --></body>
27
+ </generate>
28
+
29
+ 3. Call #playwright-test-healer subagent with prompt:
30
+
31
+ <heal>Run all tests and fix the failing ones one after another.</heal>