@smoothdeploy/playwright 1.57.1 → 1.58.1-beta-1770383926000

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


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

Files changed (264) hide show
  1. package/ThirdPartyNotices.txt +1188 -65
  2. package/lib/agents/agentParser.js +89 -0
  3. package/lib/agents/generateAgents.js +27 -74
  4. package/lib/agents/generateAgents.js.map +7 -0
  5. package/lib/agents/playwright-test-planner.agent.md +1 -0
  6. package/lib/common/config.js +6 -4
  7. package/lib/common/config.js.map +7 -0
  8. package/lib/common/configLoader.js.map +7 -0
  9. package/lib/common/esmLoaderHost.js +2 -0
  10. package/lib/common/esmLoaderHost.js.map +7 -0
  11. package/lib/common/expectBundle.js +2 -17
  12. package/lib/common/expectBundle.js.map +7 -0
  13. package/lib/common/expectBundleImpl.js +132 -132
  14. package/lib/common/expectBundleImpl.js.map +7 -0
  15. package/lib/common/fixtures.js.map +7 -0
  16. package/lib/common/globals.js.map +7 -0
  17. package/lib/common/ipc.js.map +7 -0
  18. package/lib/common/poolBuilder.js.map +7 -0
  19. package/lib/common/process.js +28 -0
  20. package/lib/common/process.js.map +7 -0
  21. package/lib/common/suiteUtils.js.map +7 -0
  22. package/lib/common/test.js.map +7 -0
  23. package/lib/common/testLoader.js.map +7 -0
  24. package/lib/common/testType.js.map +7 -0
  25. package/lib/common/validators.js +10 -10
  26. package/lib/common/validators.js.map +7 -0
  27. package/lib/fsWatcher.js.map +7 -0
  28. package/lib/index.js +205 -12
  29. package/lib/index.js.map +7 -0
  30. package/lib/internalsForTest.js.map +7 -0
  31. package/lib/isomorphic/events.js.map +7 -0
  32. package/lib/isomorphic/folders.js.map +7 -0
  33. package/lib/isomorphic/stringInternPool.js.map +7 -0
  34. package/lib/isomorphic/teleReceiver.js +15 -2
  35. package/lib/isomorphic/teleReceiver.js.map +7 -0
  36. package/lib/isomorphic/teleSuiteUpdater.js +24 -4
  37. package/lib/isomorphic/teleSuiteUpdater.js.map +7 -0
  38. package/lib/isomorphic/testServerConnection.js.map +7 -0
  39. package/lib/isomorphic/testServerInterface.js.map +7 -0
  40. package/lib/isomorphic/testTree.js +13 -18
  41. package/lib/isomorphic/testTree.js.map +7 -0
  42. package/lib/isomorphic/types.d.js.map +7 -0
  43. package/lib/loader/loaderMain.js.map +7 -0
  44. package/lib/matchers/expect.js +2 -15
  45. package/lib/matchers/expect.js.map +7 -0
  46. package/lib/matchers/matcherHint.js +1 -44
  47. package/lib/matchers/matcherHint.js.map +7 -0
  48. package/lib/matchers/matchers.js +3 -2
  49. package/lib/matchers/matchers.js.map +7 -0
  50. package/lib/matchers/toBeTruthy.js +5 -3
  51. package/lib/matchers/toBeTruthy.js.map +7 -0
  52. package/lib/matchers/toEqual.js +4 -3
  53. package/lib/matchers/toEqual.js.map +7 -0
  54. package/lib/matchers/toHaveURL.js +5 -6
  55. package/lib/matchers/toHaveURL.js.map +7 -0
  56. package/lib/matchers/toMatchAriaSnapshot.js +5 -5
  57. package/lib/matchers/toMatchAriaSnapshot.js.map +7 -0
  58. package/lib/matchers/toMatchSnapshot.js +9 -8
  59. package/lib/matchers/toMatchSnapshot.js.map +7 -0
  60. package/lib/matchers/toMatchText.js +9 -9
  61. package/lib/matchers/toMatchText.js.map +7 -0
  62. package/lib/mcp/browser/actions.d.js.map +7 -0
  63. package/lib/mcp/browser/browserContextFactory.js +62 -29
  64. package/lib/mcp/browser/browserContextFactory.js.map +7 -0
  65. package/lib/mcp/browser/browserServerBackend.js +17 -9
  66. package/lib/mcp/browser/browserServerBackend.js.map +7 -0
  67. package/lib/mcp/browser/codegen.js.map +7 -0
  68. package/lib/mcp/browser/config.js +65 -12
  69. package/lib/mcp/browser/config.js.map +7 -0
  70. package/lib/mcp/browser/context.js +71 -94
  71. package/lib/mcp/browser/context.js.map +7 -0
  72. package/lib/mcp/browser/response.js +172 -131
  73. package/lib/mcp/browser/response.js.map +7 -0
  74. package/lib/mcp/browser/sessionLog.js +19 -104
  75. package/lib/mcp/browser/sessionLog.js.map +7 -0
  76. package/lib/mcp/browser/tab.js +92 -41
  77. package/lib/mcp/browser/tab.js.map +7 -0
  78. package/lib/mcp/browser/tools/common.js +8 -6
  79. package/lib/mcp/browser/tools/common.js.map +7 -0
  80. package/lib/mcp/browser/tools/console.js +7 -5
  81. package/lib/mcp/browser/tools/console.js.map +7 -0
  82. package/lib/mcp/browser/tools/dialogs.js +4 -4
  83. package/lib/mcp/browser/tools/dialogs.js.map +7 -0
  84. package/lib/mcp/browser/tools/evaluate.js +11 -19
  85. package/lib/mcp/browser/tools/evaluate.js.map +7 -0
  86. package/lib/mcp/browser/tools/files.js +3 -3
  87. package/lib/mcp/browser/tools/files.js.map +7 -0
  88. package/lib/mcp/browser/tools/form.js +9 -19
  89. package/lib/mcp/browser/tools/form.js.map +7 -0
  90. package/lib/mcp/browser/tools/install.js +6 -3
  91. package/lib/mcp/browser/tools/install.js.map +7 -0
  92. package/lib/mcp/browser/tools/keyboard.js +34 -11
  93. package/lib/mcp/browser/tools/keyboard.js.map +7 -0
  94. package/lib/mcp/browser/tools/mouse.js +11 -11
  95. package/lib/mcp/browser/tools/mouse.js.map +7 -0
  96. package/lib/mcp/browser/tools/navigate.js +14 -5
  97. package/lib/mcp/browser/tools/navigate.js.map +7 -0
  98. package/lib/mcp/browser/tools/network.js +20 -11
  99. package/lib/mcp/browser/tools/network.js.map +7 -0
  100. package/lib/mcp/browser/tools/open.js +57 -0
  101. package/lib/mcp/browser/tools/pdf.js +9 -19
  102. package/lib/mcp/browser/tools/pdf.js.map +7 -0
  103. package/lib/mcp/browser/tools/runCode.js +11 -8
  104. package/lib/mcp/browser/tools/runCode.js.map +7 -0
  105. package/lib/mcp/browser/tools/screenshot.js +16 -29
  106. package/lib/mcp/browser/tools/screenshot.js.map +7 -0
  107. package/lib/mcp/browser/tools/snapshot.js +21 -29
  108. package/lib/mcp/browser/tools/snapshot.js.map +7 -0
  109. package/lib/mcp/browser/tools/tabs.js +12 -12
  110. package/lib/mcp/browser/tools/tabs.js.map +7 -0
  111. package/lib/mcp/browser/tools/tool.js +2 -4
  112. package/lib/mcp/browser/tools/tool.js.map +7 -0
  113. package/lib/mcp/browser/tools/tracing.js +6 -6
  114. package/lib/mcp/browser/tools/tracing.js.map +7 -0
  115. package/lib/mcp/browser/tools/utils.js +49 -44
  116. package/lib/mcp/browser/tools/utils.js.map +7 -0
  117. package/lib/mcp/browser/tools/verify.js +24 -34
  118. package/lib/mcp/browser/tools/verify.js.map +7 -0
  119. package/lib/mcp/browser/tools/wait.js +6 -6
  120. package/lib/mcp/browser/tools/wait.js.map +7 -0
  121. package/lib/mcp/browser/tools.js +3 -1
  122. package/lib/mcp/browser/tools.js.map +7 -0
  123. package/lib/mcp/browser/watchdog.js.map +7 -0
  124. package/lib/mcp/config.d.js.map +7 -0
  125. package/lib/mcp/extension/cdpRelay.js +1 -1
  126. package/lib/mcp/extension/cdpRelay.js.map +7 -0
  127. package/lib/mcp/extension/extensionContextFactory.js +6 -5
  128. package/lib/mcp/extension/extensionContextFactory.js.map +7 -0
  129. package/lib/mcp/extension/protocol.js.map +7 -0
  130. package/lib/mcp/index.js.map +7 -0
  131. package/lib/mcp/log.js.map +7 -0
  132. package/lib/mcp/program.js +15 -20
  133. package/lib/mcp/program.js.map +7 -0
  134. package/lib/mcp/sdk/bundle.js.map +7 -0
  135. package/lib/mcp/sdk/exports.js +0 -2
  136. package/lib/mcp/sdk/exports.js.map +7 -0
  137. package/lib/mcp/sdk/http.js +20 -55
  138. package/lib/mcp/sdk/http.js.map +7 -0
  139. package/lib/mcp/sdk/inProcessTransport.js.map +7 -0
  140. package/lib/mcp/sdk/proxyBackend.js.map +7 -0
  141. package/lib/mcp/sdk/server.js +29 -4
  142. package/lib/mcp/sdk/server.js.map +7 -0
  143. package/lib/mcp/sdk/tool.js +2 -2
  144. package/lib/mcp/sdk/tool.js.map +7 -0
  145. package/lib/mcp/terminal/cli.js +296 -0
  146. package/lib/mcp/terminal/command.js +56 -0
  147. package/lib/mcp/terminal/commands.js +333 -0
  148. package/lib/mcp/terminal/daemon.js +129 -0
  149. package/lib/mcp/terminal/help.json +32 -0
  150. package/lib/mcp/terminal/helpGenerator.js +88 -0
  151. package/lib/mcp/terminal/socketConnection.js +80 -0
  152. package/lib/mcp/test/browserBackend.js +3 -13
  153. package/lib/mcp/test/browserBackend.js.map +7 -0
  154. package/lib/mcp/test/generatorTools.js +9 -9
  155. package/lib/mcp/test/generatorTools.js.map +7 -0
  156. package/lib/mcp/test/plannerTools.js +23 -22
  157. package/lib/mcp/test/plannerTools.js.map +7 -0
  158. package/lib/mcp/test/seed.js.map +7 -0
  159. package/lib/mcp/test/streams.js.map +7 -0
  160. package/lib/mcp/test/testBackend.js +6 -6
  161. package/lib/mcp/test/testBackend.js.map +7 -0
  162. package/lib/mcp/test/testContext.js +9 -3
  163. package/lib/mcp/test/testContext.js.map +7 -0
  164. package/lib/mcp/test/testTool.js.map +7 -0
  165. package/lib/mcp/test/testTools.js +12 -10
  166. package/lib/mcp/test/testTools.js.map +7 -0
  167. package/lib/mcpBundleImpl.js.map +7 -0
  168. package/lib/plugins/gitCommitInfoPlugin.js.map +7 -0
  169. package/lib/plugins/index.js.map +7 -0
  170. package/lib/plugins/webServerPlugin.js.map +7 -0
  171. package/lib/program.js +18 -4
  172. package/lib/program.js.map +7 -0
  173. package/lib/reporters/base.js +29 -4
  174. package/lib/reporters/base.js.map +7 -0
  175. package/lib/reporters/blob.js +3 -0
  176. package/lib/reporters/blob.js.map +7 -0
  177. package/lib/reporters/dot.js +17 -0
  178. package/lib/reporters/dot.js.map +7 -0
  179. package/lib/reporters/empty.js.map +7 -0
  180. package/lib/reporters/github.js.map +7 -0
  181. package/lib/reporters/html.js +13 -3
  182. package/lib/reporters/html.js.map +7 -0
  183. package/lib/reporters/internalReporter.js +6 -0
  184. package/lib/reporters/internalReporter.js.map +7 -0
  185. package/lib/reporters/json.js.map +7 -0
  186. package/lib/reporters/junit.js.map +7 -0
  187. package/lib/reporters/line.js +18 -0
  188. package/lib/reporters/line.js.map +7 -0
  189. package/lib/reporters/list.js +22 -0
  190. package/lib/reporters/list.js.map +7 -0
  191. package/lib/reporters/listModeReporter.js.map +7 -0
  192. package/lib/reporters/markdown.js.map +7 -0
  193. package/lib/reporters/merge.js +25 -8
  194. package/lib/reporters/merge.js.map +7 -0
  195. package/lib/reporters/multiplexer.js +8 -0
  196. package/lib/reporters/multiplexer.js.map +7 -0
  197. package/lib/reporters/reporterV2.js.map +7 -0
  198. package/lib/reporters/smoothdeploy.js +191 -0
  199. package/lib/reporters/teleEmitter.js +22 -4
  200. package/lib/reporters/teleEmitter.js.map +7 -0
  201. package/lib/reporters/versions/blobV1.js.map +7 -0
  202. package/lib/runner/dispatcher.js +20 -4
  203. package/lib/runner/dispatcher.js.map +7 -0
  204. package/lib/runner/failureTracker.js.map +7 -0
  205. package/lib/runner/lastRun.js.map +7 -0
  206. package/lib/runner/loadUtils.js +2 -2
  207. package/lib/runner/loadUtils.js.map +7 -0
  208. package/lib/runner/loaderHost.js.map +7 -0
  209. package/lib/runner/processHost.js +19 -0
  210. package/lib/runner/processHost.js.map +7 -0
  211. package/lib/runner/projectUtils.js +1 -1
  212. package/lib/runner/projectUtils.js.map +7 -0
  213. package/lib/runner/rebase.js.map +7 -0
  214. package/lib/runner/reporters.js +3 -1
  215. package/lib/runner/reporters.js.map +7 -0
  216. package/lib/runner/sigIntWatcher.js.map +7 -0
  217. package/lib/runner/storage.js +91 -0
  218. package/lib/runner/taskRunner.js.map +7 -0
  219. package/lib/runner/tasks.js.map +7 -0
  220. package/lib/runner/testGroups.js +14 -6
  221. package/lib/runner/testGroups.js.map +7 -0
  222. package/lib/runner/testRunner.js +13 -4
  223. package/lib/runner/testRunner.js.map +7 -0
  224. package/lib/runner/testServer.js +2 -2
  225. package/lib/runner/testServer.js.map +7 -0
  226. package/lib/runner/uiModeReporter.js.map +7 -0
  227. package/lib/runner/vcs.js.map +7 -0
  228. package/lib/runner/watchMode.js +2 -1
  229. package/lib/runner/watchMode.js.map +7 -0
  230. package/lib/runner/workerHost.js +6 -0
  231. package/lib/runner/workerHost.js.map +7 -0
  232. package/lib/third_party/pirates.js.map +7 -0
  233. package/lib/third_party/tsconfig-loader.js.map +7 -0
  234. package/lib/transform/babelBundle.js +3 -0
  235. package/lib/transform/babelBundle.js.map +7 -0
  236. package/lib/transform/babelBundleImpl.js +134 -134
  237. package/lib/transform/babelBundleImpl.js.map +7 -0
  238. package/lib/transform/compilationCache.js +2 -0
  239. package/lib/transform/compilationCache.js.map +7 -0
  240. package/lib/transform/esmLoader.js +10 -11
  241. package/lib/transform/esmLoader.js.map +7 -0
  242. package/lib/transform/md.js +221 -0
  243. package/lib/transform/portTransport.js.map +7 -0
  244. package/lib/transform/transform.js +18 -8
  245. package/lib/transform/transform.js.map +7 -0
  246. package/lib/util.js +3 -6
  247. package/lib/util.js.map +7 -0
  248. package/lib/utilsBundle.js +7 -0
  249. package/lib/utilsBundle.js.map +7 -0
  250. package/lib/utilsBundleImpl.js +51 -48
  251. package/lib/utilsBundleImpl.js.map +7 -0
  252. package/lib/worker/fixtureRunner.js +6 -2
  253. package/lib/worker/fixtureRunner.js.map +7 -0
  254. package/lib/worker/testInfo.js +39 -19
  255. package/lib/worker/testInfo.js.map +7 -0
  256. package/lib/worker/testTracing.js.map +7 -0
  257. package/lib/worker/timeoutManager.js.map +7 -0
  258. package/lib/worker/util.js.map +7 -0
  259. package/lib/worker/workerMain.js +17 -16
  260. package/lib/worker/workerMain.js.map +7 -0
  261. package/package.json +2 -2
  262. package/test.mjs +1 -0
  263. package/types/test.d.ts +26 -6
  264. package/types/testReporter.d.ts +1 -0
@@ -28,19 +28,17 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
28
28
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
29
  var context_exports = {};
30
30
  __export(context_exports, {
31
- Context: () => Context,
32
- InputRecorder: () => InputRecorder
31
+ Context: () => Context
33
32
  });
34
33
  module.exports = __toCommonJS(context_exports);
35
- var import_fs = __toESM(require("fs"));
36
- var import_path = __toESM(require("path"));
37
34
  var import_utilsBundle = require("playwright-core/lib/utilsBundle");
35
+ var import_utils = require("playwright-core/lib/utils");
38
36
  var import_playwright_core = require("playwright-core");
37
+ var import_url = require("url");
38
+ var import_os = __toESM(require("os"));
39
39
  var import_log = require("../log");
40
40
  var import_tab = require("./tab");
41
41
  var import_config = require("./config");
42
- var codegen = __toESM(require("./codegen"));
43
- var import_utils = require("./tools/utils");
44
42
  const testDebug = (0, import_utilsBundle.debug)("pw:mcp:test");
45
43
  class Context {
46
44
  constructor(options) {
@@ -68,14 +66,13 @@ class Context {
68
66
  }
69
67
  currentTabOrDie() {
70
68
  if (!this._currentTab)
71
- throw new Error('No open pages available. Use the "browser_navigate" tool to navigate to a page first.');
69
+ throw new Error("No open pages available.");
72
70
  return this._currentTab;
73
71
  }
74
72
  async newTab() {
75
- const { browserContext } = await this._ensureBrowserContext();
73
+ const { browserContext } = await this._ensureBrowserContext({});
76
74
  const page = await browserContext.newPage();
77
75
  this._currentTab = this._tabs.find((t) => t.page === page);
78
- await this._currentTab.initializedPromise;
79
76
  return this._currentTab;
80
77
  }
81
78
  async selectTab(index) {
@@ -86,8 +83,8 @@ class Context {
86
83
  this._currentTab = tab;
87
84
  return tab;
88
85
  }
89
- async ensureTab() {
90
- const { browserContext } = await this._ensureBrowserContext();
86
+ async ensureTab(options = {}) {
87
+ const { browserContext } = await this._ensureBrowserContext(options);
91
88
  if (!this._currentTab)
92
89
  await browserContext.newPage();
93
90
  return this._currentTab;
@@ -137,31 +134,11 @@ class Context {
137
134
  testDebug("close context");
138
135
  const promise = this._browserContextPromise;
139
136
  this._browserContextPromise = void 0;
137
+ this._browserContextOption = void 0;
140
138
  await promise.then(async ({ browserContext, close }) => {
141
139
  if (this.config.saveTrace)
142
140
  await browserContext.tracing.stop();
143
- const videos = this.config.saveVideo ? browserContext.pages().map((page) => page.video()).filter((video) => !!video) : [];
144
- await close(async () => {
145
- for (const video of videos) {
146
- const name = await this.outputFile((0, import_utils.dateAsFileName)("webm"), { origin: "code", reason: "Saving video" });
147
- await import_fs.default.promises.mkdir(import_path.default.dirname(name), { recursive: true });
148
- const p = await video.path();
149
- if (import_fs.default.existsSync(p)) {
150
- try {
151
- await import_fs.default.promises.rename(p, name);
152
- } catch (e) {
153
- if (e.code !== "EXDEV")
154
- (0, import_log.logUnhandledError)(e);
155
- try {
156
- await import_fs.default.promises.copyFile(p, name);
157
- await import_fs.default.promises.unlink(p);
158
- } catch (e2) {
159
- (0, import_log.logUnhandledError)(e2);
160
- }
161
- }
162
- }
163
- }
164
- });
141
+ await close();
165
142
  });
166
143
  }
167
144
  async dispose() {
@@ -169,28 +146,45 @@ class Context {
169
146
  await this.closeBrowserContext();
170
147
  Context._allContexts.delete(this);
171
148
  }
172
- async ensureBrowserContext() {
173
- const { browserContext } = await this._ensureBrowserContext();
149
+ async _setupRequestInterception(context) {
150
+ if (this.config.network?.allowedOrigins?.length) {
151
+ await context.route("**", (route) => route.abort("blockedbyclient"));
152
+ for (const origin of this.config.network.allowedOrigins)
153
+ await context.route(originOrHostGlob(origin), (route) => route.continue());
154
+ }
155
+ if (this.config.network?.blockedOrigins?.length) {
156
+ for (const origin of this.config.network.blockedOrigins)
157
+ await context.route(originOrHostGlob(origin), (route) => route.abort("blockedbyclient"));
158
+ }
159
+ }
160
+ async ensureBrowserContext(options = {}) {
161
+ const { browserContext } = await this._ensureBrowserContext(options);
174
162
  return browserContext;
175
163
  }
176
- _ensureBrowserContext() {
177
- if (!this._browserContextPromise) {
178
- this._browserContextPromise = this._setupBrowserContext();
179
- this._browserContextPromise.catch(() => {
180
- this._browserContextPromise = void 0;
181
- });
182
- }
164
+ _ensureBrowserContext(options) {
165
+ if (this._browserContextPromise && (options.forceHeadless === void 0 || this._browserContextOption?.forceHeadless === options.forceHeadless))
166
+ return this._browserContextPromise;
167
+ const closePrework = this._browserContextPromise ? this.closeBrowserContext() : Promise.resolve();
168
+ this._browserContextPromise = closePrework.then(() => this._setupBrowserContext(options));
169
+ this._browserContextPromise.catch(() => {
170
+ this._browserContextPromise = void 0;
171
+ this._browserContextOption = void 0;
172
+ });
173
+ this._browserContextOption = options;
183
174
  return this._browserContextPromise;
184
175
  }
185
- async _setupBrowserContext() {
176
+ async _setupBrowserContext(options) {
186
177
  if (this._closeBrowserContextPromise)
187
178
  throw new Error("Another browser context is being closed.");
188
179
  if (this.config.testIdAttribute)
189
180
  import_playwright_core.selectors.setTestIdAttribute(this.config.testIdAttribute);
190
- const result = await this._browserContextFactory.createContext(this._clientInfo, this._abortController.signal, this._runningToolName);
181
+ const result = await this._browserContextFactory.createContext(this._clientInfo, this._abortController.signal, { toolName: this._runningToolName, ...options });
191
182
  const { browserContext } = result;
192
- if (this.sessionLog)
193
- await InputRecorder.create(this, browserContext);
183
+ if (!this.config.allowUnrestrictedFileAccess) {
184
+ browserContext._setAllowedProtocols(["http:", "https:", "about:", "data:"]);
185
+ browserContext._setAllowedDirectories(allRootPaths(this._clientInfo));
186
+ }
187
+ await this._setupRequestInterception(browserContext);
194
188
  for (const page of browserContext.pages())
195
189
  this._onPageCreated(page);
196
190
  browserContext.on("page", (page) => this._onPageCreated(page));
@@ -206,62 +200,45 @@ class Context {
206
200
  }
207
201
  lookupSecret(secretName) {
208
202
  if (!this.config.secrets?.[secretName])
209
- return { value: secretName, code: codegen.quote(secretName) };
203
+ return { value: secretName, code: (0, import_utils.escapeWithQuotes)(secretName, "'") };
210
204
  return {
211
205
  value: this.config.secrets[secretName],
212
206
  code: `process.env['${secretName}']`
213
207
  };
214
208
  }
215
- }
216
- class InputRecorder {
217
- constructor(context, browserContext) {
218
- this._context = context;
219
- this._browserContext = browserContext;
220
- }
221
- static async create(context, browserContext) {
222
- const recorder = new InputRecorder(context, browserContext);
223
- await recorder._initialize();
224
- return recorder;
209
+ firstRootPath() {
210
+ return allRootPaths(this._clientInfo)[0];
225
211
  }
226
- async _initialize() {
227
- const sessionLog = this._context.sessionLog;
228
- await this._browserContext._enableRecorder({
229
- mode: "recording",
230
- recorderMode: "api"
231
- }, {
232
- actionAdded: (page, data, code) => {
233
- if (this._context.isRunningTool())
234
- return;
235
- const tab = import_tab.Tab.forPage(page);
236
- if (tab)
237
- sessionLog.logUserAction(data.action, tab, code, false);
238
- },
239
- actionUpdated: (page, data, code) => {
240
- if (this._context.isRunningTool())
241
- return;
242
- const tab = import_tab.Tab.forPage(page);
243
- if (tab)
244
- sessionLog.logUserAction(data.action, tab, code, true);
245
- },
246
- signalAdded: (page, data) => {
247
- if (this._context.isRunningTool())
248
- return;
249
- if (data.signal.name !== "navigation")
250
- return;
251
- const tab = import_tab.Tab.forPage(page);
252
- const navigateAction = {
253
- name: "navigate",
254
- url: data.signal.url,
255
- signals: []
256
- };
257
- if (tab)
258
- sessionLog.logUserAction(navigateAction, tab, `await page.goto('${data.signal.url}');`, false);
259
- }
260
- });
212
+ }
213
+ function allRootPaths(clientInfo) {
214
+ const paths = [];
215
+ for (const root of clientInfo.roots) {
216
+ const url = new URL(root.uri);
217
+ let rootPath;
218
+ try {
219
+ rootPath = (0, import_url.fileURLToPath)(url);
220
+ } catch (e) {
221
+ if (e.code === "ERR_INVALID_FILE_URL_PATH" && import_os.default.platform() === "win32")
222
+ rootPath = decodeURIComponent(url.pathname);
223
+ }
224
+ if (!rootPath)
225
+ continue;
226
+ paths.push(rootPath);
261
227
  }
228
+ if (paths.length === 0)
229
+ paths.push(process.cwd());
230
+ return paths;
231
+ }
232
+ function originOrHostGlob(originOrHost) {
233
+ try {
234
+ const url = new URL(originOrHost);
235
+ if (url.origin !== "null")
236
+ return `${url.origin}/**`;
237
+ } catch {
238
+ }
239
+ return `*://${originOrHost}/**`;
262
240
  }
263
241
  // Annotate the CommonJS export names for ESM import in node:
264
242
  0 && (module.exports = {
265
- Context,
266
- InputRecorder
243
+ Context
267
244
  });
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/mcp/browser/context.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 { debug } from 'playwright-core/lib/utilsBundle';\nimport { selectors } from 'playwright-core';\n\nimport { logUnhandledError } from '../log';\nimport { Tab } from './tab';\nimport { outputFile } from './config';\nimport * as codegen from './codegen';\nimport { dateAsFileName } from './tools/utils';\n\nimport type * as playwright from '../../../types/test';\nimport type { FullConfig } from './config';\nimport type { BrowserContextFactory, BrowserContextFactoryResult } from './browserContextFactory';\nimport type * as actions from './actions';\nimport type { SessionLog } from './sessionLog';\nimport type { Tracing } from '../../../../playwright-core/src/client/tracing';\nimport type { ClientInfo } from '../sdk/server';\n\nconst testDebug = debug('pw:mcp:test');\n\ntype ContextOptions = {\n config: FullConfig;\n browserContextFactory: BrowserContextFactory;\n sessionLog: SessionLog | undefined;\n clientInfo: ClientInfo;\n};\n\nexport class Context {\n readonly config: FullConfig;\n readonly sessionLog: SessionLog | undefined;\n readonly options: ContextOptions;\n private _browserContextPromise: Promise<BrowserContextFactoryResult> | undefined;\n private _browserContextFactory: BrowserContextFactory;\n private _tabs: Tab[] = [];\n private _currentTab: Tab | undefined;\n private _clientInfo: ClientInfo;\n\n private static _allContexts: Set<Context> = new Set();\n private _closeBrowserContextPromise: Promise<void> | undefined;\n private _runningToolName: string | undefined;\n private _abortController = new AbortController();\n\n constructor(options: ContextOptions) {\n this.config = options.config;\n this.sessionLog = options.sessionLog;\n this.options = options;\n this._browserContextFactory = options.browserContextFactory;\n this._clientInfo = options.clientInfo;\n testDebug('create context');\n Context._allContexts.add(this);\n }\n\n static async disposeAll() {\n await Promise.all([...Context._allContexts].map(context => context.dispose()));\n }\n\n tabs(): Tab[] {\n return this._tabs;\n }\n\n currentTab(): Tab | undefined {\n return this._currentTab;\n }\n\n currentTabOrDie(): Tab {\n if (!this._currentTab)\n throw new Error('No open pages available. Use the \"browser_navigate\" tool to navigate to a page first.');\n return this._currentTab;\n }\n\n async newTab(): Promise<Tab> {\n const { browserContext } = await this._ensureBrowserContext();\n const page = await browserContext.newPage();\n this._currentTab = this._tabs.find(t => t.page === page)!;\n await this._currentTab.initializedPromise;\n return this._currentTab;\n }\n\n async selectTab(index: number) {\n const tab = this._tabs[index];\n if (!tab)\n throw new Error(`Tab ${index} not found`);\n await tab.page.bringToFront();\n this._currentTab = tab;\n return tab;\n }\n\n async ensureTab(): Promise<Tab> {\n const { browserContext } = await this._ensureBrowserContext();\n if (!this._currentTab)\n await browserContext.newPage();\n return this._currentTab!;\n }\n\n async closeTab(index: number | undefined): Promise<string> {\n const tab = index === undefined ? this._currentTab : this._tabs[index];\n if (!tab)\n throw new Error(`Tab ${index} not found`);\n const url = tab.page.url();\n await tab.page.close();\n return url;\n }\n\n async outputFile(fileName: string, options: { origin: 'code' | 'llm' | 'web', reason: string }): Promise<string> {\n return outputFile(this.config, this._clientInfo, fileName, options);\n }\n\n private _onPageCreated(page: playwright.Page) {\n const tab = new Tab(this, page, tab => this._onPageClosed(tab));\n this._tabs.push(tab);\n if (!this._currentTab)\n this._currentTab = tab;\n }\n\n private _onPageClosed(tab: Tab) {\n const index = this._tabs.indexOf(tab);\n if (index === -1)\n return;\n this._tabs.splice(index, 1);\n\n if (this._currentTab === tab)\n this._currentTab = this._tabs[Math.min(index, this._tabs.length - 1)];\n if (!this._tabs.length)\n void this.closeBrowserContext();\n }\n\n async closeBrowserContext() {\n if (!this._closeBrowserContextPromise)\n this._closeBrowserContextPromise = this._closeBrowserContextImpl().catch(logUnhandledError);\n await this._closeBrowserContextPromise;\n this._closeBrowserContextPromise = undefined;\n }\n\n isRunningTool() {\n return this._runningToolName !== undefined;\n }\n\n setRunningTool(name: string | undefined) {\n this._runningToolName = name;\n }\n\n private async _closeBrowserContextImpl() {\n if (!this._browserContextPromise)\n return;\n\n testDebug('close context');\n\n const promise = this._browserContextPromise;\n this._browserContextPromise = undefined;\n\n await promise.then(async ({ browserContext, close }) => {\n if (this.config.saveTrace)\n await browserContext.tracing.stop();\n const videos = this.config.saveVideo ? browserContext.pages().map(page => page.video()).filter(video => !!video) : [];\n await close(async () => {\n for (const video of videos) {\n const name = await this.outputFile(dateAsFileName('webm'), { origin: 'code', reason: 'Saving video' });\n await fs.promises.mkdir(path.dirname(name), { recursive: true });\n const p = await video.path();\n // video.saveAs() does not work for persistent contexts.\n if (fs.existsSync(p)) {\n try {\n await fs.promises.rename(p, name);\n } catch (e) {\n if (e.code !== 'EXDEV')\n logUnhandledError(e);\n // Retry operation (possibly cross-fs) with copy and unlink\n try {\n await fs.promises.copyFile(p, name);\n await fs.promises.unlink(p);\n } catch (e) {\n logUnhandledError(e);\n }\n }\n }\n }\n });\n });\n }\n\n async dispose() {\n this._abortController.abort('MCP context disposed');\n await this.closeBrowserContext();\n Context._allContexts.delete(this);\n }\n\n async ensureBrowserContext(): Promise<playwright.BrowserContext> {\n const { browserContext } = await this._ensureBrowserContext();\n return browserContext;\n }\n\n private _ensureBrowserContext() {\n if (!this._browserContextPromise) {\n this._browserContextPromise = this._setupBrowserContext();\n this._browserContextPromise.catch(() => {\n this._browserContextPromise = undefined;\n });\n }\n return this._browserContextPromise;\n }\n\n private async _setupBrowserContext(): Promise<BrowserContextFactoryResult> {\n if (this._closeBrowserContextPromise)\n throw new Error('Another browser context is being closed.');\n // TODO: move to the browser context factory to make it based on isolation mode.\n\n if (this.config.testIdAttribute)\n selectors.setTestIdAttribute(this.config.testIdAttribute);\n const result = await this._browserContextFactory.createContext(this._clientInfo, this._abortController.signal, this._runningToolName);\n const { browserContext } = result;\n if (this.sessionLog)\n await InputRecorder.create(this, browserContext);\n for (const page of browserContext.pages())\n this._onPageCreated(page);\n browserContext.on('page', page => this._onPageCreated(page));\n if (this.config.saveTrace) {\n await (browserContext.tracing as Tracing).start({\n name: 'trace-' + Date.now(),\n screenshots: true,\n snapshots: true,\n _live: true,\n });\n }\n return result;\n }\n\n lookupSecret(secretName: string): { value: string, code: string } {\n if (!this.config.secrets?.[secretName])\n return { value: secretName, code: codegen.quote(secretName) };\n return {\n value: this.config.secrets[secretName]!,\n code: `process.env['${secretName}']`,\n };\n }\n}\n\nexport class InputRecorder {\n private _context: Context;\n private _browserContext: playwright.BrowserContext;\n\n private constructor(context: Context, browserContext: playwright.BrowserContext) {\n this._context = context;\n this._browserContext = browserContext;\n }\n\n static async create(context: Context, browserContext: playwright.BrowserContext) {\n const recorder = new InputRecorder(context, browserContext);\n await recorder._initialize();\n return recorder;\n }\n\n private async _initialize() {\n const sessionLog = this._context.sessionLog!;\n await (this._browserContext as any)._enableRecorder({\n mode: 'recording',\n recorderMode: 'api',\n }, {\n actionAdded: (page: playwright.Page, data: actions.ActionInContext, code: string) => {\n if (this._context.isRunningTool())\n return;\n const tab = Tab.forPage(page);\n if (tab)\n sessionLog.logUserAction(data.action, tab, code, false);\n },\n actionUpdated: (page: playwright.Page, data: actions.ActionInContext, code: string) => {\n if (this._context.isRunningTool())\n return;\n const tab = Tab.forPage(page);\n if (tab)\n sessionLog.logUserAction(data.action, tab, code, true);\n },\n signalAdded: (page: playwright.Page, data: actions.SignalInContext) => {\n if (this._context.isRunningTool())\n return;\n if (data.signal.name !== 'navigation')\n return;\n const tab = Tab.forPage(page);\n const navigateAction: actions.Action = {\n name: 'navigate',\n url: data.signal.url,\n signals: [],\n };\n if (tab)\n sessionLog.logUserAction(navigateAction, tab, `await page.goto('${data.signal.url}');`, false);\n },\n });\n }\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["tab", "fs", "path", "e"]
7
+ }