playwright-browserstack 1.62.0__py3-none-win32.whl
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.
- playwright/__init__.py +19 -0
- playwright/__main__.py +33 -0
- playwright/_impl/__init__.py +0 -0
- playwright/_impl/__pyinstaller/__init__.py +20 -0
- playwright/_impl/__pyinstaller/hook-playwright.async_api.py +17 -0
- playwright/_impl/__pyinstaller/hook-playwright.sync_api.py +17 -0
- playwright/_impl/_android.py +704 -0
- playwright/_impl/_api_structures.py +365 -0
- playwright/_impl/_artifact.py +87 -0
- playwright/_impl/_assertions.py +1124 -0
- playwright/_impl/_async_base.py +105 -0
- playwright/_impl/_browser.py +293 -0
- playwright/_impl/_browser_context.py +754 -0
- playwright/_impl/_browser_type.py +368 -0
- playwright/_impl/_cdp_session.py +46 -0
- playwright/_impl/_clock.py +104 -0
- playwright/_impl/_connection.py +764 -0
- playwright/_impl/_console_message.py +98 -0
- playwright/_impl/_credentials.py +57 -0
- playwright/_impl/_debugger.py +54 -0
- playwright/_impl/_dialog.py +63 -0
- playwright/_impl/_disposable.py +96 -0
- playwright/_impl/_download.py +64 -0
- playwright/_impl/_driver.py +41 -0
- playwright/_impl/_element_handle.py +480 -0
- playwright/_impl/_errors.py +64 -0
- playwright/_impl/_event_context_manager.py +33 -0
- playwright/_impl/_fetch.py +626 -0
- playwright/_impl/_file_chooser.py +57 -0
- playwright/_impl/_form_data.py +34 -0
- playwright/_impl/_frame.py +985 -0
- playwright/_impl/_glob.py +65 -0
- playwright/_impl/_greenlets.py +49 -0
- playwright/_impl/_har_router.py +122 -0
- playwright/_impl/_helper.py +601 -0
- playwright/_impl/_impl_to_api_mapping.py +158 -0
- playwright/_impl/_input.py +111 -0
- playwright/_impl/_js_handle.py +336 -0
- playwright/_impl/_json_pipe.py +97 -0
- playwright/_impl/_local_utils.py +95 -0
- playwright/_impl/_locator.py +1024 -0
- playwright/_impl/_map.py +31 -0
- playwright/_impl/_network.py +1017 -0
- playwright/_impl/_object_factory.py +116 -0
- playwright/_impl/_page.py +1637 -0
- playwright/_impl/_path_utils.py +27 -0
- playwright/_impl/_playwright.py +68 -0
- playwright/_impl/_screencast.py +177 -0
- playwright/_impl/_selectors.py +67 -0
- playwright/_impl/_set_input_files_helpers.py +158 -0
- playwright/_impl/_str_utils.py +76 -0
- playwright/_impl/_stream.py +46 -0
- playwright/_impl/_sync_base.py +151 -0
- playwright/_impl/_tracing.py +281 -0
- playwright/_impl/_transport.py +184 -0
- playwright/_impl/_video.py +56 -0
- playwright/_impl/_waiter.py +197 -0
- playwright/_impl/_web_error.py +48 -0
- playwright/_impl/_web_storage.py +58 -0
- playwright/_impl/_writable_stream.py +42 -0
- playwright/_repo_version.py +24 -0
- playwright/async_api/__init__.py +275 -0
- playwright/async_api/_android_generated.py +462 -0
- playwright/async_api/_context_manager.py +57 -0
- playwright/async_api/_generated.py +23875 -0
- playwright/driver/LICENSE +2946 -0
- playwright/driver/README.md +1 -0
- playwright/driver/node.exe +0 -0
- playwright/driver/package/LICENSE +202 -0
- playwright/driver/package/NOTICE +5 -0
- playwright/driver/package/README.md +3 -0
- playwright/driver/package/ThirdPartyNotices.txt +13 -0
- playwright/driver/package/bin/install_media_pack.ps1 +5 -0
- playwright/driver/package/bin/install_webkit_wsl.ps1 +33 -0
- playwright/driver/package/bin/reinstall_chrome_beta_linux.sh +42 -0
- playwright/driver/package/bin/reinstall_chrome_beta_mac.sh +13 -0
- playwright/driver/package/bin/reinstall_chrome_beta_win.ps1 +24 -0
- playwright/driver/package/bin/reinstall_chrome_stable_linux.sh +42 -0
- playwright/driver/package/bin/reinstall_chrome_stable_mac.sh +12 -0
- playwright/driver/package/bin/reinstall_chrome_stable_win.ps1 +24 -0
- playwright/driver/package/bin/reinstall_msedge_beta_linux.sh +48 -0
- playwright/driver/package/bin/reinstall_msedge_beta_mac.sh +11 -0
- playwright/driver/package/bin/reinstall_msedge_beta_win.ps1 +23 -0
- playwright/driver/package/bin/reinstall_msedge_dev_linux.sh +48 -0
- playwright/driver/package/bin/reinstall_msedge_dev_mac.sh +11 -0
- playwright/driver/package/bin/reinstall_msedge_dev_win.ps1 +23 -0
- playwright/driver/package/bin/reinstall_msedge_stable_linux.sh +48 -0
- playwright/driver/package/bin/reinstall_msedge_stable_mac.sh +11 -0
- playwright/driver/package/bin/reinstall_msedge_stable_win.ps1 +24 -0
- playwright/driver/package/browsers.json +75 -0
- playwright/driver/package/cli.js +21 -0
- playwright/driver/package/index.d.ts +17 -0
- playwright/driver/package/index.js +17 -0
- playwright/driver/package/index.mjs +28 -0
- playwright/driver/package/lib/bootstrap.js +88 -0
- playwright/driver/package/lib/coreBundle.js +74830 -0
- playwright/driver/package/lib/entry/cliDaemon.js +5 -0
- playwright/driver/package/lib/entry/dashboardApp.js +3 -0
- playwright/driver/package/lib/entry/mcp.js +10 -0
- playwright/driver/package/lib/entry/oopBrowserDownload.js +3 -0
- playwright/driver/package/lib/package.js +50 -0
- playwright/driver/package/lib/server/chromium/appIcon.png +0 -0
- playwright/driver/package/lib/server/electron/loader.js +118 -0
- playwright/driver/package/lib/serverRegistry.js +7347 -0
- playwright/driver/package/lib/serverRegistry.js.LICENSE +354 -0
- playwright/driver/package/lib/tools/cli-client/channelSessions.js +141 -0
- playwright/driver/package/lib/tools/cli-client/cli.js +6 -0
- playwright/driver/package/lib/tools/cli-client/help.json +708 -0
- playwright/driver/package/lib/tools/cli-client/minimist.js +128 -0
- playwright/driver/package/lib/tools/cli-client/output.js +343 -0
- playwright/driver/package/lib/tools/cli-client/program.js +404 -0
- playwright/driver/package/lib/tools/cli-client/registry.js +176 -0
- playwright/driver/package/lib/tools/cli-client/session.js +258 -0
- playwright/driver/package/lib/tools/dashboard/appIcon.png +0 -0
- playwright/driver/package/lib/tools/skills/playwright-cli/SKILL.md +420 -0
- playwright/driver/package/lib/tools/skills/playwright-cli/references/element-attributes.md +23 -0
- playwright/driver/package/lib/tools/skills/playwright-cli/references/playwright-tests.md +39 -0
- playwright/driver/package/lib/tools/skills/playwright-cli/references/request-mocking.md +87 -0
- playwright/driver/package/lib/tools/skills/playwright-cli/references/running-code.md +241 -0
- playwright/driver/package/lib/tools/skills/playwright-cli/references/session-management.md +225 -0
- playwright/driver/package/lib/tools/skills/playwright-cli/references/storage-state.md +275 -0
- playwright/driver/package/lib/tools/skills/playwright-cli/references/test-generation.md +433 -0
- playwright/driver/package/lib/tools/skills/playwright-cli/references/tracing.md +139 -0
- playwright/driver/package/lib/tools/skills/playwright-cli/references/video-recording.md +143 -0
- playwright/driver/package/lib/tools/skills/playwright-component-testing/SKILL.md +143 -0
- playwright/driver/package/lib/tools/skills/playwright-component-testing/references/gallery-spec.md +144 -0
- playwright/driver/package/lib/tools/skills/playwright-component-testing/references/migration.md +85 -0
- playwright/driver/package/lib/tools/skills/playwright-component-testing/references/react.md +67 -0
- playwright/driver/package/lib/tools/skills/playwright-component-testing/references/vue.md +75 -0
- playwright/driver/package/lib/tools/skills/playwright-trace/SKILL.md +171 -0
- playwright/driver/package/lib/tools/utils/extension.js +101 -0
- playwright/driver/package/lib/tools/utils/socketConnection.js +108 -0
- playwright/driver/package/lib/utilsBundle.js +90764 -0
- playwright/driver/package/lib/utilsBundle.js.LICENSE +2179 -0
- playwright/driver/package/lib/vite/dashboard/assets/codicon-DCmgc-ay.ttf +0 -0
- playwright/driver/package/lib/vite/dashboard/assets/firefox-1bWoP6pv.svg +1 -0
- playwright/driver/package/lib/vite/dashboard/assets/firefox-beta-k3eOH_eK.svg +1 -0
- playwright/driver/package/lib/vite/dashboard/assets/firefox-nightly-Cp5nfeDT.svg +1 -0
- playwright/driver/package/lib/vite/dashboard/assets/index-CyWAfh-p.js +11 -0
- playwright/driver/package/lib/vite/dashboard/assets/index-DhC616m4.css +1 -0
- playwright/driver/package/lib/vite/dashboard/assets/safari-na3_-uQk.svg +1 -0
- playwright/driver/package/lib/vite/dashboard/index.html +29 -0
- playwright/driver/package/lib/vite/dashboard/playwright-logo.svg +24 -0
- playwright/driver/package/lib/vite/htmlReport/index.html +16 -0
- playwright/driver/package/lib/vite/htmlReport/report.css +2 -0
- playwright/driver/package/lib/vite/htmlReport/report.js +32 -0
- playwright/driver/package/lib/vite/recorder/assets/codeMirrorModule--QdMvsKi.css +1 -0
- playwright/driver/package/lib/vite/recorder/assets/codeMirrorModule-CwYYHbcZ.js +32 -0
- playwright/driver/package/lib/vite/recorder/assets/codicon-DCmgc-ay.ttf +0 -0
- playwright/driver/package/lib/vite/recorder/assets/index-DYjdXIbE.js +129 -0
- playwright/driver/package/lib/vite/recorder/assets/index-l_lX622x.css +1 -0
- playwright/driver/package/lib/vite/recorder/index.html +29 -0
- playwright/driver/package/lib/vite/recorder/playwright-logo.svg +9 -0
- playwright/driver/package/lib/vite/traceViewer/assets/codeMirrorModule-By56iMx7.js +32 -0
- playwright/driver/package/lib/vite/traceViewer/assets/defaultSettingsView-B34OrIms.js +181 -0
- playwright/driver/package/lib/vite/traceViewer/assets/urlMatch-L3liM589.js +1 -0
- playwright/driver/package/lib/vite/traceViewer/assets/xtermModule-COQkjINf.js +7 -0
- playwright/driver/package/lib/vite/traceViewer/codeMirrorModule.-QdMvsKi.css +1 -0
- playwright/driver/package/lib/vite/traceViewer/codicon.DCmgc-ay.ttf +0 -0
- playwright/driver/package/lib/vite/traceViewer/defaultSettingsView.BLFoOugd.css +1 -0
- playwright/driver/package/lib/vite/traceViewer/index.B_TqY17P.css +1 -0
- playwright/driver/package/lib/vite/traceViewer/index.Dl36UVQT.js +1 -0
- playwright/driver/package/lib/vite/traceViewer/index.html +44 -0
- playwright/driver/package/lib/vite/traceViewer/manifest.webmanifest +16 -0
- playwright/driver/package/lib/vite/traceViewer/playwright-logo.svg +9 -0
- playwright/driver/package/lib/vite/traceViewer/snapshot.B_Jk1wbt.js +1 -0
- playwright/driver/package/lib/vite/traceViewer/snapshot.html +10 -0
- playwright/driver/package/lib/vite/traceViewer/sw.bundle.js +4 -0
- playwright/driver/package/lib/vite/traceViewer/uiMode.C7UW1sC9.css +1 -0
- playwright/driver/package/lib/vite/traceViewer/uiMode.D962mr9b.js +5 -0
- playwright/driver/package/lib/vite/traceViewer/uiMode.html +18 -0
- playwright/driver/package/lib/vite/traceViewer/xtermModule.kHJ-D0s7.css +1 -0
- playwright/driver/package/lib/webp_codec.LICENSE +173 -0
- playwright/driver/package/lib/webp_codec.wasm +0 -0
- playwright/driver/package/lib/xdg-open +1267 -0
- playwright/driver/package/package.json +34 -0
- playwright/driver/package/types/protocol.d.ts +24842 -0
- playwright/driver/package/types/structs.d.ts +47 -0
- playwright/driver/package/types/types.d.ts +26188 -0
- playwright/py.typed +0 -0
- playwright/sync_api/__init__.py +275 -0
- playwright/sync_api/_android_generated.py +494 -0
- playwright/sync_api/_context_manager.py +98 -0
- playwright/sync_api/_generated.py +24045 -0
- playwright_browserstack-1.62.0.dist-info/METADATA +82 -0
- playwright_browserstack-1.62.0.dist-info/RECORD +192 -0
- playwright_browserstack-1.62.0.dist-info/WHEEL +5 -0
- playwright_browserstack-1.62.0.dist-info/entry_points.txt +5 -0
- playwright_browserstack-1.62.0.dist-info/licenses/LICENSE +202 -0
- playwright_browserstack-1.62.0.dist-info/licenses/LICENSE.txt +51 -0
- playwright_browserstack-1.62.0.dist-info/licenses/NOTICE +18 -0
- playwright_browserstack-1.62.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,368 @@
|
|
|
1
|
+
# Copyright (c) Microsoft Corporation.
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
|
|
15
|
+
import asyncio
|
|
16
|
+
import json
|
|
17
|
+
import pathlib
|
|
18
|
+
from pathlib import Path
|
|
19
|
+
from typing import TYPE_CHECKING, Dict, List, Optional, Pattern, Sequence, Union, cast
|
|
20
|
+
|
|
21
|
+
from playwright._impl._api_structures import (
|
|
22
|
+
ClientCertificate,
|
|
23
|
+
Geolocation,
|
|
24
|
+
HttpCredentials,
|
|
25
|
+
ProxySettings,
|
|
26
|
+
ViewportSize,
|
|
27
|
+
)
|
|
28
|
+
from playwright._impl._browser import Browser
|
|
29
|
+
from playwright._impl._browser_context import BrowserContext
|
|
30
|
+
from playwright._impl._connection import ChannelOwner, Connection, from_channel
|
|
31
|
+
from playwright._impl._errors import Error
|
|
32
|
+
from playwright._impl._helper import (
|
|
33
|
+
PLAYWRIGHT_MAX_DEADLINE,
|
|
34
|
+
ColorScheme,
|
|
35
|
+
Contrast,
|
|
36
|
+
Env,
|
|
37
|
+
ForcedColors,
|
|
38
|
+
HarContentPolicy,
|
|
39
|
+
HarMode,
|
|
40
|
+
ReducedMotion,
|
|
41
|
+
ServiceWorkersPolicy,
|
|
42
|
+
TimeoutSettings,
|
|
43
|
+
async_readfile,
|
|
44
|
+
locals_to_params,
|
|
45
|
+
)
|
|
46
|
+
from playwright._impl._json_pipe import JsonPipeTransport
|
|
47
|
+
from playwright._impl._network import serialize_headers, to_client_certificates_protocol
|
|
48
|
+
from playwright._impl._waiter import throw_on_timeout
|
|
49
|
+
|
|
50
|
+
if TYPE_CHECKING:
|
|
51
|
+
from playwright._impl._playwright import Playwright
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
class BrowserType(ChannelOwner):
|
|
55
|
+
def __init__(
|
|
56
|
+
self, parent: ChannelOwner, type: str, guid: str, initializer: Dict
|
|
57
|
+
) -> None:
|
|
58
|
+
super().__init__(parent, type, guid, initializer)
|
|
59
|
+
self._playwright: "Playwright"
|
|
60
|
+
|
|
61
|
+
def __repr__(self) -> str:
|
|
62
|
+
return f"<BrowserType name={self.name} executable_path={self.executable_path}>"
|
|
63
|
+
|
|
64
|
+
@property
|
|
65
|
+
def name(self) -> str:
|
|
66
|
+
return self._initializer["name"]
|
|
67
|
+
|
|
68
|
+
@property
|
|
69
|
+
def executable_path(self) -> str:
|
|
70
|
+
return self._initializer["executablePath"]
|
|
71
|
+
|
|
72
|
+
async def launch(
|
|
73
|
+
self,
|
|
74
|
+
executablePath: Union[str, Path] = None,
|
|
75
|
+
channel: str = None,
|
|
76
|
+
args: Sequence[str] = None,
|
|
77
|
+
ignoreDefaultArgs: Union[bool, Sequence[str]] = None,
|
|
78
|
+
handleSIGINT: bool = None,
|
|
79
|
+
handleSIGTERM: bool = None,
|
|
80
|
+
handleSIGHUP: bool = None,
|
|
81
|
+
timeout: float = None,
|
|
82
|
+
env: Env = None,
|
|
83
|
+
headless: bool = None,
|
|
84
|
+
proxy: ProxySettings = None,
|
|
85
|
+
downloadsPath: Union[str, Path] = None,
|
|
86
|
+
slowMo: float = None,
|
|
87
|
+
tracesDir: Union[pathlib.Path, str] = None,
|
|
88
|
+
artifactsDir: Union[pathlib.Path, str] = None,
|
|
89
|
+
chromiumSandbox: bool = None,
|
|
90
|
+
firefoxUserPrefs: Dict[str, Union[str, float, bool]] = None,
|
|
91
|
+
) -> Browser:
|
|
92
|
+
params = locals_to_params(locals())
|
|
93
|
+
normalize_launch_params(params)
|
|
94
|
+
browser = cast(
|
|
95
|
+
Browser,
|
|
96
|
+
from_channel(
|
|
97
|
+
await self._channel.send(
|
|
98
|
+
"launch", TimeoutSettings.launch_timeout, params
|
|
99
|
+
)
|
|
100
|
+
),
|
|
101
|
+
)
|
|
102
|
+
browser._connect_to_browser_type(
|
|
103
|
+
self, str(tracesDir) if tracesDir is not None else None
|
|
104
|
+
)
|
|
105
|
+
return browser
|
|
106
|
+
|
|
107
|
+
async def launch_persistent_context(
|
|
108
|
+
self,
|
|
109
|
+
userDataDir: Union[str, Path],
|
|
110
|
+
channel: str = None,
|
|
111
|
+
executablePath: Union[str, Path] = None,
|
|
112
|
+
args: Sequence[str] = None,
|
|
113
|
+
ignoreDefaultArgs: Union[bool, Sequence[str]] = None,
|
|
114
|
+
handleSIGINT: bool = None,
|
|
115
|
+
handleSIGTERM: bool = None,
|
|
116
|
+
handleSIGHUP: bool = None,
|
|
117
|
+
timeout: float = None,
|
|
118
|
+
env: Env = None,
|
|
119
|
+
headless: bool = None,
|
|
120
|
+
proxy: ProxySettings = None,
|
|
121
|
+
downloadsPath: Union[str, Path] = None,
|
|
122
|
+
slowMo: float = None,
|
|
123
|
+
viewport: ViewportSize = None,
|
|
124
|
+
screen: ViewportSize = None,
|
|
125
|
+
noViewport: bool = None,
|
|
126
|
+
ignoreHTTPSErrors: bool = None,
|
|
127
|
+
javaScriptEnabled: bool = None,
|
|
128
|
+
bypassCSP: bool = None,
|
|
129
|
+
userAgent: str = None,
|
|
130
|
+
locale: str = None,
|
|
131
|
+
timezoneId: str = None,
|
|
132
|
+
geolocation: Geolocation = None,
|
|
133
|
+
permissions: Sequence[str] = None,
|
|
134
|
+
extraHTTPHeaders: Dict[str, str] = None,
|
|
135
|
+
offline: bool = None,
|
|
136
|
+
httpCredentials: HttpCredentials = None,
|
|
137
|
+
deviceScaleFactor: float = None,
|
|
138
|
+
isMobile: bool = None,
|
|
139
|
+
hasTouch: bool = None,
|
|
140
|
+
colorScheme: ColorScheme = None,
|
|
141
|
+
reducedMotion: ReducedMotion = None,
|
|
142
|
+
forcedColors: ForcedColors = None,
|
|
143
|
+
contrast: Contrast = None,
|
|
144
|
+
acceptDownloads: bool = None,
|
|
145
|
+
tracesDir: Union[pathlib.Path, str] = None,
|
|
146
|
+
artifactsDir: Union[pathlib.Path, str] = None,
|
|
147
|
+
chromiumSandbox: bool = None,
|
|
148
|
+
firefoxUserPrefs: Dict[str, Union[str, float, bool]] = None,
|
|
149
|
+
recordHarPath: Union[Path, str] = None,
|
|
150
|
+
recordHarOmitContent: bool = None,
|
|
151
|
+
recordVideoDir: Union[Path, str] = None,
|
|
152
|
+
recordVideoSize: ViewportSize = None,
|
|
153
|
+
baseURL: str = None,
|
|
154
|
+
strictSelectors: bool = None,
|
|
155
|
+
serviceWorkers: ServiceWorkersPolicy = None,
|
|
156
|
+
recordHarUrlFilter: Union[Pattern[str], str] = None,
|
|
157
|
+
recordHarMode: HarMode = None,
|
|
158
|
+
recordHarContent: HarContentPolicy = None,
|
|
159
|
+
clientCertificates: List[ClientCertificate] = None,
|
|
160
|
+
) -> BrowserContext:
|
|
161
|
+
userDataDir = self._user_data_dir(userDataDir)
|
|
162
|
+
params = locals_to_params(locals())
|
|
163
|
+
await self._prepare_browser_context_params(params)
|
|
164
|
+
normalize_launch_params(params)
|
|
165
|
+
result = await self._channel.send_return_as_dict(
|
|
166
|
+
"launchPersistentContext", TimeoutSettings.launch_timeout, params
|
|
167
|
+
)
|
|
168
|
+
browser = cast(
|
|
169
|
+
Browser,
|
|
170
|
+
from_channel(result["browser"]),
|
|
171
|
+
)
|
|
172
|
+
browser._connect_to_browser_type(
|
|
173
|
+
self, str(tracesDir) if tracesDir is not None else None
|
|
174
|
+
)
|
|
175
|
+
context = cast(BrowserContext, from_channel(result["context"]))
|
|
176
|
+
await context._initialize_har_from_options(
|
|
177
|
+
record_har_content=recordHarContent,
|
|
178
|
+
record_har_mode=recordHarMode,
|
|
179
|
+
record_har_omit_content=recordHarOmitContent,
|
|
180
|
+
record_har_path=recordHarPath,
|
|
181
|
+
record_har_url_filter=recordHarUrlFilter,
|
|
182
|
+
)
|
|
183
|
+
return context
|
|
184
|
+
|
|
185
|
+
def _user_data_dir(self, userDataDir: Optional[Union[str, Path]]) -> str:
|
|
186
|
+
if not userDataDir:
|
|
187
|
+
return ""
|
|
188
|
+
if not Path(userDataDir).is_absolute():
|
|
189
|
+
return str(Path(userDataDir).resolve())
|
|
190
|
+
return str(Path(userDataDir))
|
|
191
|
+
|
|
192
|
+
async def connect_over_cdp(
|
|
193
|
+
self,
|
|
194
|
+
endpointURL: str,
|
|
195
|
+
timeout: float = None,
|
|
196
|
+
slowMo: float = None,
|
|
197
|
+
headers: Dict[str, str] = None,
|
|
198
|
+
isLocal: bool = None,
|
|
199
|
+
noDefaults: bool = None,
|
|
200
|
+
artifactsDir: Union[str, Path] = None,
|
|
201
|
+
) -> Browser:
|
|
202
|
+
params = locals_to_params(locals())
|
|
203
|
+
if params.get("headers"):
|
|
204
|
+
params["headers"] = serialize_headers(params["headers"])
|
|
205
|
+
response = await self._channel.send_return_as_dict(
|
|
206
|
+
"connectOverCDP", TimeoutSettings.launch_timeout, params
|
|
207
|
+
)
|
|
208
|
+
browser = cast(Browser, from_channel(response["browser"]))
|
|
209
|
+
browser._connect_to_browser_type(self, None)
|
|
210
|
+
|
|
211
|
+
return browser
|
|
212
|
+
|
|
213
|
+
async def connect(
|
|
214
|
+
self,
|
|
215
|
+
endpoint: str,
|
|
216
|
+
timeout: float = None,
|
|
217
|
+
slowMo: float = None,
|
|
218
|
+
headers: Dict[str, str] = None,
|
|
219
|
+
exposeNetwork: str = None,
|
|
220
|
+
) -> Browser:
|
|
221
|
+
if slowMo is None:
|
|
222
|
+
slowMo = 0
|
|
223
|
+
if timeout is None:
|
|
224
|
+
timeout = 0
|
|
225
|
+
|
|
226
|
+
headers = {**(headers if headers else {}), "x-playwright-browser": self.name}
|
|
227
|
+
local_utils = self._connection.local_utils
|
|
228
|
+
pipe_channel = (
|
|
229
|
+
await local_utils._channel.send_return_as_dict(
|
|
230
|
+
"connect",
|
|
231
|
+
lambda t: t or 0,
|
|
232
|
+
{
|
|
233
|
+
"endpoint": endpoint,
|
|
234
|
+
"headers": headers,
|
|
235
|
+
"slowMo": slowMo,
|
|
236
|
+
"timeout": timeout,
|
|
237
|
+
"exposeNetwork": exposeNetwork,
|
|
238
|
+
},
|
|
239
|
+
)
|
|
240
|
+
)["pipe"]
|
|
241
|
+
transport = JsonPipeTransport(self._connection._loop, pipe_channel)
|
|
242
|
+
|
|
243
|
+
connection = Connection(
|
|
244
|
+
self._connection._dispatcher_fiber,
|
|
245
|
+
self._connection._object_factory,
|
|
246
|
+
transport,
|
|
247
|
+
self._connection._loop,
|
|
248
|
+
local_utils=self._connection.local_utils,
|
|
249
|
+
)
|
|
250
|
+
connection.mark_as_remote()
|
|
251
|
+
|
|
252
|
+
browser = None
|
|
253
|
+
|
|
254
|
+
def handle_transport_close(reason: Optional[str]) -> None:
|
|
255
|
+
if browser:
|
|
256
|
+
for context in browser.contexts:
|
|
257
|
+
for page in context.pages:
|
|
258
|
+
page._on_close()
|
|
259
|
+
context._on_close()
|
|
260
|
+
connection.cleanup(reason)
|
|
261
|
+
# Give a chance to any API call promises to reject upon page/context closure.
|
|
262
|
+
# This happens naturally when we receive page.onClose and browser.onClose from the server
|
|
263
|
+
# in separate tasks. However, upon pipe closure we used to dispatch them all synchronously
|
|
264
|
+
# here and promises did not have a chance to reject.
|
|
265
|
+
# The order of rejects vs closure is a part of the API contract and our test runner
|
|
266
|
+
# relies on it to attribute rejections to the right test.
|
|
267
|
+
if browser:
|
|
268
|
+
connection._loop.call_soon(browser._on_close)
|
|
269
|
+
|
|
270
|
+
transport.once("close", handle_transport_close)
|
|
271
|
+
|
|
272
|
+
connection._is_sync = self._connection._is_sync
|
|
273
|
+
connection._loop.create_task(connection.run())
|
|
274
|
+
playwright_future = connection.playwright_future
|
|
275
|
+
|
|
276
|
+
timeout_future = throw_on_timeout(
|
|
277
|
+
timeout if timeout else PLAYWRIGHT_MAX_DEADLINE,
|
|
278
|
+
Error("Connection timed out"),
|
|
279
|
+
)
|
|
280
|
+
done, pending = await asyncio.wait(
|
|
281
|
+
{transport.on_error_future, playwright_future, timeout_future},
|
|
282
|
+
return_when=asyncio.FIRST_COMPLETED,
|
|
283
|
+
)
|
|
284
|
+
if not playwright_future.done():
|
|
285
|
+
playwright_future.cancel()
|
|
286
|
+
if not timeout_future.done():
|
|
287
|
+
timeout_future.cancel()
|
|
288
|
+
playwright: "Playwright" = next(iter(done)).result()
|
|
289
|
+
playwright._set_selectors(self._playwright.selectors)
|
|
290
|
+
self._connection._child_ws_connections.append(connection)
|
|
291
|
+
pre_launched_browser = playwright._initializer.get("preLaunchedBrowser")
|
|
292
|
+
assert pre_launched_browser
|
|
293
|
+
browser = cast(Browser, from_channel(pre_launched_browser))
|
|
294
|
+
browser._should_close_connection_on_close = True
|
|
295
|
+
browser._connect_to_browser_type(self, None)
|
|
296
|
+
|
|
297
|
+
return browser
|
|
298
|
+
|
|
299
|
+
async def _prepare_browser_context_params(self, params: Dict) -> None:
|
|
300
|
+
if params.get("noViewport"):
|
|
301
|
+
del params["noViewport"]
|
|
302
|
+
params["noDefaultViewport"] = True
|
|
303
|
+
if "defaultBrowserType" in params:
|
|
304
|
+
del params["defaultBrowserType"]
|
|
305
|
+
if "extraHTTPHeaders" in params:
|
|
306
|
+
params["extraHTTPHeaders"] = serialize_headers(params["extraHTTPHeaders"])
|
|
307
|
+
if "recordVideoDir" in params:
|
|
308
|
+
params["recordVideo"] = {"dir": Path(params["recordVideoDir"]).absolute()}
|
|
309
|
+
if "recordVideoSize" in params:
|
|
310
|
+
params["recordVideo"]["size"] = params["recordVideoSize"]
|
|
311
|
+
del params["recordVideoSize"]
|
|
312
|
+
del params["recordVideoDir"]
|
|
313
|
+
if "storageState" in params:
|
|
314
|
+
storageState = params["storageState"]
|
|
315
|
+
if not isinstance(storageState, dict):
|
|
316
|
+
params["storageState"] = json.loads(
|
|
317
|
+
(await async_readfile(storageState)).decode()
|
|
318
|
+
)
|
|
319
|
+
if params.get("colorScheme", None) == "null":
|
|
320
|
+
params["colorScheme"] = "no-override"
|
|
321
|
+
if params.get("reducedMotion", None) == "null":
|
|
322
|
+
params["reducedMotion"] = "no-override"
|
|
323
|
+
if params.get("forcedColors", None) == "null":
|
|
324
|
+
params["forcedColors"] = "no-override"
|
|
325
|
+
if params.get("contrast", None) == "null":
|
|
326
|
+
params["contrast"] = "no-override"
|
|
327
|
+
if "acceptDownloads" in params:
|
|
328
|
+
params["acceptDownloads"] = (
|
|
329
|
+
"accept" if params["acceptDownloads"] else "deny"
|
|
330
|
+
)
|
|
331
|
+
|
|
332
|
+
if "clientCertificates" in params:
|
|
333
|
+
params["clientCertificates"] = await to_client_certificates_protocol(
|
|
334
|
+
params["clientCertificates"]
|
|
335
|
+
)
|
|
336
|
+
params["selectorEngines"] = self._playwright.selectors._selector_engines
|
|
337
|
+
params["testIdAttributeName"] = (
|
|
338
|
+
self._playwright.selectors._test_id_attribute_name
|
|
339
|
+
)
|
|
340
|
+
|
|
341
|
+
# Remove HAR options
|
|
342
|
+
params.pop("recordHarPath", None)
|
|
343
|
+
params.pop("recordHarOmitContent", None)
|
|
344
|
+
params.pop("recordHarUrlFilter", None)
|
|
345
|
+
params.pop("recordHarMode", None)
|
|
346
|
+
params.pop("recordHarContent", None)
|
|
347
|
+
|
|
348
|
+
|
|
349
|
+
def normalize_launch_params(params: Dict) -> None:
|
|
350
|
+
if "env" in params:
|
|
351
|
+
params["env"] = [
|
|
352
|
+
{"name": name, "value": str(value)}
|
|
353
|
+
for [name, value] in params["env"].items()
|
|
354
|
+
]
|
|
355
|
+
if "ignoreDefaultArgs" in params:
|
|
356
|
+
if params["ignoreDefaultArgs"] is True:
|
|
357
|
+
params["ignoreAllDefaultArgs"] = True
|
|
358
|
+
del params["ignoreDefaultArgs"]
|
|
359
|
+
elif params["ignoreDefaultArgs"] is False:
|
|
360
|
+
del params["ignoreDefaultArgs"]
|
|
361
|
+
if "executablePath" in params:
|
|
362
|
+
params["executablePath"] = str(Path(params["executablePath"]))
|
|
363
|
+
if "downloadsPath" in params:
|
|
364
|
+
params["downloadsPath"] = str(Path(params["downloadsPath"]))
|
|
365
|
+
if "tracesDir" in params:
|
|
366
|
+
params["tracesDir"] = str(Path(params["tracesDir"]))
|
|
367
|
+
if "artifactsDir" in params:
|
|
368
|
+
params["artifactsDir"] = str(Path(params["artifactsDir"]))
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# Copyright (c) Microsoft Corporation.
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
|
|
15
|
+
from types import SimpleNamespace
|
|
16
|
+
from typing import Any, Dict
|
|
17
|
+
|
|
18
|
+
from playwright._impl._connection import ChannelOwner
|
|
19
|
+
from playwright._impl._helper import locals_to_params
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class CDPSession(ChannelOwner):
|
|
23
|
+
Events = SimpleNamespace(
|
|
24
|
+
Event="event",
|
|
25
|
+
Close="close",
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
def __init__(
|
|
29
|
+
self, parent: ChannelOwner, type: str, guid: str, initializer: Dict
|
|
30
|
+
) -> None:
|
|
31
|
+
super().__init__(parent, type, guid, initializer)
|
|
32
|
+
self._channel.on("event", lambda params: self._on_event(params))
|
|
33
|
+
self._channel.on("close", lambda _: self.emit(CDPSession.Events.Close, self))
|
|
34
|
+
|
|
35
|
+
def _on_event(self, params: Any) -> None:
|
|
36
|
+
self.emit(params["method"], params.get("params"))
|
|
37
|
+
self.emit(CDPSession.Events.Event, params)
|
|
38
|
+
|
|
39
|
+
async def send(self, method: str, params: Dict = None) -> Dict:
|
|
40
|
+
return await self._channel.send("send", None, locals_to_params(locals()))
|
|
41
|
+
|
|
42
|
+
async def detach(self) -> None:
|
|
43
|
+
await self._channel.send(
|
|
44
|
+
"detach",
|
|
45
|
+
None,
|
|
46
|
+
)
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
# Copyright (c) Microsoft Corporation.
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
|
|
15
|
+
import datetime
|
|
16
|
+
from typing import TYPE_CHECKING, Dict, Union
|
|
17
|
+
|
|
18
|
+
if TYPE_CHECKING:
|
|
19
|
+
from playwright._impl._browser_context import BrowserContext
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class Clock:
|
|
23
|
+
def __init__(self, browser_context: "BrowserContext") -> None:
|
|
24
|
+
self._browser_context = browser_context
|
|
25
|
+
self._loop = browser_context._loop
|
|
26
|
+
self._dispatcher_fiber = browser_context._dispatcher_fiber
|
|
27
|
+
|
|
28
|
+
async def install(self, time: Union[float, str, datetime.datetime] = None) -> None:
|
|
29
|
+
await self._browser_context._channel.send(
|
|
30
|
+
"clockInstall",
|
|
31
|
+
None,
|
|
32
|
+
parse_time(time) if time is not None else {},
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
async def fast_forward(
|
|
36
|
+
self,
|
|
37
|
+
ticks: Union[int, str],
|
|
38
|
+
) -> None:
|
|
39
|
+
await self._browser_context._channel.send(
|
|
40
|
+
"clockFastForward",
|
|
41
|
+
None,
|
|
42
|
+
parse_ticks(ticks),
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
async def pause_at(
|
|
46
|
+
self,
|
|
47
|
+
time: Union[float, str, datetime.datetime],
|
|
48
|
+
) -> None:
|
|
49
|
+
await self._browser_context._channel.send(
|
|
50
|
+
"clockPauseAt",
|
|
51
|
+
None,
|
|
52
|
+
parse_time(time),
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
async def resume(
|
|
56
|
+
self,
|
|
57
|
+
) -> None:
|
|
58
|
+
await self._browser_context._channel.send("clockResume", None)
|
|
59
|
+
|
|
60
|
+
async def run_for(
|
|
61
|
+
self,
|
|
62
|
+
ticks: Union[int, str],
|
|
63
|
+
) -> None:
|
|
64
|
+
await self._browser_context._channel.send(
|
|
65
|
+
"clockRunFor",
|
|
66
|
+
None,
|
|
67
|
+
parse_ticks(ticks),
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
async def set_fixed_time(
|
|
71
|
+
self,
|
|
72
|
+
time: Union[float, str, datetime.datetime],
|
|
73
|
+
) -> None:
|
|
74
|
+
await self._browser_context._channel.send(
|
|
75
|
+
"clockSetFixedTime",
|
|
76
|
+
None,
|
|
77
|
+
parse_time(time),
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
async def set_system_time(
|
|
81
|
+
self,
|
|
82
|
+
time: Union[float, str, datetime.datetime],
|
|
83
|
+
) -> None:
|
|
84
|
+
await self._browser_context._channel.send(
|
|
85
|
+
"clockSetSystemTime",
|
|
86
|
+
None,
|
|
87
|
+
parse_time(time),
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def parse_time(
|
|
92
|
+
time: Union[float, str, datetime.datetime],
|
|
93
|
+
) -> Dict[str, Union[int, str]]:
|
|
94
|
+
if isinstance(time, (float, int)):
|
|
95
|
+
return {"timeNumber": int(time * 1_000)}
|
|
96
|
+
if isinstance(time, str):
|
|
97
|
+
return {"timeString": time}
|
|
98
|
+
return {"timeNumber": int(time.timestamp() * 1_000)}
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
def parse_ticks(ticks: Union[int, str]) -> Dict[str, Union[int, str]]:
|
|
102
|
+
if isinstance(ticks, int):
|
|
103
|
+
return {"ticksNumber": ticks}
|
|
104
|
+
return {"ticksString": ticks}
|