Skip to content

Commit

Permalink
Added install and enable test (mozilla#2842)
Browse files Browse the repository at this point in the history
  • Loading branch information
b4handjr authored and lmorchard committed Sep 11, 2017
1 parent 8466ef8 commit 2d63f46
Showing 15 changed files with 178 additions and 43 deletions.
6 changes: 1 addition & 5 deletions bin/circleci/build-frontend.sh
Original file line number Diff line number Diff line change
@@ -1,8 +1,4 @@
#!/bin/bash
set -ex
if [[ $CIRCLE_BRANCH == 'master' ]]; then
NODE_ENV=production ENABLE_PONTOON=1 ENABLE_DEV_CONTENT=1 ENABLE_DEV_LOCALES=1 npm run static
else
NODE_ENV=production ENABLE_PONTOON=0 ENABLE_DEV_CONTENT=0 ENABLE_DEV_LOCALES=0 npm run static
fi
NODE_ENV=production ENABLE_PONTOON=1 ENABLE_DEV_CONTENT=1 ENABLE_DEV_LOCALES=1 npm run static
zip -r $CIRCLE_ARTIFACTS/frontend.zip frontend/build
File renamed without changes.
1 change: 1 addition & 0 deletions bin/circleci/test-firefox-dev.sh
Original file line number Diff line number Diff line change
@@ -11,4 +11,5 @@ fi
mozinstall $(ls -t /home/ubuntu/firefox-downloads/firefox_dev/*.tar.bz2 | head -1)
firefox --version
export PYTEST_ADDOPTS=--html=integration-test-results/ui-test-dev.html
export SKIP_INSTALL_TEST=True
tox -e ui-tests
1 change: 1 addition & 0 deletions bin/circleci/test-firefox-release.sh
Original file line number Diff line number Diff line change
@@ -11,4 +11,5 @@ fi
mozinstall $(ls -t /home/ubuntu/firefox-downloads/firefox/*.tar.bz2 | head -1)
firefox --version
export PYTEST_ADDOPTS=--html=integration-test-results/ui-test-release.html
export SKIP_INSTALL_TEST=True
tox -e ui-tests
4 changes: 2 additions & 2 deletions circle.yml
Original file line number Diff line number Diff line change
@@ -7,6 +7,7 @@ machine:
environment:
DISPLAY: :99
PATH: "/home/ubuntu/testpilot/firefox:$PATH"
MOZ_HEADLESS: 1
hosts:
example.com: 127.0.0.1
node:
@@ -38,8 +39,7 @@ test:
- ./bin/circleci/flake8.sh
- mkdir integration-test-results
- ./bin/circleci/test-firefox-release.sh
- ./bin/circleci/test-firefox-dev.sh
- # ./bin/circleci/test-firefox-nightly.sh
- ./bin/circleci/test-firefox-nightly.sh
post:
- bash <(curl -s https://codecov.io/bash)
- cp -r integration-test-results $CIRCLE_ARTIFACTS
2 changes: 0 additions & 2 deletions content-src/experiments/dev-example.yaml
Original file line number Diff line number Diff line change
@@ -78,8 +78,6 @@ contributors:
title: 'Engineering Intern'
avatar: /static/images/experiments/min-vid/avatars/jen-kagan.jpg
created: '2016-09-22T00:07:28.847430Z'
completed: '2016-11-16T20:15:00Z'
uninstalled: '2017-02-05T00:00:00Z'
order: 999
testpilot_options:
ratings: disabled
3 changes: 2 additions & 1 deletion frontend/test/ui/conftest.py
Original file line number Diff line number Diff line change
@@ -17,7 +17,8 @@ def firefox_options(firefox_options):
'extensions.install.requireBuiltInCerts', False)
firefox_options.set_preference('xpinstall.signatures.required', False)
firefox_options.set_preference('extensions.webapi.testing', True)
firefox_options.set_preference('example.com', 'local')
firefox_options.set_preference('testpilot.env', 'local')
firefox_options.add_argument('-foreground')
firefox_options.log.level = 'trace'
return firefox_options

2 changes: 1 addition & 1 deletion frontend/test/ui/pages/desktop/base.py
Original file line number Diff line number Diff line change
@@ -9,7 +9,7 @@ class Base(Page):

def __init__(self, selenium, base_url, **kwargs):
super(Base, self).__init__(
selenium, base_url, timeout=10, **kwargs)
selenium, base_url, timeout=30, **kwargs)

def wait_for_page_to_load(self):
self.wait.until(lambda _: self.find_element(
28 changes: 28 additions & 0 deletions frontend/test/ui/pages/desktop/detail.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from pypom import Region
from selenium.webdriver.common.by import By

from pages.desktop.base import Base
@@ -7,9 +8,36 @@ class Detail(Base):
"""Represents the individual details page of an experiment"""
_root_locator = (By.CLASS_NAME, 'default-background')
_name_locator = (By.CSS_SELECTOR, '.details-header > header > h1')
_enable_locator = (By.ID, 'install-button')

def wait_for_page_to_load(self):
self.wait.until(
lambda _: self.find_element(*self._name_locator).is_displayed())

@property
def enabled_popup(self):
return self.EnabledPopup(self)

@property
def name(self):
"""Returns the experiments name from the details page"""
self.wait.until(lambda _: self.find_element(*self._name_locator))
return self.find_element(*self._name_locator).text

def enable(self):
self.wait_for_page_to_load()
self.wait.until(lambda _: self.find_element(
*self._enable_locator).is_displayed())
self.find_element(*self._enable_locator).click()

class EnabledPopup(Region):
_root_locator = (By.CSS_SELECTOR, '.tour-modal')
_popup_header_locator = (By.CSS_SELECTOR, '.modal-header-wrapper')

def wait_for_region_to_load(self):
self.wait.until(
lambda _: self.root.is_displayed())

def is_popup_displayed(self):
el = self.find_element(*self._popup_header_locator).is_displayed()
return el
72 changes: 72 additions & 0 deletions frontend/test/ui/pages/desktop/experiments.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
from pypom import Region
from selenium.webdriver.common.by import By

from pages.desktop.base import Base


class Experiments(Base):
"""Represents the experiments page"""

_experiment_locator = (By.CLASS_NAME, 'experiment-summary')

@property
def welcome_popup(self):
return self.WelcomePopup(self)

@property
def list(self):
"""Return list of experiments on experiments page."""
experiments = self.find_elements(*self._experiment_locator)
return [self.ExperimentsPreview(self, el) for el in experiments]

def find_experiment(self, experiment=None):
"""Locate experiment given.
Args:
str: Experiment name.
Returns:
obj: Experiment Detail object.
"""
for item in self.list:
if experiment in item.name:
item.click()
from pages.desktop.detail import Detail
return Detail(self.selenium, self.base_url)
else:
continue
raise AttributeError('Experiment: {0}, not found.'.format(experiment))

class WelcomePopup(Region):
_root_locator = (By.ID, 'first-page')
_close_button_locator = (By.CSS_SELECTOR, '.modal-cancel')
_popup_locator_title = (By.CSS_SELECTOR, '.modal-header-wrapper h3')

def wait_for_region_to_load(self):
self.wait.until(lambda _: 'Welcome to Test Pilot!' in self.title)

def close(self):
"""Close welcome popup using the close button."""
self.find_element(*self._close_button_locator).click()

@property
def title(self):
"""Return title text of popup."""
return self.find_element(*self._popup_locator_title).text

class ExperimentsPreview(Region):
"""Represents the experiments region."""
_name_locator = (By.CSS_SELECTOR, '.experiment-information > \
header > div > h3')

@property
def name(self):
"""Returns the experiments name."""
return self.find_element(*self._name_locator).text

def click(self):
"""Clicks on the experiment."""
self.root.click()
from pages.desktop.detail import Detail
return Detail(self.selenium, self.page.base_url)
40 changes: 23 additions & 17 deletions frontend/test/ui/pages/desktop/home.py
Original file line number Diff line number Diff line change
@@ -26,63 +26,69 @@ class Header(Region):

@property
def is_copter_displayed(self):
"""Return if firefox copter is displayed."""
return self.find_element(*self._copter_locator).is_displayed()

@property
def is_install_button_displayed(self):
"""Return if the testplot addon install button is displayed."""
return self.find_element(*self._install_locator).is_displayed()

def click_install_button(self):
"""Clicks the button to install the testpilot addon.
Returns:
obj: Experiments object.
"""
self.find_element(*self._install_locator).click()
from .experiments import Experiments
return Experiments(self.selenium, self.page.base_url)

class Body(Region):
"""Represents the main body of the page"""
_root_locator = (By.CLASS_NAME, 'layout-wrapper--card-list')
_experiment_locator = (By.CLASS_NAME, 'experiment-summary')

@property
def experiments(self):
"""Return list of experiements on home page."""
experiments = self.find_elements(*self._experiment_locator)
return [self.Experiments(self.page, el) for el in experiments]

class Experiments(Region):
"""Represents the experiments region"""
"""Represents the experiments region."""
_name_locator = (By.CSS_SELECTOR, '.experiment-information > \
header > div > h3')

@property
def name(self):
"""Returns the experiments name"""
"""Returns the experiments name."""
return self.find_element(*self._name_locator).text

def click(self):
"""Clicks on the experiment"""
"""Clicks on the experiment."""
self.root.click()
from pages.desktop.detail import Detail
return Detail(self.selenium, self.page.base_url)

class SignUpFooter(Region):
"""Represents the footer"""
"""Represents the footer."""
_root_locator = (By.CLASS_NAME, 'newsletter-footer')
_error_locator = (By.CLASS_NAME, 'error')
_privacy_checkbox_locator = (By.CSS_SELECTOR, '.revealed-field input')
_privacy_checkbox_locator = (By.CSS_SELECTOR, 'input#privacy')
_sign_up_locator = (By.CSS_SELECTOR, 'input')
_sign_up_now_locator = (By.CLASS_NAME, 'button')
_stay_informed_locator = (By.CSS_SELECTOR, 'h2')

def sign_up(self, email):
"""Signs up with an email provided"""
"""Signs up with an email provided."""
email_input = self.find_element(*self._sign_up_locator)
email_input.send_keys(email)
self.wait.until(
lambda _: self.find_element(*self._privacy_checkbox_locator))
self.find_element(*self._privacy_checkbox_locator).click()
self.find_element(*self._sign_up_now_locator).click()

@property
def is_stay_informed_displayed(self):
return self.find_element(*self._stay_informed_locator).is_displayed

@property
def email_error_header(self):
self.wait.until(
lambda _: self.find_element(
*self._error_locator).is_displayed())
return self.find_element(*self._error_locator)
"""Return if stay informed is displayed."""
return self.find_element(
*self._stay_informed_locator).is_displayed()
2 changes: 2 additions & 0 deletions frontend/test/ui/requirements/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
PyPOM==1.2.0
pytest==3.2.2
pytest-selenium==1.11.1
pytest-firefox==0.1.0
pytest-repeat==0.4.1
pytest-variables==1.7.0
pytest-xdist==1.20.0
requests==2.18.4
15 changes: 3 additions & 12 deletions frontend/test/ui/test_homepage.py
Original file line number Diff line number Diff line change
@@ -30,12 +30,12 @@ def test_number_of_experiments(base_url, selenium):
url = '{0}/{1}'.format(base_url, 'api/experiments.json')
# Ping api to get current number of completed experiments
data = requests.get(url, verify=False).json()
# add one for dev experiment
completed_experiments = len(
[value for value in data['results'] if 'completed' in value and
value['completed'] < str(datetime.utcnow())])
# Subtract 1 from the experiments found through the api due to locale
value['completed'] < str(datetime.utcnow())]) + 1
assert len(page.body.experiments) == int(
len(data['results']) - completed_experiments) - 1
len(data['results']) - completed_experiments)


@pytest.mark.nondestructive
@@ -58,15 +58,6 @@ def test_support_pages(base_url, selenium, page, title):
assert title in page.title


@pytest.mark.nondestructive
def test_bad_email(base_url, selenium):
"""Test email signup with uncompleted url"""
page = Home(selenium, base_url).open()
assert page.signup_footer.is_stay_informed_displayed
page.signup_footer.sign_up('test@mozilla')
assert page.signup_footer.email_error_header.is_displayed


@pytest.mark.nondestructive
def test_incomplete_email(base_url, selenium):
"""Test signup with incorrect email"""
37 changes: 37 additions & 0 deletions frontend/test/ui/test_install.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import os

import pytest

from pages.desktop.home import Home
from pages.desktop.detail import Detail


@pytest.mark.nondestructive
@pytest.mark.skipif(os.environ.get('SKIP_INSTALL_TEST') is not None,
reason='Skip install on Release and Beta Firefox.')
def test_install_of_test_pilot_addon(
base_url, selenium, firefox, notifications):
"""Check that the testpilot addon is installable and installs."""
page = Home(selenium, base_url).open()
experiments = page.header.click_install_button()
firefox.browser.wait_for_notification(notifications.AddOnInstallComplete)
assert 'Welcome to Test Pilot!' in experiments.welcome_popup.title


@pytest.mark.nondestructive
@pytest.mark.skipif(os.environ.get('SKIP_INSTALL_TEST') is not None,
reason='Skip install on Release and Beta Firefox.')
def test_enable_experiment(base_url, selenium, firefox, notifications):
"""Test enabling of an experiment."""
page = Home(selenium, base_url).open()
experiments = page.header.click_install_button()
experiments.welcome_popup.close()
experiment = experiments.find_experiment(experiment='Dev Example')
experiment.enable()
firefox.browser.wait_for_notification(
notifications.AddOnInstallComplete).close()
firefox.browser.wait_for_notification(
notifications.AddOnInstallConfirmation).install()
firefox.browser.wait_for_notification(
notifications.AddOnInstallComplete).close()
assert Detail(selenium, base_url).enabled_popup.is_popup_displayed()
8 changes: 5 additions & 3 deletions tox.ini
Original file line number Diff line number Diff line change
@@ -3,11 +3,13 @@ envlist = ui-tests, flake8
skipsdist = True

[testenv:ui-tests]
passenv = DISPLAY PYTEST_ADDOPTS
passenv = DISPLAY PYTEST_ADDOPTS MOZ_HEADLESS SKIP_INSTALL_TEST
basepython = python3.6
deps = -rfrontend/test/ui/requirements/requirements.txt
whitelist_externals =
bash
commands =
bash bin/circleci/run-integration-tests.sh
bash bin/circleci/start-server.sh
pytest -v --verify-base-url --driver=Firefox --self-contained-html frontend/test/ui {posargs}

[testenv:flake8]
@@ -16,7 +18,7 @@ deps = -rfrontend/test/ui/requirements/flake8.txt
commands = flake8 {posargs:.}

[flake8]
exclude = .tox, node_modules
exclude = .tox,node_modules

[pytest]
base_url = https://example.com:8000

0 comments on commit 2d63f46

Please sign in to comment.