Source code

Revision control

Copy as Markdown

Other Tools

import time
import pytest
from webdriver.error import NoSuchElementException
POPUP_CSS = ".ebd-modal-root"
GOOGLE_LOGIN_CSS = "#credential_picker_container"
FIRST_PRODUCT_CSS = "a[href^='https://www.eyebuydirect.ca/sunglasses/frames/']"
FIRST_FRAME_SIZE_CSS = "button[class*='size-list_size']"
SELECTED_FRAME_SIZE_CSS = "button[class*='size-list_size'][class*='size-list_current']"
SELECT_LENSES_CSS = "[aria-label='Select Lenses']"
NON_PRESCRIPTION_CSS = ".use-for-non-rx"
FIRST_COLOR_TYPE_CSS = "#color-type-container [data-option-name]"
BASIC_TYPE_CSS = "#sunglasses, #sunglasses-non-rx"
FIRST_COLOR_OPT_CSS = "[data-color-value-id]"
FIRST_COLOR_OPT_SELECTED_CSS = "[data-color-value-id].current"
CONFIRM_COLOR_BTN_CSS = "button.color-confirm"
STANDARD_LENSES_CSS = ".package-show.package-standard.lenses"
ADD_TO_CART_CSS = "button.btn-add-cart"
PAYPAL_CHECKOUT_CSS = "#paypal-checkout-button"
PAYPAL_OVERLAY_CSS = "[id^='paypal-overlay-uid']"
NON_PRESCRIPTION_OPT_CSS = (
"[class*=lens-prescription_select-lens] [aria-label^=Non-Prescription]"
)
NON_PRESCRIPTION_OPT_SELECTED_CSS = (
"[aria-label^=Non-Prescription][class^=lens-prescription_selected]"
)
async def can_click_paypal_button(client):
await client.make_preload_script(
f"""
document.addEventListener("DOMContentLoaded", () => {{
const s = document.createElement("style");
s.textContent = "{POPUP_CSS}, {GOOGLE_LOGIN_CSS} {{ opacity:0 !important; pointer-events:none !important; }}";
document.head.appendChild(s);
}});
"""
)
await client.navigate(URL)
client.soft_click(client.await_css(FIRST_PRODUCT_CSS))
# we must wait for the DOM listeners to be added before the selectors will
# react, so just keep clicking and checking a few times until they do.
for tries in range(10):
non_rx = client.await_css(NON_PRESCRIPTION_OPT_CSS, is_displayed=True)
if client.find_css(NON_PRESCRIPTION_OPT_SELECTED_CSS, is_displayed=True):
break
non_rx.click()
time.sleep(0.5)
try:
first_frame_size = client.await_css(
FIRST_FRAME_SIZE_CSS, is_displayed=True, timeout=4
)
if first_frame_size:
for tries in range(10):
first_frame_size.click()
time.sleep(0.5)
if client.find_css(SELECTED_FRAME_SIZE_CSS, is_displayed=True):
break
except NoSuchElementException:
pass
client.click(client.await_css(SELECT_LENSES_CSS, is_displayed=True), force=True)
client.soft_click(client.await_css(FIRST_COLOR_TYPE_CSS, is_displayed=True))
client.soft_click(client.await_css(BASIC_TYPE_CSS, is_displayed=True))
first_color_opt = client.await_css(FIRST_COLOR_OPT_CSS, is_displayed=True)
for tries in range(10):
if client.find_css(FIRST_COLOR_OPT_SELECTED_CSS, is_displayed=True):
break
first_color_opt.click()
time.sleep(0.5)
client.soft_click(client.await_css(CONFIRM_COLOR_BTN_CSS, is_displayed=True))
client.soft_click(client.await_css(STANDARD_LENSES_CSS, is_displayed=True))
client.soft_click(client.await_css(ADD_TO_CART_CSS, is_displayed=True))
# Now the tricky parts begin. When we click on the PayPal button, if things
# are working then the PayPal iframe will receive the click event. But in
# the broken case, the underlying top frame will receive it instead. As such,
# we check which frame receives a mousedown. But in order to do so, we need
# to use chrome js functions, as WebDriver currently does not send mouse
# events via APZ. And we have to click a few times, as it's possible that the
# first clicks will still target the top frame, despite simulating APZ clicks.
frame = client.await_css(f"{PAYPAL_CHECKOUT_CSS} iframe")
while True:
client.switch_to_frame(frame)
buttons = client.await_css("#buttons-container", timeout=20)
client.execute_script(
"""
arguments[0].addEventListener("mousedown", e => {
window.__clicked = true;
}, true);
""",
buttons,
)
break
client.switch_to_frame()
# Now we mousedown over the PayPal button. Note that we only send mousedown
# events here to limit the chances that we will trigger any reaction from
# the page aside from our own mousedown-detection listener above. We try
# to mousedown multiple times as it does not always work the first time
# for some unknown reason (and may still fail outright intermittently).
for i in range(10):
await client.apz_down(element=frame)
time.sleep(0.2)
client.switch_to_frame(frame)
return client.execute_script("return !!window.__clicked")
@pytest.mark.skip_platforms("android")
@pytest.mark.only_firefox_versions(max=134)
@pytest.mark.asyncio
@pytest.mark.with_interventions
async def test_enabled(client):
assert await can_click_paypal_button(client)
@pytest.mark.skip_platforms("android")
@pytest.mark.only_firefox_versions(max=134)
@pytest.mark.asyncio
@pytest.mark.without_interventions
async def test_disabled(client):
assert not await can_click_paypal_button(client)
@pytest.mark.skip_platforms("android")
@pytest.mark.only_firefox_versions(min=135)
@pytest.mark.asyncio
@pytest.mark.without_interventions
async def test_regression(client):
assert await can_click_paypal_button(client)