Source code
Revision control
Copy as Markdown
Other Tools
import asyncio
from random import randint
import pytest
JUGAR_BUTTON_TEXT = "¡Jugar!"
CARD1_CSS = "#board .react-card-flip:nth-of-type(1)"
CARD2_CSS = "#board .react-card-flip:nth-of-type(2)"
CARD3_CSS = "#board .react-card-flip:nth-of-type(3)"
CARD4_CSS = "#board .react-card-flip:nth-of-type(4)"
CARD5_CSS = "#board .react-card-flip:nth-of-type(5)"
LETTERS_CSS = "#keyboard button:not(:has(svg))" # avoid check and delete buttons
async def letters_sometimes_vanish(client):
await client.navigate(URL, wait="load")
client.await_text(JUGAR_BUTTON_TEXT, is_displayed=True).click()
letters = client.await_css(LETTERS_CSS, is_displayed=True, all=True)
body = client.find_css("body")
# This is a very subtle test, because the problem isn't well-understood. I found that I could
# only reproduce the issue if I move the mouse immediately after clicking a letter, while the
# css animation runs. Then the card will sometimes vanish immediately after the animation ends,
# and if I move the mouse again, it seems to reappear. So this test will simulate that kind of
# movement while clicking on 5 random letters, then wait a half-second, see if any of the cards
# are invisible (by taking a "screenshot" of the element, with their CSS borders hidden to make
# is_one_solid_color not have to fuzz), and try another 5 random letters a few times just to make
# sure the cards always appear. The need for delaying the various simulated events during the
# animation makes this test slower than it probably needs to be, but that's fine.
client.add_stylesheet(
"#board .react-card-flip * { border:0 !important; animation-duration:0.5s !important; }"
)
# click on 5 random letters, check if any are invisible, then delete them and retry
# repeat this 10 times, and presume everything is fine if none disappear.
for attempt in range(10):
for click_five_keys in range(5):
letter = letters[randint(0, len(letters) - 1)]
coords = client.get_element_screen_position(letter)
coords = [coords[0] + 20, coords[1] + 20]
await client.apz_down(coords=coords)
await asyncio.sleep(0.025)
coords = [coords[0] + 20, coords[1] + 20]
await client.send_apz_mouse_event("move", coords=coords)
await client.apz_up(coords=coords)
await asyncio.sleep(0.025)
await client.send_apz_mouse_event(
"move", coords=[coords[0] + 50, coords[1] + 50]
)
await asyncio.sleep(0.025)
await client.send_apz_mouse_event(
"move", coords=[coords[0] + 100, coords[1] + 100]
)
await asyncio.sleep(0.025)
await client.send_apz_mouse_event(
"move", coords=[coords[0] + 150, coords[1] + 150]
)
await asyncio.sleep(0.025)
await client.send_apz_mouse_event(
"move", coords=[coords[0] + 200, coords[1] + 200]
)
await asyncio.sleep(0.025)
# wait a moment to let the animations settle down to increase the
# likelihood that we'll see the problem.
await asyncio.sleep(0.5)
if (
client.is_one_solid_color(client.find_css(CARD1_CSS))
or client.is_one_solid_color(client.find_css(CARD2_CSS))
or client.is_one_solid_color(client.find_css(CARD3_CSS))
or client.is_one_solid_color(client.find_css(CARD4_CSS))
or client.is_one_solid_color(client.find_css(CARD5_CSS))
):
return True
# press backspace key 5 times to clear the inputs so we can try again
for backspace in range(5):
body.send_keys("\ue003")
return False
@pytest.mark.skip_platforms("android")
@pytest.mark.asyncio
@pytest.mark.with_interventions
async def test_enabled(client):
assert not await letters_sometimes_vanish(client)
@pytest.mark.skip_platforms("android")
@pytest.mark.asyncio
@pytest.mark.without_interventions
async def test_disabled(client):
assert await letters_sometimes_vanish(client)