зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1715900 - Add initial tests (and helpers) for the mach test-interventions command; r=jgraham
Depends on D138384 Differential Revision: https://phabricator.services.mozilla.com/D138540
This commit is contained in:
Родитель
10326d782c
Коммит
1fbbcbbcc2
|
@ -0,0 +1,131 @@
|
|||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
import pytest
|
||||
import time
|
||||
|
||||
from selenium.common.exceptions import NoAlertPresentException, NoSuchElementException
|
||||
from selenium.webdriver.common.by import By
|
||||
|
||||
|
||||
def expect_alert(session, text=None):
|
||||
try:
|
||||
alert = session.switch_to.alert
|
||||
if text is not None:
|
||||
assert alert.text == text
|
||||
alert.dismiss()
|
||||
except NoAlertPresentException:
|
||||
pass
|
||||
|
||||
|
||||
def is_float_cleared(session, elem1, elem2):
|
||||
return session.execute_script(
|
||||
"""return (function(a, b) {
|
||||
// Ensure that a is placed under
|
||||
// (and not to the right of) b
|
||||
return a?.offsetTop >= b?.offsetTop + b?.offsetHeight &&
|
||||
a?.offsetLeft < b?.offsetLeft + b?.offsetWidth;
|
||||
}(arguments[0], arguments[1]));""",
|
||||
elem1,
|
||||
elem2,
|
||||
)
|
||||
|
||||
|
||||
def await_getUserMedia_call_on_click(session, elem_to_click):
|
||||
return session.execute_script(
|
||||
"""
|
||||
navigator.mediaDevices.getUserMedia =
|
||||
navigator.mozGetUserMedia =
|
||||
navigator.getUserMedia =
|
||||
() => { window.__gumCalled = true; };
|
||||
"""
|
||||
)
|
||||
elem_to_click.click()
|
||||
return session.execute_async_script(
|
||||
"""
|
||||
var done = arguments[0];
|
||||
setInterval(500, () => {
|
||||
if (window.__gumCalled === true) {
|
||||
done();
|
||||
}
|
||||
});
|
||||
"""
|
||||
)
|
||||
|
||||
|
||||
class Xpath:
|
||||
by = By.XPATH
|
||||
|
||||
def __init__(self, value):
|
||||
self.value = value
|
||||
|
||||
|
||||
class Css:
|
||||
by = By.CSS_SELECTOR
|
||||
|
||||
def __init__(self, value):
|
||||
self.value = value
|
||||
|
||||
|
||||
class Text:
|
||||
by = By.XPATH
|
||||
|
||||
def __init__(self, value):
|
||||
self.value = f"//*[contains(text(),'{value}')]"
|
||||
|
||||
|
||||
Missing = object()
|
||||
|
||||
|
||||
def find_elements(session, selector, all=True, default=Missing):
|
||||
try:
|
||||
if all:
|
||||
return session.find_elements(selector.by, selector.value)
|
||||
return session.find_element(selector.by, selector.value)
|
||||
except NoSuchElementException:
|
||||
if default is not Missing:
|
||||
return default
|
||||
raise
|
||||
|
||||
|
||||
def find_element(session, selector, default=Missing):
|
||||
return find_elements(session, selector, all=False, default=default)
|
||||
|
||||
|
||||
def assert_not_element(session, sel):
|
||||
with pytest.raises(NoSuchElementException):
|
||||
find_element(session, sel)
|
||||
|
||||
|
||||
def await_first_element_of(session, selectors, timeout=None, is_displayed=False):
|
||||
t0 = time.time()
|
||||
exc = None
|
||||
if timeout is None:
|
||||
timeout = 10
|
||||
found = [None for sel in selectors]
|
||||
while time.time() < t0 + timeout:
|
||||
for i, selector in enumerate(selectors):
|
||||
try:
|
||||
ele = find_element(session, selector)
|
||||
if not is_displayed or ele.is_displayed():
|
||||
found[i] = ele
|
||||
return found
|
||||
except NoSuchElementException as e:
|
||||
exc = e
|
||||
time.sleep(0.5)
|
||||
raise exc if exc is not None else NoSuchElementException
|
||||
return found
|
||||
|
||||
|
||||
def await_element(session, selector, timeout=None):
|
||||
return await_first_element_of(session, [selector], timeout)[0]
|
||||
|
||||
|
||||
def load_page_and_wait_for_iframe(session, url, selector, loads=1, timeout=None):
|
||||
while loads > 0:
|
||||
session.get(url)
|
||||
frame = await_element(session, selector, timeout=timeout)
|
||||
loads -= 1
|
||||
session.switch_to.frame(frame)
|
||||
return frame
|
|
@ -0,0 +1,17 @@
|
|||
import pytest
|
||||
from helpers import Css, expect_alert, find_element
|
||||
|
||||
URL = "https://ib.absa.co.za/absa-online/login.jsp"
|
||||
|
||||
|
||||
@pytest.mark.with_interventions
|
||||
def test_enabled(session):
|
||||
session.get(URL)
|
||||
assert find_element(session, Css("html.gecko"))
|
||||
|
||||
|
||||
@pytest.mark.without_interventions
|
||||
def test_disabled(session):
|
||||
session.get(URL)
|
||||
expect_alert(session, text="Browser unsupported")
|
||||
assert find_element(session, Css("html.unknown"))
|
|
@ -0,0 +1,16 @@
|
|||
import pytest
|
||||
|
||||
|
||||
URL = "http://histography.io/"
|
||||
|
||||
|
||||
@pytest.mark.with_interventions
|
||||
def test_enabled(session):
|
||||
session.get(URL)
|
||||
assert session.current_url == URL
|
||||
|
||||
|
||||
@pytest.mark.without_interventions
|
||||
def test_disabled(session):
|
||||
session.get(URL)
|
||||
assert session.current_url == "http://histography.io/browser_support.htm"
|
|
@ -0,0 +1,19 @@
|
|||
import time
|
||||
import pytest
|
||||
from helpers import Css, await_element, find_element
|
||||
|
||||
URL = "https://www.bankofamerica.com/"
|
||||
|
||||
|
||||
@pytest.mark.with_interventions
|
||||
def test_enabled(session):
|
||||
session.get(URL)
|
||||
time.sleep(3)
|
||||
assert find_element(session, Css("#browserUpgradeNoticeBar"), default=None) is None
|
||||
|
||||
|
||||
@pytest.mark.without_interventions
|
||||
def test_disabled(session):
|
||||
session.get(URL)
|
||||
warning = await_element(session, Css("#browserUpgradeNoticeBar"), timeout=3)
|
||||
assert warning.is_displayed()
|
|
@ -0,0 +1,92 @@
|
|||
import pytest
|
||||
from helpers import (
|
||||
Css,
|
||||
Text,
|
||||
Xpath,
|
||||
await_element,
|
||||
await_first_element_of,
|
||||
await_getUserMedia_call_on_click,
|
||||
find_element,
|
||||
assert_not_element,
|
||||
)
|
||||
|
||||
|
||||
URL = "https://steamcommunity.com/chat"
|
||||
|
||||
|
||||
USERID_CSS = Css("input#input_username")
|
||||
PASSWORD_CSS = Css("input#input_password")
|
||||
SIGNIN_CSS = Css("#login_btn_signin button")
|
||||
GEAR_CSS = Css(".friendSettingsButton")
|
||||
AUTH_CSS = Css("input#authcode")
|
||||
RATE_TEXT = Text("too many login failures")
|
||||
VOICE_XPATH = Xpath(
|
||||
"//*[contains(text(), 'Voice') and "
|
||||
"contains(@class, 'pagedsettings_PagedSettingsDialog_PageListItem')]"
|
||||
)
|
||||
MIC_BUTTON_CSS = Css("button.LocalMicTestButton")
|
||||
UNSUPPORTED_TEXT = Text("currently unsupported in Firefox")
|
||||
|
||||
|
||||
def load_mic_test(session, credentials):
|
||||
session.get(URL)
|
||||
|
||||
userid = find_element(session, USERID_CSS)
|
||||
password = find_element(session, PASSWORD_CSS)
|
||||
submit = find_element(session, SIGNIN_CSS)
|
||||
assert userid.is_displayed()
|
||||
assert password.is_displayed()
|
||||
assert submit.is_displayed()
|
||||
|
||||
userid.send_keys(credentials["username"])
|
||||
password.send_keys(credentials["password"])
|
||||
submit.click()
|
||||
|
||||
while True:
|
||||
[gear, auth, rate] = await_first_element_of(
|
||||
session, [GEAR_CSS, AUTH_CSS, RATE_TEXT], is_displayed=True, timeout=20
|
||||
)
|
||||
if rate:
|
||||
pytest.skip(
|
||||
"Too many Steam login attempts detected in a short time; try again later."
|
||||
)
|
||||
return None
|
||||
elif auth:
|
||||
pytest.skip("Two-factor authentication requested; disable Steam Guard.")
|
||||
return None
|
||||
else:
|
||||
break
|
||||
assert gear
|
||||
gear.click()
|
||||
|
||||
voice = await_element(session, VOICE_XPATH)
|
||||
assert voice.is_displayed()
|
||||
voice.click()
|
||||
|
||||
mic_test = await_element(session, MIC_BUTTON_CSS)
|
||||
assert mic_test.is_displayed()
|
||||
|
||||
return mic_test
|
||||
|
||||
|
||||
@pytest.mark.with_interventions
|
||||
def test_enabled(session, credentials):
|
||||
mic_test = load_mic_test(session, credentials)
|
||||
if not mic_test:
|
||||
return
|
||||
|
||||
await_getUserMedia_call_on_click(session, mic_test)
|
||||
|
||||
assert_not_element(session, UNSUPPORTED_TEXT)
|
||||
|
||||
|
||||
@pytest.mark.without_interventions
|
||||
def test_disabled(session, credentials):
|
||||
mic_test = load_mic_test(session, credentials)
|
||||
if not mic_test:
|
||||
return
|
||||
|
||||
mic_test.click()
|
||||
|
||||
unsupported = await_element(session, UNSUPPORTED_TEXT)
|
||||
assert unsupported.is_displayed()
|
|
@ -0,0 +1,43 @@
|
|||
import pytest
|
||||
from helpers import Css, Text, find_element
|
||||
|
||||
|
||||
def load_site(session):
|
||||
session.get("https://www.mobilesuica.com/")
|
||||
|
||||
address = find_element(session, Css("input[name=MailAddress]"), default=None)
|
||||
password = find_element(session, Css("input[name=Password]"), default=None)
|
||||
error = find_element(session, Css("input[name=winclosebutton]"), default=None)
|
||||
|
||||
# The page can be down at certain times, making testing impossible. For instance:
|
||||
# "モバイルSuicaサービスが可能な時間は4:00~翌日2:00です。
|
||||
# 時間をお確かめの上、再度実行してください。"
|
||||
# "Mobile Suica service is available from 4:00 to 2:00 the next day.
|
||||
# Please check the time and try again."
|
||||
site_is_down = None is not find_element(
|
||||
session, Text("時間をお確かめの上、再度実行してください。"), default=None
|
||||
)
|
||||
if site_is_down:
|
||||
pytest.xfail("Site is currently down")
|
||||
|
||||
return address, password, error, site_is_down
|
||||
|
||||
|
||||
@pytest.mark.with_interventions
|
||||
def test_enabled(session):
|
||||
address, password, error, site_is_down = load_site(session)
|
||||
if site_is_down:
|
||||
return
|
||||
assert address.is_displayed()
|
||||
assert password.is_displayed()
|
||||
assert error is None
|
||||
|
||||
|
||||
@pytest.mark.without_interventions
|
||||
def test_disabled(session):
|
||||
address, password, error, site_is_down = load_site(session)
|
||||
if site_is_down:
|
||||
return
|
||||
assert address is None
|
||||
assert password is None
|
||||
assert error.is_displayed()
|
|
@ -0,0 +1,42 @@
|
|||
import pytest
|
||||
from helpers import (
|
||||
Css,
|
||||
Text,
|
||||
await_element,
|
||||
load_page_and_wait_for_iframe,
|
||||
find_element,
|
||||
)
|
||||
|
||||
# Note that we have to load this page twice, as when it is loaded the
|
||||
# first time by the tests, the webcompat issue is avoided somehow
|
||||
# (presumably a script race condition somewhere). However, it is
|
||||
# triggered consistently the second time it is loaded.
|
||||
|
||||
|
||||
URL = "https://ageor.dipot.com/2020/03/Covid-19-in-Greece.html"
|
||||
FRAME_SELECTOR = Css("iframe[src^='https://datastudio.google.com/']")
|
||||
FRAME_TEXT = Text("Coranavirus SARS-CoV-2 (Covid-19) in Greece")
|
||||
|
||||
|
||||
@pytest.mark.with_interventions
|
||||
def test_enabled(session):
|
||||
load_page_and_wait_for_iframe(session, URL, FRAME_SELECTOR, loads=2)
|
||||
assert session.execute_script("return window.indexedDB === undefined;")
|
||||
success_text = await_element(session, FRAME_TEXT)
|
||||
assert success_text.is_displayed()
|
||||
|
||||
|
||||
@pytest.mark.without_interventions
|
||||
def test_disabled(session):
|
||||
load_page_and_wait_for_iframe(session, URL, FRAME_SELECTOR, loads=2)
|
||||
assert session.execute_script(
|
||||
"""
|
||||
try {
|
||||
window.indexedDB;
|
||||
return false;
|
||||
} catch (_) {
|
||||
return true;
|
||||
}
|
||||
"""
|
||||
)
|
||||
assert find_element(session, FRAME_TEXT, default=None) is None
|
|
@ -0,0 +1,21 @@
|
|||
import pytest
|
||||
from helpers import Css, await_element, find_element
|
||||
|
||||
|
||||
URL = "https://m.aliexpress.com/?tracelog=wwwhome2mobilesitehome"
|
||||
SELECTOR = Css("#header input[placeholder]")
|
||||
DISABLED_SELECTOR = Css(f"{SELECTOR.value}:disabled")
|
||||
|
||||
|
||||
@pytest.mark.with_interventions
|
||||
def test_enabled(session):
|
||||
session.get(URL)
|
||||
find_element(session, SELECTOR)
|
||||
assert find_element(session, DISABLED_SELECTOR, default=None) is None
|
||||
|
||||
|
||||
@pytest.mark.without_interventions
|
||||
def test_disabled(session):
|
||||
session.get(URL)
|
||||
await_element(session, SELECTOR)
|
||||
find_element(session, DISABLED_SELECTOR)
|
|
@ -0,0 +1,17 @@
|
|||
import pytest
|
||||
|
||||
|
||||
URL = "https://buskocchi.desuca.co.jp/smartPhone.html"
|
||||
SCRIPT = """return document.getElementById("map_canvas")?.clientHeight;"""
|
||||
|
||||
|
||||
@pytest.mark.with_interventions
|
||||
def test_enabled(session):
|
||||
session.get(URL)
|
||||
assert session.execute_script(SCRIPT)
|
||||
|
||||
|
||||
@pytest.mark.without_interventions
|
||||
def test_disabled(session):
|
||||
session.get(URL)
|
||||
assert session.execute_script(SCRIPT)
|
|
@ -0,0 +1,28 @@
|
|||
import pytest
|
||||
from helpers import Css, find_element
|
||||
|
||||
|
||||
URL = (
|
||||
"https://www.saxoinvestor.fr/login/?adobe_mc="
|
||||
"MCORGID%3D173338B35278510F0A490D4C%2540AdobeOrg%7CTS%3D1621688498"
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.skip_platforms("linux")
|
||||
@pytest.mark.with_interventions
|
||||
def test_enabled(session):
|
||||
session.get(URL)
|
||||
userid = find_element(session, Css("input#field_userid"))
|
||||
password = find_element(session, Css("input#field_password"))
|
||||
submit = find_element(session, Css("input#button_login"))
|
||||
assert userid.is_displayed()
|
||||
assert password.is_displayed()
|
||||
assert submit.is_displayed()
|
||||
|
||||
|
||||
@pytest.mark.skip_platforms("linux")
|
||||
@pytest.mark.without_interventions
|
||||
def test_disabled(session):
|
||||
session.get(URL)
|
||||
warning = find_element(session, Css("#browser_support_section"))
|
||||
assert warning.is_displayed()
|
|
@ -0,0 +1,28 @@
|
|||
import pytest
|
||||
from helpers import Css, is_float_cleared, find_element
|
||||
|
||||
|
||||
URL = (
|
||||
"https://www.lcbo.com/webapp/wcs/stores/servlet/PhysicalStoreInventoryView"
|
||||
"?langId=-1&storeId=10203&catalogId=10051&productId=54875"
|
||||
)
|
||||
|
||||
|
||||
PRODUCT_INFO = Css("#content > div")
|
||||
LOCATIONS = Css("#inventoryTable")
|
||||
|
||||
|
||||
@pytest.mark.with_interventions
|
||||
def test_enabled(session):
|
||||
session.get(URL)
|
||||
product_info = find_element(session, PRODUCT_INFO)
|
||||
locations = find_element(session, LOCATIONS)
|
||||
assert is_float_cleared(session, locations, product_info)
|
||||
|
||||
|
||||
@pytest.mark.without_interventions
|
||||
def test_disabled(session):
|
||||
session.get(URL)
|
||||
product_info = find_element(session, PRODUCT_INFO)
|
||||
locations = find_element(session, LOCATIONS)
|
||||
assert not is_float_cleared(session, locations, product_info)
|
|
@ -0,0 +1,25 @@
|
|||
import pytest
|
||||
from helpers import Css, is_float_cleared, find_element
|
||||
|
||||
|
||||
URL = "https://curriculum.gov.bc.ca/curriculum/arts-education/10/media-arts"
|
||||
|
||||
|
||||
SHOULD_CLEAR = Css(".curriculum_big_ideas")
|
||||
SHOULD_BE_CLEARED = Css(".view-display-id-attachment_1")
|
||||
|
||||
|
||||
@pytest.mark.with_interventions
|
||||
def test_enabled(session):
|
||||
session.get(URL)
|
||||
should_clear = find_element(session, SHOULD_CLEAR)
|
||||
should_be_cleared = find_element(session, SHOULD_BE_CLEARED)
|
||||
assert is_float_cleared(session, should_clear, should_be_cleared)
|
||||
|
||||
|
||||
@pytest.mark.without_interventions
|
||||
def test_disabled(session):
|
||||
session.get(URL)
|
||||
should_clear = find_element(session, SHOULD_CLEAR)
|
||||
should_be_cleared = find_element(session, SHOULD_BE_CLEARED)
|
||||
assert not is_float_cleared(session, should_clear, should_be_cleared)
|
Загрузка…
Ссылка в новой задаче