kaliiiiiiiiii / Selenium-Driverless

undetected Selenium without usage of chromedriver
https://kaliiiiiiiiii.github.io/Selenium-Driverless/
Other
404 stars 52 forks source link

[BUG] support for `frame`s missing #231

Open plonknimbuzz opened 1 month ago

plonknimbuzz commented 1 month ago

Hi, I got this error, and when i try to read your code, I think u still not implemented switch_to.frame correctly. because u treat frame like an iframe while both of them have different element behaviour

top.window.frame2.document.querySelector('input')

selenium_driverless: 1.9.3.1

https://github.com/kaliiiiiiiiii/Selenium-Driverless/blob/348b95dbb0025d1343fc3c6ade3540129269ae37/src/selenium_driverless/scripts/switch_to.py#L119-L121

frameset.html

<html>  
<head>  
    <title>Frame tag</title>  
</head>  
    <frameset cols="50%,50%">  
        <frame  name="frame1" framespacing="0" border="0" frameborder="NO" src="input1.html">  
        <frame  name="frame2" framespacing="0" border="0" frameborder="NO" src="input2.html">     
    </frameset>  
</html>  

input1.html

<html>
    <head></head>
    <body>
        <label>input1</label>
        <input type="text" name="input1">
    </body>
</html>

input2.html

<html>
    <head></head>
    <body>
        <label>input2</label>
        <input type="text" name="input2">
    </body>
</html>

test.py

async def main2():
    options = webdriver.ChromeOptions()
    async with webdriver.Chrome(options=options) as driver:
        await driver.get("http://localhost/frameset.html", wait_load=True)
        time.sleep(1)
        frame = await driver.switch_to.frame('frame2')

asyncio.run(main2())

error

Traceback (most recent call last):
  File "C:\xampp\htdocs\other\mutasi-mudah\debug\test.py", line 60, in <module>
    asyncio.run(main2())
  File "C:\Python310\lib\asyncio\runners.py", line 44, in run
    return loop.run_until_complete(main)
  File "C:\Python310\lib\asyncio\base_events.py", line 646, in run_until_complete
    return future.result()
  File "C:\xampp\htdocs\other\mutasi-mudah\debug\test.py", line 58, in main2
    frame = await driver.switch_to.frame('frame2')
  File "C:\Python310\lib\site-packages\selenium_driverless\scripts\switch_to.py", line 121, in frame
    target = await self._context.current_target.get_target_for_iframe(frame_reference)
  File "C:\Python310\lib\site-packages\selenium_driverless\types\target.py", line 267, in get_target_for_iframe
    raise NoSuchIframe(iframe, "no target for iframe found")
selenium_driverless.types.target.NoSuchIframe: no target for iframe found
kaliiiiiiiiii commented 1 month ago

https://kaliiiiiiiiii.github.io/Selenium-Driverless/api/Chrome/#selenium_driverless.scripts.switch_to.SwitchTo

https://github.com/kaliiiiiiiiii/Selenium-Driverless?tab=readme-ov-file#iframes

driver.switch_to.frame shouldn't be used

in Readme:

Note: This project is moving away from the selenium syntax

plonknimbuzz commented 1 month ago

so how to access frame element?

selenium_driverless

options = webdriver.ChromeOptions()
async with webdriver.Chrome(options=options) as driver:
    await driver.get("http://localhost/frameset.html", wait_load=True)
    time.sleep(1)
    iframes = await driver.find_elements(By.TAG_NAME, "frame")
    await asyncio.sleep(0.5)
    iframe_document = await iframes[1].content_document
    inpt = iframe_document.find_elements(By.CSS_SELECTOR,'input')
    inpt.send_keys('aaa')
    time.sleep(2)

error

Traceback (most recent call last):
  File "C:\xampp\htdocs\other\mutasi-mudah\debug\test.py", line 80, in <module>
    asyncio.run(main2())
  File "C:\Python310\lib\asyncio\runners.py", line 44, in run
    return loop.run_until_complete(main)
  File "C:\Python310\lib\asyncio\base_events.py", line 646, in run_until_complete
    return future.result()
  File "C:\xampp\htdocs\other\mutasi-mudah\debug\test.py", line 61, in main2
    inpt = iframe_document.find_elements(By.CSS_SELECTOR,'input')
AttributeError: 'NoneType' object has no attribute 'find_elements'

with selenium i can do this, but idk how to do it with selenium_driverless

from selenium import webdriver as webdriver2
from selenium.webdriver.common.by import By as By2
from selenium.webdriver.chrome.options import Options
options = Options()
options.binary_location = "C:/selenium/chrome/chrome.exe"
driver = webdriver2.Chrome(options=options )
driver.get("http://localhost/frameset.html")
time.sleep(1)
driver.switch_to.frame('frame2')
inpt = driver.find_element(By2.CSS_SELECTOR,'input')
inpt.send_keys('aaa')
time.sleep(2)
driver.quit()

thanks for you fast reply

kaliiiiiiiiii commented 1 month ago

my bad let's leave it open for now

kaliiiiiiiiii commented 1 month ago

changing https://github.com/kaliiiiiiiiii/Selenium-Driverless/blob/348b95dbb0025d1343fc3c6ade3540129269ae37/src/selenium_driverless/types/webelement.py#L203 to in ["iframe", "frame"] might resolve the issue.

https://chromedevtools.github.io/devtools-protocol/tot/DOM/#type-Node for reference

plonknimbuzz commented 1 month ago

232 pull request done

thanks for your help mate