@one2x/playwright 1.57.0-alpha.1 → 1.57.0-alpha.2

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 (155) hide show
  1. package/package.json +2 -2
  2. package/lib/agents/generateAgents.js.map +0 -7
  3. package/lib/common/config.js.map +0 -7
  4. package/lib/common/configLoader.js.map +0 -7
  5. package/lib/common/esmLoaderHost.js.map +0 -7
  6. package/lib/common/expectBundle.js.map +0 -7
  7. package/lib/common/expectBundleImpl.js.map +0 -7
  8. package/lib/common/fixtures.js.map +0 -7
  9. package/lib/common/globals.js.map +0 -7
  10. package/lib/common/ipc.js.map +0 -7
  11. package/lib/common/poolBuilder.js.map +0 -7
  12. package/lib/common/process.js.map +0 -7
  13. package/lib/common/suiteUtils.js.map +0 -7
  14. package/lib/common/test.js.map +0 -7
  15. package/lib/common/testLoader.js.map +0 -7
  16. package/lib/common/testType.js.map +0 -7
  17. package/lib/common/validators.js.map +0 -7
  18. package/lib/fsWatcher.js.map +0 -7
  19. package/lib/index.js.map +0 -7
  20. package/lib/internalsForTest.js.map +0 -7
  21. package/lib/isomorphic/events.js.map +0 -7
  22. package/lib/isomorphic/folders.js.map +0 -7
  23. package/lib/isomorphic/stringInternPool.js.map +0 -7
  24. package/lib/isomorphic/teleReceiver.js.map +0 -7
  25. package/lib/isomorphic/teleSuiteUpdater.js.map +0 -7
  26. package/lib/isomorphic/testServerConnection.js.map +0 -7
  27. package/lib/isomorphic/testServerInterface.js.map +0 -7
  28. package/lib/isomorphic/testTree.js.map +0 -7
  29. package/lib/isomorphic/types.d.js.map +0 -7
  30. package/lib/loader/loaderMain.js.map +0 -7
  31. package/lib/matchers/expect.js.map +0 -7
  32. package/lib/matchers/matcherHint.js.map +0 -7
  33. package/lib/matchers/matchers.js.map +0 -7
  34. package/lib/matchers/toBeTruthy.js.map +0 -7
  35. package/lib/matchers/toEqual.js.map +0 -7
  36. package/lib/matchers/toHaveURL.js.map +0 -7
  37. package/lib/matchers/toMatchAriaSnapshot.js.map +0 -7
  38. package/lib/matchers/toMatchSnapshot.js.map +0 -7
  39. package/lib/matchers/toMatchText.js.map +0 -7
  40. package/lib/mcp/browser/actions.d.js.map +0 -7
  41. package/lib/mcp/browser/browserContextFactory.js.map +0 -7
  42. package/lib/mcp/browser/browserServerBackend.js.map +0 -7
  43. package/lib/mcp/browser/codegen.js.map +0 -7
  44. package/lib/mcp/browser/config.js.map +0 -7
  45. package/lib/mcp/browser/context.js.map +0 -7
  46. package/lib/mcp/browser/response.js.map +0 -7
  47. package/lib/mcp/browser/sessionLog.js.map +0 -7
  48. package/lib/mcp/browser/tab.js.map +0 -7
  49. package/lib/mcp/browser/tools/actionRetry.js.map +0 -7
  50. package/lib/mcp/browser/tools/common.js.map +0 -7
  51. package/lib/mcp/browser/tools/console.js.map +0 -7
  52. package/lib/mcp/browser/tools/dialogs.js.map +0 -7
  53. package/lib/mcp/browser/tools/evaluate.js.map +0 -7
  54. package/lib/mcp/browser/tools/files.js.map +0 -7
  55. package/lib/mcp/browser/tools/form.js.map +0 -7
  56. package/lib/mcp/browser/tools/install.js.map +0 -7
  57. package/lib/mcp/browser/tools/keyboard.js.map +0 -7
  58. package/lib/mcp/browser/tools/mouse.js.map +0 -7
  59. package/lib/mcp/browser/tools/navigate.js.map +0 -7
  60. package/lib/mcp/browser/tools/network.js.map +0 -7
  61. package/lib/mcp/browser/tools/pdf.js.map +0 -7
  62. package/lib/mcp/browser/tools/screenshot.js.map +0 -7
  63. package/lib/mcp/browser/tools/snapshot.js.map +0 -7
  64. package/lib/mcp/browser/tools/tabs.js.map +0 -7
  65. package/lib/mcp/browser/tools/tool.js.map +0 -7
  66. package/lib/mcp/browser/tools/tracing.js.map +0 -7
  67. package/lib/mcp/browser/tools/utils.js.map +0 -7
  68. package/lib/mcp/browser/tools/verify.js.map +0 -7
  69. package/lib/mcp/browser/tools/wait.js.map +0 -7
  70. package/lib/mcp/browser/tools.js.map +0 -7
  71. package/lib/mcp/browser/watchdog.js.map +0 -7
  72. package/lib/mcp/config.d.js.map +0 -7
  73. package/lib/mcp/extension/cdpRelay.js.map +0 -7
  74. package/lib/mcp/extension/extensionContextFactory.js.map +0 -7
  75. package/lib/mcp/extension/protocol.js.map +0 -7
  76. package/lib/mcp/index.js.map +0 -7
  77. package/lib/mcp/log.js.map +0 -7
  78. package/lib/mcp/program.js.map +0 -7
  79. package/lib/mcp/sdk/bundle.js.map +0 -7
  80. package/lib/mcp/sdk/exports.js.map +0 -7
  81. package/lib/mcp/sdk/http.js.map +0 -7
  82. package/lib/mcp/sdk/inProcessTransport.js.map +0 -7
  83. package/lib/mcp/sdk/mdb.js.map +0 -7
  84. package/lib/mcp/sdk/proxyBackend.js.map +0 -7
  85. package/lib/mcp/sdk/server.js.map +0 -7
  86. package/lib/mcp/sdk/tool.js.map +0 -7
  87. package/lib/mcp/test/browserBackend.js.map +0 -7
  88. package/lib/mcp/test/generatorTools.js.map +0 -7
  89. package/lib/mcp/test/plannerTools.js.map +0 -7
  90. package/lib/mcp/test/seed.js.map +0 -7
  91. package/lib/mcp/test/streams.js.map +0 -7
  92. package/lib/mcp/test/testBackend.js.map +0 -7
  93. package/lib/mcp/test/testContext.js.map +0 -7
  94. package/lib/mcp/test/testTool.js.map +0 -7
  95. package/lib/mcp/test/testTools.js.map +0 -7
  96. package/lib/mcpBundleImpl.js.map +0 -7
  97. package/lib/plugins/gitCommitInfoPlugin.js.map +0 -7
  98. package/lib/plugins/index.js.map +0 -7
  99. package/lib/plugins/webServerPlugin.js.map +0 -7
  100. package/lib/program.js.map +0 -7
  101. package/lib/reporters/base.js.map +0 -7
  102. package/lib/reporters/blob.js.map +0 -7
  103. package/lib/reporters/dot.js.map +0 -7
  104. package/lib/reporters/empty.js.map +0 -7
  105. package/lib/reporters/github.js.map +0 -7
  106. package/lib/reporters/html.js.map +0 -7
  107. package/lib/reporters/internalReporter.js.map +0 -7
  108. package/lib/reporters/json.js.map +0 -7
  109. package/lib/reporters/junit.js.map +0 -7
  110. package/lib/reporters/line.js.map +0 -7
  111. package/lib/reporters/list.js.map +0 -7
  112. package/lib/reporters/listModeReporter.js.map +0 -7
  113. package/lib/reporters/markdown.js.map +0 -7
  114. package/lib/reporters/merge.js.map +0 -7
  115. package/lib/reporters/multiplexer.js.map +0 -7
  116. package/lib/reporters/reporterV2.js.map +0 -7
  117. package/lib/reporters/teleEmitter.js.map +0 -7
  118. package/lib/reporters/versions/blobV1.js.map +0 -7
  119. package/lib/runner/dispatcher.js.map +0 -7
  120. package/lib/runner/failureTracker.js.map +0 -7
  121. package/lib/runner/lastRun.js.map +0 -7
  122. package/lib/runner/loadUtils.js.map +0 -7
  123. package/lib/runner/loaderHost.js.map +0 -7
  124. package/lib/runner/processHost.js.map +0 -7
  125. package/lib/runner/projectUtils.js.map +0 -7
  126. package/lib/runner/rebase.js.map +0 -7
  127. package/lib/runner/reporters.js.map +0 -7
  128. package/lib/runner/runner.js +0 -110
  129. package/lib/runner/sigIntWatcher.js.map +0 -7
  130. package/lib/runner/taskRunner.js.map +0 -7
  131. package/lib/runner/tasks.js.map +0 -7
  132. package/lib/runner/testGroups.js.map +0 -7
  133. package/lib/runner/testRunner.js.map +0 -7
  134. package/lib/runner/testServer.js.map +0 -7
  135. package/lib/runner/uiModeReporter.js.map +0 -7
  136. package/lib/runner/vcs.js.map +0 -7
  137. package/lib/runner/watchMode.js.map +0 -7
  138. package/lib/runner/workerHost.js.map +0 -7
  139. package/lib/third_party/pirates.js.map +0 -7
  140. package/lib/third_party/tsconfig-loader.js.map +0 -7
  141. package/lib/transform/babelBundle.js.map +0 -7
  142. package/lib/transform/babelBundleImpl.js.map +0 -7
  143. package/lib/transform/compilationCache.js.map +0 -7
  144. package/lib/transform/esmLoader.js.map +0 -7
  145. package/lib/transform/portTransport.js.map +0 -7
  146. package/lib/transform/transform.js.map +0 -7
  147. package/lib/util.js.map +0 -7
  148. package/lib/utilsBundle.js.map +0 -7
  149. package/lib/utilsBundleImpl.js.map +0 -7
  150. package/lib/worker/fixtureRunner.js.map +0 -7
  151. package/lib/worker/testInfo.js.map +0 -7
  152. package/lib/worker/testTracing.js.map +0 -7
  153. package/lib/worker/timeoutManager.js.map +0 -7
  154. package/lib/worker/util.js.map +0 -7
  155. package/lib/worker/workerMain.js.map +0 -7
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../../src/mcp/sdk/mdb.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 { debug } from 'playwright-core/lib/utilsBundle';\nimport { ManualPromise } from 'playwright-core/lib/utils';\n\nimport { defineToolSchema } from './tool';\nimport * as mcpBundle from './bundle';\nimport * as mcpServer from './server';\nimport * as mcpHttp from './http';\n\nimport type { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js';\nimport type { Client } from '@modelcontextprotocol/sdk/client/index.js';\n\nconst mdbDebug = debug('pw:mcp:mdb');\nconst errorsDebug = debug('pw:mcp:errors');\nconst z = mcpBundle.z;\n\nexport class MDBBackend implements mcpServer.ServerBackend {\n private _onPauseClient: { client: Client, tools: mcpServer.Tool[], transport: StreamableHTTPClientTransport } | undefined;\n private _interruptPromise: ManualPromise<mcpServer.CallToolResult> | undefined;\n private _mainBackend: mcpServer.ServerBackend;\n private _clientInfo: mcpServer.ClientInfo | undefined;\n private _progress: mcpServer.CallToolResult['content'] = [];\n private _progressCallback: mcpServer.ProgressCallback;\n\n constructor(mainBackend: mcpServer.ServerBackend) {\n this._mainBackend = mainBackend;\n this._progressCallback = (params: mcpServer.ProgressParams) => {\n if (params.message)\n this._progress.push({ type: 'text', text: params.message });\n };\n }\n\n async initialize(server: mcpServer.Server, clientInfo: mcpServer.ClientInfo): Promise<void> {\n if (!this._clientInfo) {\n this._clientInfo = clientInfo;\n await this._mainBackend.initialize?.(server, clientInfo);\n }\n }\n\n async listTools(): Promise<mcpServer.Tool[]> {\n return await this._mainBackend.listTools();\n }\n\n async callTool(name: string, args: mcpServer.CallToolRequest['params']['arguments']): Promise<mcpServer.CallToolResult> {\n if (name === pushToolsSchema.name) {\n await this._createOnPauseClient(pushToolsSchema.inputSchema.parse(args || {}));\n return { content: [{ type: 'text', text: 'Tools pushed' }] };\n }\n\n if (this._onPauseClient?.tools.find(tool => tool.name === name)) {\n const result = await this._onPauseClient.client.callTool({\n name,\n arguments: args,\n }) as mcpServer.CallToolResult;\n await this._mainBackend.afterCallTool?.(name, args, result);\n return result;\n }\n\n await this._onPauseClient?.transport.terminateSession().catch(errorsDebug);\n await this._onPauseClient?.client.close().catch(errorsDebug);\n this._onPauseClient = undefined;\n\n const resultPromise = new ManualPromise<mcpServer.CallToolResult>();\n const interruptPromise = new ManualPromise<mcpServer.CallToolResult>();\n this._interruptPromise = interruptPromise;\n\n this._mainBackend.callTool(name, args, this._progressCallback).then(result => {\n resultPromise.resolve(result as mcpServer.CallToolResult);\n }).catch(e => {\n resultPromise.resolve({ content: [{ type: 'text', text: String(e) }], isError: true });\n });\n\n const result = await Promise.race([interruptPromise, resultPromise]);\n if (interruptPromise.isDone())\n mdbDebug('client call intercepted', result);\n else\n mdbDebug('client call result', result);\n result.content.unshift(...this._progress);\n this._progress.length = 0;\n return result;\n }\n\n private async _createOnPauseClient(params: { mcpUrl: string, introMessage?: string }) {\n if (this._onPauseClient)\n await this._onPauseClient.client.close().catch(errorsDebug);\n\n this._onPauseClient = await this._createClient(params.mcpUrl);\n\n this._interruptPromise?.resolve({\n content: [{\n type: 'text',\n text: params.introMessage || '',\n }],\n });\n this._interruptPromise = undefined;\n }\n\n private async _createClient(url: string): Promise<{ client: Client, tools: mcpServer.Tool[], transport: StreamableHTTPClientTransport }> {\n const client = new mcpBundle.Client({ name: 'Interrupting client', version: '0.0.0' }, { capabilities: { roots: {} } });\n client.setRequestHandler(mcpBundle.ListRootsRequestSchema, () => ({ roots: this._clientInfo?.roots || [] }));\n client.setRequestHandler(mcpBundle.PingRequestSchema, () => ({}));\n client.setNotificationHandler(mcpBundle.ProgressNotificationSchema, notification => {\n if (notification.method === 'notifications/progress') {\n const { message } = notification.params;\n if (message)\n this._progress.push({ type: 'text', text: message });\n }\n });\n const transport = new mcpBundle.StreamableHTTPClientTransport(new URL(url));\n await client.connect(transport);\n const { tools } = await client.listTools();\n return { client, tools, transport };\n }\n}\n\nconst pushToolsSchema = defineToolSchema({\n name: 'mdb_push_tools',\n title: 'Push MCP tools to the tools stack',\n description: 'Push MCP tools to the tools stack',\n inputSchema: z.object({\n mcpUrl: z.string(),\n introMessage: z.string().optional(),\n }),\n type: 'readOnly',\n});\n\nexport async function runMainBackend(backendFactory: mcpServer.ServerBackendFactory, options?: { port?: number }): Promise<string | undefined> {\n const mdbBackend = new MDBBackend(backendFactory.create(backendFactory.config));\n // Start HTTP unconditionally.\n const factory: mcpServer.ServerBackendFactory = {\n ...backendFactory,\n create: (cfg) => mdbBackend\n };\n const url = await startAsHttp(factory, { port: options?.port || 0 });\n process.env.PLAYWRIGHT_DEBUGGER_MCP = url;\n\n if (options?.port !== undefined)\n return url;\n\n // Start stdio conditionally.\n await mcpServer.connect(factory, new mcpBundle.StdioServerTransport(), false);\n}\n\nexport async function runOnPauseBackendLoop(backend: mcpServer.ServerBackend, introMessage: string) {\n const wrappedBackend = new ServerBackendWithCloseListener(backend);\n\n const factory: mcpServer.ServerBackendFactory = {\n name: 'on-pause-backend',\n nameInConfig: 'on-pause-backend',\n version: '0.0.0',\n config: {} as any, // MDB doesn't use config\n create: () => wrappedBackend,\n };\n\n const httpServer = await mcpHttp.startHttpServer({ port: 0 });\n const url = await mcpHttp.installHttpTransport(httpServer, factory, true);\n\n const client = new mcpBundle.Client({ name: 'Pushing client', version: '0.0.0' });\n client.setRequestHandler(mcpBundle.PingRequestSchema, () => ({}));\n const transport = new mcpBundle.StreamableHTTPClientTransport(new URL(process.env.PLAYWRIGHT_DEBUGGER_MCP!));\n await client.connect(transport);\n\n const pushToolsResult = await client.callTool({\n name: pushToolsSchema.name,\n arguments: {\n mcpUrl: url,\n introMessage,\n },\n });\n if (pushToolsResult.isError)\n errorsDebug('Failed to push tools', pushToolsResult.content);\n await transport.terminateSession();\n await client.close();\n\n await wrappedBackend.waitForClosed();\n httpServer.close();\n}\n\nasync function startAsHttp(backendFactory: mcpServer.ServerBackendFactory, options: { port: number }) {\n const httpServer = await mcpHttp.startHttpServer(options);\n return await mcpHttp.installHttpTransport(httpServer, backendFactory, true);\n}\n\n\nclass ServerBackendWithCloseListener implements mcpServer.ServerBackend {\n private _backend: mcpServer.ServerBackend;\n private _serverClosedPromise = new ManualPromise<void>();\n\n constructor(backend: mcpServer.ServerBackend) {\n this._backend = backend;\n }\n\n async initialize(server: mcpServer.Server, clientInfo: mcpServer.ClientInfo): Promise<void> {\n await this._backend.initialize?.(server, clientInfo);\n }\n\n async listTools(): Promise<mcpServer.Tool[]> {\n return this._backend.listTools();\n }\n\n async callTool(name: string, args: mcpServer.CallToolRequest['params']['arguments'], progress: mcpServer.ProgressCallback): Promise<mcpServer.CallToolResult> {\n return this._backend.callTool(name, args, progress);\n }\n\n serverClosed(server: mcpServer.Server) {\n this._backend.serverClosed?.(server);\n this._serverClosedPromise.resolve();\n }\n\n async waitForClosed() {\n await this._serverClosedPromise;\n }\n}\n"],
5
- "mappings": "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",
6
- "names": ["result"]
7
- }
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../../src/mcp/sdk/proxyBackend.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 { debug } from 'playwright-core/lib/utilsBundle';\n\nimport * as mcpBundle from './bundle';\n\nimport type { ServerBackend, ClientInfo, Server } from './server';\nimport type { Transport } from '@modelcontextprotocol/sdk/shared/transport.js';\nimport type { Tool, CallToolResult, CallToolRequest } from '@modelcontextprotocol/sdk/types.js';\nimport type { Client } from '@modelcontextprotocol/sdk/client/index.js';\n\nexport type MCPProvider = {\n name: string;\n description: string;\n connect(): Promise<Transport>;\n};\n\nconst errorsDebug = debug('pw:mcp:errors');\nconst { z, zodToJsonSchema } = mcpBundle;\n\nexport class ProxyBackend implements ServerBackend {\n private _mcpProviders: MCPProvider[];\n private _currentClient: Client | undefined;\n private _contextSwitchTool: Tool;\n private _clientInfo: ClientInfo | undefined;\n\n constructor(mcpProviders: MCPProvider[]) {\n this._mcpProviders = mcpProviders;\n this._contextSwitchTool = this._defineContextSwitchTool();\n }\n\n async initialize(server: Server, clientInfo: ClientInfo): Promise<void> {\n this._clientInfo = clientInfo;\n }\n\n async listTools(): Promise<Tool[]> {\n const currentClient = await this._ensureCurrentClient();\n const response = await currentClient.listTools();\n if (this._mcpProviders.length === 1)\n return response.tools;\n return [\n ...response.tools,\n this._contextSwitchTool,\n ];\n }\n\n async callTool(name: string, args: CallToolRequest['params']['arguments']): Promise<CallToolResult> {\n if (name === this._contextSwitchTool.name)\n return this._callContextSwitchTool(args);\n const currentClient = await this._ensureCurrentClient();\n return await currentClient.callTool({\n name,\n arguments: args,\n }) as CallToolResult;\n }\n\n serverClosed?(): void {\n void this._currentClient?.close().catch(errorsDebug);\n }\n\n private async _callContextSwitchTool(params: any): Promise<CallToolResult> {\n try {\n const factory = this._mcpProviders.find(factory => factory.name === params.name);\n if (!factory)\n throw new Error('Unknown connection method: ' + params.name);\n\n await this._setCurrentClient(factory);\n return {\n content: [{ type: 'text', text: '### Result\\nSuccessfully changed connection method.\\n' }],\n };\n } catch (error) {\n return {\n content: [{ type: 'text', text: `### Result\\nError: ${error}\\n` }],\n isError: true,\n };\n }\n }\n\n private _defineContextSwitchTool(): Tool {\n return {\n name: 'browser_connect',\n description: [\n 'Connect to a browser using one of the available methods:',\n ...this._mcpProviders.map(factory => `- \"${factory.name}\": ${factory.description}`),\n ].join('\\n'),\n inputSchema: zodToJsonSchema(z.object({\n name: z.enum(this._mcpProviders.map(factory => factory.name) as [string, ...string[]]).default(this._mcpProviders[0].name).describe('The method to use to connect to the browser'),\n }), { strictUnions: true }) as Tool['inputSchema'],\n annotations: {\n title: 'Connect to a browser context',\n readOnlyHint: true,\n openWorldHint: false,\n },\n };\n }\n\n private async _ensureCurrentClient(): Promise<Client> {\n if (this._currentClient)\n return this._currentClient;\n return await this._setCurrentClient(this._mcpProviders[0]);\n }\n\n private async _setCurrentClient(factory: MCPProvider) {\n await this._currentClient?.close();\n this._currentClient = undefined;\n\n const client = new mcpBundle.Client({ name: 'Playwright MCP Proxy', version: '0.0.0' });\n client.registerCapabilities({\n roots: {\n listRoots: true,\n },\n });\n client.setRequestHandler(mcpBundle.ListRootsRequestSchema, () => ({ roots: this._clientInfo?.roots || [] }));\n client.setRequestHandler(mcpBundle.PingRequestSchema, () => ({}));\n\n const transport = await factory.connect();\n await client.connect(transport);\n this._currentClient = client;\n return client;\n }\n}\n"],
5
- "mappings": "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",
6
- "names": ["factory"]
7
- }
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../../src/mcp/sdk/server.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 { fileURLToPath } from 'url';\n\nimport { debug } from 'playwright-core/lib/utilsBundle';\n\nimport * as mcpBundle from './bundle';\nimport { installHttpTransport, startHttpServer } from './http';\nimport { InProcessTransport } from './inProcessTransport';\n\nimport type { Tool, CallToolResult, CallToolRequest, Root } from '@modelcontextprotocol/sdk/types.js';\nimport type { Transport } from '@modelcontextprotocol/sdk/shared/transport.js';\nexport type { Server } from '@modelcontextprotocol/sdk/server/index.js';\nexport type { Tool, CallToolResult, CallToolRequest, Root } from '@modelcontextprotocol/sdk/types.js';\nimport type { Server } from '@modelcontextprotocol/sdk/server/index.js';\nimport type { FullConfig } from '../browser/config';\n\nconst serverDebug = debug('pw:mcp:server');\n\nexport type ClientInfo = {\n name: string;\n version: string;\n roots: Root[];\n timestamp: number;\n};\n\nexport type ProgressParams = { message?: string, progress?: number, total?: number };\nexport type ProgressCallback = (params: ProgressParams) => void;\n\nexport interface ServerBackend {\n initialize?(server: Server, clientInfo: ClientInfo): Promise<void>;\n listTools(): Promise<Tool[]>;\n afterCallTool?(name: string, args: CallToolRequest['params']['arguments'], result: CallToolResult): Promise<void>;\n callTool(name: string, args: CallToolRequest['params']['arguments'], progress: ProgressCallback): Promise<CallToolResult>;\n serverClosed?(server: Server): void;\n}\n\nexport type ServerBackendFactory = {\n name: string;\n nameInConfig: string;\n version: string;\n config: FullConfig;\n create: (config: FullConfig) => ServerBackend;\n};\n\nexport async function connect(factory: ServerBackendFactory, transport: Transport, runHeartbeat: boolean, config?: FullConfig) {\n const backend = factory.create(config || factory.config);\n const server = createServer(factory.name, factory.version, backend, runHeartbeat);\n await server.connect(transport);\n}\n\nexport async function wrapInProcess(backend: ServerBackend): Promise<Transport> {\n const server = createServer('Internal', '0.0.0', backend, false);\n return new InProcessTransport(server);\n}\n\nexport function createServer(name: string, version: string, backend: ServerBackend, runHeartbeat: boolean): Server {\n const server = new mcpBundle.Server({ name, version }, {\n capabilities: {\n tools: {},\n }\n });\n\n server.setRequestHandler(mcpBundle.ListToolsRequestSchema, async () => {\n serverDebug('listTools');\n const tools = await backend.listTools();\n return { tools };\n });\n\n let initializePromise: Promise<void> | undefined;\n server.setRequestHandler(mcpBundle.CallToolRequestSchema, async (request, extra) => {\n serverDebug('callTool', request);\n\n const progressToken = request.params._meta?.progressToken;\n let progressCounter = 0;\n\n const progress = progressToken ? (params: ProgressParams) => {\n extra.sendNotification({\n method: 'notifications/progress',\n params: {\n progressToken,\n progress: params.progress ?? ++progressCounter,\n total: params.total,\n message: params.message,\n },\n }).catch(serverDebug);\n } : () => {};\n\n try {\n if (!initializePromise)\n initializePromise = initializeServer(server, backend, runHeartbeat);\n await initializePromise;\n return mergeTextParts(await backend.callTool(request.params.name, request.params.arguments || {}, progress));\n } catch (error) {\n return {\n content: [{ type: 'text', text: '### Result\\n' + String(error) }],\n isError: true,\n };\n }\n });\n addServerListener(server, 'close', () => backend.serverClosed?.(server));\n return server;\n}\n\nconst initializeServer = async (server: Server, backend: ServerBackend, runHeartbeat: boolean) => {\n const capabilities = server.getClientCapabilities();\n let clientRoots: Root[] = [];\n if (capabilities?.roots) {\n const { roots } = await server.listRoots().catch(e => {\n serverDebug(e);\n return { roots: [] };\n });\n clientRoots = roots;\n }\n\n const clientInfo: ClientInfo = {\n name: server.getClientVersion()?.name ?? 'unknown',\n version: server.getClientVersion()?.version ?? 'unknown',\n roots: clientRoots,\n timestamp: Date.now(),\n };\n\n await backend.initialize?.(server, clientInfo);\n if (runHeartbeat)\n startHeartbeat(server);\n};\n\nconst startHeartbeat = (server: Server) => {\n const beat = () => {\n Promise.race([\n server.ping(),\n new Promise((_, reject) => setTimeout(() => reject(new Error('ping timeout')), 5000)),\n ]).then(() => {\n setTimeout(beat, 3000);\n }).catch(() => {\n void server.close();\n });\n };\n\n beat();\n};\n\nfunction addServerListener(server: Server, event: 'close' | 'initialized', listener: () => void) {\n const oldListener = server[`on${event}`];\n server[`on${event}`] = () => {\n oldListener?.();\n listener();\n };\n}\n\nexport async function start(serverBackendFactory: ServerBackendFactory, options: { host?: string; port?: number, allowedHosts?: string[] }) {\n if (options.port === undefined) {\n await connect(serverBackendFactory, new mcpBundle.StdioServerTransport(), false);\n return;\n }\n\n const httpServer = await startHttpServer(options);\n const url = await installHttpTransport(httpServer, serverBackendFactory, false, options.allowedHosts);\n\n const mcpConfig: any = { mcpServers: { } };\n mcpConfig.mcpServers[serverBackendFactory.nameInConfig] = {\n url: `${url}/mcp`\n };\n const message = [\n `Listening on ${url}`,\n 'Put this in your client config:',\n JSON.stringify(mcpConfig, undefined, 2),\n 'For legacy SSE transport support, you can use the /sse endpoint instead.',\n ].join('\\n');\n // eslint-disable-next-line no-console\n console.error(message);\n}\n\nexport function firstRootPath(clientInfo: ClientInfo): string | undefined {\n if (clientInfo.roots.length === 0)\n return undefined;\n const firstRootUri = clientInfo.roots[0]?.uri;\n const url = firstRootUri ? new URL(firstRootUri) : undefined;\n return url ? fileURLToPath(url) : undefined;\n}\n\nfunction mergeTextParts(result: CallToolResult): CallToolResult {\n const content: CallToolResult['content'] = [];\n const testParts: string[] = [];\n for (const part of result.content) {\n if (part.type === 'text') {\n testParts.push(part.text);\n continue;\n }\n if (testParts.length > 0) {\n content.push({ type: 'text', text: testParts.join('\\n') });\n testParts.length = 0;\n }\n content.push(part);\n }\n if (testParts.length > 0)\n content.push({ type: 'text', text: testParts.join('\\n') });\n return {\n ...result,\n content,\n };\n}\n"],
5
- "mappings": "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",
6
- "names": []
7
- }
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../../src/mcp/sdk/tool.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 { z as zod, zodToJsonSchema } from '../sdk/bundle';\n\nimport type { z } from 'zod';\nimport type * as mcpServer from './server';\n\nexport type ToolSchema<Input extends z.Schema> = {\n name: string;\n title: string;\n description: string;\n inputSchema: Input;\n type: 'input' | 'assertion' | 'action' | 'readOnly';\n};\n\nconst typesWithIntent = ['action', 'assertion', 'input'];\n\nexport function toMcpTool(tool: ToolSchema<any>, options?: { addIntent?: boolean }): mcpServer.Tool {\n const inputSchema = options?.addIntent && typesWithIntent.includes(tool.type) ? tool.inputSchema.extend({\n intent: zod.string().describe('The intent of the call, for example the test step description plan idea')\n }) : tool.inputSchema;\n const readOnly = tool.type === 'readOnly' || tool.type === 'assertion';\n return {\n name: tool.name,\n description: tool.description,\n inputSchema: zodToJsonSchema(inputSchema, { strictUnions: true }) as mcpServer.Tool['inputSchema'],\n annotations: {\n title: tool.title,\n readOnlyHint: readOnly,\n destructiveHint: !readOnly,\n openWorldHint: true,\n },\n };\n}\n\nexport function defineToolSchema<Input extends z.Schema>(tool: ToolSchema<Input>): ToolSchema<Input> {\n return tool;\n}\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAgBA,oBAA2C;AAa3C,MAAM,kBAAkB,CAAC,UAAU,aAAa,OAAO;AAEhD,SAAS,UAAU,MAAuB,SAAmD;AAClG,QAAM,cAAc,SAAS,aAAa,gBAAgB,SAAS,KAAK,IAAI,IAAI,KAAK,YAAY,OAAO;AAAA,IACtG,QAAQ,cAAAA,EAAI,OAAO,EAAE,SAAS,yEAAyE;AAAA,EACzG,CAAC,IAAI,KAAK;AACV,QAAM,WAAW,KAAK,SAAS,cAAc,KAAK,SAAS;AAC3D,SAAO;AAAA,IACL,MAAM,KAAK;AAAA,IACX,aAAa,KAAK;AAAA,IAClB,iBAAa,+BAAgB,aAAa,EAAE,cAAc,KAAK,CAAC;AAAA,IAChE,aAAa;AAAA,MACX,OAAO,KAAK;AAAA,MACZ,cAAc;AAAA,MACd,iBAAiB,CAAC;AAAA,MAClB,eAAe;AAAA,IACjB;AAAA,EACF;AACF;AAEO,SAAS,iBAAyC,MAA4C;AACnG,SAAO;AACT;",
6
- "names": ["zod"]
7
- }
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../../src/mcp/test/browserBackend.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 * as mcp from '../sdk/exports';\nimport { currentTestInfo } from '../../common/globals';\nimport { stripAnsiEscapes } from '../../util';\nimport { defaultConfig, FullConfig } from '../browser/config';\nimport { BrowserServerBackend } from '../browser/browserServerBackend';\nimport { Tab } from '../browser/tab';\n\nimport type * as playwright from '../../../index';\nimport type { Page } from '../../../../playwright-core/src/client/page';\nimport type { BrowserContextFactory } from '../browser/browserContextFactory';\nimport type { ClientInfo } from '../sdk/server';\n\nexport async function runBrowserBackendAtEnd(context: playwright.BrowserContext, errorMessage?: string) {\n const testInfo = currentTestInfo();\n if (!testInfo)\n return;\n\n const shouldPause = errorMessage ? testInfo?._pauseOnError() : testInfo?._pauseAtEnd();\n if (!shouldPause)\n return;\n\n const lines: string[] = [];\n if (errorMessage)\n lines.push(`### Paused on error:`, stripAnsiEscapes(errorMessage));\n else\n lines.push(`### Paused at end of test. ready for interaction`);\n\n for (let i = 0; i < context.pages().length; i++) {\n const page = context.pages()[i];\n const stateSuffix = context.pages().length > 1 ? (i + 1) + ' of ' + (context.pages().length) : 'state';\n lines.push(\n '',\n `### Page ${stateSuffix}`,\n `- Page URL: ${page.url()}`,\n `- Page Title: ${await page.title()}`.trim()\n );\n // Only print console errors when pausing on error, not when everything works as expected.\n let console = errorMessage ? await Tab.collectConsoleMessages(page) : [];\n console = console.filter(msg => !msg.type || msg.type === 'error');\n if (console.length) {\n lines.push('- Console Messages:');\n for (const message of console)\n lines.push(` - ${message.toString()}`);\n }\n lines.push(\n `- Page Snapshot:`,\n '```yaml',\n await (page as Page)._snapshotForAI(),\n '```',\n );\n }\n\n lines.push('');\n if (errorMessage)\n lines.push(`### Task`, `Try recovering from the error prior to continuing`);\n\n const config: FullConfig = {\n ...defaultConfig,\n capabilities: ['testing'],\n };\n\n await mcp.runOnPauseBackendLoop(new BrowserServerBackend(config, identityFactory(context)), lines.join('\\n'));\n}\n\nfunction identityFactory(browserContext: playwright.BrowserContext): BrowserContextFactory {\n return {\n createContext: async (clientInfo: ClientInfo, abortSignal: AbortSignal, toolName: string | undefined) => {\n return {\n browserContext,\n close: async () => {}\n };\n }\n };\n}\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAgBA,UAAqB;AACrB,qBAAgC;AAChC,kBAAiC;AACjC,oBAA0C;AAC1C,kCAAqC;AACrC,iBAAoB;AAOpB,eAAsB,uBAAuB,SAAoC,cAAuB;AACtG,QAAM,eAAW,gCAAgB;AACjC,MAAI,CAAC;AACH;AAEF,QAAM,cAAc,eAAe,UAAU,cAAc,IAAI,UAAU,YAAY;AACrF,MAAI,CAAC;AACH;AAEF,QAAM,QAAkB,CAAC;AACzB,MAAI;AACF,UAAM,KAAK,4BAAwB,8BAAiB,YAAY,CAAC;AAAA;AAEjE,UAAM,KAAK,kDAAkD;AAE/D,WAAS,IAAI,GAAG,IAAI,QAAQ,MAAM,EAAE,QAAQ,KAAK;AAC/C,UAAM,OAAO,QAAQ,MAAM,EAAE,CAAC;AAC9B,UAAM,cAAc,QAAQ,MAAM,EAAE,SAAS,IAAK,IAAI,IAAK,SAAU,QAAQ,MAAM,EAAE,SAAU;AAC/F,UAAM;AAAA,MACF;AAAA,MACA,YAAY,WAAW;AAAA,MACvB,eAAe,KAAK,IAAI,CAAC;AAAA,MACzB,iBAAiB,MAAM,KAAK,MAAM,CAAC,GAAG,KAAK;AAAA,IAC/C;AAEA,QAAI,UAAU,eAAe,MAAM,eAAI,uBAAuB,IAAI,IAAI,CAAC;AACvE,cAAU,QAAQ,OAAO,SAAO,CAAC,IAAI,QAAQ,IAAI,SAAS,OAAO;AACjE,QAAI,QAAQ,QAAQ;AAClB,YAAM,KAAK,qBAAqB;AAChC,iBAAW,WAAW;AACpB,cAAM,KAAK,OAAO,QAAQ,SAAS,CAAC,EAAE;AAAA,IAC1C;AACA,UAAM;AAAA,MACF;AAAA,MACA;AAAA,MACA,MAAO,KAAc,eAAe;AAAA,MACpC;AAAA,IACJ;AAAA,EACF;AAEA,QAAM,KAAK,EAAE;AACb,MAAI;AACF,UAAM,KAAK,YAAY,mDAAmD;AAE5E,QAAM,SAAqB;AAAA,IACzB,GAAG;AAAA,IACH,cAAc,CAAC,SAAS;AAAA,EAC1B;AAEA,QAAM,IAAI,sBAAsB,IAAI,iDAAqB,QAAQ,gBAAgB,OAAO,CAAC,GAAG,MAAM,KAAK,IAAI,CAAC;AAC9G;AAEA,SAAS,gBAAgB,gBAAkE;AACzF,SAAO;AAAA,IACL,eAAe,OAAO,YAAwB,aAA0B,aAAiC;AACvG,aAAO;AAAA,QACL;AAAA,QACA,OAAO,YAAY;AAAA,QAAC;AAAA,MACtB;AAAA,IACF;AAAA,EACF;AACF;",
6
- "names": []
7
- }
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../../src/mcp/test/generatorTools.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\nimport { z } from '../sdk/bundle';\nimport { defineTestTool } from './testTool';\nimport { GeneratorJournal } from './testContext';\n\nexport const setupPage = defineTestTool({\n schema: {\n name: 'generator_setup_page',\n title: 'Setup generator page',\n description: 'Setup the page for test.',\n inputSchema: z.object({\n plan: z.string().describe('The plan for the test. This should be the actual test plan with all the steps.'),\n project: z.string().optional().describe('Project to use for setup. For example: \"chromium\", if no project is provided uses the first project in the config.'),\n seedFile: z.string().optional().describe('A seed file contains a single test that is used to setup the page for testing, for example: \"tests/seed.spec.ts\". If no seed file is provided, a default seed file is created.'),\n }),\n type: 'readOnly',\n },\n\n handle: async (context, params, progress) => {\n const seed = await context.getOrCreateSeedFile(params.seedFile, params.project);\n context.generatorJournal = new GeneratorJournal(context.rootPath, params.plan, seed);\n await context.runSeedTest(seed.file, seed.projectName, progress);\n return { content: [] };\n },\n});\n\nexport const generatorReadLog = defineTestTool({\n schema: {\n name: 'generator_read_log',\n title: 'Retrieve test log',\n description: 'Retrieve the performed test log',\n inputSchema: z.object({}),\n type: 'readOnly',\n },\n\n handle: async context => {\n if (!context.generatorJournal)\n throw new Error(`Please setup page using \"${setupPage.schema.name}\" first.`);\n const result = context.generatorJournal.journal();\n return { content: [{\n type: 'text',\n text: result,\n }] };\n },\n});\n\nexport const generatorWriteTest = defineTestTool({\n schema: {\n name: 'generator_write_test',\n title: 'Write test',\n description: 'Write the generated test to the test file',\n inputSchema: z.object({\n fileName: z.string().describe('The file to write the test to'),\n code: z.string().describe('The generated test code'),\n }),\n type: 'readOnly',\n },\n\n handle: async (context, params) => {\n if (!context.generatorJournal)\n throw new Error(`Please setup page using \"${setupPage.schema.name}\" first.`);\n\n const testRunner = context.existingTestRunner();\n if (!testRunner)\n throw new Error('No test runner found, please setup page and perform actions first.');\n const config = await testRunner.loadConfig();\n\n const dirs: string[] = [];\n for (const project of config.projects) {\n const testDir = path.relative(context.rootPath, project.project.testDir).replace(/\\\\/g, '/');\n const fileName = params.fileName.replace(/\\\\/g, '/');\n if (fileName.startsWith(testDir)) {\n const resolvedFile = path.resolve(context.rootPath, fileName);\n await fs.promises.mkdir(path.dirname(resolvedFile), { recursive: true });\n await fs.promises.writeFile(resolvedFile, params.code);\n return {\n content: [{\n type: 'text',\n text: `### Result\\nTest written to ${params.fileName}`,\n }]\n };\n }\n dirs.push(testDir);\n }\n throw new Error(`Test file did not match any of the test dirs: ${dirs.join(', ')}`);\n },\n});\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAgBA,gBAAe;AACf,kBAAiB;AAEjB,oBAAkB;AAClB,sBAA+B;AAC/B,yBAAiC;AAE1B,MAAM,gBAAY,gCAAe;AAAA,EACtC,QAAQ;AAAA,IACN,MAAM;AAAA,IACN,OAAO;AAAA,IACP,aAAa;AAAA,IACb,aAAa,gBAAE,OAAO;AAAA,MACpB,MAAM,gBAAE,OAAO,EAAE,SAAS,gFAAgF;AAAA,MAC1G,SAAS,gBAAE,OAAO,EAAE,SAAS,EAAE,SAAS,oHAAoH;AAAA,MAC5J,UAAU,gBAAE,OAAO,EAAE,SAAS,EAAE,SAAS,gLAAgL;AAAA,IAC3N,CAAC;AAAA,IACD,MAAM;AAAA,EACR;AAAA,EAEA,QAAQ,OAAO,SAAS,QAAQ,aAAa;AAC3C,UAAM,OAAO,MAAM,QAAQ,oBAAoB,OAAO,UAAU,OAAO,OAAO;AAC9E,YAAQ,mBAAmB,IAAI,oCAAiB,QAAQ,UAAU,OAAO,MAAM,IAAI;AACnF,UAAM,QAAQ,YAAY,KAAK,MAAM,KAAK,aAAa,QAAQ;AAC/D,WAAO,EAAE,SAAS,CAAC,EAAE;AAAA,EACvB;AACF,CAAC;AAEM,MAAM,uBAAmB,gCAAe;AAAA,EAC7C,QAAQ;AAAA,IACN,MAAM;AAAA,IACN,OAAO;AAAA,IACP,aAAa;AAAA,IACb,aAAa,gBAAE,OAAO,CAAC,CAAC;AAAA,IACxB,MAAM;AAAA,EACR;AAAA,EAEA,QAAQ,OAAM,YAAW;AACvB,QAAI,CAAC,QAAQ;AACX,YAAM,IAAI,MAAM,4BAA4B,UAAU,OAAO,IAAI,UAAU;AAC7E,UAAM,SAAS,QAAQ,iBAAiB,QAAQ;AAChD,WAAO,EAAE,SAAS,CAAC;AAAA,MACjB,MAAM;AAAA,MACN,MAAM;AAAA,IACR,CAAC,EAAE;AAAA,EACL;AACF,CAAC;AAEM,MAAM,yBAAqB,gCAAe;AAAA,EAC/C,QAAQ;AAAA,IACN,MAAM;AAAA,IACN,OAAO;AAAA,IACP,aAAa;AAAA,IACb,aAAa,gBAAE,OAAO;AAAA,MACpB,UAAU,gBAAE,OAAO,EAAE,SAAS,+BAA+B;AAAA,MAC7D,MAAM,gBAAE,OAAO,EAAE,SAAS,yBAAyB;AAAA,IACrD,CAAC;AAAA,IACD,MAAM;AAAA,EACR;AAAA,EAEA,QAAQ,OAAO,SAAS,WAAW;AACjC,QAAI,CAAC,QAAQ;AACX,YAAM,IAAI,MAAM,4BAA4B,UAAU,OAAO,IAAI,UAAU;AAE7E,UAAM,aAAa,QAAQ,mBAAmB;AAC9C,QAAI,CAAC;AACH,YAAM,IAAI,MAAM,oEAAoE;AACtF,UAAM,SAAS,MAAM,WAAW,WAAW;AAE3C,UAAM,OAAiB,CAAC;AACxB,eAAW,WAAW,OAAO,UAAU;AACrC,YAAM,UAAU,YAAAA,QAAK,SAAS,QAAQ,UAAU,QAAQ,QAAQ,OAAO,EAAE,QAAQ,OAAO,GAAG;AAC3F,YAAM,WAAW,OAAO,SAAS,QAAQ,OAAO,GAAG;AACnD,UAAI,SAAS,WAAW,OAAO,GAAG;AAChC,cAAM,eAAe,YAAAA,QAAK,QAAQ,QAAQ,UAAU,QAAQ;AAC5D,cAAM,UAAAC,QAAG,SAAS,MAAM,YAAAD,QAAK,QAAQ,YAAY,GAAG,EAAE,WAAW,KAAK,CAAC;AACvE,cAAM,UAAAC,QAAG,SAAS,UAAU,cAAc,OAAO,IAAI;AACrD,eAAO;AAAA,UACL,SAAS,CAAC;AAAA,YACR,MAAM;AAAA,YACN,MAAM;AAAA,kBAA+B,OAAO,QAAQ;AAAA,UACtD,CAAC;AAAA,QACH;AAAA,MACF;AACA,WAAK,KAAK,OAAO;AAAA,IACnB;AACA,UAAM,IAAI,MAAM,iDAAiD,KAAK,KAAK,IAAI,CAAC,EAAE;AAAA,EACpF;AACF,CAAC;",
6
- "names": ["path", "fs"]
7
- }
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../../src/mcp/test/plannerTools.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 { z } from '../sdk/bundle';\nimport { defineTestTool } from './testTool';\n\nexport const setupPage = defineTestTool({\n schema: {\n name: 'planner_setup_page',\n title: 'Setup planner page',\n description: 'Setup the page for test planning',\n inputSchema: z.object({\n project: z.string().optional().describe('Project to use for setup. For example: \"chromium\", if no project is provided uses the first project in the config.'),\n seedFile: z.string().optional().describe('A seed file contains a single test that is used to setup the page for testing, for example: \"tests/seed.spec.ts\". If no seed file is provided, a default seed file is created.'),\n }),\n type: 'readOnly',\n },\n\n handle: async (context, params, progress) => {\n const seed = await context.getOrCreateSeedFile(params.seedFile, params.project);\n await context.runSeedTest(seed.file, seed.projectName, progress);\n return { content: [] };\n },\n});\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAgBA,oBAAkB;AAClB,sBAA+B;AAExB,MAAM,gBAAY,gCAAe;AAAA,EACtC,QAAQ;AAAA,IACN,MAAM;AAAA,IACN,OAAO;AAAA,IACP,aAAa;AAAA,IACb,aAAa,gBAAE,OAAO;AAAA,MACpB,SAAS,gBAAE,OAAO,EAAE,SAAS,EAAE,SAAS,oHAAoH;AAAA,MAC5J,UAAU,gBAAE,OAAO,EAAE,SAAS,EAAE,SAAS,gLAAgL;AAAA,IAC3N,CAAC;AAAA,IACD,MAAM;AAAA,EACR;AAAA,EAEA,QAAQ,OAAO,SAAS,QAAQ,aAAa;AAC3C,UAAM,OAAO,MAAM,QAAQ,oBAAoB,OAAO,UAAU,OAAO,OAAO;AAC9E,UAAM,QAAQ,YAAY,KAAK,MAAM,KAAK,aAAa,QAAQ;AAC/D,WAAO,EAAE,SAAS,CAAC,EAAE;AAAA,EACvB;AACF,CAAC;",
6
- "names": []
7
- }
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../../src/mcp/test/seed.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\nimport { mkdirIfNeeded } from 'playwright-core/lib/utils';\nimport { collectFilesForProject, findTopLevelProjects } from '../../runner/projectUtils';\n\nimport type { FullConfigInternal, FullProjectInternal } from '../../common/config';\n\nexport function seedProject(config: FullConfigInternal, projectName?: string) {\n if (!projectName)\n return findTopLevelProjects(config)[0];\n const project = config.projects.find(p => p.project.name === projectName);\n if (!project)\n throw new Error(`Project ${projectName} not found`);\n return project;\n}\n\nexport async function findSeedFile(project: FullProjectInternal) {\n const files = await collectFilesForProject(project);\n return files.find(file => path.basename(file).includes('seed'));\n}\n\nexport function defaultSeedFile(project: FullProjectInternal) {\n const testDir = project.project.testDir;\n return path.resolve(testDir, 'seed.spec.ts');\n}\n\nexport async function ensureSeedFile(project: FullProjectInternal) {\n const seedFile = await findSeedFile(project);\n if (seedFile)\n return seedFile;\n const seedFilePath = defaultSeedFile(project);\n await mkdirIfNeeded(seedFilePath);\n await fs.promises.writeFile(seedFilePath, seedFileContent);\n return seedFilePath;\n}\n\nexport const seedFileContent = `import { test, expect } from '@playwright/test';\n\ntest.describe('Test group', () => {\n test('seed', async ({ page }) => {\n // generate code here.\n });\n});\n`;\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAgBA,gBAAe;AACf,kBAAiB;AAEjB,mBAA8B;AAC9B,0BAA6D;AAItD,SAAS,YAAY,QAA4B,aAAsB;AAC5E,MAAI,CAAC;AACH,eAAO,0CAAqB,MAAM,EAAE,CAAC;AACvC,QAAM,UAAU,OAAO,SAAS,KAAK,OAAK,EAAE,QAAQ,SAAS,WAAW;AACxE,MAAI,CAAC;AACH,UAAM,IAAI,MAAM,WAAW,WAAW,YAAY;AACpD,SAAO;AACT;AAEA,eAAsB,aAAa,SAA8B;AAC/D,QAAM,QAAQ,UAAM,4CAAuB,OAAO;AAClD,SAAO,MAAM,KAAK,UAAQ,YAAAA,QAAK,SAAS,IAAI,EAAE,SAAS,MAAM,CAAC;AAChE;AAEO,SAAS,gBAAgB,SAA8B;AAC5D,QAAM,UAAU,QAAQ,QAAQ;AAChC,SAAO,YAAAA,QAAK,QAAQ,SAAS,cAAc;AAC7C;AAEA,eAAsB,eAAe,SAA8B;AACjE,QAAM,WAAW,MAAM,aAAa,OAAO;AAC3C,MAAI;AACF,WAAO;AACT,QAAM,eAAe,gBAAgB,OAAO;AAC5C,YAAM,4BAAc,YAAY;AAChC,QAAM,UAAAC,QAAG,SAAS,UAAU,cAAc,eAAe;AACzD,SAAO;AACT;AAEO,MAAM,kBAAkB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;",
6
- "names": ["path", "fs"]
7
- }
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../../src/mcp/test/streams.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 { Writable } from 'stream';\n\nimport { stripAnsiEscapes } from '../../util';\n\nimport type { ProgressCallback } from '../sdk/server';\n\nexport class StringWriteStream extends Writable {\n private _progress: ProgressCallback;\n private _prefix: string;\n\n constructor(progress: ProgressCallback, stdio: 'stdout' | 'stderr') {\n super();\n this._progress = progress;\n this._prefix = stdio === 'stdout' ? '' : '[err] ';\n }\n\n override _write(chunk: any, encoding: any, callback: any) {\n const text = stripAnsiEscapes(chunk.toString());\n // Progress wraps these as individual messages.\n this._progress({ message: `${this._prefix}${text.endsWith('\\n') ? text.slice(0, -1) : text}` });\n callback();\n }\n}\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAgBA,oBAAyB;AAEzB,kBAAiC;AAI1B,MAAM,0BAA0B,uBAAS;AAAA,EAI9C,YAAY,UAA4B,OAA4B;AAClE,UAAM;AACN,SAAK,YAAY;AACjB,SAAK,UAAU,UAAU,WAAW,KAAK;AAAA,EAC3C;AAAA,EAES,OAAO,OAAY,UAAe,UAAe;AACxD,UAAM,WAAO,8BAAiB,MAAM,SAAS,CAAC;AAE9C,SAAK,UAAU,EAAE,SAAS,GAAG,KAAK,OAAO,GAAG,KAAK,SAAS,IAAI,IAAI,KAAK,MAAM,GAAG,EAAE,IAAI,IAAI,GAAG,CAAC;AAC9F,aAAS;AAAA,EACX;AACF;",
6
- "names": []
7
- }
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../../src/mcp/test/testBackend.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 * as mcp from '../sdk/exports';\nimport { TestContext } from './testContext';\nimport * as testTools from './testTools.js';\nimport * as generatorTools from './generatorTools.js';\nimport * as plannerTools from './plannerTools.js';\nimport { browserTools } from '../browser/tools';\nimport { resolveConfigLocation } from '../../common/configLoader';\nimport { parseResponse } from '../browser/response';\n\nimport type { TestTool } from './testTool';\n\nexport class TestServerBackend implements mcp.ServerBackend {\n readonly name = 'Playwright';\n readonly version = '0.0.1';\n private _tools: TestTool<any>[] = [\n plannerTools.setupPage,\n generatorTools.setupPage,\n generatorTools.generatorReadLog,\n generatorTools.generatorWriteTest,\n testTools.listTests,\n testTools.runTests,\n testTools.debugTest,\n ];\n private _context: TestContext;\n private _configOption: string | undefined;\n\n constructor(configOption: string | undefined, options?: { muteConsole?: boolean, headless?: boolean }) {\n this._context = new TestContext(options);\n this._configOption = configOption;\n }\n\n async initialize(server: mcp.Server, clientInfo: mcp.ClientInfo): Promise<void> {\n const rootPath = mcp.firstRootPath(clientInfo);\n\n if (this._configOption) {\n this._context.initialize(rootPath, resolveConfigLocation(this._configOption));\n return;\n }\n\n if (rootPath) {\n this._context.initialize(rootPath, resolveConfigLocation(rootPath));\n return;\n }\n\n this._context.initialize(rootPath, resolveConfigLocation(undefined));\n }\n\n async listTools(): Promise<mcp.Tool[]> {\n return [\n ...this._tools.map(tool => mcp.toMcpTool(tool.schema)),\n ...browserTools.map(tool => mcp.toMcpTool(tool.schema, { addIntent: true })),\n ];\n }\n\n async afterCallTool(name: string, args: mcp.CallToolRequest['params']['arguments'], result: mcp.CallToolResult) {\n if (!browserTools.find(tool => tool.schema.name === name))\n return;\n const response = parseResponse(result);\n if (response && !response.isError && response.code && typeof args?.['intent'] === 'string')\n this._context.generatorJournal?.logStep(args['intent'], response.code);\n }\n\n async callTool(name: string, args: mcp.CallToolRequest['params']['arguments'], progress: mcp.ProgressCallback): Promise<mcp.CallToolResult> {\n const tool = this._tools.find(tool => tool.schema.name === name);\n if (!tool)\n throw new Error(`Tool not found: ${name}. Available tools: ${this._tools.map(tool => tool.schema.name).join(', ')}`);\n const parsedArguments = tool.schema.inputSchema.parse(args || {});\n return await tool.handle(this._context!, parsedArguments, progress);\n }\n\n serverClosed() {\n void this._context!.close();\n }\n}\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAgBA,UAAqB;AACrB,yBAA4B;AAC5B,gBAA2B;AAC3B,qBAAgC;AAChC,mBAA8B;AAC9B,mBAA6B;AAC7B,0BAAsC;AACtC,sBAA8B;AAIvB,MAAM,kBAA+C;AAAA,EAe1D,YAAY,cAAkC,SAAyD;AAdvG,SAAS,OAAO;AAChB,SAAS,UAAU;AACnB,SAAQ,SAA0B;AAAA,MAChC,aAAa;AAAA,MACb,eAAe;AAAA,MACf,eAAe;AAAA,MACf,eAAe;AAAA,MACf,UAAU;AAAA,MACV,UAAU;AAAA,MACV,UAAU;AAAA,IACZ;AAKE,SAAK,WAAW,IAAI,+BAAY,OAAO;AACvC,SAAK,gBAAgB;AAAA,EACvB;AAAA,EAEA,MAAM,WAAW,QAAoB,YAA2C;AAC9E,UAAM,WAAW,IAAI,cAAc,UAAU;AAE7C,QAAI,KAAK,eAAe;AACtB,WAAK,SAAS,WAAW,cAAU,2CAAsB,KAAK,aAAa,CAAC;AAC5E;AAAA,IACF;AAEA,QAAI,UAAU;AACZ,WAAK,SAAS,WAAW,cAAU,2CAAsB,QAAQ,CAAC;AAClE;AAAA,IACF;AAEA,SAAK,SAAS,WAAW,cAAU,2CAAsB,MAAS,CAAC;AAAA,EACrE;AAAA,EAEA,MAAM,YAAiC;AACrC,WAAO;AAAA,MACL,GAAG,KAAK,OAAO,IAAI,UAAQ,IAAI,UAAU,KAAK,MAAM,CAAC;AAAA,MACrD,GAAG,0BAAa,IAAI,UAAQ,IAAI,UAAU,KAAK,QAAQ,EAAE,WAAW,KAAK,CAAC,CAAC;AAAA,IAC7E;AAAA,EACF;AAAA,EAEA,MAAM,cAAc,MAAc,MAAkD,QAA4B;AAC9G,QAAI,CAAC,0BAAa,KAAK,UAAQ,KAAK,OAAO,SAAS,IAAI;AACtD;AACF,UAAM,eAAW,+BAAc,MAAM;AACrC,QAAI,YAAY,CAAC,SAAS,WAAW,SAAS,QAAQ,OAAO,OAAO,QAAQ,MAAM;AAChF,WAAK,SAAS,kBAAkB,QAAQ,KAAK,QAAQ,GAAG,SAAS,IAAI;AAAA,EACzE;AAAA,EAEA,MAAM,SAAS,MAAc,MAAkD,UAA6D;AAC1I,UAAM,OAAO,KAAK,OAAO,KAAK,CAAAA,UAAQA,MAAK,OAAO,SAAS,IAAI;AAC/D,QAAI,CAAC;AACH,YAAM,IAAI,MAAM,mBAAmB,IAAI,sBAAsB,KAAK,OAAO,IAAI,CAAAA,UAAQA,MAAK,OAAO,IAAI,EAAE,KAAK,IAAI,CAAC,EAAE;AACrH,UAAM,kBAAkB,KAAK,OAAO,YAAY,MAAM,QAAQ,CAAC,CAAC;AAChE,WAAO,MAAM,KAAK,OAAO,KAAK,UAAW,iBAAiB,QAAQ;AAAA,EACpE;AAAA,EAEA,eAAe;AACb,SAAK,KAAK,SAAU,MAAM;AAAA,EAC5B;AACF;",
6
- "names": ["tool"]
7
- }
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../../src/mcp/test/testContext.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\nimport { noColors, escapeRegExp } from 'playwright-core/lib/utils';\n\nimport { terminalScreen } from '../../reporters/base';\nimport ListReporter from '../../reporters/list';\nimport { StringWriteStream } from './streams';\nimport { fileExistsAsync } from '../../util';\nimport { TestRunner, TestRunnerEvent } from '../../runner/testRunner';\nimport { ensureSeedFile, seedProject } from './seed';\n\nimport type { ProgressCallback } from '../sdk/server';\nimport type { ConfigLocation } from '../../common/config';\n\nexport type SeedFile = {\n file: string;\n content: string;\n};\n\nexport class GeneratorJournal {\n private _rootPath: string;\n private _plan: string;\n private _seed: SeedFile;\n private _steps: { title: string, code: string }[];\n\n constructor(rootPath: string, plan: string, seed: SeedFile) {\n this._rootPath = rootPath;\n this._plan = plan;\n this._seed = seed;\n this._steps = [];\n }\n\n logStep(title: string | undefined, code: string) {\n if (title)\n this._steps.push({ title, code });\n }\n\n journal() {\n const result: string[] = [];\n result.push(`# Plan`);\n result.push(this._plan);\n result.push(`# Seed file: ${path.relative(this._rootPath, this._seed.file)}`);\n result.push('```ts');\n result.push(this._seed.content);\n result.push('```');\n result.push(`# Steps`);\n result.push(this._steps.map(step => `### ${step.title}\n\\`\\`\\`ts\n${step.code}\n\\`\\`\\``).join('\\n\\n'));\n result.push(bestPracticesMarkdown);\n return result.join('\\n\\n');\n }\n}\n\nexport class TestContext {\n private _testRunner: TestRunner | undefined;\n readonly options?: { muteConsole?: boolean, headless?: boolean };\n configLocation!: ConfigLocation;\n rootPath!: string;\n generatorJournal: GeneratorJournal | undefined;\n\n constructor(options?: { muteConsole?: boolean, headless?: boolean }) {\n this.options = options;\n }\n\n initialize(rootPath: string | undefined, configLocation: ConfigLocation) {\n this.configLocation = configLocation;\n this.rootPath = rootPath || configLocation.configDir;\n }\n\n existingTestRunner(): TestRunner | undefined {\n return this._testRunner;\n }\n\n async createTestRunner(): Promise<TestRunner> {\n if (this._testRunner)\n await this._testRunner.stopTests();\n const testRunner = new TestRunner(this.configLocation!, {});\n await testRunner.initialize({});\n this._testRunner = testRunner;\n testRunner.on(TestRunnerEvent.TestFilesChanged, testFiles => {\n this._testRunner?.emit(TestRunnerEvent.TestFilesChanged, testFiles);\n });\n this._testRunner = testRunner;\n return testRunner;\n }\n\n async getOrCreateSeedFile(seedFile: string | undefined, projectName: string | undefined) {\n const configDir = this.configLocation.configDir;\n const testRunner = await this.createTestRunner();\n const config = await testRunner.loadConfig();\n const project = seedProject(config, projectName);\n\n if (!seedFile) {\n seedFile = await ensureSeedFile(project);\n } else {\n const candidateFiles: string[] = [];\n const testDir = project.project.testDir;\n candidateFiles.push(path.resolve(testDir, seedFile));\n candidateFiles.push(path.resolve(configDir, seedFile));\n candidateFiles.push(path.resolve(this.rootPath, seedFile));\n let resolvedSeedFile: string | undefined;\n for (const candidateFile of candidateFiles) {\n if (await fileExistsAsync(candidateFile)) {\n resolvedSeedFile = candidateFile;\n break;\n }\n }\n if (!resolvedSeedFile)\n throw new Error('seed test not found.');\n seedFile = resolvedSeedFile;\n }\n\n const seedFileContent = await fs.promises.readFile(seedFile, 'utf8');\n return {\n file: seedFile,\n content: seedFileContent,\n projectName: project.project.name,\n };\n }\n\n async runSeedTest(seedFile: string, projectName: string, progress: ProgressCallback) {\n await this.runWithGlobalSetup(async (testRunner, reporter) => {\n const result = await testRunner.runTests(reporter, {\n headed: !this.options?.headless,\n locations: ['/' + escapeRegExp(seedFile) + '/'],\n projects: [projectName],\n timeout: 0,\n workers: 1,\n pauseAtEnd: true,\n disableConfigReporters: true,\n failOnLoadErrors: true,\n });\n // Ideally, we should check that page was indeed created and browser mcp has kicked in.\n // However, that is handled in the upper layer, so hard to check here.\n if (result.status === 'passed' && !reporter.suite?.allTests().length)\n throw new Error('seed test not found.');\n\n if (result.status !== 'passed')\n throw new Error('Errors while running the seed test.');\n }, progress);\n }\n\n async runWithGlobalSetup(\n callback: (testRunner: TestRunner, reporter: ListReporter) => Promise<void>,\n progress: ProgressCallback): Promise<void> {\n const { screen, claimStdio, releaseStdio } = createScreen(progress);\n const configDir = this.configLocation.configDir;\n const testRunner = await this.createTestRunner();\n\n claimStdio();\n try {\n const setupReporter = new ListReporter({ configDir, screen, includeTestId: true });\n const { status } = await testRunner.runGlobalSetup([setupReporter]);\n if (status !== 'passed')\n throw new Error('Failed to run global setup');\n } finally {\n releaseStdio();\n }\n\n try {\n const reporter = new ListReporter({ configDir, screen, includeTestId: true });\n return await callback(testRunner, reporter);\n } finally {\n claimStdio();\n await testRunner.runGlobalTeardown().finally(() => {\n releaseStdio();\n });\n }\n }\n\n async close() {\n }\n}\n\nexport function createScreen(progress: ProgressCallback) {\n const stdout = new StringWriteStream(progress, 'stdout');\n const stderr = new StringWriteStream(progress, 'stderr');\n\n const screen = {\n ...terminalScreen,\n isTTY: false,\n colors: noColors,\n stdout: stdout as unknown as NodeJS.WriteStream,\n stderr: stderr as unknown as NodeJS.WriteStream,\n };\n\n /* eslint-disable no-restricted-properties */\n const originalStdoutWrite = process.stdout.write;\n const originalStderrWrite = process.stderr.write;\n\n const claimStdio = () => {\n process.stdout.write = (chunk: string | Buffer) => {\n stdout.write(chunk);\n return true;\n };\n process.stderr.write = (chunk: string | Buffer) => {\n stderr.write(chunk);\n return true;\n };\n };\n\n const releaseStdio = () => {\n process.stdout.write = originalStdoutWrite;\n process.stderr.write = originalStderrWrite;\n };\n /* eslint-enable no-restricted-properties */\n\n return { screen, claimStdio, releaseStdio };\n}\n\nconst bestPracticesMarkdown = `\n# Best practices\n- Do not improvise, do not add directives that were not asked for\n- Use clear, descriptive assertions to validate the expected behavior\n- Use reliable locators from this log\n- Use local variables for locators that are used multiple times\n- Use Playwright waiting assertions and best practices from this log\n- NEVER! use page.waitForLoadState()\n- NEVER! use page.waitForNavigation()\n- NEVER! use page.waitForTimeout()\n- NEVER! use page.evaluate()\n`;\n"],
5
- "mappings": "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",
6
- "names": ["path", "fs", "ListReporter"]
7
- }
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../../src/mcp/test/testTool.ts"],
4
- "sourcesContent": ["/**\n * Copyright (c) Microsoft Corporation.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type { z } from 'zod';\nimport type { TestContext } from './testContext.js';\nimport type { CallToolResult } from '@modelcontextprotocol/sdk/types.js';\nimport type { ToolSchema } from '../sdk/tool.js';\nimport type { ProgressCallback } from '../sdk/server.js';\n\nexport type TestTool<Input extends z.Schema = z.Schema> = {\n schema: ToolSchema<Input>;\n handle: (context: TestContext, params: z.output<Input>, progress: ProgressCallback) => Promise<CallToolResult>;\n};\n\nexport function defineTestTool<Input extends z.Schema>(tool: TestTool<Input>): TestTool<Input> {\n return tool;\n}\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AA2BO,SAAS,eAAuC,MAAwC;AAC7F,SAAO;AACT;",
6
- "names": []
7
- }
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../../src/mcp/test/testTools.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 { z } from '../sdk/bundle';\nimport ListModeReporter from '../../reporters/listModeReporter';\nimport { defineTestTool } from './testTool';\nimport { createScreen } from './testContext';\n\nexport const listTests = defineTestTool({\n schema: {\n name: 'test_list',\n title: 'List tests',\n description: 'List tests',\n inputSchema: z.object({}),\n type: 'readOnly',\n },\n\n handle: async (context, _, progress) => {\n const { screen } = createScreen(progress);\n const reporter = new ListModeReporter({ screen, includeTestId: true });\n const testRunner = await context.createTestRunner();\n await testRunner.listTests(reporter, {});\n\n return { content: [] };\n },\n});\n\nexport const runTests = defineTestTool({\n schema: {\n name: 'test_run',\n title: 'Run tests',\n description: 'Run tests',\n inputSchema: z.object({\n locations: z.array(z.string()).optional().describe('Folder, file or location to run: \"test/e2e\" or \"test/e2e/file.spec.ts\" or \"test/e2e/file.spec.ts:20\"'),\n projects: z.array(z.string()).optional().describe('Projects to run, projects from playwright.config.ts, by default runs all projects. Running with \"chromium\" is a good start'),\n }),\n type: 'readOnly',\n },\n\n handle: async (context, params, progress) => {\n await context.runWithGlobalSetup(async (testRunner, reporter) => {\n await testRunner.runTests(reporter, {\n locations: params.locations,\n projects: params.projects,\n disableConfigReporters: true,\n });\n }, progress);\n\n return { content: [] };\n },\n});\n\nexport const debugTest = defineTestTool({\n schema: {\n name: 'test_debug',\n title: 'Debug single test',\n description: 'Debug single test',\n inputSchema: z.object({\n test: z.object({\n id: z.string().describe('Test ID to debug.'),\n title: z.string().describe('Human readable test title for granting permission to debug the test.'),\n }),\n }),\n type: 'readOnly',\n },\n\n handle: async (context, params, progress) => {\n await context.runWithGlobalSetup(async (testRunner, reporter) => {\n await testRunner.runTests(reporter, {\n headed: !context.options?.headless,\n testIds: [params.test.id],\n // For automatic recovery\n timeout: 0,\n workers: 1,\n pauseOnError: true,\n disableConfigReporters: true,\n });\n }, progress);\n\n return { content: [] };\n },\n});\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAgBA,oBAAkB;AAClB,8BAA6B;AAC7B,sBAA+B;AAC/B,yBAA6B;AAEtB,MAAM,gBAAY,gCAAe;AAAA,EACtC,QAAQ;AAAA,IACN,MAAM;AAAA,IACN,OAAO;AAAA,IACP,aAAa;AAAA,IACb,aAAa,gBAAE,OAAO,CAAC,CAAC;AAAA,IACxB,MAAM;AAAA,EACR;AAAA,EAEA,QAAQ,OAAO,SAAS,GAAG,aAAa;AACtC,UAAM,EAAE,OAAO,QAAI,iCAAa,QAAQ;AACxC,UAAM,WAAW,IAAI,wBAAAA,QAAiB,EAAE,QAAQ,eAAe,KAAK,CAAC;AACrE,UAAM,aAAa,MAAM,QAAQ,iBAAiB;AAClD,UAAM,WAAW,UAAU,UAAU,CAAC,CAAC;AAEvC,WAAO,EAAE,SAAS,CAAC,EAAE;AAAA,EACvB;AACF,CAAC;AAEM,MAAM,eAAW,gCAAe;AAAA,EACrC,QAAQ;AAAA,IACN,MAAM;AAAA,IACN,OAAO;AAAA,IACP,aAAa;AAAA,IACb,aAAa,gBAAE,OAAO;AAAA,MACpB,WAAW,gBAAE,MAAM,gBAAE,OAAO,CAAC,EAAE,SAAS,EAAE,SAAS,sGAAsG;AAAA,MACzJ,UAAU,gBAAE,MAAM,gBAAE,OAAO,CAAC,EAAE,SAAS,EAAE,SAAS,4HAA4H;AAAA,IAChL,CAAC;AAAA,IACD,MAAM;AAAA,EACR;AAAA,EAEA,QAAQ,OAAO,SAAS,QAAQ,aAAa;AAC3C,UAAM,QAAQ,mBAAmB,OAAO,YAAY,aAAa;AAC/D,YAAM,WAAW,SAAS,UAAU;AAAA,QAClC,WAAW,OAAO;AAAA,QAClB,UAAU,OAAO;AAAA,QACjB,wBAAwB;AAAA,MAC1B,CAAC;AAAA,IACH,GAAG,QAAQ;AAEX,WAAO,EAAE,SAAS,CAAC,EAAE;AAAA,EACvB;AACF,CAAC;AAEM,MAAM,gBAAY,gCAAe;AAAA,EACtC,QAAQ;AAAA,IACN,MAAM;AAAA,IACN,OAAO;AAAA,IACP,aAAa;AAAA,IACb,aAAa,gBAAE,OAAO;AAAA,MACpB,MAAM,gBAAE,OAAO;AAAA,QACb,IAAI,gBAAE,OAAO,EAAE,SAAS,mBAAmB;AAAA,QAC3C,OAAO,gBAAE,OAAO,EAAE,SAAS,sEAAsE;AAAA,MACnG,CAAC;AAAA,IACH,CAAC;AAAA,IACD,MAAM;AAAA,EACR;AAAA,EAEA,QAAQ,OAAO,SAAS,QAAQ,aAAa;AAC3C,UAAM,QAAQ,mBAAmB,OAAO,YAAY,aAAa;AAC/D,YAAM,WAAW,SAAS,UAAU;AAAA,QAClC,QAAQ,CAAC,QAAQ,SAAS;AAAA,QAC1B,SAAS,CAAC,OAAO,KAAK,EAAE;AAAA;AAAA,QAExB,SAAS;AAAA,QACT,SAAS;AAAA,QACT,cAAc;AAAA,QACd,wBAAwB;AAAA,MAC1B,CAAC;AAAA,IACH,GAAG,QAAQ;AAEX,WAAO,EAAE,SAAS,CAAC,EAAE;AAAA,EACvB;AACF,CAAC;",
6
- "names": ["ListModeReporter"]
7
- }