HyperionGray / trio-chrome-devtools-protocol

Trio driver for Chrome DevTools Protocol (CDP)
MIT License
60 stars 17 forks source link

CmEventProxy is returning an empty value #15

Closed AutomatedTester closed 3 years ago

AutomatedTester commented 3 years ago

Hi,

Sorry for raising an issue, happy to move this to a chat if there is one.

I am trying, via a very roundabout way, to use parts of this project and integrate it into Selenium to add new evented APIs from CDP. We can't use this project directly as we need want to support multiple chromium versions at once so we generate and integrate it into wheel.

It all works in that I see that an event happens but I can't get the exact event that happened.

I have used an asynccontext manager but what is returned is an empty CmEventProxy object.

Not knowing the code well enough, and the eventing model in trio, I can't see how https://github.com/HyperionGray/trio-chrome-devtools-protocol/blob/master/trio_cdp/__init__.py#L129-L132 works. I can see that the event happens how does event get into proxy.value.

Any help would be greatly appreciated, happy to help with documentation and examples for this repo in return.

AutomatedTester commented 3 years ago

I've managed to get a little further but it's left me with more questions on how to use your code.

The CmEventProxy object appears to get populated then the lifecycle of the @asynccontextmanager ends.

e.g.

If we update the test in the link above, this for simplicity to look like

async def test_check_console_messages(driver, pages):
    pages.load("javascriptPage.html")
    from selenium.webdriver.common.bidi.console import Console
    lets_see = None
    async with driver.add_listener(Console.ALL) as messages:
        driver.execute_script("console.log('I love cheese')")
        driver.execute_script("console.log('I love cheese')")

        lets_see = messages
    lets_see

The variable lets_see get populated when the context manager is no longer in scope.

AutomatedTester commented 3 years ago

links updated to work again

mehaase commented 3 years ago

This repo isn't being maintained by the company anymore (I and the other developer who built it have changed jobs) so you may not want to write new code on top of it. But I can explain the API a bit.

wait_for(…) waits for a single event. Here's an example that navigates and waits for the load event to fire.

async with session.wait_for(page.LoadEventFired):
    await page.navigate(url="http://foobar")

print("Load finished")

The idea is that if you want to listen for an event, you need to set up the event listener before you trigger the event. The async with sets up the listener, then it enters the block. In the block, you need to provide code that will trigger the event. Then it waits for the event before it leaves the async with block, and it sets the event proxy so that you can retrieve the event after the block exits. Then the print() call happens after the page load event fires.

If you want to process multiple events, then you should use the listen(...) API:

async for event in session.listen(page.LoadEvent):
     print(f"received event {event}")

You can see a better example in this other issue thread: https://github.com/HyperionGray/trio-chrome-devtools-protocol/issues/3#issuecomment-563293385

AutomatedTester commented 3 years ago

@mehaase thanks for taking the time to help. It's helped me grok how this should work and I have got most things working.

I've got a few other issues that I can't get my head around but hopefully over time that will come.