_frame.py 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915
  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. import asyncio
  15. from pathlib import Path
  16. from typing import (
  17. TYPE_CHECKING,
  18. Any,
  19. Dict,
  20. List,
  21. Literal,
  22. Optional,
  23. Pattern,
  24. Sequence,
  25. Set,
  26. Union,
  27. cast,
  28. )
  29. from pyee import EventEmitter
  30. from playwright._impl._api_structures import (
  31. AriaRole,
  32. FilePayload,
  33. FrameExpectOptions,
  34. FrameExpectResult,
  35. Position,
  36. )
  37. from playwright._impl._connection import (
  38. ChannelOwner,
  39. from_channel,
  40. from_nullable_channel,
  41. )
  42. from playwright._impl._element_handle import ElementHandle, convert_select_option_values
  43. from playwright._impl._errors import Error
  44. from playwright._impl._event_context_manager import EventContextManagerImpl
  45. from playwright._impl._helper import (
  46. DocumentLoadState,
  47. FrameNavigatedEvent,
  48. KeyboardModifier,
  49. MouseButton,
  50. TimeoutSettings,
  51. URLMatch,
  52. async_readfile,
  53. locals_to_params,
  54. monotonic_time,
  55. url_matches,
  56. )
  57. from playwright._impl._js_handle import (
  58. JSHandle,
  59. Serializable,
  60. add_source_url_to_script,
  61. parse_result,
  62. parse_value,
  63. serialize_argument,
  64. )
  65. from playwright._impl._locator import (
  66. FrameLocator,
  67. Locator,
  68. get_by_alt_text_selector,
  69. get_by_label_selector,
  70. get_by_placeholder_selector,
  71. get_by_role_selector,
  72. get_by_test_id_selector,
  73. get_by_text_selector,
  74. get_by_title_selector,
  75. test_id_attribute_name,
  76. )
  77. from playwright._impl._network import Response
  78. from playwright._impl._set_input_files_helpers import convert_input_files
  79. from playwright._impl._waiter import Waiter
  80. if TYPE_CHECKING: # pragma: no cover
  81. from playwright._impl._page import Page
  82. class Frame(ChannelOwner):
  83. def __init__(
  84. self, parent: ChannelOwner, type: str, guid: str, initializer: Dict
  85. ) -> None:
  86. super().__init__(parent, type, guid, initializer)
  87. self._parent_frame = from_nullable_channel(initializer.get("parentFrame"))
  88. if self._parent_frame:
  89. self._parent_frame._child_frames.append(self)
  90. self._name = initializer["name"]
  91. self._url = initializer["url"]
  92. self._detached = False
  93. self._child_frames: List[Frame] = []
  94. self._page: Optional[Page] = None
  95. self._load_states: Set[str] = set(initializer["loadStates"])
  96. self._event_emitter = EventEmitter()
  97. self._channel.on(
  98. "loadstate",
  99. lambda params: self._on_load_state(params.get("add"), params.get("remove")),
  100. )
  101. self._channel.on(
  102. "navigated",
  103. lambda params: self._on_frame_navigated(params),
  104. )
  105. def __repr__(self) -> str:
  106. return f"<Frame name={self.name} url={self.url!r}>"
  107. def _on_load_state(
  108. self, add: DocumentLoadState = None, remove: DocumentLoadState = None
  109. ) -> None:
  110. if add:
  111. self._load_states.add(add)
  112. self._event_emitter.emit("loadstate", add)
  113. elif remove and remove in self._load_states:
  114. self._load_states.remove(remove)
  115. if not self._parent_frame and add == "load" and self._page:
  116. self._page.emit("load", self._page)
  117. if not self._parent_frame and add == "domcontentloaded" and self._page:
  118. self._page.emit("domcontentloaded", self._page)
  119. def _on_frame_navigated(self, event: FrameNavigatedEvent) -> None:
  120. self._url = event["url"]
  121. self._name = event["name"]
  122. self._event_emitter.emit("navigated", event)
  123. if "error" not in event and self._page:
  124. self._page.emit("framenavigated", self)
  125. async def _query_count(self, selector: str) -> int:
  126. return await self._channel.send("queryCount", None, {"selector": selector})
  127. @property
  128. def page(self) -> "Page":
  129. assert self._page
  130. return self._page
  131. async def goto(
  132. self,
  133. url: str,
  134. timeout: float = None,
  135. waitUntil: DocumentLoadState = None,
  136. referer: str = None,
  137. ) -> Optional[Response]:
  138. return cast(
  139. Optional[Response],
  140. from_nullable_channel(
  141. await self._channel.send(
  142. "goto", self._navigation_timeout, locals_to_params(locals())
  143. )
  144. ),
  145. )
  146. def _setup_navigation_waiter(self, wait_name: str, timeout: float = None) -> Waiter:
  147. assert self._page
  148. waiter = Waiter(self._page, f"frame.{wait_name}")
  149. waiter.reject_on_event(
  150. self._page,
  151. "close",
  152. lambda: cast("Page", self._page)._close_error_with_reason(),
  153. )
  154. waiter.reject_on_event(
  155. self._page, "crash", Error("Navigation failed because page crashed!")
  156. )
  157. waiter.reject_on_event(
  158. self._page,
  159. "framedetached",
  160. Error("Navigating frame was detached!"),
  161. lambda frame: frame == self,
  162. )
  163. timeout = self._page._timeout_settings.navigation_timeout(timeout)
  164. waiter.reject_on_timeout(timeout, f"Timeout {timeout}ms exceeded.")
  165. return waiter
  166. async def _expect(
  167. self,
  168. selector: Optional[str],
  169. expression: str,
  170. options: FrameExpectOptions,
  171. title: str = None,
  172. ) -> FrameExpectResult:
  173. if "expectedValue" in options:
  174. options["expectedValue"] = serialize_argument(options["expectedValue"])
  175. result = await self._channel.send_return_as_dict(
  176. "expect",
  177. self._timeout,
  178. {
  179. "selector": selector,
  180. "expression": expression,
  181. **options,
  182. },
  183. title=title,
  184. )
  185. if result.get("received"):
  186. result["received"] = parse_value(result["received"])
  187. return result
  188. def expect_navigation(
  189. self,
  190. url: URLMatch = None,
  191. waitUntil: DocumentLoadState = None,
  192. timeout: float = None,
  193. ) -> EventContextManagerImpl[Response]:
  194. assert self._page
  195. if not waitUntil:
  196. waitUntil = "load"
  197. if timeout is None:
  198. timeout = self._page._timeout_settings.navigation_timeout()
  199. deadline = monotonic_time() + timeout
  200. waiter = self._setup_navigation_waiter("expect_navigation", timeout)
  201. to_url = f' to "{url}"' if url else ""
  202. waiter.log(f"waiting for navigation{to_url} until '{waitUntil}'")
  203. def predicate(event: Any) -> bool:
  204. # Any failed navigation results in a rejection.
  205. if event.get("error"):
  206. return True
  207. waiter.log(f' navigated to "{event["url"]}"')
  208. return url_matches(
  209. cast("Page", self._page)._browser_context._base_url,
  210. event["url"],
  211. url,
  212. )
  213. waiter.wait_for_event(
  214. self._event_emitter,
  215. "navigated",
  216. predicate=predicate,
  217. )
  218. async def continuation() -> Optional[Response]:
  219. event = await waiter.result()
  220. if "error" in event:
  221. raise Error(event["error"])
  222. if waitUntil not in self._load_states:
  223. t = deadline - monotonic_time()
  224. if t > 0:
  225. await self._wait_for_load_state_impl(state=waitUntil, timeout=t)
  226. if "newDocument" in event and "request" in event["newDocument"]:
  227. request = from_channel(event["newDocument"]["request"])
  228. return await request.response()
  229. return None
  230. return EventContextManagerImpl(asyncio.create_task(continuation()))
  231. async def wait_for_url(
  232. self,
  233. url: URLMatch,
  234. waitUntil: DocumentLoadState = None,
  235. timeout: float = None,
  236. ) -> None:
  237. assert self._page
  238. if url_matches(self._page._browser_context._base_url, self.url, url):
  239. await self._wait_for_load_state_impl(state=waitUntil, timeout=timeout)
  240. return
  241. async with self.expect_navigation(
  242. url=url, waitUntil=waitUntil, timeout=timeout
  243. ):
  244. pass
  245. async def wait_for_load_state(
  246. self,
  247. state: Literal["domcontentloaded", "load", "networkidle"] = None,
  248. timeout: float = None,
  249. ) -> None:
  250. return await self._wait_for_load_state_impl(state, timeout)
  251. async def _wait_for_load_state_impl(
  252. self, state: DocumentLoadState = None, timeout: float = None
  253. ) -> None:
  254. if not state:
  255. state = "load"
  256. if state not in ("load", "domcontentloaded", "networkidle", "commit"):
  257. raise Error(
  258. "state: expected one of (load|domcontentloaded|networkidle|commit)"
  259. )
  260. waiter = self._setup_navigation_waiter("wait_for_load_state", timeout)
  261. if state in self._load_states:
  262. waiter.log(f' not waiting, "{state}" event already fired')
  263. # TODO: align with upstream
  264. waiter._fulfill(None)
  265. else:
  266. def handle_load_state_event(actual_state: str) -> bool:
  267. waiter.log(f'"{actual_state}" event fired')
  268. return actual_state == state
  269. waiter.wait_for_event(
  270. self._event_emitter,
  271. "loadstate",
  272. handle_load_state_event,
  273. )
  274. await waiter.result()
  275. def _timeout(self, timeout: Optional[float]) -> float:
  276. timeout_settings = (
  277. self._page._timeout_settings if self._page else TimeoutSettings(None)
  278. )
  279. return timeout_settings.timeout(timeout)
  280. def _navigation_timeout(self, timeout: Optional[float]) -> float:
  281. timeout_settings = (
  282. self._page._timeout_settings if self._page else TimeoutSettings(None)
  283. )
  284. return timeout_settings.navigation_timeout(timeout)
  285. async def frame_element(self) -> ElementHandle:
  286. return from_channel(await self._channel.send("frameElement", None))
  287. async def evaluate(self, expression: str, arg: Serializable = None) -> Any:
  288. return parse_result(
  289. await self._channel.send(
  290. "evaluateExpression",
  291. None,
  292. dict(
  293. expression=expression,
  294. arg=serialize_argument(arg),
  295. ),
  296. )
  297. )
  298. async def evaluate_handle(
  299. self, expression: str, arg: Serializable = None
  300. ) -> JSHandle:
  301. return from_channel(
  302. await self._channel.send(
  303. "evaluateExpressionHandle",
  304. None,
  305. dict(
  306. expression=expression,
  307. arg=serialize_argument(arg),
  308. ),
  309. )
  310. )
  311. async def query_selector(
  312. self, selector: str, strict: bool = None
  313. ) -> Optional[ElementHandle]:
  314. return from_nullable_channel(
  315. await self._channel.send("querySelector", None, locals_to_params(locals()))
  316. )
  317. async def query_selector_all(self, selector: str) -> List[ElementHandle]:
  318. return list(
  319. map(
  320. from_channel,
  321. await self._channel.send(
  322. "querySelectorAll", None, dict(selector=selector)
  323. ),
  324. )
  325. )
  326. async def wait_for_selector(
  327. self,
  328. selector: str,
  329. strict: bool = None,
  330. timeout: float = None,
  331. state: Literal["attached", "detached", "hidden", "visible"] = None,
  332. ) -> Optional[ElementHandle]:
  333. return from_nullable_channel(
  334. await self._channel.send(
  335. "waitForSelector", self._timeout, locals_to_params(locals())
  336. )
  337. )
  338. async def is_checked(
  339. self, selector: str, strict: bool = None, timeout: float = None
  340. ) -> bool:
  341. return await self._channel.send(
  342. "isChecked", self._timeout, locals_to_params(locals())
  343. )
  344. async def is_disabled(
  345. self, selector: str, strict: bool = None, timeout: float = None
  346. ) -> bool:
  347. return await self._channel.send(
  348. "isDisabled", self._timeout, locals_to_params(locals())
  349. )
  350. async def is_editable(
  351. self, selector: str, strict: bool = None, timeout: float = None
  352. ) -> bool:
  353. return await self._channel.send(
  354. "isEditable", self._timeout, locals_to_params(locals())
  355. )
  356. async def is_enabled(
  357. self, selector: str, strict: bool = None, timeout: float = None
  358. ) -> bool:
  359. return await self._channel.send(
  360. "isEnabled", self._timeout, locals_to_params(locals())
  361. )
  362. async def is_hidden(self, selector: str, strict: bool = None) -> bool:
  363. return await self._channel.send(
  364. "isHidden", self._timeout, locals_to_params(locals())
  365. )
  366. async def is_visible(self, selector: str, strict: bool = None) -> bool:
  367. return await self._channel.send(
  368. "isVisible", self._timeout, locals_to_params(locals())
  369. )
  370. async def dispatch_event(
  371. self,
  372. selector: str,
  373. type: str,
  374. eventInit: Dict = None,
  375. strict: bool = None,
  376. timeout: float = None,
  377. ) -> None:
  378. await self._channel.send(
  379. "dispatchEvent",
  380. self._timeout,
  381. locals_to_params(
  382. dict(
  383. selector=selector,
  384. type=type,
  385. eventInit=serialize_argument(eventInit),
  386. strict=strict,
  387. timeout=timeout,
  388. ),
  389. ),
  390. )
  391. async def eval_on_selector(
  392. self,
  393. selector: str,
  394. expression: str,
  395. arg: Serializable = None,
  396. strict: bool = None,
  397. ) -> Any:
  398. return parse_result(
  399. await self._channel.send(
  400. "evalOnSelector",
  401. None,
  402. locals_to_params(
  403. dict(
  404. selector=selector,
  405. expression=expression,
  406. arg=serialize_argument(arg),
  407. strict=strict,
  408. )
  409. ),
  410. )
  411. )
  412. async def eval_on_selector_all(
  413. self,
  414. selector: str,
  415. expression: str,
  416. arg: Serializable = None,
  417. ) -> Any:
  418. return parse_result(
  419. await self._channel.send(
  420. "evalOnSelectorAll",
  421. None,
  422. dict(
  423. selector=selector,
  424. expression=expression,
  425. arg=serialize_argument(arg),
  426. ),
  427. )
  428. )
  429. async def content(self) -> str:
  430. return await self._channel.send("content", None)
  431. async def set_content(
  432. self,
  433. html: str,
  434. timeout: float = None,
  435. waitUntil: DocumentLoadState = None,
  436. ) -> None:
  437. await self._channel.send(
  438. "setContent", self._navigation_timeout, locals_to_params(locals())
  439. )
  440. @property
  441. def name(self) -> str:
  442. return self._name or ""
  443. @property
  444. def url(self) -> str:
  445. return self._url or ""
  446. @property
  447. def parent_frame(self) -> Optional["Frame"]:
  448. return self._parent_frame
  449. @property
  450. def child_frames(self) -> List["Frame"]:
  451. return self._child_frames.copy()
  452. def is_detached(self) -> bool:
  453. return self._detached
  454. async def add_script_tag(
  455. self,
  456. url: str = None,
  457. path: Union[str, Path] = None,
  458. content: str = None,
  459. type: str = None,
  460. ) -> ElementHandle:
  461. params = locals_to_params(locals())
  462. if path:
  463. params["content"] = add_source_url_to_script(
  464. (await async_readfile(path)).decode(), path
  465. )
  466. del params["path"]
  467. return from_channel(await self._channel.send("addScriptTag", None, params))
  468. async def add_style_tag(
  469. self, url: str = None, path: Union[str, Path] = None, content: str = None
  470. ) -> ElementHandle:
  471. params = locals_to_params(locals())
  472. if path:
  473. params["content"] = (
  474. (await async_readfile(path)).decode()
  475. + "\n/*# sourceURL="
  476. + str(Path(path))
  477. + "*/"
  478. )
  479. del params["path"]
  480. return from_channel(await self._channel.send("addStyleTag", None, params))
  481. async def click(
  482. self,
  483. selector: str,
  484. modifiers: Sequence[KeyboardModifier] = None,
  485. position: Position = None,
  486. delay: float = None,
  487. button: MouseButton = None,
  488. clickCount: int = None,
  489. timeout: float = None,
  490. force: bool = None,
  491. noWaitAfter: bool = None,
  492. strict: bool = None,
  493. trial: bool = None,
  494. ) -> None:
  495. await self._click(**locals_to_params(locals()))
  496. async def _click(
  497. self,
  498. selector: str,
  499. modifiers: Sequence[KeyboardModifier] = None,
  500. position: Position = None,
  501. delay: float = None,
  502. button: MouseButton = None,
  503. clickCount: int = None,
  504. timeout: float = None,
  505. force: bool = None,
  506. noWaitAfter: bool = None,
  507. strict: bool = None,
  508. trial: bool = None,
  509. steps: int = None,
  510. ) -> None:
  511. await self._channel.send("click", self._timeout, locals_to_params(locals()))
  512. async def dblclick(
  513. self,
  514. selector: str,
  515. modifiers: Sequence[KeyboardModifier] = None,
  516. position: Position = None,
  517. delay: float = None,
  518. button: MouseButton = None,
  519. timeout: float = None,
  520. force: bool = None,
  521. noWaitAfter: bool = None,
  522. strict: bool = None,
  523. trial: bool = None,
  524. ) -> None:
  525. await self._channel.send(
  526. "dblclick", self._timeout, locals_to_params(locals()), title="Double click"
  527. )
  528. async def tap(
  529. self,
  530. selector: str,
  531. modifiers: Sequence[KeyboardModifier] = None,
  532. position: Position = None,
  533. timeout: float = None,
  534. force: bool = None,
  535. noWaitAfter: bool = None,
  536. strict: bool = None,
  537. trial: bool = None,
  538. ) -> None:
  539. await self._channel.send("tap", self._timeout, locals_to_params(locals()))
  540. async def fill(
  541. self,
  542. selector: str,
  543. value: str,
  544. timeout: float = None,
  545. noWaitAfter: bool = None,
  546. strict: bool = None,
  547. force: bool = None,
  548. ) -> None:
  549. await self._fill(**locals_to_params(locals()))
  550. async def _fill(
  551. self,
  552. selector: str,
  553. value: str,
  554. timeout: float = None,
  555. noWaitAfter: bool = None,
  556. strict: bool = None,
  557. force: bool = None,
  558. title: str = None,
  559. ) -> None:
  560. await self._channel.send("fill", self._timeout, locals_to_params(locals()))
  561. def locator(
  562. self,
  563. selector: str,
  564. hasText: Union[str, Pattern[str]] = None,
  565. hasNotText: Union[str, Pattern[str]] = None,
  566. has: Locator = None,
  567. hasNot: Locator = None,
  568. ) -> Locator:
  569. return Locator(
  570. self,
  571. selector,
  572. has_text=hasText,
  573. has_not_text=hasNotText,
  574. has=has,
  575. has_not=hasNot,
  576. )
  577. def get_by_alt_text(
  578. self, text: Union[str, Pattern[str]], exact: bool = None
  579. ) -> "Locator":
  580. return self.locator(get_by_alt_text_selector(text, exact=exact))
  581. def get_by_label(
  582. self, text: Union[str, Pattern[str]], exact: bool = None
  583. ) -> "Locator":
  584. return self.locator(get_by_label_selector(text, exact=exact))
  585. def get_by_placeholder(
  586. self, text: Union[str, Pattern[str]], exact: bool = None
  587. ) -> "Locator":
  588. return self.locator(get_by_placeholder_selector(text, exact=exact))
  589. def get_by_role(
  590. self,
  591. role: AriaRole,
  592. checked: bool = None,
  593. disabled: bool = None,
  594. expanded: bool = None,
  595. includeHidden: bool = None,
  596. level: int = None,
  597. name: Union[str, Pattern[str]] = None,
  598. pressed: bool = None,
  599. selected: bool = None,
  600. exact: bool = None,
  601. ) -> "Locator":
  602. return self.locator(
  603. get_by_role_selector(
  604. role,
  605. checked=checked,
  606. disabled=disabled,
  607. expanded=expanded,
  608. includeHidden=includeHidden,
  609. level=level,
  610. name=name,
  611. pressed=pressed,
  612. selected=selected,
  613. exact=exact,
  614. )
  615. )
  616. def get_by_test_id(self, testId: Union[str, Pattern[str]]) -> "Locator":
  617. return self.locator(get_by_test_id_selector(test_id_attribute_name(), testId))
  618. def get_by_text(
  619. self, text: Union[str, Pattern[str]], exact: bool = None
  620. ) -> "Locator":
  621. return self.locator(get_by_text_selector(text, exact=exact))
  622. def get_by_title(
  623. self, text: Union[str, Pattern[str]], exact: bool = None
  624. ) -> "Locator":
  625. return self.locator(get_by_title_selector(text, exact=exact))
  626. def frame_locator(self, selector: str) -> FrameLocator:
  627. return FrameLocator(self, selector)
  628. async def focus(
  629. self, selector: str, strict: bool = None, timeout: float = None
  630. ) -> None:
  631. await self._channel.send("focus", self._timeout, locals_to_params(locals()))
  632. async def text_content(
  633. self, selector: str, strict: bool = None, timeout: float = None
  634. ) -> Optional[str]:
  635. return await self._channel.send(
  636. "textContent", self._timeout, locals_to_params(locals())
  637. )
  638. async def inner_text(
  639. self, selector: str, strict: bool = None, timeout: float = None
  640. ) -> str:
  641. return await self._channel.send(
  642. "innerText", self._timeout, locals_to_params(locals())
  643. )
  644. async def inner_html(
  645. self, selector: str, strict: bool = None, timeout: float = None
  646. ) -> str:
  647. return await self._channel.send(
  648. "innerHTML", self._timeout, locals_to_params(locals())
  649. )
  650. async def get_attribute(
  651. self, selector: str, name: str, strict: bool = None, timeout: float = None
  652. ) -> Optional[str]:
  653. return await self._channel.send(
  654. "getAttribute", self._timeout, locals_to_params(locals())
  655. )
  656. async def hover(
  657. self,
  658. selector: str,
  659. modifiers: Sequence[KeyboardModifier] = None,
  660. position: Position = None,
  661. timeout: float = None,
  662. noWaitAfter: bool = None,
  663. force: bool = None,
  664. strict: bool = None,
  665. trial: bool = None,
  666. ) -> None:
  667. await self._channel.send("hover", self._timeout, locals_to_params(locals()))
  668. async def drag_and_drop(
  669. self,
  670. source: str,
  671. target: str,
  672. sourcePosition: Position = None,
  673. targetPosition: Position = None,
  674. force: bool = None,
  675. noWaitAfter: bool = None,
  676. strict: bool = None,
  677. timeout: float = None,
  678. trial: bool = None,
  679. steps: int = None,
  680. ) -> None:
  681. await self._channel.send(
  682. "dragAndDrop", self._timeout, locals_to_params(locals())
  683. )
  684. async def select_option(
  685. self,
  686. selector: str,
  687. value: Union[str, Sequence[str]] = None,
  688. index: Union[int, Sequence[int]] = None,
  689. label: Union[str, Sequence[str]] = None,
  690. element: Union["ElementHandle", Sequence["ElementHandle"]] = None,
  691. timeout: float = None,
  692. noWaitAfter: bool = None,
  693. strict: bool = None,
  694. force: bool = None,
  695. ) -> List[str]:
  696. params = locals_to_params(
  697. dict(
  698. selector=selector,
  699. timeout=timeout,
  700. strict=strict,
  701. force=force,
  702. **convert_select_option_values(value, index, label, element),
  703. )
  704. )
  705. return await self._channel.send("selectOption", self._timeout, params)
  706. async def input_value(
  707. self,
  708. selector: str,
  709. strict: bool = None,
  710. timeout: float = None,
  711. ) -> str:
  712. return await self._channel.send(
  713. "inputValue", self._timeout, locals_to_params(locals())
  714. )
  715. async def set_input_files(
  716. self,
  717. selector: str,
  718. files: Union[
  719. str, Path, FilePayload, Sequence[Union[str, Path]], Sequence[FilePayload]
  720. ],
  721. strict: bool = None,
  722. timeout: float = None,
  723. noWaitAfter: bool = None,
  724. ) -> None:
  725. converted = await convert_input_files(files, self.page.context)
  726. await self._channel.send(
  727. "setInputFiles",
  728. self._timeout,
  729. {
  730. "selector": selector,
  731. "strict": strict,
  732. "timeout": self._timeout(timeout),
  733. **converted,
  734. },
  735. )
  736. async def type(
  737. self,
  738. selector: str,
  739. text: str,
  740. delay: float = None,
  741. strict: bool = None,
  742. timeout: float = None,
  743. noWaitAfter: bool = None,
  744. ) -> None:
  745. await self._channel.send("type", self._timeout, locals_to_params(locals()))
  746. async def press(
  747. self,
  748. selector: str,
  749. key: str,
  750. delay: float = None,
  751. strict: bool = None,
  752. timeout: float = None,
  753. noWaitAfter: bool = None,
  754. ) -> None:
  755. await self._channel.send("press", self._timeout, locals_to_params(locals()))
  756. async def check(
  757. self,
  758. selector: str,
  759. position: Position = None,
  760. timeout: float = None,
  761. force: bool = None,
  762. noWaitAfter: bool = None,
  763. strict: bool = None,
  764. trial: bool = None,
  765. ) -> None:
  766. await self._channel.send("check", self._timeout, locals_to_params(locals()))
  767. async def uncheck(
  768. self,
  769. selector: str,
  770. position: Position = None,
  771. timeout: float = None,
  772. force: bool = None,
  773. noWaitAfter: bool = None,
  774. strict: bool = None,
  775. trial: bool = None,
  776. ) -> None:
  777. await self._channel.send("uncheck", self._timeout, locals_to_params(locals()))
  778. async def wait_for_timeout(self, timeout: float) -> None:
  779. await self._channel.send("waitForTimeout", None, {"waitTimeout": timeout})
  780. async def wait_for_function(
  781. self,
  782. expression: str,
  783. arg: Serializable = None,
  784. timeout: float = None,
  785. polling: Union[float, Literal["raf"]] = None,
  786. ) -> JSHandle:
  787. if isinstance(polling, str) and polling != "raf":
  788. raise Error(f"Unknown polling option: {polling}")
  789. params = locals_to_params(locals())
  790. params["arg"] = serialize_argument(arg)
  791. if polling is not None and polling != "raf":
  792. params["pollingInterval"] = polling
  793. return from_channel(
  794. await self._channel.send("waitForFunction", self._timeout, params)
  795. )
  796. async def title(self) -> str:
  797. return await self._channel.send("title", None)
  798. async def set_checked(
  799. self,
  800. selector: str,
  801. checked: bool,
  802. position: Position = None,
  803. timeout: float = None,
  804. force: bool = None,
  805. noWaitAfter: bool = None,
  806. strict: bool = None,
  807. trial: bool = None,
  808. ) -> None:
  809. if checked:
  810. await self.check(
  811. selector=selector,
  812. position=position,
  813. timeout=timeout,
  814. force=force,
  815. strict=strict,
  816. trial=trial,
  817. )
  818. else:
  819. await self.uncheck(
  820. selector=selector,
  821. position=position,
  822. timeout=timeout,
  823. force=force,
  824. strict=strict,
  825. trial=trial,
  826. )
  827. async def _highlight(self, selector: str) -> None:
  828. await self._channel.send("highlight", None, {"selector": selector})