HENNGE / arsenic

Async WebDriver implementation for asyncio and asyncio-compatible frameworks
Other
350 stars 53 forks source link

How to interact with frames? #67

Open ioistired opened 5 years ago

ioistired commented 5 years ago

I need to click on a checkbox inside of an iframe. How can I do that? This code gets an empty list:

await session.wait_for_element(float('inf'), 'iframe')
children = await session.get_elements('iframe *')

Selenium's python webdriver library lets you do this by first switching to the iframe. Is this supported?

ava7 commented 3 years ago

Bump

dimaqq commented 3 years ago

RFC: https://www.w3.org/TR/webdriver/#switch-to-frame

mjarosie commented 1 year ago

There's been a similar question on stackoverflow. You can switch to an iframe like that:

await session.request(
    url="/frame",
    method="POST",
    data={"id": iframe.id},
)

Additionally - if you want the equivalent of Selenium's driver.switch_to.default_content() - you just invoke the "switch to frame" WebDriver API with None as the id parameter (as the spec says):

await session.request(
    url="/frame",
    method="POST",
    data={"id": None},
)

That'd be great to have it explicitly documented. Perhaps even an actual Session.switchToFrame(el: Element) could be introduced? I'm happy to fill in a pull request as long as the maintainers are fine with that.

EDIT: Actually... no, I still didn't get it working. I'm trying to switch to the frame by providing its ID, but WebDriver API returns this sort of error: data did not match any variant of untagged enum FrameId. I've tried invoking it with the value of the id attribute of the iframe element on the page, that didn't work neither...

EDIT2: Ok, I managed to get it working, just needed to RTFM. The id field has to be a JSON object which represents a web element according to the spec, which means having a constant element-6066-11e4-a52e-4f735466cecf as a key, and a web element reference as a value. So the request should look like this:

await session.request(
    url="/frame",
    method="POST",
    data={"id": {"element-6066-11e4-a52e-4f735466cecf": iframe.id}}
)