Initial UI integration tests
This commit is contained in:
Родитель
1bce407fa1
Коммит
fefca816a0
|
@ -0,0 +1,60 @@
|
|||
import datetime
|
||||
import os
|
||||
import urlparse
|
||||
|
||||
from fxapom.fxapom import DEV_URL, PROD_URL, FxATestAccount
|
||||
import jwt
|
||||
import pytest
|
||||
import requests
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def fxa_account(base_url):
|
||||
url = DEV_URL if 'dev' in base_url else PROD_URL
|
||||
return FxATestAccount(url)
|
||||
|
||||
|
||||
@pytest.fixture(scope='session')
|
||||
def jwt_issuer(base_url, variables):
|
||||
try:
|
||||
hostname = [urlparse.urlsplit(base_url).hostname]
|
||||
return variables['api'][hostname]['jwt_issuer']
|
||||
except KeyError:
|
||||
return os.getenv('JWT_ISSUER')
|
||||
|
||||
|
||||
@pytest.fixture(scope='session')
|
||||
def jwt_secret(base_url, variables):
|
||||
try:
|
||||
hostname = [urlparse.urlsplit(base_url).hostname]
|
||||
return variables['api'][hostname]['jwt_secret']
|
||||
except KeyError:
|
||||
return os.getenv('JWT_SECRET')
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def jwt_token(base_url, jwt_issuer, jwt_secret):
|
||||
payload = {
|
||||
'iss': jwt_issuer,
|
||||
'iat': datetime.datetime.utcnow(),
|
||||
'exp': datetime.datetime.utcnow() + datetime.timedelta(seconds=30)}
|
||||
return jwt.encode(payload, jwt_secret, algorithm='HS256')
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def user(base_url, fxa_account, jwt_token):
|
||||
user = {
|
||||
'email': fxa_account.email,
|
||||
'password': fxa_account.password,
|
||||
'username': fxa_account.email.split('@')[0]}
|
||||
url = '{base_url}/api/v3/accounts/super-create/'.format(base_url=base_url)
|
||||
params = {
|
||||
'email': user['email'],
|
||||
'username': user['username'],
|
||||
'password': user['password'],
|
||||
'fxa_id': fxa_account.session.uid}
|
||||
headers = {'Authorization': 'JWT {token}'.format(token=jwt_token)}
|
||||
r = requests.post(url, data=params, headers=headers)
|
||||
assert requests.codes.created == r.status_code
|
||||
user.update(r.json())
|
||||
return user
|
|
@ -0,0 +1,50 @@
|
|||
from pypom import Page, Region
|
||||
from selenium.webdriver.common.by import By
|
||||
from selenium.webdriver.common.action_chains import ActionChains
|
||||
|
||||
|
||||
class Base(Page):
|
||||
|
||||
_url = '{base_url}/{locale}'
|
||||
|
||||
def __init__(self, selenium, base_url, locale='en-US', **kwargs):
|
||||
super(Base, self).__init__(selenium, base_url, locale=locale, **kwargs)
|
||||
|
||||
@property
|
||||
def header(self):
|
||||
return self.Header(self)
|
||||
|
||||
@property
|
||||
def logged_in(self):
|
||||
"""Returns True if a user is logged in"""
|
||||
return self.is_element_displayed(*self.header._user_locator)
|
||||
|
||||
def login(self, email, password):
|
||||
login_page = self.header.click_login()
|
||||
login_page.login(email, password)
|
||||
|
||||
def logout(self):
|
||||
self.header.click_logout()
|
||||
|
||||
class Header(Region):
|
||||
|
||||
_root_locator = (By.CLASS_NAME, 'amo-header')
|
||||
_login_locator = (By.CSS_SELECTOR, '#aux-nav .account a:nth-child(2)')
|
||||
_logout_locator = (By.CSS_SELECTOR, '.logout > a')
|
||||
_user_locator = (By.CSS_SELECTOR, '#aux-nav .account .user')
|
||||
|
||||
def click_login(self):
|
||||
self.find_element(*self._login_locator).click()
|
||||
from pages.desktop.login import Login
|
||||
return Login(self.selenium, self.page.base_url)
|
||||
|
||||
def click_logout(self):
|
||||
user = self.find_element(*self._user_locator)
|
||||
logout = self.find_element(*self._logout_locator)
|
||||
action = ActionChains(self.selenium)
|
||||
action.move_to_element(user)
|
||||
action.move_to_element(logout)
|
||||
action.click()
|
||||
action.perform()
|
||||
self.wait.until(lambda s: self.is_element_displayed(
|
||||
*self._login_locator))
|
|
@ -0,0 +1,41 @@
|
|||
from pypom import Region
|
||||
from selenium.webdriver.common.by import By
|
||||
|
||||
from base import Base
|
||||
|
||||
|
||||
class Home(Base):
|
||||
|
||||
@property
|
||||
def most_popular(self):
|
||||
return self.MostPopular(self)
|
||||
|
||||
class MostPopular(Region):
|
||||
"""Most popular extensions region"""
|
||||
|
||||
_root_locator = (By.ID, 'popular-extensions')
|
||||
_extension_locator = (By.CSS_SELECTOR, '.toplist li')
|
||||
|
||||
@property
|
||||
def extensions(self):
|
||||
return [self.Extension(self.page, el) for el in self.find_elements(
|
||||
*self._extension_locator)]
|
||||
|
||||
class Extension(Region):
|
||||
|
||||
_name_locator = (By.CLASS_NAME, 'name')
|
||||
_users_locator = (By.TAG_NAME, 'small')
|
||||
|
||||
def __repr__(self):
|
||||
return '{0.name} ({0.users:,} users)'.format(self)
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
"""Extension name"""
|
||||
return self.find_element(*self._name_locator).text
|
||||
|
||||
@property
|
||||
def users(self):
|
||||
"""Number of users that have downloaded the extension"""
|
||||
users_str = self.find_element(*self._users_locator).text
|
||||
return int(users_str.split()[0].replace(',', ''))
|
|
@ -0,0 +1,21 @@
|
|||
from selenium.webdriver.common.by import By
|
||||
|
||||
from pages.desktop.base import Base
|
||||
|
||||
|
||||
class Login(Base):
|
||||
|
||||
_email_locator = (By.ID, 'id_username')
|
||||
_continue_locator = (By.CSS_SELECTOR, '#normal-login .login-source-button')
|
||||
|
||||
def login(self, email, password):
|
||||
self.find_element(*self._email_locator).send_keys(email)
|
||||
self.find_element(*self._continue_locator).click()
|
||||
from fxapom.pages.sign_in import SignIn
|
||||
sign_in = SignIn(self.selenium)
|
||||
# TODO https://github.com/mozilla/fxapom/issues/33
|
||||
self.wait.until(lambda s: self.is_element_displayed(
|
||||
*sign_in._email_input_locator))
|
||||
sign_in.login_password = password
|
||||
sign_in.click_sign_in()
|
||||
self.wait.until(lambda s: self.logged_in)
|
|
@ -0,0 +1,8 @@
|
|||
fxapom==1.8.0
|
||||
PyJWT==1.4.0
|
||||
PyPOM==1.0
|
||||
pytest==2.9.2
|
||||
pytest-instafail==0.3.0
|
||||
pytest-selenium==1.2.1
|
||||
pytest-variables==1.4
|
||||
pytest-xdist==1.14
|
|
@ -0,0 +1,5 @@
|
|||
[pytest]
|
||||
addopts = -r=a --verbose
|
||||
base_url = https://addons-dev.allizom.org
|
||||
sensitive_url = mozilla\.(com|org)
|
||||
xfail_strict = true
|
|
@ -0,0 +1,19 @@
|
|||
import pytest
|
||||
|
||||
from pages.desktop.home import Home
|
||||
|
||||
|
||||
@pytest.mark.nondestructive
|
||||
def test_there_are_ten_most_popular_extensions(base_url, selenium):
|
||||
"""Ten most popular add-ons are listed"""
|
||||
page = Home(selenium, base_url).open()
|
||||
assert len(page.most_popular.extensions) == 10
|
||||
|
||||
|
||||
@pytest.mark.nondestructive
|
||||
def test_most_popular_extensions_are_sorted_by_users(base_url, selenium):
|
||||
"""Most popular add-ons are sorted by popularity"""
|
||||
page = Home(selenium, base_url).open()
|
||||
extensions = page.most_popular.extensions
|
||||
sorted_by_users = sorted(extensions, key=lambda e: e.users, reverse=True)
|
||||
assert sorted_by_users == extensions
|
|
@ -0,0 +1,23 @@
|
|||
import pytest
|
||||
|
||||
from pages.desktop.home import Home
|
||||
|
||||
|
||||
@pytest.mark.skip(
|
||||
reason='https://github.com/mozilla/addons-server/issues/2462')
|
||||
def test_login(base_url, selenium, user):
|
||||
"""User can login"""
|
||||
page = Home(selenium, base_url).open()
|
||||
assert not page.logged_in
|
||||
page.login(user['email'], user['password'])
|
||||
assert page.logged_in
|
||||
|
||||
|
||||
@pytest.mark.skip(
|
||||
reason='https://github.com/mozilla/addons-server/issues/2462')
|
||||
def test_logout(base_url, selenium, user):
|
||||
"""User can logout"""
|
||||
page = Home(selenium, base_url).open()
|
||||
page.login(user['email'], user['password'])
|
||||
page.logout()
|
||||
assert not page.logged_in
|
11
tox.ini
11
tox.ini
|
@ -1,5 +1,5 @@
|
|||
[tox]
|
||||
envlist = es, addons, devhub, editors, main, flake8, docs, assets
|
||||
envlist = es, addons, devhub, editors, main, ui-tests, flake8, docs, assets
|
||||
|
||||
[testenv]
|
||||
basepython = python2.7
|
||||
|
@ -16,7 +16,7 @@ whitelist_externals =
|
|||
commands =
|
||||
make update_deps
|
||||
npm install {toxinidir}
|
||||
py.test -m es_tests --cov-report= --cov-report= --cov=src/olympia/ -v {posargs}
|
||||
py.test -m es_tests --ignore=tests/ui/ --cov-report= --cov-report= --cov=src/olympia/ -v {posargs}
|
||||
|
||||
[testenv:addons]
|
||||
commands =
|
||||
|
@ -40,7 +40,12 @@ commands =
|
|||
commands =
|
||||
make update_deps
|
||||
npm install {toxinidir}
|
||||
py.test --create-db -n 3 -m 'not es_tests' -v --ignore src/olympia/addons/ --ignore src/olympia/devhub/ --ignore src/olympia/editors/ --cov-report= --cov=src/olympia/ {posargs}
|
||||
py.test --create-db -n 3 -m 'not es_tests' -v --ignore=tests/ui/ --ignore src/olympia/addons/ --ignore src/olympia/devhub/ --ignore src/olympia/editors/ --cov-report= --cov=src/olympia/ {posargs}
|
||||
|
||||
[testenv:ui-tests]
|
||||
install_command = pip install {packages}
|
||||
deps = -rtests/ui/requirements.txt
|
||||
commands = py.test --verify-base-url --driver=Firefox tests/ui {posargs}
|
||||
|
||||
[testenv:assets]
|
||||
commands =
|
||||
|
|
Загрузка…
Ссылка в новой задаче