@checkly/playwright-core 1.47.20-alpha → 1.48.20

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 (203) hide show
  1. package/browsers.json +14 -10
  2. package/lib/checkly/escapeRegExp.js +33 -0
  3. package/lib/checkly/secretsFilter.js +23 -0
  4. package/lib/cli/program.js +26 -14
  5. package/lib/client/api.js +6 -0
  6. package/lib/client/browserContext.js +20 -2
  7. package/lib/client/channelOwner.js +5 -2
  8. package/lib/client/connection.js +3 -0
  9. package/lib/client/fetch.js +16 -3
  10. package/lib/client/jsHandle.js +0 -8
  11. package/lib/client/localUtils.js +1 -0
  12. package/lib/client/network.js +175 -17
  13. package/lib/client/page.js +21 -0
  14. package/lib/client/playwright.js +6 -3
  15. package/lib/client/tracing.js +16 -20
  16. package/lib/generated/consoleApiSource.js +1 -1
  17. package/lib/generated/injectedScriptSource.js +1 -1
  18. package/lib/generated/pollingRecorderSource.js +7 -0
  19. package/lib/generated/webSocketMockSource.js +7 -0
  20. package/lib/protocol/validator.js +80 -14
  21. package/lib/server/bidi/bidiBrowser.js +23 -8
  22. package/lib/server/bidi/bidiChromium.js +124 -0
  23. package/lib/server/bidi/bidiConnection.js +1 -1
  24. package/lib/server/bidi/bidiExecutionContext.js +0 -3
  25. package/lib/server/bidi/bidiFirefox.js +15 -21
  26. package/lib/server/bidi/bidiInput.js +16 -32
  27. package/lib/server/bidi/bidiNetworkManager.js +39 -5
  28. package/lib/server/bidi/bidiOverCdp.js +103 -0
  29. package/lib/server/bidi/bidiPage.js +98 -25
  30. package/lib/server/bidi/bidiPdf.js +140 -0
  31. package/lib/server/bidi/third_party/firefoxPrefs.js +221 -0
  32. package/lib/server/browser.js +13 -2
  33. package/lib/server/browserContext.js +6 -23
  34. package/lib/server/browserType.js +39 -11
  35. package/lib/server/chromium/chromium.js +3 -15
  36. package/lib/server/chromium/chromiumSwitches.js +3 -1
  37. package/lib/server/chromium/crBrowser.js +4 -3
  38. package/lib/server/chromium/crExecutionContext.js +0 -7
  39. package/lib/server/chromium/crPage.js +5 -2
  40. package/lib/server/chromium/videoRecorder.js +1 -1
  41. package/lib/server/codegen/csharp.js +2 -2
  42. package/lib/server/codegen/java.js +1 -1
  43. package/lib/server/codegen/javascript.js +1 -1
  44. package/lib/server/codegen/language.js +14 -2
  45. package/lib/server/codegen/python.js +2 -2
  46. package/lib/server/cookieStore.js +73 -0
  47. package/lib/server/debugController.js +2 -2
  48. package/lib/server/deviceDescriptorsSource.json +51 -51
  49. package/lib/server/dialog.js +1 -0
  50. package/lib/server/dispatchers/browserContextDispatcher.js +19 -2
  51. package/lib/server/dispatchers/jsHandleDispatcher.js +0 -5
  52. package/lib/server/dispatchers/pageDispatcher.js +9 -0
  53. package/lib/server/dispatchers/playwrightDispatcher.js +2 -1
  54. package/lib/server/dispatchers/webSocketRouteDispatcher.js +189 -0
  55. package/lib/server/download.js +9 -2
  56. package/lib/server/fetch.js +96 -99
  57. package/lib/server/firefox/ffBrowser.js +6 -4
  58. package/lib/server/firefox/ffExecutionContext.js +0 -3
  59. package/lib/server/firefox/ffPage.js +3 -0
  60. package/lib/server/firefox/firefox.js +2 -13
  61. package/lib/server/frameSelectors.js +1 -1
  62. package/lib/server/frames.js +3 -2
  63. package/lib/server/har/harTracer.js +11 -0
  64. package/lib/server/input.js +0 -1
  65. package/lib/server/javascript.js +0 -7
  66. package/lib/server/page.js +5 -1
  67. package/lib/server/playwright.js +5 -2
  68. package/lib/server/recorder/contextRecorder.js +33 -50
  69. package/lib/server/recorder/recorderActions.js +2 -1
  70. package/lib/server/recorder/recorderApp.js +16 -10
  71. package/lib/server/recorder/recorderCollection.js +68 -79
  72. package/lib/server/recorder/recorderFrontend.js +5 -0
  73. package/lib/server/recorder/recorderInTraceViewer.js +144 -0
  74. package/lib/server/recorder/recorderRunner.js +75 -97
  75. package/lib/server/recorder/recorderUtils.js +47 -6
  76. package/lib/server/recorder.js +30 -25
  77. package/lib/server/registry/index.js +85 -4
  78. package/lib/server/socksClientCertificatesInterceptor.js +15 -3
  79. package/lib/server/trace/recorder/snapshotter.js +1 -0
  80. package/lib/server/trace/recorder/snapshotterInjected.js +2 -2
  81. package/lib/server/trace/recorder/tracing.js +70 -5
  82. package/lib/server/trace/test/inMemorySnapshotter.js +1 -1
  83. package/lib/server/trace/viewer/traceViewer.js +2 -5
  84. package/lib/server/webkit/webkit.js +1 -1
  85. package/lib/server/webkit/wkBrowser.js +6 -5
  86. package/lib/server/webkit/wkExecutionContext.js +0 -3
  87. package/lib/server/webkit/wkPage.js +4 -1
  88. package/lib/utils/happy-eyeballs.js +13 -0
  89. package/lib/utils/hostPlatform.js +2 -2
  90. package/lib/utils/httpServer.js +1 -0
  91. package/lib/utils/isomorphic/locatorGenerators.js +9 -18
  92. package/lib/utils/isomorphic/locatorParser.js +2 -2
  93. package/lib/utils/isomorphic/recorderUtils.js +195 -0
  94. package/lib/vite/htmlReport/index.html +12 -12
  95. package/lib/vite/recorder/assets/codeMirrorModule-d0KhC1qL.js +24 -0
  96. package/lib/vite/recorder/assets/{index-B-MT5gKo.css → index-BW-aOBcL.css} +1 -1
  97. package/lib/vite/recorder/assets/{index-D-5S5PPN.js → index-Bxxcmxlu.js} +10 -15
  98. package/lib/vite/recorder/index.html +2 -2
  99. package/lib/vite/traceViewer/assets/codeMirrorModule-BTYWvxEC.js +16437 -0
  100. package/lib/vite/traceViewer/assets/codeMirrorModule-BdBhzV6t.js +16443 -0
  101. package/lib/vite/traceViewer/assets/codeMirrorModule-BqcXH1AO.js +16838 -0
  102. package/lib/vite/traceViewer/assets/codeMirrorModule-Ca-1BNel.js +24 -0
  103. package/lib/vite/traceViewer/assets/codeMirrorModule-CcviAl53.js +16831 -0
  104. package/lib/vite/traceViewer/assets/codeMirrorModule-DS3v0XrQ.js +24 -0
  105. package/lib/vite/traceViewer/assets/codeMirrorModule-DZoSgqUd.js +24 -0
  106. package/lib/vite/traceViewer/assets/codeMirrorModule-DblsdhjA.js +16449 -0
  107. package/lib/vite/traceViewer/assets/codeMirrorModule-DtXZtbmO.js +16437 -0
  108. package/lib/vite/traceViewer/assets/codeMirrorModule-EhKN7Okm.js +16449 -0
  109. package/lib/vite/{recorder/assets/codeMirrorModule-C-fQ5QZD.js → traceViewer/assets/codeMirrorModule-MzSmL4X2.js} +1 -1
  110. package/lib/vite/traceViewer/assets/codeMirrorModule-U6XMqGkV.js +16437 -0
  111. package/lib/vite/traceViewer/assets/codeMirrorModule-lDjkI8Ax.js +24 -0
  112. package/lib/vite/traceViewer/assets/inspectorTab-BABZNwlH.js +17351 -0
  113. package/lib/vite/traceViewer/assets/inspectorTab-BB2Bm-wy.js +17361 -0
  114. package/lib/vite/traceViewer/assets/inspectorTab-BHcfR9dD.js +64 -0
  115. package/lib/vite/traceViewer/assets/inspectorTab-BPzVEZSf.js +17351 -0
  116. package/lib/vite/traceViewer/assets/inspectorTab-BPzhNk9r.js +64 -0
  117. package/lib/vite/traceViewer/assets/inspectorTab-Bbgq0hgt.js +64 -0
  118. package/lib/vite/traceViewer/assets/inspectorTab-C_OTuI8x.js +17361 -0
  119. package/lib/vite/traceViewer/assets/inspectorTab-DOc4D3cX.js +17361 -0
  120. package/lib/vite/traceViewer/assets/inspectorTab-DhBbZz8I.js +64 -0
  121. package/lib/vite/traceViewer/assets/inspectorTab-DpvLVMq5.js +17351 -0
  122. package/lib/vite/traceViewer/assets/workbench-B13nfocr.js +9 -0
  123. package/lib/vite/traceViewer/assets/workbench-BcgGQnKb.js +1473 -0
  124. package/lib/vite/traceViewer/assets/workbench-BwodYCgl.js +19119 -0
  125. package/lib/vite/traceViewer/assets/workbench-ByyWxoT8.js +1473 -0
  126. package/lib/vite/traceViewer/assets/workbench-CWtpwfKK.js +1473 -0
  127. package/lib/vite/traceViewer/assets/workbench-Crj6jzdv.js +19119 -0
  128. package/lib/vite/traceViewer/assets/workbench-DLv_q9ji.js +9 -0
  129. package/lib/vite/traceViewer/assets/workbench-DZqNXdoV.js +9 -0
  130. package/lib/vite/traceViewer/assets/workbench-DhqI6jeL.js +1473 -0
  131. package/lib/vite/traceViewer/assets/workbench-I4s6sWjN.js +1473 -0
  132. package/lib/vite/traceViewer/assets/workbench-M-Dh_RgU.js +1473 -0
  133. package/lib/vite/traceViewer/assets/workbench-Pa1v1Ojh.js +72 -0
  134. package/lib/vite/traceViewer/assets/workbench-gtYcQBNA.js +9 -0
  135. package/lib/vite/traceViewer/assets/xtermModule-DZP0glxx.js +5982 -0
  136. package/lib/vite/traceViewer/embedded.27BGR_eD.js +105 -0
  137. package/lib/vite/traceViewer/embedded.BBZ9gQEw.js +104 -0
  138. package/lib/vite/traceViewer/embedded.BIubxTi3.js +2 -0
  139. package/lib/vite/traceViewer/embedded.CHH7D63q.js +106 -0
  140. package/lib/vite/traceViewer/embedded.CorI3dFX.js +104 -0
  141. package/lib/vite/traceViewer/embedded.D4lqGydT.js +2 -0
  142. package/lib/vite/traceViewer/embedded.DTjd2aiy.js +105 -0
  143. package/lib/vite/traceViewer/embedded.DbzY7Q8w.js +2 -0
  144. package/lib/vite/traceViewer/embedded.Dxe2heQk.js +2 -0
  145. package/lib/vite/traceViewer/embedded.SsjKHrxC.js +105 -0
  146. package/lib/vite/traceViewer/embedded.Zu332ZC1.js +106 -0
  147. package/lib/vite/traceViewer/embedded.f-PLGsBT.js +2 -0
  148. package/lib/vite/traceViewer/embedded.html +5 -3
  149. package/lib/vite/traceViewer/embedded.ymLJ2mBS.js +106 -0
  150. package/lib/vite/traceViewer/index.B7aiTMfZ.js +2 -0
  151. package/lib/vite/traceViewer/index.BSak5QT9.js +2 -0
  152. package/lib/vite/traceViewer/index.Bfh46hDK.js +197 -0
  153. package/lib/vite/traceViewer/index.BrT2kfuc.js +2 -0
  154. package/lib/vite/traceViewer/index.C8ZWP1Qw.js +197 -0
  155. package/lib/vite/traceViewer/index.CB297BuW.js +2 -0
  156. package/lib/vite/traceViewer/index.CLxsp2W_.js +197 -0
  157. package/lib/vite/traceViewer/index.DPD22sZn.js +2 -0
  158. package/lib/vite/traceViewer/index.DkRbtWVo.js +195 -0
  159. package/lib/vite/traceViewer/index.DsjmhbB6.js +195 -0
  160. package/lib/vite/traceViewer/index.Dz3icWJV.js +196 -0
  161. package/lib/vite/traceViewer/index.PqcsvBxQ.js +196 -0
  162. package/lib/vite/traceViewer/index.html +5 -3
  163. package/lib/vite/traceViewer/index.yxAwzeWG.js +196 -0
  164. package/lib/vite/traceViewer/inspectorTab.DGJWXOSd.css +3145 -0
  165. package/lib/vite/traceViewer/inspectorTab.DLjBDrQR.css +1 -0
  166. package/lib/vite/traceViewer/recorder.7Wl6HrQl.js +550 -0
  167. package/lib/vite/traceViewer/recorder.BHq8OXiu.js +551 -0
  168. package/lib/vite/traceViewer/recorder.B_SY1GJM.css +0 -0
  169. package/lib/vite/traceViewer/recorder.BaRuS6Pc.js +2 -0
  170. package/lib/vite/traceViewer/recorder.BufKu9Hp.js +550 -0
  171. package/lib/vite/traceViewer/recorder.C88JDknq.js +2 -0
  172. package/lib/vite/traceViewer/recorder.Ch-WHviK.js +2 -0
  173. package/lib/vite/traceViewer/recorder.DBDpiNOK.css +15 -0
  174. package/lib/vite/traceViewer/recorder.Fwf59ZKh.js +551 -0
  175. package/lib/vite/traceViewer/recorder.POd-toIn.js +2 -0
  176. package/lib/vite/traceViewer/recorder.am-MV-DQ.js +550 -0
  177. package/lib/vite/traceViewer/recorder.html +17 -0
  178. package/lib/vite/traceViewer/recorder.zV_xPHM4.js +551 -0
  179. package/lib/vite/traceViewer/sw.bundle.js +3 -3
  180. package/lib/vite/traceViewer/uiMode.2tr9k625.js +5 -0
  181. package/lib/vite/traceViewer/uiMode.B11wexdJ.js +5 -0
  182. package/lib/vite/traceViewer/uiMode.BEZVCe5O.js +5 -0
  183. package/lib/vite/traceViewer/uiMode.BH2Nj2h0.js +1724 -0
  184. package/lib/vite/traceViewer/uiMode.BZoFj6zV.js +1723 -0
  185. package/lib/vite/traceViewer/uiMode.C4nbcio6.js +1730 -0
  186. package/lib/vite/traceViewer/uiMode.CAYqod-m.css +1 -0
  187. package/lib/vite/traceViewer/uiMode.CBRJkC_K.js +1724 -0
  188. package/lib/vite/traceViewer/uiMode.CpC2B27N.js +1724 -0
  189. package/lib/vite/traceViewer/uiMode.DRmgrHSk.css +1462 -0
  190. package/lib/vite/traceViewer/uiMode.DdtUZZVS.js +5 -0
  191. package/lib/vite/traceViewer/uiMode.Dlo9s_YX.js +1723 -0
  192. package/lib/vite/traceViewer/uiMode.O07awP3T.js +10 -0
  193. package/lib/vite/traceViewer/uiMode.gGHHTsyL.js +1730 -0
  194. package/lib/vite/traceViewer/uiMode.html +6 -4
  195. package/lib/vite/traceViewer/uiMode.wsGnVMQK.js +1723 -0
  196. package/lib/vite/traceViewer/workbench.9Es1K_T7.css +549 -0
  197. package/lib/vite/traceViewer/workbench.BQNDbcQ0.css +550 -0
  198. package/lib/vite/traceViewer/workbench.DjbIuxix.css +1 -0
  199. package/lib/vite/traceViewer/workbench.DlsCx8k5.css +1 -0
  200. package/lib/vite/traceViewer/workbench.wuxQoE2z.css +3703 -0
  201. package/package.json +1 -1
  202. package/types/protocol.d.ts +610 -173
  203. package/types/types.d.ts +2037 -949
@@ -107,6 +107,8 @@ const DOWNLOAD_PATHS = {
107
107
  'mac13-arm64': 'builds/chromium/%s/chromium-mac-arm64.zip',
108
108
  'mac14': 'builds/chromium/%s/chromium-mac.zip',
109
109
  'mac14-arm64': 'builds/chromium/%s/chromium-mac-arm64.zip',
110
+ 'mac15': 'builds/chromium/%s/chromium-mac.zip',
111
+ 'mac15-arm64': 'builds/chromium/%s/chromium-mac-arm64.zip',
110
112
  'win64': 'builds/chromium/%s/chromium-win64.zip'
111
113
  },
112
114
  'chromium-tip-of-tree': {
@@ -134,6 +136,8 @@ const DOWNLOAD_PATHS = {
134
136
  'mac13-arm64': 'builds/chromium-tip-of-tree/%s/chromium-tip-of-tree-mac-arm64.zip',
135
137
  'mac14': 'builds/chromium-tip-of-tree/%s/chromium-tip-of-tree-mac.zip',
136
138
  'mac14-arm64': 'builds/chromium-tip-of-tree/%s/chromium-tip-of-tree-mac-arm64.zip',
139
+ 'mac15': 'builds/chromium-tip-of-tree/%s/chromium-tip-of-tree-mac.zip',
140
+ 'mac15-arm64': 'builds/chromium-tip-of-tree/%s/chromium-tip-of-tree-mac-arm64.zip',
137
141
  'win64': 'builds/chromium-tip-of-tree/%s/chromium-tip-of-tree-win64.zip'
138
142
  },
139
143
  'firefox': {
@@ -161,6 +165,8 @@ const DOWNLOAD_PATHS = {
161
165
  'mac13-arm64': 'builds/firefox/%s/firefox-mac-arm64.zip',
162
166
  'mac14': 'builds/firefox/%s/firefox-mac.zip',
163
167
  'mac14-arm64': 'builds/firefox/%s/firefox-mac-arm64.zip',
168
+ 'mac15': 'builds/firefox/%s/firefox-mac.zip',
169
+ 'mac15-arm64': 'builds/firefox/%s/firefox-mac-arm64.zip',
164
170
  'win64': 'builds/firefox/%s/firefox-win64.zip'
165
171
  },
166
172
  'firefox-beta': {
@@ -188,6 +194,8 @@ const DOWNLOAD_PATHS = {
188
194
  'mac13-arm64': 'builds/firefox-beta/%s/firefox-beta-mac-arm64.zip',
189
195
  'mac14': 'builds/firefox-beta/%s/firefox-beta-mac.zip',
190
196
  'mac14-arm64': 'builds/firefox-beta/%s/firefox-beta-mac-arm64.zip',
197
+ 'mac15': 'builds/firefox-beta/%s/firefox-beta-mac.zip',
198
+ 'mac15-arm64': 'builds/firefox-beta/%s/firefox-beta-mac-arm64.zip',
191
199
  'win64': 'builds/firefox-beta/%s/firefox-beta-win64.zip'
192
200
  },
193
201
  'webkit': {
@@ -215,6 +223,8 @@ const DOWNLOAD_PATHS = {
215
223
  'mac13-arm64': 'builds/webkit/%s/webkit-mac-13-arm64.zip',
216
224
  'mac14': 'builds/webkit/%s/webkit-mac-14.zip',
217
225
  'mac14-arm64': 'builds/webkit/%s/webkit-mac-14-arm64.zip',
226
+ 'mac15': 'builds/webkit/%s/webkit-mac-15.zip',
227
+ 'mac15-arm64': 'builds/webkit/%s/webkit-mac-15-arm64.zip',
218
228
  'win64': 'builds/webkit/%s/webkit-win64.zip'
219
229
  },
220
230
  'ffmpeg': {
@@ -242,6 +252,8 @@ const DOWNLOAD_PATHS = {
242
252
  'mac13-arm64': 'builds/ffmpeg/%s/ffmpeg-mac-arm64.zip',
243
253
  'mac14': 'builds/ffmpeg/%s/ffmpeg-mac.zip',
244
254
  'mac14-arm64': 'builds/ffmpeg/%s/ffmpeg-mac-arm64.zip',
255
+ 'mac15': 'builds/ffmpeg/%s/ffmpeg-mac.zip',
256
+ 'mac15-arm64': 'builds/ffmpeg/%s/ffmpeg-mac-arm64.zip',
245
257
  'win64': 'builds/ffmpeg/%s/ffmpeg-win64.zip'
246
258
  },
247
259
  'android': {
@@ -269,6 +281,8 @@ const DOWNLOAD_PATHS = {
269
281
  'mac13-arm64': 'builds/android/%s/android.zip',
270
282
  'mac14': 'builds/android/%s/android.zip',
271
283
  'mac14-arm64': 'builds/android/%s/android.zip',
284
+ 'mac15': 'builds/android/%s/android.zip',
285
+ 'mac15-arm64': 'builds/android/%s/android.zip',
272
286
  'win64': 'builds/android/%s/android.zip'
273
287
  },
274
288
  // TODO(bidi): implement downloads.
@@ -442,11 +456,46 @@ class Registry {
442
456
  'darwin': '/Applications/Microsoft Edge Canary.app/Contents/MacOS/Microsoft Edge Canary',
443
457
  'win32': `\\Microsoft\\Edge SxS\\Application\\msedge.exe`
444
458
  }));
445
- this._executables.push(this._createBidiChannel('bidi-firefox-stable', {
446
- 'linux': '/usr/bin/firefox',
447
- 'darwin': '/Applications/Firefox.app/Contents/MacOS/firefox',
448
- 'win32': '\\Mozilla Firefox\\firefox.exe'
459
+ this._executables.push(this._createBidiFirefoxChannel('bidi-firefox-stable', {
460
+ 'linux': '/firefox/firefox',
461
+ 'darwin': '/Firefox.app/Contents/MacOS/firefox',
462
+ 'win32': '\\core\\firefox.exe'
449
463
  }));
464
+ this._executables.push(this._createBidiFirefoxChannel('bidi-firefox-beta', {
465
+ 'linux': '/firefox/firefox',
466
+ 'darwin': '/Firefox.app/Contents/MacOS/firefox',
467
+ 'win32': '\\core\\firefox.exe'
468
+ }));
469
+ this._executables.push(this._createBidiFirefoxChannel('bidi-firefox-nightly', {
470
+ 'linux': '/firefox/firefox',
471
+ 'darwin': '/Firefox Nightly.app/Contents/MacOS/firefox',
472
+ 'win32': '\\firefox\\firefox.exe'
473
+ }));
474
+ this._executables.push(this._createBidiChannel('bidi-chrome-stable', {
475
+ 'linux': '/opt/google/chrome/chrome',
476
+ 'darwin': '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome',
477
+ 'win32': `\\Google\\Chrome\\Application\\chrome.exe`
478
+ }));
479
+ this._executables.push(this._createBidiChannel('bidi-chrome-canary', {
480
+ 'linux': '',
481
+ 'darwin': '/Applications/Google Chrome Canary.app/Contents/MacOS/Google Chrome Canary',
482
+ 'win32': `\\Google\\Chrome SxS\\Application\\chrome.exe`
483
+ }));
484
+ this._executables.push({
485
+ type: 'browser',
486
+ name: 'bidi-chromium',
487
+ browserName: 'bidi',
488
+ directory: chromium.dir,
489
+ executablePath: () => chromiumExecutable,
490
+ executablePathOrDie: sdkLanguage => executablePathOrDie('chromium', chromiumExecutable, chromium.installByDefault, sdkLanguage),
491
+ installType: 'download-on-demand',
492
+ _validateHostRequirements: sdkLanguage => this._validateHostRequirements(sdkLanguage, 'chromium', chromium.dir, ['chrome-linux'], [], ['chrome-win']),
493
+ downloadURLs: this._downloadURLs(chromium),
494
+ browserVersion: chromium.browserVersion,
495
+ _install: () => this._downloadExecutable(chromium, chromiumExecutable),
496
+ _dependencyGroup: 'chromium',
497
+ _isHermeticInstallation: true
498
+ });
450
499
  const firefox = descriptors.find(d => d.name === 'firefox');
451
500
  const firefoxExecutable = findExecutablePath(firefox.dir, 'firefox');
452
501
  this._executables.push({
@@ -575,6 +624,38 @@ class Registry {
575
624
  _install: install
576
625
  };
577
626
  }
627
+ _createBidiFirefoxChannel(name, lookAt, install) {
628
+ const executablePath = (sdkLanguage, shouldThrow) => {
629
+ const suffix = lookAt[process.platform];
630
+ if (!suffix) {
631
+ if (shouldThrow) throw new Error(`Firefox distribution '${name}' is not supported on ${process.platform}`);
632
+ return undefined;
633
+ }
634
+ const folder = _path.default.resolve('firefox');
635
+ let channelName = 'stable';
636
+ if (name.includes('beta')) channelName = 'beta';else if (name.includes('nightly')) channelName = 'nightly';
637
+ const installedVersions = fs.readdirSync(folder);
638
+ const found = installedVersions.filter(e => e.includes(channelName));
639
+ if (found.length === 1) return _path.default.join(folder, found[0], suffix);
640
+ if (found.length > 1) {
641
+ if (shouldThrow) throw new Error(`Multiple Firefox installations found for channel '${name}': ${found.join(', ')}`);else return undefined;
642
+ }
643
+ if (shouldThrow) throw new Error(`Cannot find Firefox installation for channel '${name}' under ${folder}`);
644
+ return undefined;
645
+ };
646
+ return {
647
+ type: 'channel',
648
+ name,
649
+ browserName: 'bidi',
650
+ directory: undefined,
651
+ executablePath: sdkLanguage => executablePath(sdkLanguage, false),
652
+ executablePathOrDie: sdkLanguage => executablePath(sdkLanguage, true),
653
+ installType: 'none',
654
+ _validateHostRequirements: () => Promise.resolve(),
655
+ _isHermeticInstallation: true,
656
+ _install: install
657
+ };
658
+ }
578
659
  _createBidiChannel(name, lookAt, install) {
579
660
  const executablePath = (sdkLanguage, shouldThrow) => {
580
661
  const suffix = lookAt[process.platform];
@@ -14,6 +14,9 @@ var _happyEyeballs = require("../utils/happy-eyeballs");
14
14
  var _utils = require("../utils");
15
15
  var _socksProxy = require("../common/socksProxy");
16
16
  var _debugLogger = require("../utils/debugLogger");
17
+ var _fetch = require("./fetch");
18
+ var _events = require("events");
19
+ var _browserContext = require("./browserContext");
17
20
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
18
21
  /**
19
22
  * Copyright (c) Microsoft Corporation.
@@ -104,7 +107,11 @@ class SocksProxyConnection {
104
107
  };
105
108
  }
106
109
  async connect() {
107
- this.target = await (0, _happyEyeballs.createSocket)(rewriteToLocalhostIfNeeded(this.host), this.port);
110
+ if (this.socksProxy.proxyAgentFromOptions) this.target = await this.socksProxy.proxyAgentFromOptions.callback(new _events.EventEmitter(), {
111
+ host: rewriteToLocalhostIfNeeded(this.host),
112
+ port: this.port,
113
+ secureEndpoint: false
114
+ });else this.target = await (0, _happyEyeballs.createSocket)(rewriteToLocalhostIfNeeded(this.host), this.port);
108
115
  this.target.once('close', this._targetCloseEventListener);
109
116
  this.target.once('error', error => this.socksProxy._socksProxy.sendSocketError({
110
117
  uid: this.uid,
@@ -231,8 +238,11 @@ class ClientCertificatesProxy {
231
238
  this.ignoreHTTPSErrors = void 0;
232
239
  this.secureContextMap = new Map();
233
240
  this.alpnCache = void 0;
241
+ this.proxyAgentFromOptions = void 0;
242
+ (0, _browserContext.verifyClientCertificates)(contextOptions.clientCertificates);
234
243
  this.alpnCache = new ALPNCache();
235
244
  this.ignoreHTTPSErrors = contextOptions.ignoreHTTPSErrors;
245
+ this.proxyAgentFromOptions = contextOptions.proxy ? (0, _fetch.createProxyAgent)(contextOptions.proxy) : undefined;
236
246
  this._initSecureContexts(contextOptions.clientCertificates);
237
247
  this._socksProxy = new _socksProxy.SocksProxy();
238
248
  this._socksProxy.setPattern('*');
@@ -281,7 +291,9 @@ class ClientCertificatesProxy {
281
291
  }
282
292
  async listen() {
283
293
  const port = await this._socksProxy.listen(0, '127.0.0.1');
284
- return `socks5://127.0.0.1:${port}`;
294
+ return {
295
+ server: `socks5://127.0.0.1:${port}`
296
+ };
285
297
  }
286
298
  async close() {
287
299
  await this._socksProxy.close();
@@ -323,6 +335,6 @@ function rewriteToLocalhostIfNeeded(host) {
323
335
  return host === 'local.playwright' ? 'localhost' : host;
324
336
  }
325
337
  function rewriteOpenSSLErrorIfNeeded(error) {
326
- if (error.message !== 'unsupported') return error;
338
+ if (error.message !== 'unsupported' && error.code !== 'ERR_CRYPTO_UNSUPPORTED_OPERATION') return error;
327
339
  return (0, _utils.rewriteErrorMessage)(error, ['Unsupported TLS certificate.', 'Most likely, the security algorithm of the given certificate was deprecated by OpenSSL.', 'For more details, see https://github.com/openssl/openssl/blob/master/README-PROVIDERS.md#the-legacy-provider', 'You could probably modernize the certificate by following the steps at https://github.com/nodejs/node/issues/40672#issuecomment-1243648223'].join('\n'));
328
340
  }
@@ -111,6 +111,7 @@ class Snapshotter {
111
111
  html: data.html,
112
112
  viewport: data.viewport,
113
113
  timestamp: (0, _utils.monotonicTime)(),
114
+ wallTime: data.wallTime,
114
115
  collectionTime: data.collectionTime,
115
116
  resourceOverrides: [],
116
117
  isMainFrame: page.mainFrame() === frame
@@ -467,7 +467,7 @@ function frameSnapshotStreamer(snapshotStreamer, removeNoScript) {
467
467
  height: window.innerHeight
468
468
  },
469
469
  url: location.href,
470
- timestamp,
470
+ wallTime: Date.now(),
471
471
  collectionTime: 0
472
472
  };
473
473
  for (const sheet of this._staleStyleSheets) {
@@ -485,7 +485,7 @@ function frameSnapshotStreamer(snapshotStreamer, removeNoScript) {
485
485
  contentType: 'text/css'
486
486
  });
487
487
  }
488
- result.collectionTime = performance.now() - result.timestamp;
488
+ result.collectionTime = performance.now() - timestamp;
489
489
  return result;
490
490
  }
491
491
  }
@@ -18,6 +18,7 @@ var _harTracer = require("../../har/harTracer");
18
18
  var _snapshotter = require("./snapshotter");
19
19
  var _dispatcher = require("../../dispatchers/dispatcher");
20
20
  var _errors = require("../../errors");
21
+ var _secretsFilter = require("../../../checkly/secretsFilter");
21
22
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
22
23
  /**
23
24
  * Copyright (c) Microsoft Corporation.
@@ -58,8 +59,10 @@ class Tracing extends _instrumentation.SdkObject {
58
59
  this._allResources = new Set();
59
60
  this._contextCreatedEvent = void 0;
60
61
  this._pendingHarEntries = new Set();
62
+ this._secretsFilter = void 0;
61
63
  this._context = context;
62
64
  this._precreatedTracesDir = tracesDir;
65
+ this._secretsFilter = (0, _secretsFilter.secretsFilter)();
63
66
  this._harTracer = new _harTracer.HarTracer(context, null, this, {
64
67
  content: 'attach',
65
68
  includeTraceInfo: true,
@@ -146,7 +149,7 @@ class Tracing extends _instrumentation.SdkObject {
146
149
  wallTime: Date.now(),
147
150
  monotonicTime: (0, _utils.monotonicTime)()
148
151
  };
149
- this._fs.appendFile(this._state.traceFile, JSON.stringify(event) + '\n');
152
+ this._appendTraceEvent(event);
150
153
  this._context.instrumentation.addListener(this, this._context);
151
154
  this._eventListeners.push(_utils.eventsHelper.addEventListener(this._context, _browserContext.BrowserContext.Events.Console, this._onConsoleMessage.bind(this)), _utils.eventsHelper.addEventListener(this._context, _browserContext.BrowserContext.Events.PageError, this._onPageError.bind(this)));
152
155
  if (this._state.options.screenshots) this._startScreencast();
@@ -331,7 +334,8 @@ class Tracing extends _instrumentation.SdkObject {
331
334
  snapshot: entry
332
335
  };
333
336
  const visited = visitTraceEvent(event, this._state.networkSha1s);
334
- this._fs.appendFile(this._state.networkFile, JSON.stringify(visited) + '\n', true /* flush */);
337
+ const harEntryString = this._secretsFilter(JSON.stringify(visited) + '\n');
338
+ this._fs.appendFile(this._state.networkFile, harEntryString, true /* flush */);
335
339
  }
336
340
  flushHarEntries() {
337
341
  const harLines = [];
@@ -344,7 +348,10 @@ class Tracing extends _instrumentation.SdkObject {
344
348
  harLines.push(JSON.stringify(visited));
345
349
  }
346
350
  this._pendingHarEntries.clear();
347
- if (harLines.length) this._fs.appendFile(this._state.networkFile, harLines.join('\n') + '\n', true /* flush */);
351
+ if (harLines.length) {
352
+ const harString = this._secretsFilter(harLines.join('\n') + '\n');
353
+ this._fs.appendFile(this._state.networkFile, harString, true /* flush */);
354
+ }
348
355
  }
349
356
  onContentBlob(sha1, buffer) {
350
357
  this._appendResource(sha1, buffer);
@@ -374,6 +381,61 @@ class Tracing extends _instrumentation.SdkObject {
374
381
  };
375
382
  this._appendTraceEvent(event);
376
383
  }
384
+ onDialog(dialog) {
385
+ const event = {
386
+ type: 'event',
387
+ time: (0, _utils.monotonicTime)(),
388
+ class: 'BrowserContext',
389
+ method: 'dialog',
390
+ params: {
391
+ pageId: dialog.page().guid,
392
+ type: dialog.type(),
393
+ message: dialog.message(),
394
+ defaultValue: dialog.defaultValue()
395
+ }
396
+ };
397
+ this._appendTraceEvent(event);
398
+ }
399
+ onDownload(page, download) {
400
+ const event = {
401
+ type: 'event',
402
+ time: (0, _utils.monotonicTime)(),
403
+ class: 'BrowserContext',
404
+ method: 'download',
405
+ params: {
406
+ pageId: page.guid,
407
+ url: download.url,
408
+ suggestedFilename: download.suggestedFilename()
409
+ }
410
+ };
411
+ this._appendTraceEvent(event);
412
+ }
413
+ onPageOpen(page) {
414
+ var _page$opener;
415
+ const event = {
416
+ type: 'event',
417
+ time: (0, _utils.monotonicTime)(),
418
+ class: 'BrowserContext',
419
+ method: 'page',
420
+ params: {
421
+ pageId: page.guid,
422
+ openerPageId: (_page$opener = page.opener()) === null || _page$opener === void 0 ? void 0 : _page$opener.guid
423
+ }
424
+ };
425
+ this._appendTraceEvent(event);
426
+ }
427
+ onPageClose(page) {
428
+ const event = {
429
+ type: 'event',
430
+ time: (0, _utils.monotonicTime)(),
431
+ class: 'BrowserContext',
432
+ method: 'pageClosed',
433
+ params: {
434
+ pageId: page.guid
435
+ }
436
+ };
437
+ this._appendTraceEvent(event);
438
+ }
377
439
  _onPageError(error, page) {
378
440
  const event = {
379
441
  type: 'event',
@@ -399,7 +461,8 @@ class Tracing extends _instrumentation.SdkObject {
399
461
  sha1,
400
462
  width: params.width,
401
463
  height: params.height,
402
- timestamp: (0, _utils.monotonicTime)()
464
+ timestamp: (0, _utils.monotonicTime)(),
465
+ frameSwapWallTime: params.frameSwapWallTime
403
466
  };
404
467
  // Make sure to write the screencast frame before adding a reference to it.
405
468
  this._appendResource(sha1, params.buffer);
@@ -410,7 +473,9 @@ class Tracing extends _instrumentation.SdkObject {
410
473
  const visited = visitTraceEvent(event, this._state.traceSha1s);
411
474
  // Do not flush (console) events, they are too noisy, unless we are in ui mode (live).
412
475
  const flush = this._state.options.live || event.type !== 'event' && event.type !== 'console' && event.type !== 'log';
413
- this._fs.appendFile(this._state.traceFile, JSON.stringify(visited) + '\n', flush);
476
+ const json = JSON.stringify(visited) + '\n';
477
+ const filtered = this._secretsFilter(json);
478
+ this._fs.appendFile(this._state.traceFile, filtered, flush);
414
479
  }
415
480
  _appendResource(sha1, buffer) {
416
481
  if (this._allResources.has(sha1)) return;
@@ -4,7 +4,7 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.InMemorySnapshotter = void 0;
7
- var _snapshotStorage = require("../../../../../trace-viewer/src/snapshotStorage");
7
+ var _snapshotStorage = require("../../../../../trace-viewer/src/sw/snapshotStorage");
8
8
  var _snapshotter = require("../recorder/snapshotter");
9
9
  var _harTracer = require("../../har/harTracer");
10
10
  var _utils = require("../../../utils");
@@ -84,6 +84,7 @@ async function startTraceViewerServer(options) {
84
84
  }
85
85
  async function installRootRedirect(server, traceUrls, options) {
86
86
  const params = new URLSearchParams();
87
+ if (_path.default.sep !== _path.default.posix.sep) params.set('pathSeparator', _path.default.sep);
87
88
  for (const traceUrl of traceUrls) params.append('trace', traceUrl);
88
89
  if (server.wsGuid()) params.append('ws', server.wsGuid());
89
90
  if (options !== null && options !== void 0 && options.isServer) params.append('isServer', '');
@@ -92,11 +93,6 @@ async function installRootRedirect(server, traceUrls, options) {
92
93
  if (options.grep) params.append('grep', options.grep);
93
94
  if (options.grepInvert) params.append('grepInvert', options.grepInvert);
94
95
  for (const project of options.project || []) params.append('project', project);
95
- if (options.workers) params.append('workers', String(options.workers));
96
- if (options.timeout) params.append('timeout', String(options.timeout));
97
- if (options.headed) params.append('headed', '');
98
- if (options.outputDir) params.append('outputDir', options.outputDir);
99
- if (options.updateSnapshots) params.append('updateSnapshots', options.updateSnapshots);
100
96
  for (const reporter of options.reporter || []) params.append('reporter', reporter);
101
97
  const urlPath = `./trace/${options.webApp || 'index.html'}?${params.toString()}`;
102
98
  server.routePath('/', (_, response) => {
@@ -172,6 +168,7 @@ class StdinServer {
172
168
  });
173
169
  process.stdin.on('close', () => (0, _utils.gracefullyProcessExitDoNotHang)(0));
174
170
  }
171
+ onconnect() {}
175
172
  async dispatch(method, params) {
176
173
  if (method === 'initialize') {
177
174
  if (this._traceUrl) this._loadTrace(this._traceUrl);
@@ -55,7 +55,6 @@ class WebKit extends _browserType.BrowserType {
55
55
  defaultArgs(options, isPersistent, userDataDir) {
56
56
  const {
57
57
  args = [],
58
- proxy,
59
58
  headless
60
59
  } = options;
61
60
  const userDataDirArg = args.find(arg => arg.startsWith('--user-data-dir'));
@@ -65,6 +64,7 @@ class WebKit extends _browserType.BrowserType {
65
64
  if (process.platform === 'win32') webkitArguments.push('--disable-accelerated-compositing');
66
65
  if (headless) webkitArguments.push('--headless');
67
66
  if (isPersistent) webkitArguments.push(`--user-data-dir=${userDataDir}`);else webkitArguments.push(`--no-startup-window`);
67
+ const proxy = options.proxyOverride || options.proxy;
68
68
  if (proxy) {
69
69
  if (process.platform === 'darwin') {
70
70
  webkitArguments.push(`--proxy=${proxy.server}`);
@@ -72,11 +72,12 @@ class WKBrowser extends _browser.Browser {
72
72
  this._didClose();
73
73
  }
74
74
  async doCreateNewContext(options) {
75
- const createOptions = options.proxy ? {
76
- // Enable socks5 hostname resolution on Windows. Workaround can be removed once fixed upstream.
75
+ const proxy = options.proxyOverride || options.proxy;
76
+ const createOptions = proxy ? {
77
+ // Enable socks5 hostname resolution on Windows.
77
78
  // See https://github.com/microsoft/playwright/issues/20451
78
- proxyServer: process.platform === 'win32' ? options.proxy.server.replace(/^socks5:\/\//, 'socks5h://') : options.proxy.server,
79
- proxyBypassList: options.proxy.bypass
79
+ proxyServer: process.platform === 'win32' ? proxy.server.replace(/^socks5:\/\//, 'socks5h://') : proxy.server,
80
+ proxyBypassList: proxy.bypass
80
81
  } : undefined;
81
82
  const {
82
83
  browserContextId
@@ -192,7 +193,7 @@ class WKBrowserContext extends _browserContext.BrowserContext {
192
193
  downloadPath: this._browser.options.downloadsPath,
193
194
  browserContextId
194
195
  }));
195
- if (this._options.ignoreHTTPSErrors) promises.push(this._browser._browserSession.send('Playwright.setIgnoreCertificateErrors', {
196
+ if (this._options.ignoreHTTPSErrors || this._options.internalIgnoreHTTPSErrors) promises.push(this._browser._browserSession.send('Playwright.setIgnoreCertificateErrors', {
196
197
  browserContextId,
197
198
  ignore: true
198
199
  }));
@@ -116,9 +116,6 @@ class WKExecutionContext {
116
116
  objectId
117
117
  });
118
118
  }
119
- objectCount(objectId) {
120
- throw new Error('Method not implemented in WebKit.');
121
- }
122
119
  }
123
120
  exports.WKExecutionContext = WKExecutionContext;
124
121
  function potentiallyUnserializableValue(remoteObject) {
@@ -746,6 +746,9 @@ class WKPage {
746
746
  throw error;
747
747
  });
748
748
  }
749
+ async requestGC() {
750
+ await this._session.send('Heap.gc');
751
+ }
749
752
  async addInitScript(initScript) {
750
753
  await this._updateBootstrapScript();
751
754
  }
@@ -1070,7 +1073,7 @@ class WKPage {
1070
1073
  this._requestIdToResponseReceivedPayloadEvent.set(event.requestId, event);
1071
1074
  const response = request.createResponse(event.response);
1072
1075
  this._page._frameManager.requestReceivedResponse(response);
1073
- if (response.status() === 204) {
1076
+ if (response.status() === 204 && request.request.isNavigationRequest()) {
1074
1077
  this._onLoadingFailed(session, {
1075
1078
  requestId: event.requestId,
1076
1079
  errorText: 'Aborted: 204 No Content',
@@ -7,6 +7,7 @@ exports.createConnectionAsync = createConnectionAsync;
7
7
  exports.createSocket = createSocket;
8
8
  exports.createTLSSocket = createTLSSocket;
9
9
  exports.httpsHappyEyeballsAgent = exports.httpHappyEyeballsTimings = exports.httpHappyEyeballsAgent = void 0;
10
+ exports.timingForSocket = timingForSocket;
10
11
  var dns = _interopRequireWildcard(require("dns"));
11
12
  var http = _interopRequireWildcard(require("http"));
12
13
  var https = _interopRequireWildcard(require("https"));
@@ -14,6 +15,7 @@ var net = _interopRequireWildcard(require("net"));
14
15
  var tls = _interopRequireWildcard(require("tls"));
15
16
  var _manualPromise = require("./manualPromise");
16
17
  var _debug = require("./debug");
18
+ var _time = require("./time");
17
19
  function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
18
20
  function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
19
21
  /**
@@ -46,6 +48,8 @@ const timings = {
46
48
  },
47
49
  agent: false
48
50
  };
51
+ const kDNSLookupAt = Symbol('kDNSLookupAt');
52
+ const kTCPConnectionAt = Symbol('kTCPConnectionAt');
49
53
  class HttpHappyEyeballsAgent extends http.Agent {
50
54
  createConnection(options, oncreate) {
51
55
  // There is no ambiguity in case of IP address.
@@ -113,6 +117,7 @@ async function createConnectionAsync(options, oncreate, useTLS) {
113
117
  const lookup = options.__testHookLookup || lookupAddresses;
114
118
  const hostname = clientRequestArgsToHostName(options);
115
119
  const addresses = await lookup(hostname);
120
+ const dnsLookupAt = (0, _time.monotonicTime)();
116
121
  const sockets = new Set();
117
122
  let firstError;
118
123
  let errorCount = 0;
@@ -139,10 +144,12 @@ async function createConnectionAsync(options, oncreate, useTLS) {
139
144
  });
140
145
  // Socket created
141
146
  timings.values.socket = performance.now() - timings.values.startTimeNow;
147
+ socket[kDNSLookupAt] = dnsLookupAt;
142
148
 
143
149
  // Each socket may fire only one of 'connect', 'timeout' or 'error' events.
144
150
  // None of these events are fired after socket.destroy() is called.
145
151
  socket.on('connect', () => {
152
+ socket[kTCPConnectionAt] = (0, _time.monotonicTime)();
146
153
  timings.values.connect = performance.now() - timings.values.startTimeNow;
147
154
  connected.resolve();
148
155
  oncreate === null || oncreate === void 0 || oncreate(null, socket);
@@ -194,4 +201,10 @@ function clientRequestArgsToHostName(options) {
194
201
  if (options.hostname) return options.hostname;
195
202
  if (options.host) return options.host;
196
203
  throw new Error('Either options.hostname or options.host must be provided');
204
+ }
205
+ function timingForSocket(socket) {
206
+ return {
207
+ dnsLookupAt: socket[kDNSLookupAt],
208
+ tcpConnectionAt: socket[kTCPConnectionAt]
209
+ };
197
210
  }
@@ -37,9 +37,9 @@ function calculatePlatform() {
37
37
  macVersion = 'mac10.15';
38
38
  } else {
39
39
  // ver[0] >= 20
40
- const LAST_STABLE_MAC_MAJOR_VERSION = 14;
40
+ const LAST_STABLE_MACOS_MAJOR_VERSION = 15;
41
41
  // Best-effort support for MacOS beta versions.
42
- macVersion = 'mac' + Math.min(ver[0] - 9, LAST_STABLE_MAC_MAJOR_VERSION);
42
+ macVersion = 'mac' + Math.min(ver[0] - 9, LAST_STABLE_MACOS_MAJOR_VERSION);
43
43
  // BigSur is the first version that might run on Apple Silicon.
44
44
  if (_os.default.cpus().some(cpu => cpu.model.includes('Apple'))) macVersion += '-arm64';
45
45
  }
@@ -76,6 +76,7 @@ class HttpServer {
76
76
  path: '/' + this._wsGuid
77
77
  });
78
78
  wss.on('connection', ws => {
79
+ transport.onconnect();
79
80
  transport.sendEvent = (method, params) => ws.send(JSON.stringify({
80
81
  method,
81
82
  params
@@ -37,15 +37,6 @@ function asLocators(lang, selector, isFrameLocator = false, maxOutputSize = 20,
37
37
  }
38
38
  function innerAsLocators(factory, parsed, isFrameLocator = false, maxOutputSize = 20) {
39
39
  const parts = [...parsed.parts];
40
- // frameLocator('iframe').first is actually "iframe >> nth=0 >> internal:control=enter-frame"
41
- // To make it easier to parse, we turn it into "iframe >> internal:control=enter-frame >> nth=0"
42
- for (let index = 0; index < parts.length - 1; index++) {
43
- if (parts[index].name === 'nth' && parts[index + 1].name === 'internal:control' && parts[index + 1].body === 'enter-frame') {
44
- // Swap nth and enter-frame.
45
- const [nth] = parts.splice(index, 1);
46
- parts.splice(index + 1, 0, nth);
47
- }
48
- }
49
40
  const tokens = [];
50
41
  let nextBase = isFrameLocator ? 'frame-locator' : 'page';
51
42
  for (let index = 0; index < parts.length; index++) {
@@ -183,13 +174,13 @@ function innerAsLocators(factory, parsed, isFrameLocator = false, maxOutputSize
183
174
  continue;
184
175
  }
185
176
  }
186
- let locatorType = 'default';
187
- const nextPart = parts[index + 1];
188
- if (nextPart && nextPart.name === 'internal:control' && nextPart.body === 'enter-frame') {
189
- locatorType = 'frame';
177
+ if (part.name === 'internal:control' && part.body === 'enter-frame') {
178
+ tokens.push([factory.generateLocator(base, 'frame', '')]);
190
179
  nextBase = 'frame-locator';
191
- index++;
180
+ continue;
192
181
  }
182
+ let locatorType = 'default';
183
+ const nextPart = parts[index + 1];
193
184
  const selectorPart = (0, _selectorParser.stringifySelector)({
194
185
  parts: [part]
195
186
  });
@@ -277,7 +268,7 @@ class JavaScriptLocatorFactory {
277
268
  if (options.hasNotText !== undefined) return `locator(${this.quote(body)}, { hasNotText: ${this.toHasText(options.hasNotText)} })`;
278
269
  return `locator(${this.quote(body)})`;
279
270
  case 'frame':
280
- return `frameLocator(${this.quote(body)})`;
271
+ return `contentFrame()`;
281
272
  case 'nth':
282
273
  return `nth(${body})`;
283
274
  case 'first':
@@ -360,7 +351,7 @@ class PythonLocatorFactory {
360
351
  if (options.hasNotText !== undefined) return `locator(${this.quote(body)}, has_not_text=${this.toHasText(options.hasNotText)})`;
361
352
  return `locator(${this.quote(body)})`;
362
353
  case 'frame':
363
- return `frame_locator(${this.quote(body)})`;
354
+ return `content_frame`;
364
355
  case 'nth':
365
356
  return `nth(${body})`;
366
357
  case 'first':
@@ -460,7 +451,7 @@ class JavaLocatorFactory {
460
451
  if (options.hasNotText !== undefined) return `locator(${this.quote(body)}, new ${clazz}.LocatorOptions().setHasNotText(${this.toHasText(options.hasNotText)}))`;
461
452
  return `locator(${this.quote(body)})`;
462
453
  case 'frame':
463
- return `frameLocator(${this.quote(body)})`;
454
+ return `contentFrame()`;
464
455
  case 'nth':
465
456
  return `nth(${body})`;
466
457
  case 'first':
@@ -544,7 +535,7 @@ class CSharpLocatorFactory {
544
535
  if (options.hasNotText !== undefined) return `Locator(${this.quote(body)}, new() { ${this.toHasNotText(options.hasNotText)} })`;
545
536
  return `Locator(${this.quote(body)})`;
546
537
  case 'frame':
547
- return `FrameLocator(${this.quote(body)})`;
538
+ return `ContentFrame`;
548
539
  case 'nth':
549
540
  return `Nth(${body})`;
550
541
  case 'first':
@@ -63,7 +63,7 @@ function parseLocator(locator, testIdAttributeName) {
63
63
  }
64
64
 
65
65
  // Equalize languages.
66
- template = template.toLowerCase().replace(/get_by_alt_text/g, 'getbyalttext').replace(/get_by_test_id/g, 'getbytestid').replace(/get_by_([\w]+)/g, 'getby$1').replace(/has_not_text/g, 'hasnottext').replace(/has_text/g, 'hastext').replace(/has_not/g, 'hasnot').replace(/frame_locator/g, 'framelocator').replace(/[{}\s]/g, '').replace(/new\(\)/g, '').replace(/new[\w]+\.[\w]+options\(\)/g, '').replace(/\.set/g, ',set').replace(/\.or_\(/g, 'or(') // Python has "or_" instead of "or".
66
+ template = template.toLowerCase().replace(/get_by_alt_text/g, 'getbyalttext').replace(/get_by_test_id/g, 'getbytestid').replace(/get_by_([\w]+)/g, 'getby$1').replace(/has_not_text/g, 'hasnottext').replace(/has_text/g, 'hastext').replace(/has_not/g, 'hasnot').replace(/frame_locator/g, 'framelocator').replace(/content_frame/g, 'contentframe').replace(/[{}\s]/g, '').replace(/new\(\)/g, '').replace(/new[\w]+\.[\w]+options\(\)/g, '').replace(/\.set/g, ',set').replace(/\.or_\(/g, 'or(') // Python has "or_" instead of "or".
67
67
  .replace(/\.and_\(/g, 'and(') // Python has "and_" instead of "and".
68
68
  .replace(/:/g, '=').replace(/,re\.ignorecase/g, 'i').replace(/,pattern.case_insensitive/g, 'i').replace(/,regexoptions.ignorecase/g, 'i').replace(/re.compile\(([^)]+)\)/g, '$1') // Python has regex strings as r"foo"
69
69
  .replace(/pattern.compile\(([^)]+)\)/g, 'r$1').replace(/newregex\(([^)]+)\)/g, 'r$1').replace(/string=/g, '=').replace(/regex=/g, '=').replace(/,,/g, ',');
@@ -123,7 +123,7 @@ function transform(template, params, testIdAttributeName) {
123
123
  }
124
124
 
125
125
  // Transform to selector engines.
126
- template = template.replace(/\,set([\w]+)\(([^)]+)\)/g, (_, group1, group2) => ',' + group1.toLowerCase() + '=' + group2.toLowerCase()).replace(/framelocator\(([^)]+)\)/g, '$1.internal:control=enter-frame').replace(/locator\(([^)]+),hastext=([^),]+)\)/g, 'locator($1).internal:has-text=$2').replace(/locator\(([^)]+),hasnottext=([^),]+)\)/g, 'locator($1).internal:has-not-text=$2').replace(/locator\(([^)]+),hastext=([^),]+)\)/g, 'locator($1).internal:has-text=$2').replace(/locator\(([^)]+)\)/g, '$1').replace(/getbyrole\(([^)]+)\)/g, 'internal:role=$1').replace(/getbytext\(([^)]+)\)/g, 'internal:text=$1').replace(/getbylabel\(([^)]+)\)/g, 'internal:label=$1').replace(/getbytestid\(([^)]+)\)/g, `internal:testid=[${testIdAttributeName}=$1]`).replace(/getby(placeholder|alt|title)(?:text)?\(([^)]+)\)/g, 'internal:attr=[$1=$2]').replace(/first(\(\))?/g, 'nth=0').replace(/last(\(\))?/g, 'nth=-1').replace(/nth\(([^)]+)\)/g, 'nth=$1').replace(/filter\(,?hastext=([^)]+)\)/g, 'internal:has-text=$1').replace(/filter\(,?hasnottext=([^)]+)\)/g, 'internal:has-not-text=$1').replace(/filter\(,?has2=([^)]+)\)/g, 'internal:has=$1').replace(/filter\(,?hasnot2=([^)]+)\)/g, 'internal:has-not=$1').replace(/,exact=false/g, '').replace(/,exact=true/g, 's').replace(/\,/g, '][');
126
+ template = template.replace(/\,set([\w]+)\(([^)]+)\)/g, (_, group1, group2) => ',' + group1.toLowerCase() + '=' + group2.toLowerCase()).replace(/framelocator\(([^)]+)\)/g, '$1.internal:control=enter-frame').replace(/contentframe(\(\))?/g, 'internal:control=enter-frame').replace(/locator\(([^)]+),hastext=([^),]+)\)/g, 'locator($1).internal:has-text=$2').replace(/locator\(([^)]+),hasnottext=([^),]+)\)/g, 'locator($1).internal:has-not-text=$2').replace(/locator\(([^)]+),hastext=([^),]+)\)/g, 'locator($1).internal:has-text=$2').replace(/locator\(([^)]+)\)/g, '$1').replace(/getbyrole\(([^)]+)\)/g, 'internal:role=$1').replace(/getbytext\(([^)]+)\)/g, 'internal:text=$1').replace(/getbylabel\(([^)]+)\)/g, 'internal:label=$1').replace(/getbytestid\(([^)]+)\)/g, `internal:testid=[${testIdAttributeName}=$1]`).replace(/getby(placeholder|alt|title)(?:text)?\(([^)]+)\)/g, 'internal:attr=[$1=$2]').replace(/first(\(\))?/g, 'nth=0').replace(/last(\(\))?/g, 'nth=-1').replace(/nth\(([^)]+)\)/g, 'nth=$1').replace(/filter\(,?hastext=([^)]+)\)/g, 'internal:has-text=$1').replace(/filter\(,?hasnottext=([^)]+)\)/g, 'internal:has-not-text=$1').replace(/filter\(,?has2=([^)]+)\)/g, 'internal:has=$1').replace(/filter\(,?hasnot2=([^)]+)\)/g, 'internal:has-not=$1').replace(/,exact=false/g, '').replace(/,exact=true/g, 's').replace(/\,/g, '][');
127
127
  const parts = template.split('.');
128
128
  // Turn "internal:control=enter-frame >> nth=0" into "nth=0 >> internal:control=enter-frame"
129
129
  // because these are swapped in locators vs selectors.