diff --git a/CHANGELOG.md b/CHANGELOG.md index 0257ac88..778eeec4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ where X.Y.Z is the semver of the most recent choreographer release. ## [Unreleased] ### Fixed +- Fix the page-ready check so that a URL without a trailing slash no longer causes a false load timeout [[#295](https://github.com/plotly/choreographer/pull/295)] - Build the `ChromeNotFoundError` message as one string, so it no longer prints as a tuple [[#314](https://github.com/plotly/choreographer/pull/314)], with thanks to @Blizzeq for the contribution! diff --git a/src/choreographer/protocol/devtools_async_helpers.py b/src/choreographer/protocol/devtools_async_helpers.py index c1d2d250..4b9b2dff 100644 --- a/src/choreographer/protocol/devtools_async_helpers.py +++ b/src/choreographer/protocol/devtools_async_helpers.py @@ -34,9 +34,9 @@ async def _check_document_ready(session: Session, url: str) -> BrowserResponse: new Promise((resolve) => { if ( (document.readyState === 'complete') && - (window.location==`""" # CONCATENATE! + (window.location.href.startsWith(`""" # CONCATENATE! f"{url!s}" - """`) + """`)) ){ resolve("Was complete"); } else { diff --git a/tests/test_devtools_async_helpers.py b/tests/test_devtools_async_helpers.py index 86a83132..842def31 100644 --- a/tests/test_devtools_async_helpers.py +++ b/tests/test_devtools_async_helpers.py @@ -4,6 +4,7 @@ import pytest from choreographer.protocol.devtools_async_helpers import ( + _check_document_ready, create_and_wait, execute_js_and_wait, navigate_and_wait, @@ -52,6 +53,31 @@ async def test_create_and_wait(browser): await create_and_wait(browser, url="http://192.0.2.1:9999", timeout=0.5) +@pytest.mark.asyncio +async def test_check_document_ready_tolerates_missing_trailing_slash(browser): + """Test that the ready check tolerates a missing trailing slash""" + _logger.info("testing _check_document_ready...") + # Chrome normalizes "https://www.example.com" to "https://www.example.com/", + # so an exact comparison against the input URL never matches + url = "https://www.example.com" + tab = await create_and_wait(browser, url=url, timeout=5.0) + + session = await tab.create_session() + try: + # Chrome already fired the load event for this tab, so it never fires + # again. The check must take the readyState branch or it hangs + response = await asyncio.wait_for( + _check_document_ready(session, url), + timeout=5.0, + ) + except TimeoutError: + pytest.fail("The ready check hung, so it did not match the normalized URL") + finally: + await tab.close_session(session.session_id) + + assert response["result"]["result"]["value"] == "Was complete" + + @pytest.mark.asyncio async def test_navigate_and_wait(browser): """Test navigate_and_wait with both valid data URL and bad URL."""