Updated discopane tests and setup server to be able to run in HTTPS m… (#3808)
This commit is contained in:
Родитель
ba9efe0685
Коммит
b5ee4ca994
101
.travis.yml
101
.travis.yml
|
@ -1,42 +1,73 @@
|
|||
sudo: required
|
||||
_aliases:
|
||||
- &tox
|
||||
language: python
|
||||
python: 3.6
|
||||
before_install: nvm install 6
|
||||
install: pip install tox
|
||||
script: tox
|
||||
- &node-prod
|
||||
# This is the NodeJS version we run in production.
|
||||
language: node_js
|
||||
node_js: '6'
|
||||
before_install: npm install -g yarn
|
||||
- &node-next
|
||||
# This is the next NodeJS version we will support.
|
||||
language: node_js
|
||||
node_js: '8'
|
||||
before_install: npm install -g yarn
|
||||
services:
|
||||
- docker
|
||||
addons:
|
||||
# This should go back to `firefox: latest` after fixing
|
||||
# https://github.com/mozilla/addons-frontend/issues/3910
|
||||
firefox: "56.0"
|
||||
language: node_js
|
||||
node_js:
|
||||
- '6'
|
||||
- '8'
|
||||
env:
|
||||
matrix:
|
||||
# This is currently failing on master only.
|
||||
# See https://github.com/mozilla/addons-frontend/issues/2691
|
||||
# - TASK=build CHECK_BUNDLESIZE=1 ADDONS_FRONTEND_BUILD_ALL=1
|
||||
- TASK=build ADDONS_FRONTEND_BUILD_ALL=1
|
||||
- TASK=lint
|
||||
- TASK=test-ci
|
||||
- TASK=nsp-check
|
||||
- TOXENV=discopane-ui-tests GUI=1 PYTEST_BASE_URL=http://localhost:4000
|
||||
- TOXENV=flake8
|
||||
- TOXENV=dennis-lint
|
||||
cache:
|
||||
yarn: true
|
||||
directories:
|
||||
- node_modules
|
||||
before_install:
|
||||
- npm install -g yarn
|
||||
- if [ $TOXENV ]; then sudo pip install tox; fi
|
||||
- if [[ $TOXENV == 'discopane-ui-tests' ]]; then wget -O geckodriver.tar.gz https://github.com/mozilla/geckodriver/releases/download/v0.14.0/geckodriver-v0.14.0-linux64.tar.gz; fi
|
||||
- if [[ $TOXENV == 'discopane-ui-tests' ]]; then gunzip -c geckodriver.tar.gz | tar xopf -; fi
|
||||
- if [[ $TOXENV == 'discopane-ui-tests' ]]; then chmod +x geckodriver && sudo mv geckodriver /usr/local/bin; fi
|
||||
before_script:
|
||||
- if [ $GUI ]; then export DISPLAY=:99.0 && sh -e /etc/init.d/xvfb start && sleep 3; fi
|
||||
script:
|
||||
- if [[ $TOXENV == 'discopane-ui-tests' ]]; then
|
||||
yarn start-func-test-server;
|
||||
fi
|
||||
- if [ $TOXENV ]; then tox; fi
|
||||
- if [ $TASK ]; then yarn $TASK; fi
|
||||
- if [ $CHECK_BUNDLESIZE ]; then yarn bundlesize; fi
|
||||
jobs:
|
||||
include:
|
||||
# Test the build process.
|
||||
- stage:
|
||||
<<: *node-prod
|
||||
env: ADDONS_FRONTEND_BUILD_ALL=1
|
||||
script: yarn build
|
||||
- stage:
|
||||
<<: *node-next
|
||||
env: ADDONS_FRONTEND_BUILD_ALL=1
|
||||
script: yarn build
|
||||
# Run the unit/integration tests.
|
||||
- stage:
|
||||
<<: *node-prod
|
||||
script: yarn test-ci
|
||||
- stage:
|
||||
<<: *node-next
|
||||
script: yarn test-ci
|
||||
- stage:
|
||||
<<: *node-prod
|
||||
script: yarn lint
|
||||
- stage:
|
||||
<<: *node-prod
|
||||
script: yarn nsp-check
|
||||
# Run the functional tests.
|
||||
- stage:
|
||||
<<: *tox
|
||||
addons:
|
||||
firefox: latest-nightly
|
||||
hosts: example.com
|
||||
env: TOXENV=discopane-ui-tests GECKODRIVER=0.19.1 MOZ_HEADLESS=1 PATH=./node_modules/.bin:$PATH
|
||||
install:
|
||||
- yarn
|
||||
- yarn start-func-test-server &
|
||||
before_script:
|
||||
- wget -O /tmp/geckodriver.tar.gz https://github.com/mozilla/geckodriver/releases/download/v$GECKODRIVER/geckodriver-v$GECKODRIVER-linux64.tar.gz
|
||||
- mkdir $HOME/geckodriver && tar xvf /tmp/geckodriver.tar.gz -C $HOME/geckodriver
|
||||
- export PATH=$HOME/geckodriver:$PATH
|
||||
- firefox --version
|
||||
- geckodriver --version
|
||||
- pip install tox
|
||||
# Wait for server to be available
|
||||
- until $(curl --output /dev/null --silent --head --fail -k https://example.com:4000); do printf '.'; sleep 5; done
|
||||
- stage:
|
||||
<<: *tox
|
||||
env: TOXENV=flake8
|
||||
- stage:
|
||||
<<: *tox
|
||||
env: TOXENV=dennis-lint
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
# Local server SSL certs
|
||||
|
||||
These certs are used to enable SSL for local testing of discopane. They could probably be used elsewhere
|
||||
but this has not been tested as enabling SSL can interfere with the API proxy functionality.
|
|
@ -0,0 +1,25 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIEHjCCAwagAwIBAgIJAM6Q+Crh5gZfMA0GCSqGSIb3DQEBBQUAMGcxCzAJBgNV
|
||||
BAYTAlVTMQ0wCwYDVQQIEwRVdGFoMQ4wDAYDVQQHEwVQcm92bzEjMCEGA1UEChMa
|
||||
QUNNRSBTaWduaW5nIEF1dGhvcml0eSBJbmMxFDASBgNVBAMTC2V4YW1wbGUuY29t
|
||||
MB4XDTE2MDkyMDIxMjgwNFoXDTE5MDcxMTIxMjgwNFowZzELMAkGA1UEBhMCVVMx
|
||||
DTALBgNVBAgTBFV0YWgxDjAMBgNVBAcTBVByb3ZvMSMwIQYDVQQKExpBQ01FIFNp
|
||||
Z25pbmcgQXV0aG9yaXR5IEluYzEUMBIGA1UEAxMLZXhhbXBsZS5jb20wggEiMA0G
|
||||
CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCnarXdtAkPnBfo+ES8KEqEEltEOCpj
|
||||
9A15+ULR9LBq2WRverQatnBjS4dBYfjDehSMMu6UAwzU5k2uIv0Djg5ZKqKkBFIZ
|
||||
CClpkGklt2LHwWjC5YWgtdxyLD7fvW8erIOuOo+LdYBb+7qxKdwA+B+VPGqagiEB
|
||||
0X0LMnnUDhrFMdbT5YoH2L7RtUJOQcGRjrpsk3GWF5uROcIRLW9z74qeHGXCT6vS
|
||||
IW138N9zP/3N5uq7S1sdUop2oT55AH9NK4+sYDuhVAvOlAo173282B1BGvJpQ1b2
|
||||
5O/AVIokRwPgVldXBTJxJBWrsRvoX2SVLHy9PtW/kcm2W/U6BII4xa+3AgMBAAGj
|
||||
gcwwgckwHQYDVR0OBBYEFNv9msiJNDGbYNL0BTKmysRi3w1sMIGZBgNVHSMEgZEw
|
||||
gY6AFNv9msiJNDGbYNL0BTKmysRi3w1soWukaTBnMQswCQYDVQQGEwJVUzENMAsG
|
||||
A1UECBMEVXRhaDEOMAwGA1UEBxMFUHJvdm8xIzAhBgNVBAoTGkFDTUUgU2lnbmlu
|
||||
ZyBBdXRob3JpdHkgSW5jMRQwEgYDVQQDEwtleGFtcGxlLmNvbYIJAM6Q+Crh5gZf
|
||||
MAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBACwzXmdQLIX9O06hoFNH
|
||||
+4J8UlFC3d5EW38dxo86CjKB5SDZW3SU5jUwhHxULQ/96ruLnjGLOUkINKggiSjo
|
||||
NtnJUEUH8TTYr7HyIY8u2xG+09DQ0yRBGj4AD/wEaqSdPUpjjUc9DzJfI8h9O7Pc
|
||||
BCM3bSS8tBQMBT/tqTN36P6BrafK6R8vsPaOw9NhUz9/NdH0C7ufit8XcX75jZnS
|
||||
eYGMR9QMT/P5b+TTS9ilWxakBaBe5e8Y7dMhAISLzzqUn7XQAyS08lVSc4e6uK0d
|
||||
sQQjSb/8BAkxEHoVaglu0A3yzm/PLMXzxA8KbrNJiKbtBiHHjEqHkafG5Atf+X5b
|
||||
9Is=
|
||||
-----END CERTIFICATE-----
|
|
@ -0,0 +1,20 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIDPTCCAiUCCQC0vMkfhGs6UTANBgkqhkiG9w0BAQUFADBnMQswCQYDVQQGEwJV
|
||||
UzENMAsGA1UECBMEVXRhaDEOMAwGA1UEBxMFUHJvdm8xIzAhBgNVBAoTGkFDTUUg
|
||||
U2lnbmluZyBBdXRob3JpdHkgSW5jMRQwEgYDVQQDEwtleGFtcGxlLmNvbTAeFw0x
|
||||
NjA5MjAyMTI5MzRaFw00NDAyMDUyMTI5MzRaMFoxCzAJBgNVBAYTAlVTMQ0wCwYD
|
||||
VQQIEwRVdGFoMQ4wDAYDVQQHEwVQcm92bzEWMBQGA1UEChMNQUNNRSBUZWNoIElu
|
||||
YzEUMBIGA1UEAxMLZXhhbXBsZS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
|
||||
ggEKAoIBAQCb0LpXuWRQ+OEU2KpNy6cUGZRWOF0vacrzq4duuG+G9DGJ/XHb8nok
|
||||
LOBmZCYCFd73WlGSYo5lIemH+ulFMMAUKxwj2TtG2s8jCCVSdH57hEr1s5g+Duz/
|
||||
wNt+BCa6ltFWTqVYAPlLNJpMIccIG78+MbY+CshmvGcSy56HE3+QKXqDGm4IGkSk
|
||||
AZ2Wtzbgs84A/fWNe/47TCM/wBWU4NR2hcA5se1tIT9JOhLqO8nUStn6JCw0gG44
|
||||
eiglFw/ESPsDtI7ktqVfabqjOVTf8hCPOphPbj+xMgdguV1SHV9PlNIVcldAzfFr
|
||||
uHy7pmVorgJUL1QVDDyqzLDqvt6FXGV/AgMBAAEwDQYJKoZIhvcNAQEFBQADggEB
|
||||
AFKSQ1qhZUVa0t5w/iznJZelvvQ4BYYid8q2/I9sIxAmjd9brt7xVwRERMcCOja6
|
||||
vwECefEiGfM5jPQ084QxYlkmelpDoufIRCmoWacgGBlTGIs7/JK2B2M72kQrqvzJ
|
||||
h3i8xD1kLAa5Xi9Yq//L4cVJehHmgkeBtXsWZ8qUzHSlszbO8kzKPK/XFfq4y+WU
|
||||
uHDLFnF5oZtfvfyAF4vmGrYvkQZhjzMbn+UZk9ha98qP75s2/tZB7DwFwwErf50n
|
||||
Rv+yhmMV0gEB4mI5iP/sz3bzhgPdmfT8R8NR3qvjm9ZlZERhLsXoAaGjrFrXlARC
|
||||
bP7PbA4tloTTWNK9hPijKb0=
|
||||
-----END CERTIFICATE-----
|
|
@ -0,0 +1,27 @@
|
|||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEowIBAAKCAQEAm9C6V7lkUPjhFNiqTcunFBmUVjhdL2nK86uHbrhvhvQxif1x
|
||||
2/J6JCzgZmQmAhXe91pRkmKOZSHph/rpRTDAFCscI9k7RtrPIwglUnR+e4RK9bOY
|
||||
Pg7s/8DbfgQmupbRVk6lWAD5SzSaTCHHCBu/PjG2PgrIZrxnEsuehxN/kCl6gxpu
|
||||
CBpEpAGdlrc24LPOAP31jXv+O0wjP8AVlODUdoXAObHtbSE/SToS6jvJ1ErZ+iQs
|
||||
NIBuOHooJRcPxEj7A7SO5LalX2m6ozlU3/IQjzqYT24/sTIHYLldUh1fT5TSFXJX
|
||||
QM3xa7h8u6ZlaK4CVC9UFQw8qsyw6r7ehVxlfwIDAQABAoIBAGRgW5rlsI1FN2LB
|
||||
jTyepFybeebtWoKPyZGd/5pBMH+k0kENx4qkszCYxFrRy3ZudnuscH44BXl7FkFm
|
||||
T14mYKbderxRVhF4JhZwSfLLXyvc9plAACSCYwUDTaLps7ViMStDcNq3jeF32qqO
|
||||
2/QKQ/Ih/kALnDwqxM/j4pUr53KLdIXajwUYr2eP6Ad7Zn4oWxuQX24ovsEmEZao
|
||||
SvM/B/pZ0Q2MvErT5d8EZ61Eudw87ZqCRNz1+B1dIy5xC/tR6kp/pUcmmoaoffZL
|
||||
P/U5BoRu0ZJw0W0KR4BsSddxFoAJq6XlPj8wOlfuEoWQ+6MZj4wOKZkgeqsxh7lJ
|
||||
fvqTKWECgYEAzwyvf9aqlawgN6nf8TzprDDXlI+tHnl1uFP1zqbRBK8vZGM5NfVx
|
||||
apzEqE8dAiTfjqucvWKrDX+PsicwZLQuYO5N9cBIJUC9M0AkXvFP/qNB4sXJgnat
|
||||
WPLGwBpKWga2XyjuVN5N9900wI86kUF7VSMEh2s11lHrjQEYIpoq4nECgYEAwKcu
|
||||
S4U4FtMQ+1rLxor9g3r1jfyA3CsMa/74WEM2mvZTWUbWeSwrWsb3lgYAUMvJOHn/
|
||||
+bSbnYUt9TP7KSKu+Ar++OgDsqPsAVDMfJu+VYjPo+QWC3flYwMQx29DsGrd20mZ
|
||||
VY6MmiUJDygHMIgo/S+IIgBGIRpFeC4Q2IbF3u8CgYBpfp0tFcN0327K7dMcp1yo
|
||||
T3qIR2x9yoUglib4VCbLrDcJf0T3KUfQem/5EdZF8WO23dnO5SciiYw9yZnutZ+r
|
||||
47/1JzObR5EfO99MQMfxhl1bnks+HhnU6F48IykfFax2b/R/aYVwdVUbh97fg+3D
|
||||
Q0Rbe1TDDppmDdiuSL7xAQKBgQCIN+15Apo1MUpJn9qD6RT12YQ0v/xRMLMYzXDF
|
||||
38iFa3RlpLvTc9K33gWD83xXpLADmefPpM9/YoKrZPTLEjYLNqMwVcT/k/40s+/S
|
||||
j8DV8+V1abnYpA7yomFD0r1WyUlTW0frAd8SwusT52al/zCUTP6BpBXyJARIxLGu
|
||||
mCTiywKBgDBZXf7JKowyLpsqL+UqJylQK6AU+3qpyxjxL5NX4TRzftksyZwiAVSV
|
||||
70dt9lNR9pmo46bRa066kFsI24FjiHYnmYC93ESYdTemrropJqOHnRIsR3JsrPWj
|
||||
Jk+BJtRyAGyIKgdWfDCTs4bGC4N4R5IA/YKPEH7GheF/GwTW/Im/
|
||||
-----END RSA PRIVATE KEY-----
|
|
@ -116,11 +116,16 @@ new Promise((resolve) => {
|
|||
const runArgs = [
|
||||
'run',
|
||||
'-d',
|
||||
`--add-host=example.com:0.0.0.0`,
|
||||
'-p=4000:4000',
|
||||
'-e',
|
||||
`NODE_APP_INSTANCE=${appInstance}`,
|
||||
'-e',
|
||||
`NODE_ENV=${nodeEnv}`,
|
||||
'-e',
|
||||
`USE_HTTPS_FOR_DEV=true`,
|
||||
`-e`,
|
||||
`SERVER_HOST=example.com`,
|
||||
`--cidfile=${containerIdFile}`,
|
||||
// This will make sure we can read the logs.
|
||||
'--log-driver=json-file',
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import https from 'https';
|
||||
|
||||
import 'babel-polyfill';
|
||||
import 'raf/polyfill';
|
||||
|
@ -379,6 +380,8 @@ export function runServer({
|
|||
const host = config.get('serverHost');
|
||||
const appName = config.get('appName');
|
||||
|
||||
const useHttpsForDev = process.env.USE_HTTPS_FOR_DEV;
|
||||
|
||||
const isoMorphicServer = new WebpackIsomorphicTools(WebpackIsomorphicToolsConfig);
|
||||
|
||||
return new Promise((resolve) => {
|
||||
|
@ -397,9 +400,23 @@ export function runServer({
|
|||
const routes = require(`${appName}/routes`).default;
|
||||
const createStore = require(`${appName}/store`).default;
|
||||
/* eslint-enable global-require, import/no-dynamic-require */
|
||||
const server = baseServer(
|
||||
let server = baseServer(
|
||||
routes, createStore, { appInstanceName: appName });
|
||||
if (listen === true) {
|
||||
if (useHttpsForDev) {
|
||||
if (host === 'example.com') {
|
||||
const options = {
|
||||
key: fs.readFileSync('bin/local-dev-server-certs/example.com.key.pem'),
|
||||
cert: fs.readFileSync('bin/local-dev-server-certs/example.com.crt.pem'),
|
||||
ca: fs.readFileSync('bin/local-dev-server-certs/example.com.ca.crt.pem'),
|
||||
passphrase: '',
|
||||
};
|
||||
server = https.createServer(options, server);
|
||||
} else {
|
||||
log.info(
|
||||
`To use the HTTPS server you must serve the site at example.com (host was "${host}")`);
|
||||
}
|
||||
}
|
||||
server.listen(port, host, (err) => {
|
||||
if (err) {
|
||||
return reject(err);
|
||||
|
@ -423,7 +440,7 @@ export function runServer({
|
|||
`👁 Open your browser at http://localhost:${proxyPort} to view it.`);
|
||||
} else {
|
||||
log.info(
|
||||
`👁 Open your browser at http://${host}:${port} to view it.`);
|
||||
`👁 Open your browser at http${useHttpsForDev ? 's' : ''}://${host}:${port} to view it.`);
|
||||
}
|
||||
return resolve(server);
|
||||
});
|
||||
|
|
|
@ -14,22 +14,22 @@ If you think you would like to contribute to the tests by writing or maintaining
|
|||
it would be a good idea to create a fork of this repository first, and then clone that.
|
||||
GitHub also has great instructions for [forking a repository][git-fork].
|
||||
|
||||
### Edit your hosts file
|
||||
These tests rely on the url `https://example.com`. You must add a hostname alias to your /etc/hosts
|
||||
|
||||
```bash
|
||||
echo '127.0.0.1 example.com' | sudo tee -a /etc/hosts
|
||||
```
|
||||
|
||||
### Run the tests
|
||||
The tests must be run in Firefox 48 or later.
|
||||
The tests must be run in Firefox 57 or later.
|
||||
|
||||
1. Install [Tox]
|
||||
1. Download geckodriver [v0.14.0][geckodriver] and ensure it's executable and
|
||||
1. Download geckodriver [v0.19.1][geckodriver] and ensure it's executable and
|
||||
in your path
|
||||
1. Make sure you have [docker][] installed and start the server with
|
||||
`yarn start-func-test-server`
|
||||
1. Run `PYTEST_BASE_URL=http://localhost:4000 tox`
|
||||
|
||||
To run against a different environment, change the `PYTEST_BASE_URL` environment
|
||||
variable, like so:
|
||||
|
||||
```bash
|
||||
PYTEST_BASE_URL=https://discovery.addons.allizom.org tox
|
||||
```
|
||||
1. Run `tox`
|
||||
|
||||
The pytest plugin that we use for running tests has a number of advanced
|
||||
command line options available. To see the options available, run
|
||||
|
|
|
@ -1,8 +1,53 @@
|
|||
"""Configuration fixtures and functions for pytest."""
|
||||
|
||||
import sys
|
||||
|
||||
import pytest
|
||||
|
||||
from pages.discopane import DiscoveryPane
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def capabilities(capabilities):
|
||||
# In order to run these tests in Firefox 48, marionette is required
|
||||
"""Set Firefox capabilities."""
|
||||
capabilities['marionette'] = True
|
||||
capabilities['acceptInsecureCerts'] = True
|
||||
return capabilities
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def my_base_url(base_url, firefox):
|
||||
"""Create custom base url depending on os and firefox version."""
|
||||
ff_version = firefox.browser.firefox_version
|
||||
os = sys.platform
|
||||
return '{0}/discovery/pane/{1}.0/{2}/normal'.format(
|
||||
base_url, ff_version, os)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def open_discopane(my_base_url, selenium):
|
||||
"""Open discopane via the menu."""
|
||||
with selenium.context(selenium.CONTEXT_CHROME):
|
||||
toolbar = selenium.find_element_by_id('menu_ToolsPopup')
|
||||
toolbar.click()
|
||||
addons = selenium.find_element_by_id('menu_openAddons')
|
||||
addons.click()
|
||||
return DiscoveryPane(selenium, my_base_url).wait_for_page_to_load()
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def discovery_pane(selenium, my_base_url):
|
||||
"""Open the discovery pane via the URL."""
|
||||
return DiscoveryPane(selenium, my_base_url).open()
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def firefox_options(firefox_options):
|
||||
"""Configure Firefox preferences and additonal arguments."""
|
||||
firefox_options.set_preference('extensions.legacy.enabled', True)
|
||||
firefox_options.set_preference('extensions.webapi.testing', True)
|
||||
firefox_options.set_preference('xpinstall.signatures.required', False)
|
||||
firefox_options.set_preference(
|
||||
'extensions.install.requireBuiltInCerts', False)
|
||||
firefox_options.add_argument('-foreground')
|
||||
return firefox_options
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
"""Module containing the different pages regarding discovery pane."""
|
|
@ -1,39 +1,88 @@
|
|||
from pypom import Page
|
||||
"""Represent the Discovery Pane page."""
|
||||
|
||||
from pypom import Page, Region
|
||||
from selenium.webdriver.common.by import By
|
||||
|
||||
|
||||
class DiscoveryPane(Page):
|
||||
"""Contain the locators and actions relating to the discovery pane."""
|
||||
|
||||
_discopane_content_locator = (By.CSS_SELECTOR, '.disco-pane')
|
||||
_play_video_locator = (By.CSS_SELECTOR, '.play-video')
|
||||
_uninstalled_toggles_locator = (By.CSS_SELECTOR, '.switch.uninstalled')
|
||||
_close_video_link_locator = (By.CSS_SELECTOR, '.close-video')
|
||||
_see_more_addons_locator = (By.CSS_SELECTOR, '.amo-link')
|
||||
_root_locator = (By.CLASS_NAME, 'disco-pane')
|
||||
_close_video_locator = (By.CLASS_NAME, 'close-video')
|
||||
_extensions_locator = (By.CLASS_NAME, 'extension')
|
||||
_discopane_error_alert_locator = (
|
||||
By.CSS_SELECTOR, '#discover-error .alert')
|
||||
_discopane_header_locator = (By.CLASS_NAME, 'disco-header')
|
||||
_discovery_list_item_locator = (By.ID, 'category-discover')
|
||||
_play_video_locator = (By.CLASS_NAME, 'play-video-text')
|
||||
_see_more_btn_locator = (By.CLASS_NAME, 'amo-link')
|
||||
_themes_locator = (By.CLASS_NAME, 'theme')
|
||||
|
||||
def _wait_for_page_to_load(self):
|
||||
"""Wait for page load."""
|
||||
self.wait.until(
|
||||
lambda s: s.find_element(
|
||||
*self._discovery_list_item_locator).is_displayed())
|
||||
return self
|
||||
|
||||
@property
|
||||
def is_close_video_displayed(self):
|
||||
return self.is_element_displayed(*self._close_video_link_locator)
|
||||
def is_error_alert_displayed(self):
|
||||
"""Check to see if the error alert is displayed."""
|
||||
return self.wait.until(
|
||||
lambda s: s.find_element(
|
||||
*self._discopane_error_alert_locator).is_displayed())
|
||||
|
||||
@property
|
||||
def is_header_displayed(self):
|
||||
"""Check to see if the header is displayed."""
|
||||
return self.is_element_displayed(*self._discopane_header_locator)
|
||||
|
||||
def play_video(self):
|
||||
"""Plays the welcome video."""
|
||||
self.find_element(*self._play_video_locator).click()
|
||||
|
||||
@property
|
||||
def is_play_video_displayed(self):
|
||||
"""Check to see if the welcome video is displayed."""
|
||||
return self.is_element_displayed(*self._play_video_locator)
|
||||
|
||||
def play_video(self):
|
||||
self.find_element(*self._play_video_locator).click()
|
||||
self.wait.until(lambda s: self.is_close_video_displayed)
|
||||
|
||||
def close_video(self):
|
||||
self.find_element(*self._close_video_link_locator).click()
|
||||
self.wait.until(lambda s: self.is_play_video_displayed)
|
||||
"""Close the welcome video."""
|
||||
self.find_element(*self._close_video_locator).click()
|
||||
|
||||
@property
|
||||
def is_discopane_visible(self):
|
||||
return self.is_element_displayed(*self._discopane_content_locator)
|
||||
def is_close_video_displayed(self):
|
||||
"""Check to see if welcome video is closed."""
|
||||
return self.is_element_displayed(*self._close_video_locator)
|
||||
|
||||
@property
|
||||
def uninstalled_addons(self):
|
||||
return self.find_elements(*self._uninstalled_toggles_locator)
|
||||
def is_see_more_btn_displayed(self):
|
||||
"""Check if see ore button is displayed at the bottom of page."""
|
||||
return self.is_element_displayed(*self._see_more_btn_locator)
|
||||
|
||||
@property
|
||||
def is_see_more_addons_displayed(self):
|
||||
return self.is_element_displayed(*self._see_more_addons_locator)
|
||||
def addons(self):
|
||||
"""List of addons."""
|
||||
els = self.find_elements(*self._extensions_locator)
|
||||
return [self.Addon(self, el) for el in els]
|
||||
|
||||
@property
|
||||
def themes(self):
|
||||
"""List of themes."""
|
||||
els = self.find_elements(*self._themes_locator)
|
||||
return [self.Addon(self, el) for el in els]
|
||||
|
||||
class Addon(Region):
|
||||
"""Contains all locators and functions for extensions and themes."""
|
||||
|
||||
_install_button_locator = (By.CLASS_NAME, 'InstallButton-switch')
|
||||
_success_switch_locator = (By.CLASS_NAME, 'Switch--success')
|
||||
|
||||
def install(self):
|
||||
"""Install the theme or extension."""
|
||||
self.find_element(*self._install_button_locator).click()
|
||||
|
||||
@property
|
||||
def is_installed(self):
|
||||
"""Check if theme or extensions is installed."""
|
||||
return self.is_element_displayed(*self._success_switch_locator)
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
flake8==3.5.0
|
||||
flake8-isort==2.2.2
|
||||
flake8-docstrings==1.1.0
|
|
@ -0,0 +1,28 @@
|
|||
apipkg==1.4
|
||||
attrs==17.3.0
|
||||
certifi==2017.11.5
|
||||
chardet==3.0.4
|
||||
execnet==1.5.0
|
||||
FoxPuppet==1.0.1
|
||||
funcsigs==1.0.2
|
||||
idna==2.6
|
||||
pluggy==0.6.0
|
||||
py==1.5.2
|
||||
PyPOM==1.2.0
|
||||
pytest==3.3.1
|
||||
pytest-base-url==1.4.1
|
||||
pytest-firefox==0.1.1
|
||||
pytest-forked==0.2
|
||||
pytest-html==1.16.0
|
||||
pytest-metadata==1.5.1
|
||||
pytest-repeat==0.4.1
|
||||
pytest-selenium==1.11.3
|
||||
pytest-variables==1.7.0
|
||||
pytest-xdist==1.20.1
|
||||
requests==2.18.4
|
||||
selenium==3.8.0
|
||||
six==1.10.0
|
||||
urllib3==1.22
|
||||
zope.component==4.4.1
|
||||
zope.event==4.3.0
|
||||
zope.interface==4.4.3
|
|
@ -1,4 +1,4 @@
|
|||
[tool:pytest]
|
||||
addopts=--driver=Firefox
|
||||
base_url=https://discovery.addons.mozilla.org
|
||||
xfail_strict=true
|
||||
base_url=https://example.com:4000
|
||||
|
||||
[isort]
|
||||
|
|
|
@ -1,56 +0,0 @@
|
|||
import pytest
|
||||
|
||||
from pages.discopane import DiscoveryPane
|
||||
|
||||
|
||||
@pytest.fixture(scope='session')
|
||||
def base_url(base_url):
|
||||
'''
|
||||
This is hardcoded for now, once we go through about:addons
|
||||
we'll be able to use the template expansion
|
||||
'''
|
||||
base_url += '/en-US/firefox/discovery/pane/48.0/Darwin/normal'
|
||||
return base_url
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def firefox_profile(firefox_profile, base_url):
|
||||
'''
|
||||
Set preferences necessary to load discovery pane, and
|
||||
for installing extensions and toggling switches to
|
||||
install and uninstall.
|
||||
'''
|
||||
firefox_profile.set_preference('extensions.webapi.testing', True)
|
||||
firefox_profile.set_preference('extensions.webservice.discoverURL',
|
||||
base_url)
|
||||
firefox_profile.update_preferences()
|
||||
return firefox_profile
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def discovery_pane(selenium, base_url):
|
||||
return DiscoveryPane(selenium, base_url).open()
|
||||
|
||||
|
||||
@pytest.mark.xfail(
|
||||
'localhost' in pytest.config.getoption('base_url'),
|
||||
reason='Add-ons cannot be installed without SSL on local')
|
||||
@pytest.mark.nondestructive
|
||||
def test_that_discovery_pane_loads(discovery_pane):
|
||||
assert discovery_pane.is_discopane_visible
|
||||
assert len(discovery_pane.uninstalled_addons) == 7
|
||||
|
||||
|
||||
@pytest.mark.nondestructive
|
||||
def test_that_welcome_video_plays(discovery_pane):
|
||||
assert not discovery_pane.is_close_video_displayed
|
||||
discovery_pane.play_video()
|
||||
assert not discovery_pane.is_play_video_displayed
|
||||
discovery_pane.close_video()
|
||||
assert discovery_pane.is_play_video_displayed
|
||||
assert not discovery_pane.is_close_video_displayed
|
||||
|
||||
|
||||
@pytest.mark.nondestructive
|
||||
def test_see_more_addons_button(discovery_pane):
|
||||
assert discovery_pane.is_see_more_addons_displayed
|
|
@ -0,0 +1 @@
|
|||
"""Module containing the test files."""
|
|
@ -0,0 +1,65 @@
|
|||
"""Discovery pane tests."""
|
||||
|
||||
import pytest
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def incorrect_disco_url(firefox_options):
|
||||
"""Fixture to setup an incorrect discovery URL."""
|
||||
firefox_options.set_preference(
|
||||
'extensions.webservice.discoverURL', 'addons')
|
||||
return firefox_options
|
||||
|
||||
|
||||
@pytest.mark.nondestructive
|
||||
def test_discopane_error_loads(incorrect_disco_url, selenium, open_discopane):
|
||||
"""Test that the error alert shows."""
|
||||
discovery_pane = open_discopane
|
||||
assert discovery_pane.is_error_alert_displayed
|
||||
|
||||
|
||||
@pytest.mark.nondestructive
|
||||
def test_discopane_loads(discovery_pane):
|
||||
"""Test that discovery pane loads."""
|
||||
assert discovery_pane.is_header_displayed
|
||||
|
||||
|
||||
@pytest.mark.nondestructive
|
||||
def test_that_welcome_video_plays(discovery_pane):
|
||||
"""Test the welcome video."""
|
||||
assert not discovery_pane.is_close_video_displayed
|
||||
discovery_pane.play_video()
|
||||
assert not discovery_pane.is_play_video_displayed
|
||||
discovery_pane.close_video()
|
||||
assert discovery_pane.is_play_video_displayed
|
||||
assert not discovery_pane.is_close_video_displayed
|
||||
|
||||
|
||||
@pytest.mark.nondestructive
|
||||
def test_see_more_button_is_displayed(discovery_pane):
|
||||
"""Test to make sure the see more button is displayed."""
|
||||
assert discovery_pane.is_see_more_btn_displayed
|
||||
|
||||
|
||||
@pytest.mark.nondestructive
|
||||
def test_addon_installs(discovery_pane, firefox, notifications):
|
||||
"""Test addon installation from discovery pane."""
|
||||
addon = discovery_pane.addons[0]
|
||||
addon.install()
|
||||
firefox.browser.wait_for_notification(
|
||||
notifications.AddOnInstallConfirmation).install()
|
||||
firefox.browser.wait_for_notification(
|
||||
notifications.AddOnInstallComplete).close()
|
||||
assert addon.is_installed
|
||||
|
||||
|
||||
@pytest.mark.nondestructive
|
||||
def test_theme_installs(discovery_pane, firefox, notifications):
|
||||
"""Test theme install from discovery pane."""
|
||||
theme = discovery_pane.themes[0]
|
||||
theme.install()
|
||||
firefox.browser.wait_for_notification(
|
||||
notifications.AddOnInstallConfirmation).install()
|
||||
firefox.browser.wait_for_notification(
|
||||
notifications.AddOnInstallComplete).close()
|
||||
assert theme.is_installed
|
29
tox.ini
29
tox.ini
|
@ -3,30 +3,15 @@ skipsdist = true
|
|||
envlist = discopane-ui-tests, flake8
|
||||
|
||||
[testenv:discopane-ui-tests]
|
||||
passenv = DISPLAY PYTEST_ADDOPTS PYTEST_BASE_URL
|
||||
deps =
|
||||
appdirs==1.4.2
|
||||
packaging==16.8
|
||||
PyPOM==1.1.1
|
||||
py==1.4.32
|
||||
pyparsing==2.1.10
|
||||
pytest==3.0.6
|
||||
pytest_base_url==1.3.0
|
||||
pytest_html==1.14.1
|
||||
pytest-metadata==1.2.0
|
||||
pytest-selenium==1.9.0
|
||||
pytest_variables==1.4
|
||||
requests==2.13.0
|
||||
selenium==3.0.2
|
||||
six==1.10.0
|
||||
zope.component==4.3.0
|
||||
zope.event==4.2.0
|
||||
zope.interface==4.3.0
|
||||
install_command = pip install --no-deps {opts} {packages}
|
||||
commands = pytest tests/ui/test_discopane.py {posargs}
|
||||
passenv = DISPLAY MOZ_HEADLESS PYTEST_ADDOPTS PYTEST_BASE_URL
|
||||
deps = -r{toxinidir}/tests/ui/requirements/requirements.txt
|
||||
install_command = pip install --no-deps {packages}
|
||||
commands = pytest --driver Firefox tests/ui/tests/test_discopane.py {posargs}
|
||||
|
||||
[testenv:flake8]
|
||||
deps = flake8==3.3.0
|
||||
deps =
|
||||
-r{toxinidir}/tests/ui/requirements/requirements.txt
|
||||
-r{toxinidir}/tests/ui/requirements/flake8.txt
|
||||
commands = flake8 {posargs:.}
|
||||
|
||||
[testenv:dennis-lint]
|
||||
|
|
Загрузка…
Ссылка в новой задаче