I'm trying to automate the www.freeinvaders.org version of Space Invaders using Python and Selenium. The actual game works through a HTML5 canvas element, which is wrapped in a shadow-root.
Using the answer to this question, I'm attempting to expand the shadow-root, so I can click the canvas and 'play' the game.
My current code:
def expand_shadow_element(element):
shadowRoot = browser.execute_script('return arguments[0].shadowRoot', element)
return shadowRoot
browser = webdriver.Firefox()
browser.get("http://www.freeinvaders.org/")
#wait for element to load
el = WebDriverWait(browser, timeout=20).until(lambda d:d.find_element_by_tag_name("ruffle-player"))
time.sleep(5)
#expand the shadowroot and click the canvas
host = browser.find_element_by_tag_name("ruffle-player")
shadowRoot = expand_shadow_element(host)
canvas = shadowRoot.find_element_by_tag_name("canvas")
canvas.click()
The HTML structure of the page is like this: (abridged for legibility)
<!DOCTYPE html>
<html lang="en-US">
<head>
<title>Free Invaders</title>
</head>
<body>
<div id='full-page-container'>
<main>
<div id="game-container">
<ruffle-player>
#shadow-root (open)
<div id="container" style="visibility: visible;">
<canvas width="1600" height="760" style="touch-action: none; cursor: auto;"></canvas>
</div><!--container-->
</ruffle-player>
</div><!--game-container-->
</div><!--fullpagecontainer-->
</body>
When running the above Pyhton script, it fails on this line:
shadowRoot = browser.execute_script('return arguments[0].shadowRoot', element)
with a Javascript error:
selenium.common.exceptions.JavascriptException: Message: Cyclic object value
I know that error is supposed to mean there is a self-referencing item in the returned JSON string, but that shouldn't be the case here.
Can anyone help me by explaining why this error occurs and what course of action might alleviate the issue?
I'm using Python 3.8.5, Selenium 3.141.0 and Firefox 86.0. All of this runs on Linux Mint 20.1.
Edit I have also attempted the alternative Javascript:
shadowRoot = browser.execute_script('document.querySelector("ruffle-player").shadowRoot')
But that just returns another error:
AttributeError: 'NoneType' object has no attribute 'find_element_by_tag_name'
Which indicates it doesn't even find any objects.