@smoothdeploy/playwright-core 1.57.1 → 1.58.1-beta-1770452953000

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-core might be problematic. Click here for more details.

Files changed (155) hide show
  1. package/ThirdPartyNotices.txt +3223 -308
  2. package/browsers.json +21 -22
  3. package/lib/cli/program.js +4 -5
  4. package/lib/client/api.js +3 -0
  5. package/lib/client/browser.js +3 -5
  6. package/lib/client/browserContext.js +35 -0
  7. package/lib/client/browserType.js +4 -3
  8. package/lib/client/channelOwner.js +4 -3
  9. package/lib/client/clientInstrumentation.js +10 -0
  10. package/lib/client/connection.js +4 -0
  11. package/lib/client/elementHandle.js +3 -0
  12. package/lib/client/events.js +3 -0
  13. package/lib/client/fetch.js +3 -4
  14. package/lib/client/frame.js +1 -0
  15. package/lib/client/page.js +28 -1
  16. package/lib/client/pageAgent.js +64 -0
  17. package/lib/client/platform.js +3 -0
  18. package/lib/generated/injectedScriptSource.js +1 -1
  19. package/lib/generated/pollingRecorderSource.js +1 -1
  20. package/lib/mcpBundle.js +84 -0
  21. package/lib/mcpBundleImpl/index.js +147 -0
  22. package/lib/protocol/serializers.js +5 -0
  23. package/lib/protocol/validator.js +92 -3
  24. package/lib/remote/playwrightServer.js +1 -2
  25. package/lib/server/agent/actionRunner.js +335 -0
  26. package/lib/server/agent/actions.js +128 -0
  27. package/lib/server/agent/codegen.js +111 -0
  28. package/lib/server/agent/context.js +150 -0
  29. package/lib/server/agent/expectTools.js +156 -0
  30. package/lib/server/agent/pageAgent.js +204 -0
  31. package/lib/server/agent/performTools.js +262 -0
  32. package/lib/server/agent/tool.js +109 -0
  33. package/lib/server/artifact.js +1 -1
  34. package/lib/server/bidi/bidiBrowser.js +56 -12
  35. package/lib/server/bidi/bidiChromium.js +6 -11
  36. package/lib/server/bidi/bidiConnection.js +1 -0
  37. package/lib/server/bidi/bidiDeserializer.js +116 -0
  38. package/lib/server/bidi/bidiExecutionContext.js +75 -29
  39. package/lib/server/bidi/bidiFirefox.js +6 -8
  40. package/lib/server/bidi/bidiNetworkManager.js +1 -1
  41. package/lib/server/bidi/bidiPage.js +39 -28
  42. package/lib/server/bidi/third_party/bidiProtocolCore.js +1 -0
  43. package/lib/server/browserContext.js +32 -25
  44. package/lib/server/browserType.js +12 -4
  45. package/lib/server/chromium/chromium.js +14 -21
  46. package/lib/server/chromium/chromiumSwitches.js +2 -2
  47. package/lib/server/chromium/crBrowser.js +22 -12
  48. package/lib/server/chromium/crConnection.js +0 -5
  49. package/lib/server/chromium/crDevTools.js +0 -2
  50. package/lib/server/chromium/crNetworkManager.js +43 -2
  51. package/lib/server/chromium/crPage.js +19 -87
  52. package/lib/server/codegen/javascript.js +6 -29
  53. package/lib/server/deviceDescriptorsSource.json +56 -56
  54. package/lib/server/dispatchers/browserContextDispatcher.js +3 -0
  55. package/lib/server/dispatchers/dispatcher.js +6 -13
  56. package/lib/server/dispatchers/frameDispatcher.js +1 -1
  57. package/lib/server/dispatchers/pageAgentDispatcher.js +96 -0
  58. package/lib/server/dispatchers/pageDispatcher.js +4 -0
  59. package/lib/server/dom.js +12 -3
  60. package/lib/server/electron/electron.js +5 -2
  61. package/lib/server/firefox/ffBrowser.js +10 -20
  62. package/lib/server/firefox/ffConnection.js +0 -5
  63. package/lib/server/firefox/ffNetworkManager.js +2 -2
  64. package/lib/server/firefox/ffPage.js +15 -18
  65. package/lib/server/firefox/firefox.js +6 -8
  66. package/lib/server/frameSelectors.js +9 -3
  67. package/lib/server/frames.js +49 -33
  68. package/lib/server/instrumentation.js +3 -0
  69. package/lib/server/network.js +50 -12
  70. package/lib/server/page.js +33 -89
  71. package/lib/server/progress.js +26 -6
  72. package/lib/server/recorder/recorderApp.js +79 -100
  73. package/lib/server/recorder.js +55 -0
  74. package/lib/server/registry/browserFetcher.js +6 -4
  75. package/lib/server/registry/index.js +172 -149
  76. package/lib/server/registry/oopDownloadBrowserMain.js +3 -0
  77. package/lib/server/screencast.js +190 -0
  78. package/lib/server/screenshotCompositor.js +153 -0
  79. package/lib/server/trace/recorder/snapshotterInjected.js +21 -1
  80. package/lib/server/trace/recorder/tracing.js +21 -21
  81. package/lib/server/trace/viewer/traceParser.js +72 -0
  82. package/lib/server/trace/viewer/traceViewer.js +17 -13
  83. package/lib/server/utils/expectUtils.js +87 -2
  84. package/lib/server/utils/httpServer.js +4 -19
  85. package/lib/server/utils/network.js +37 -28
  86. package/lib/server/utils/nodePlatform.js +6 -0
  87. package/lib/server/videoRecorder.js +124 -0
  88. package/lib/server/webkit/webkit.js +4 -6
  89. package/lib/server/webkit/wkBrowser.js +2 -6
  90. package/lib/server/webkit/wkConnection.js +1 -6
  91. package/lib/server/webkit/wkInterceptableRequest.js +29 -1
  92. package/lib/server/webkit/wkPage.js +75 -46
  93. package/lib/utils/isomorphic/ariaSnapshot.js +60 -2
  94. package/lib/utils/isomorphic/lruCache.js +51 -0
  95. package/lib/utils/isomorphic/protocolMetainfo.js +9 -1
  96. package/lib/utils/isomorphic/stringUtils.js +49 -0
  97. package/lib/utils/isomorphic/trace/entries.js +16 -0
  98. package/lib/utils/isomorphic/trace/snapshotRenderer.js +499 -0
  99. package/lib/utils/isomorphic/trace/snapshotServer.js +120 -0
  100. package/lib/utils/isomorphic/trace/snapshotStorage.js +89 -0
  101. package/lib/utils/isomorphic/trace/traceLoader.js +131 -0
  102. package/lib/utils/isomorphic/trace/traceModel.js +365 -0
  103. package/lib/utils/isomorphic/trace/traceModernizer.js +400 -0
  104. package/lib/utils/isomorphic/trace/versions/traceV3.js +16 -0
  105. package/lib/utils/isomorphic/trace/versions/traceV4.js +16 -0
  106. package/lib/utils/isomorphic/trace/versions/traceV5.js +16 -0
  107. package/lib/utils/isomorphic/trace/versions/traceV6.js +16 -0
  108. package/lib/utils/isomorphic/trace/versions/traceV7.js +16 -0
  109. package/lib/utils/isomorphic/trace/versions/traceV8.js +16 -0
  110. package/lib/utils/isomorphic/yaml.js +84 -0
  111. package/lib/utils.js +2 -0
  112. package/lib/utilsBundle.js +2 -5
  113. package/lib/utilsBundleImpl/index.js +165 -165
  114. package/lib/vite/htmlReport/index.html +21 -21
  115. package/lib/vite/recorder/assets/{codeMirrorModule-C3UTv-Ge.css → codeMirrorModule-DYBRYzYX.css} +1 -1
  116. package/lib/vite/recorder/assets/codeMirrorModule-DadYNm1I.js +32 -0
  117. package/lib/vite/recorder/assets/{index-Ri0uHF7I.css → index-BSjZa4pk.css} +1 -1
  118. package/lib/vite/recorder/assets/index-BhTWtUlo.js +193 -0
  119. package/lib/vite/recorder/index.html +2 -2
  120. package/lib/vite/traceViewer/assets/codeMirrorModule-8UJPCtp4.js +16884 -0
  121. package/lib/vite/{recorder/assets/codeMirrorModule-BoWUGj0J.js → traceViewer/assets/codeMirrorModule-BNr6yhVP.js} +1 -1
  122. package/lib/vite/traceViewer/assets/codeMirrorModule-Dimjuz94.js +32 -0
  123. package/lib/vite/traceViewer/assets/codeMirrorModule-DkmsYcws.js +32 -0
  124. package/lib/vite/traceViewer/assets/codeMirrorModule-DySgctgr.js +16884 -0
  125. package/lib/vite/traceViewer/assets/defaultSettingsView-B1vuWQsF.js +266 -0
  126. package/lib/vite/traceViewer/assets/defaultSettingsView-CtEsdeVH.js +266 -0
  127. package/lib/vite/traceViewer/assets/defaultSettingsView-D4fm31R-.js +34087 -0
  128. package/lib/vite/traceViewer/assets/defaultSettingsView-JtyB0yzL.js +34087 -0
  129. package/lib/vite/traceViewer/assets/defaultSettingsView-tEZf-LNj.js +266 -0
  130. package/lib/vite/traceViewer/assets/xtermModule-DDw6eROI.js +6168 -0
  131. package/lib/vite/traceViewer/codeMirrorModule.DYBRYzYX.css +1 -0
  132. package/lib/vite/traceViewer/codeMirrorModule.DuST8d_k.css +344 -0
  133. package/lib/vite/traceViewer/defaultSettingsView.5FCqBwKs.css +3986 -0
  134. package/lib/vite/traceViewer/defaultSettingsView.7ch9cixO.css +1 -0
  135. package/lib/vite/traceViewer/index.BQs8gGhY.js +249 -0
  136. package/lib/vite/traceViewer/index.BVu7tZDe.css +1 -0
  137. package/lib/vite/traceViewer/index.BoLn624r.js +2 -0
  138. package/lib/vite/traceViewer/index.Bq_EaK8x.js +249 -0
  139. package/lib/vite/traceViewer/index.C8YVh4B5.js +2 -0
  140. package/lib/vite/traceViewer/index.Cr7-GRf8.js +2 -0
  141. package/lib/vite/traceViewer/index.G-7UhDxt.css +164 -0
  142. package/lib/vite/traceViewer/index.html +4 -4
  143. package/lib/vite/traceViewer/sw.bundle.js +5 -3
  144. package/lib/vite/traceViewer/uiMode.-Kflt2XM.css +1440 -0
  145. package/lib/vite/traceViewer/uiMode.BTRKnokb.js +5 -0
  146. package/lib/vite/traceViewer/uiMode.CEZ5RVHh.js +5 -0
  147. package/lib/vite/traceViewer/uiMode.CIWF23si.js +1829 -0
  148. package/lib/vite/traceViewer/uiMode.Wi-DvIEY.js +1829 -0
  149. package/lib/vite/traceViewer/uiMode.html +3 -3
  150. package/lib/vite/traceViewer/uiMode.zEH1ejvz.js +5 -0
  151. package/lib/vite/traceViewer/xtermModule.BKlWQB97.css +218 -0
  152. package/package.json +3 -1
  153. package/types/protocol.d.ts +738 -159
  154. package/types/types.d.ts +25 -38
  155. package/lib/vite/recorder/assets/index-DJqDAOZp.js +0 -193
@@ -296,6 +296,10 @@ class CRNetworkManager {
296
296
  if (requestPausedEvent) {
297
297
  if (redirectedFrom || !this._userRequestInterceptionEnabled && this._protocolRequestInterceptionEnabled) {
298
298
  headersOverride = redirectedFrom?._originalRequestRoute?._alreadyContinuedParams?.headers;
299
+ if (headersOverride) {
300
+ const originalHeaders = Object.entries(requestPausedEvent.request.headers).map(([name, value]) => ({ name, value }));
301
+ headersOverride = network.applyHeadersOverrides(originalHeaders, headersOverride);
302
+ }
299
303
  requestPausedSessionInfo.session._sendMayFail("Fetch.continueRequest", { requestId: requestPausedEvent.requestId, headers: headersOverride });
300
304
  } else {
301
305
  route = new RouteImpl(requestPausedSessionInfo.session, requestPausedEvent.requestId);
@@ -482,12 +486,11 @@ class InterceptableRequest {
482
486
  url,
483
487
  postDataEntries = null
484
488
  } = requestPausedEvent ? requestPausedEvent.request : requestWillBeSentEvent.request;
485
- const type = (requestWillBeSentEvent.type || "").toLowerCase();
486
489
  let postDataBuffer = null;
487
490
  const entries = postDataEntries?.filter((entry) => entry.bytes);
488
491
  if (entries && entries.length)
489
492
  postDataBuffer = Buffer.concat(entries.map((entry) => Buffer.from(entry.bytes, "base64")));
490
- this.request = new network.Request(context, frame, serviceWorker, redirectedFrom?.request || null, documentId, url, type, method, postDataBuffer, headersOverride || (0, import_utils.headersObjectToArray)(headers));
493
+ this.request = new network.Request(context, frame, serviceWorker, redirectedFrom?.request || null, documentId, url, toResourceType(requestWillBeSentEvent.type || "Other"), method, postDataBuffer, headersOverride || (0, import_utils.headersObjectToArray)(headers));
491
494
  }
492
495
  }
493
496
  class RouteImpl {
@@ -660,6 +663,44 @@ class ResponseExtraInfoTracker {
660
663
  this._requests.delete(requestId);
661
664
  }
662
665
  }
666
+ function toResourceType(type) {
667
+ switch (type) {
668
+ case "Document":
669
+ return "document";
670
+ case "Stylesheet":
671
+ return "stylesheet";
672
+ case "Image":
673
+ return "image";
674
+ case "Media":
675
+ return "media";
676
+ case "Font":
677
+ return "font";
678
+ case "Script":
679
+ return "script";
680
+ case "TextTrack":
681
+ return "texttrack";
682
+ case "XHR":
683
+ return "xhr";
684
+ case "Fetch":
685
+ return "fetch";
686
+ case "EventSource":
687
+ return "eventsource";
688
+ case "WebSocket":
689
+ return "websocket";
690
+ case "Manifest":
691
+ return "manifest";
692
+ case "Ping":
693
+ return "ping";
694
+ case "CSPViolationReport":
695
+ return "cspreport";
696
+ case "Prefetch":
697
+ case "SignedExchange":
698
+ case "Preflight":
699
+ case "FedCM":
700
+ default:
701
+ return "other";
702
+ }
703
+ }
663
704
  // Annotate the CommonJS export names for ESM import in node:
664
705
  0 && (module.exports = {
665
706
  CRNetworkManager
@@ -31,9 +31,7 @@ __export(crPage_exports, {
31
31
  CRPage: () => CRPage
32
32
  });
33
33
  module.exports = __toCommonJS(crPage_exports);
34
- var import_path = __toESM(require("path"));
35
34
  var import_assert = require("../../utils/isomorphic/assert");
36
- var import_crypto = require("../utils/crypto");
37
35
  var import_eventsHelper = require("../utils/eventsHelper");
38
36
  var import_stackTrace = require("../../utils/isomorphic/stackTrace");
39
37
  var dialog = __toESM(require("../dialog"));
@@ -42,7 +40,6 @@ var frames = __toESM(require("../frames"));
42
40
  var import_helper = require("../helper");
43
41
  var network = __toESM(require("../network"));
44
42
  var import_page = require("../page");
45
- var import_registry = require("../registry");
46
43
  var import_crCoverage = require("./crCoverage");
47
44
  var import_crDragDrop = require("./crDragDrop");
48
45
  var import_crExecutionContext = require("./crExecutionContext");
@@ -51,7 +48,6 @@ var import_crNetworkManager = require("./crNetworkManager");
51
48
  var import_crPdf = require("./crPdf");
52
49
  var import_crProtocolHelper = require("./crProtocolHelper");
53
50
  var import_defaultFontFamilies = require("./defaultFontFamilies");
54
- var import_videoRecorder = require("./videoRecorder");
55
51
  var import_errors = require("../errors");
56
52
  var import_protocolError = require("../protocolError");
57
53
  class CRPage {
@@ -236,17 +232,16 @@ class CRPage {
236
232
  async scrollRectIntoViewIfNeeded(handle, rect) {
237
233
  return this._sessionForHandle(handle)._scrollRectIntoViewIfNeeded(handle, rect);
238
234
  }
239
- async setScreencastOptions(options) {
240
- if (options) {
241
- await this._mainFrameSession._startScreencast(this, {
242
- format: "jpeg",
243
- quality: options.quality,
244
- maxWidth: options.width,
245
- maxHeight: options.height
246
- });
247
- } else {
248
- await this._mainFrameSession._stopScreencast(this);
249
- }
235
+ async startScreencast(options) {
236
+ await this._mainFrameSession._client.send("Page.startScreencast", {
237
+ format: "jpeg",
238
+ quality: options.quality,
239
+ maxWidth: options.width,
240
+ maxHeight: options.height
241
+ });
242
+ }
243
+ async stopScreencast() {
244
+ await this._mainFrameSession._client._sendMayFail("Page.stopScreencast");
250
245
  }
251
246
  rafCountForStablePosition() {
252
247
  return 1;
@@ -311,9 +306,6 @@ class FrameSession {
311
306
  // Marks the oopif session that remote -> local transition has happened in the parent.
312
307
  // See Target.detachedFromTarget handler for details.
313
308
  this._swappedIn = false;
314
- this._videoRecorder = null;
315
- this._screencastId = null;
316
- this._screencastClients = /* @__PURE__ */ new Set();
317
309
  this._workerSessions = /* @__PURE__ */ new Map();
318
310
  this._initScriptIds = /* @__PURE__ */ new Map();
319
311
  this._client = client;
@@ -365,23 +357,9 @@ class FrameSession {
365
357
  const { windowId } = await this._client.send("Browser.getWindowForTarget");
366
358
  this._windowId = windowId;
367
359
  }
368
- let screencastOptions;
369
- if (!this._page.isStorageStatePage && this._isMainFrame() && this._crPage._browserContext._options.recordVideo && hasUIWindow) {
370
- const screencastId = (0, import_crypto.createGuid)();
371
- const outputFile = import_path.default.join(this._crPage._browserContext._options.recordVideo.dir, screencastId + ".webm");
372
- screencastOptions = {
373
- // validateBrowserContextOptions ensures correct video size.
374
- ...this._crPage._browserContext._options.recordVideo.size,
375
- outputFile
376
- };
377
- await this._crPage._browserContext._ensureVideosPath();
378
- await this._createVideoRecorder(screencastId, screencastOptions);
379
- this._crPage._page.waitForInitializedOrError().then((p) => {
380
- if (p instanceof Error)
381
- this._stopVideoRecording().catch(() => {
382
- });
383
- });
384
- }
360
+ let videoOptions;
361
+ if (!this._page.isStorageStatePage && this._isMainFrame() && hasUIWindow)
362
+ videoOptions = this._crPage._page.screencast.launchVideoRecorder();
385
363
  let lifecycleEventsEnabled;
386
364
  if (!this._isMainFrame())
387
365
  this._addRendererListeners();
@@ -461,15 +439,15 @@ class FrameSession {
461
439
  true
462
440
  /* runImmediately */
463
441
  ));
464
- if (screencastOptions)
465
- promises.push(this._startVideoRecording(screencastOptions));
442
+ if (videoOptions)
443
+ promises.push(this._crPage._page.screencast.startVideoRecording(videoOptions));
466
444
  }
467
445
  promises.push(this._client.send("Runtime.runIfWaitingForDebugger"));
468
446
  promises.push(this._firstNonInitialNavigationCommittedPromise);
469
447
  await Promise.all(promises);
470
448
  }
471
449
  dispose() {
472
- this._firstNonInitialNavigationCommittedReject(new import_errors.TargetClosedError());
450
+ this._firstNonInitialNavigationCommittedReject(new import_errors.TargetClosedError(this._page.closeReason()));
473
451
  for (const childSession of this._childSessions)
474
452
  childSession.dispose();
475
453
  if (this._parentSession)
@@ -730,63 +708,17 @@ class FrameSession {
730
708
  }
731
709
  }
732
710
  _onScreencastFrame(payload) {
733
- this._page.throttleScreencastFrameAck(() => {
734
- this._client.send("Page.screencastFrameAck", { sessionId: payload.sessionId }).catch(() => {
735
- });
711
+ this._page.screencast.throttleFrameAck(() => {
712
+ this._client._sendMayFail("Page.screencastFrameAck", { sessionId: payload.sessionId });
736
713
  });
737
714
  const buffer = Buffer.from(payload.data, "base64");
738
715
  this._page.emit(import_page.Page.Events.ScreencastFrame, {
739
716
  buffer,
740
- frameSwapWallTime: payload.metadata.timestamp ? payload.metadata.timestamp * 1e3 : void 0,
717
+ frameSwapWallTime: payload.metadata.timestamp ? payload.metadata.timestamp * 1e3 : Date.now(),
741
718
  width: payload.metadata.deviceWidth,
742
719
  height: payload.metadata.deviceHeight
743
720
  });
744
721
  }
745
- async _createVideoRecorder(screencastId, options) {
746
- (0, import_assert.assert)(!this._screencastId);
747
- const ffmpegPath = import_registry.registry.findExecutable("ffmpeg").executablePathOrDie(this._page.browserContext._browser.sdkLanguage());
748
- this._videoRecorder = await import_videoRecorder.VideoRecorder.launch(this._crPage._page, ffmpegPath, options);
749
- this._screencastId = screencastId;
750
- }
751
- async _startVideoRecording(options) {
752
- const screencastId = this._screencastId;
753
- (0, import_assert.assert)(screencastId);
754
- this._page.once(import_page.Page.Events.Close, () => this._stopVideoRecording().catch(() => {
755
- }));
756
- const gotFirstFrame = new Promise((f) => this._client.once("Page.screencastFrame", f));
757
- await this._startScreencast(this._videoRecorder, {
758
- format: "jpeg",
759
- quality: 90,
760
- maxWidth: options.width,
761
- maxHeight: options.height
762
- });
763
- gotFirstFrame.then(() => {
764
- this._crPage._browserContext._browser._videoStarted(this._crPage._browserContext, screencastId, options.outputFile, this._crPage._page.waitForInitializedOrError());
765
- });
766
- }
767
- async _stopVideoRecording() {
768
- if (!this._screencastId)
769
- return;
770
- const screencastId = this._screencastId;
771
- this._screencastId = null;
772
- const recorder = this._videoRecorder;
773
- this._videoRecorder = null;
774
- await this._stopScreencast(recorder);
775
- await recorder.stop().catch(() => {
776
- });
777
- const video = this._crPage._browserContext._browser._takeVideo(screencastId);
778
- video?.reportFinished();
779
- }
780
- async _startScreencast(client, options = {}) {
781
- this._screencastClients.add(client);
782
- if (this._screencastClients.size === 1)
783
- await this._client.send("Page.startScreencast", options);
784
- }
785
- async _stopScreencast(client) {
786
- this._screencastClients.delete(client);
787
- if (!this._screencastClients.size)
788
- await this._client._sendMayFail("Page.stopScreencast");
789
- }
790
722
  async _updateGeolocation(initial) {
791
723
  const geolocation = this._crPage._browserContext._options.geolocation;
792
724
  if (!initial || geolocation)
@@ -90,7 +90,7 @@ class JavaScriptLanguageGenerator {
90
90
  case "fill":
91
91
  return `await ${subject}.${this._asLocator(action.selector)}.fill(${quote(action.text)});`;
92
92
  case "setInputFiles":
93
- return `await ${subject}.${this._asLocator(action.selector)}.setInputFiles(${formatObject(action.files.length === 1 ? action.files[0] : action.files)});`;
93
+ return `await ${subject}.${this._asLocator(action.selector)}.setInputFiles(${(0, import_utils.formatObject)(action.files.length === 1 ? action.files[0] : action.files)});`;
94
94
  case "press": {
95
95
  const modifiers = (0, import_language.toKeyboardModifiers)(action.modifiers);
96
96
  const shortcut = [...modifiers, action.key].join("+");
@@ -99,7 +99,7 @@ class JavaScriptLanguageGenerator {
99
99
  case "navigate":
100
100
  return `await ${subject}.goto(${quote(action.url)});`;
101
101
  case "select":
102
- return `await ${subject}.${this._asLocator(action.selector)}.selectOption(${formatObject(action.options.length === 1 ? action.options[0] : action.options)});`;
102
+ return `await ${subject}.${this._asLocator(action.selector)}.selectOption(${(0, import_utils.formatObject)(action.options.length === 1 ? action.options[0] : action.options)});`;
103
103
  case "assertText":
104
104
  return `${this._isTest ? "" : "// "}await expect(${subject}.${this._asLocator(action.selector)}).${action.substring ? "toContainText" : "toHaveText"}(${quote(action.text)});`;
105
105
  case "assertChecked":
@@ -151,7 +151,7 @@ ${useText ? "\ntest.use(" + useText + ");\n" : ""}
151
151
  const { ${options.browserName}${options.deviceName ? ", devices" : ""} } = require('playwright');
152
152
 
153
153
  (async () => {
154
- const browser = await ${options.browserName}.launch(${formatObjectOrVoid(options.launchOptions)});
154
+ const browser = await ${options.browserName}.launch(${(0, import_utils.formatObjectOrVoid)(options.launchOptions)});
155
155
  const context = await browser.newContext(${formatContextOptions(options.contextOptions, options.deviceName, false)});`);
156
156
  if (options.contextOptions.recordHar)
157
157
  formatter.add(` await context.routeFromHAR(${quote(options.contextOptions.recordHar.path)});`);
@@ -171,37 +171,14 @@ function formatOptions(value, hasArguments) {
171
171
  const keys = Object.keys(value).filter((key) => value[key] !== void 0);
172
172
  if (!keys.length)
173
173
  return "";
174
- return (hasArguments ? ", " : "") + formatObject(value);
175
- }
176
- function formatObject(value, indent = " ") {
177
- if (typeof value === "string")
178
- return quote(value);
179
- if (Array.isArray(value))
180
- return `[${value.map((o) => formatObject(o)).join(", ")}]`;
181
- if (typeof value === "object") {
182
- const keys = Object.keys(value).filter((key) => value[key] !== void 0).sort();
183
- if (!keys.length)
184
- return "{}";
185
- const tokens = [];
186
- for (const key of keys)
187
- tokens.push(`${key}: ${formatObject(value[key])}`);
188
- return `{
189
- ${indent}${tokens.join(`,
190
- ${indent}`)}
191
- }`;
192
- }
193
- return String(value);
194
- }
195
- function formatObjectOrVoid(value, indent = " ") {
196
- const result = formatObject(value, indent);
197
- return result === "{}" ? "" : result;
174
+ return (hasArguments ? ", " : "") + (0, import_utils.formatObject)(value);
198
175
  }
199
176
  function formatContextOptions(options, deviceName, isTest) {
200
177
  const device = deviceName && import_deviceDescriptors.deviceDescriptors[deviceName];
201
178
  options = { ...options, recordHar: void 0 };
202
179
  if (!device)
203
- return formatObjectOrVoid(options);
204
- let serializedObject = formatObjectOrVoid((0, import_language.sanitizeDeviceOptions)(device, options));
180
+ return (0, import_utils.formatObjectOrVoid)(options);
181
+ let serializedObject = (0, import_utils.formatObjectOrVoid)((0, import_language.sanitizeDeviceOptions)(device, options));
205
182
  if (!serializedObject)
206
183
  serializedObject = "{\n}";
207
184
  const lines = serializedObject.split("\n");