Addon Install Test (#6641)
* Use docker-compose>=1.18 and minimal docker-compose config version to 2.3 * Starts ui-tests in Firefox docker container * Let's the Firefox docker-container hit directly nginx * makes use of https://github.com/jrbenny35/selenium-firefox/ firefox+selenium image * makes use of /user-media/ serving directly via nginx for XPI installs * Adds a helper that creates an installable add-on * Update `firefox_options` fixture with all options needed to install add-ons with a test signing signature Fixes #7270 Fixes #2488
This commit is contained in:
Родитель
0a7a2cd69f
Коммит
8a646cadc4
|
@ -127,17 +127,28 @@ reindex:
|
|||
|
||||
ui-tests:
|
||||
rm -rf ./user-media/* ./tmp/*
|
||||
# Reset the database and fake database migrations
|
||||
python manage.py reset_db --noinput
|
||||
python manage.py syncdb --noinput
|
||||
python manage.py loaddata initial.json
|
||||
python manage.py import_prod_versions
|
||||
schematic --fake src/olympia/migrations/
|
||||
|
||||
# Let's load some initial data and import mozilla-product versions
|
||||
python manage.py loaddata initial.json
|
||||
python manage.py loaddata zadmin/users
|
||||
python manage.py update_permissions_from_mc
|
||||
python manage.py loaddata src/olympia/access/fixtures/initial.json
|
||||
|
||||
python manage.py import_prod_versions
|
||||
python manage.py update_permissions_from_mc
|
||||
|
||||
# Create a proper superuser that can be used to access the API
|
||||
python manage.py waffle_switch super-create-accounts on
|
||||
python manage.py waffle_switch activate-autograph-signing on
|
||||
python manage.py createsuperuser --email=uitest@mozilla.com --username=uitest --noinput --add-to-supercreate-group --save-api-credentials=tests/ui/variables.json --hostname=olympia.dev
|
||||
python manage.py reindex --wipe --force --noinput
|
||||
|
||||
# Generate test add-ons and force a reindex to make sure things are updated
|
||||
python manage.py generate_ui_test_addons
|
||||
python manage.py reindex --force --noinput --wipe
|
||||
|
||||
pip install --no-deps -r requirements/uitests.txt
|
||||
|
||||
initialize: update_deps initialize_db update_assets populate_data
|
||||
|
|
|
@ -59,7 +59,8 @@ jobs:
|
|||
name: Install Docker Compose
|
||||
command: |
|
||||
set -x
|
||||
sudo pip install docker-compose
|
||||
pip install docker-compose>=1.18
|
||||
docker-compose --version
|
||||
- run:
|
||||
name: Start container, verify it's running and start tests
|
||||
command: |
|
||||
|
@ -73,9 +74,10 @@ jobs:
|
|||
docker-compose exec worker supervisorctl restart all
|
||||
docker-compose exec web make -f Makefile-docker update_deps
|
||||
docker-compose exec web supervisorctl restart all
|
||||
docker-compose exec web bash /code/scripts/ui-test.sh
|
||||
# Start Test in Firefox docker container
|
||||
docker-compose exec selenium-firefox tox -e ui-tests
|
||||
- store_artifacts:
|
||||
path: ui-test-results
|
||||
path: ui-test.html
|
||||
- save_cache:
|
||||
key: uitest-cache-{{ checksum "requirements/docs.txt" }}
|
||||
paths:
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
version: "2"
|
||||
version: "2.3"
|
||||
|
||||
services:
|
||||
nginx:
|
||||
|
|
|
@ -1,26 +1,29 @@
|
|||
version: "2"
|
||||
version: "2.3"
|
||||
|
||||
x-env-mapping: &env
|
||||
environment:
|
||||
- CELERY_BROKER_URL=amqp://olympia:olympia@rabbitmq/olympia
|
||||
- CELERY_RESULT_BACKEND=redis://redis:6379/1
|
||||
- DATABASE_URL=mysql://root:@mysqld/olympia
|
||||
- ELASTICSEARCH_LOCATION=elasticsearch:9200
|
||||
- MEMCACHE_LOCATION=memcached:11211
|
||||
- MYSQL_DATABASE=olympia
|
||||
- MYSQL_ROOT_PASSWORD=docker
|
||||
- OLYMPIA_SITE_URL=http://olympia.dev
|
||||
- PYTHONDONTWRITEBYTECODE=1
|
||||
- PYTHONUNBUFFERED=1
|
||||
- RECURSION_LIMIT=10000
|
||||
- REDIS_LOCATION=redis://redis:6379/0?socket_timeout=0.5
|
||||
- TERM=xterm-256color
|
||||
|
||||
services:
|
||||
worker: &worker
|
||||
<<: *env
|
||||
image: addons/addons-server
|
||||
command: supervisord -n -c /code/docker/supervisor-celery.conf
|
||||
entrypoint: ./scripts/start-docker.sh
|
||||
volumes:
|
||||
- .:/code
|
||||
environment:
|
||||
- CELERY_BROKER_URL=amqp://olympia:olympia@rabbitmq/olympia
|
||||
- CELERY_RESULT_BACKEND=redis://redis:6379/1
|
||||
- DATABASE_URL=mysql://root:@mysqld/olympia
|
||||
- ELASTICSEARCH_LOCATION=elasticsearch:9200
|
||||
- MEMCACHE_LOCATION=memcached:11211
|
||||
- MYSQL_DATABASE=olympia
|
||||
- MYSQL_ROOT_PASSWORD=docker
|
||||
- OLYMPIA_SITE_URL=http://olympia.dev
|
||||
- PYTHONDONTWRITEBYTECODE=1
|
||||
- PYTHONUNBUFFERED=1
|
||||
- RECURSION_LIMIT=10000
|
||||
- REDIS_LOCATION=redis://redis:6379/0?socket_timeout=0.5
|
||||
- TERM=xterm-256color
|
||||
extra_hosts:
|
||||
- "olympia.dev:127.0.0.1"
|
||||
|
||||
|
@ -68,11 +71,14 @@ services:
|
|||
image: mozilla/autograph:2.0.5
|
||||
|
||||
selenium-firefox:
|
||||
image: selenium/standalone-firefox-debug
|
||||
<<: *env
|
||||
image: b4handjr/selenium-firefox
|
||||
volumes:
|
||||
- .:/code
|
||||
expose:
|
||||
- "4444"
|
||||
ports:
|
||||
- "5900"
|
||||
shm_size: 2g
|
||||
links:
|
||||
- "web:olympia.dev"
|
||||
- "nginx:olympia.dev"
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
FoxPuppet==1.0.1 \
|
||||
--hash=sha256:e912d18e15c202dd3bfe4b2b837411f267b231925feb170bc5af26787fccb4c2 \
|
||||
--hash=sha256:a78918ea0b4846fe54cc853e3ab1bd11aa1c5ec6647a65eaa62c79a056b39581
|
||||
fxapom==1.10.1 \
|
||||
--hash=sha256:2d3c6cb8182b6d0f525628c6cf84cfe7d8f9dbd1dad487e8514cc2f5461e5009 \
|
||||
--hash=sha256:062c114b16281774470fffbbe80772f3fa9976cb4d2fe9db1a81d2028243a82c
|
||||
|
@ -23,6 +26,9 @@ pytest-base-url==1.4.1 \
|
|||
pytest-html==1.16.1 \
|
||||
--hash=sha256:135ea10b9ec0a5e370dc1820a5552d761aa3fec8400eabc0b06646f90f5c820e \
|
||||
--hash=sha256:d6ae1ae5d10158d290b603ccf46b5d103e93cf7d67df42bb7d6516fb4f1317f3
|
||||
pytest-firefox==0.1.1 \
|
||||
--hash=sha256:d91ddd9b7090986d6e45df38830328d7178e95a846eafb1a975a12b7eb5a9fdb \
|
||||
--hash=sha256:7c7acb4dc3d068a6d356797f18731b6ad2f64b5681043c0119f4b821bf20ea07
|
||||
pytest-instafail==0.3.0 \
|
||||
--hash=sha256:b4d5fc3ca81e530a8d0e15a7771dc14b06fc9a0930c4b3909a7f4527040572c3
|
||||
pytest-metadata==1.5.1 \
|
||||
|
|
|
@ -1,10 +0,0 @@
|
|||
#!/bin/sh
|
||||
echo 127.0.0.1 olympia.dev | tee -a /etc/hosts
|
||||
yum -y install curl
|
||||
curl https://raw.githubusercontent.com/creationix/nvm/v0.30.2/install.sh > install-nvm.sh
|
||||
sh install-nvm.sh
|
||||
source ~/.bash_profile
|
||||
nvm install node
|
||||
unset NPM_CONFIG_PREFIX
|
||||
pip install tox
|
||||
tox -e ui-tests
|
|
@ -857,7 +857,7 @@ def version_factory(file_kw=None, **kw):
|
|||
ApplicationsVersions.objects.get_or_create(application=application,
|
||||
version=ver, min=av_min,
|
||||
max=av_max)
|
||||
if addon_type != amo.ADDON_PERSONA:
|
||||
if addon_type != amo.ADDON_PERSONA and file_kw is not False:
|
||||
file_kw = file_kw or {}
|
||||
file_factory(version=ver, **file_kw)
|
||||
return ver
|
||||
|
|
|
@ -2,6 +2,7 @@ from django.core.cache import cache
|
|||
from django.core.management import call_command
|
||||
from django.core.management.base import BaseCommand
|
||||
from django.utils import translation
|
||||
from django.test.utils import override_settings
|
||||
|
||||
from olympia.landfill.serializers import GenerateAddonsSerializer
|
||||
|
||||
|
@ -21,12 +22,15 @@ class Command(BaseCommand):
|
|||
"""
|
||||
|
||||
def handle(self, *args, **kwargs):
|
||||
translation.activate('en-US')
|
||||
serializer = GenerateAddonsSerializer()
|
||||
serializer.create_generic_featured_addons()
|
||||
serializer.create_featured_addon_with_version()
|
||||
serializer.create_featured_theme()
|
||||
serializer.create_featured_collections()
|
||||
serializer.create_featured_themes()
|
||||
with override_settings(CELERY_ALWAYS_EAGER=True):
|
||||
translation.activate('en-US')
|
||||
serializer = GenerateAddonsSerializer()
|
||||
serializer.create_generic_featured_addons()
|
||||
serializer.create_featured_addon_with_version()
|
||||
serializer.create_featured_theme()
|
||||
serializer.create_featured_collections()
|
||||
serializer.create_featured_themes()
|
||||
serializer.create_installable_addon()
|
||||
|
||||
cache.clear()
|
||||
call_command('clear_cache')
|
||||
|
|
|
@ -1,19 +1,29 @@
|
|||
import mimetypes
|
||||
import random
|
||||
|
||||
from django.conf import settings
|
||||
from django.utils.translation import activate
|
||||
from django.core.files.uploadedfile import SimpleUploadedFile
|
||||
from rest_framework import serializers
|
||||
|
||||
from olympia.amo.tests import user_factory, addon_factory, copy_file_to_temp
|
||||
from olympia import amo
|
||||
from olympia.addons.forms import icons
|
||||
from olympia.addons.models import AddonUser, Preview
|
||||
from olympia.addons.models import AddonUser, Preview, Addon
|
||||
from olympia.addons.utils import generate_addon_guid
|
||||
from olympia.amo.tests import addon_factory, user_factory, version_factory
|
||||
from olympia.amo.tests import version_factory
|
||||
from olympia.constants.applications import APPS, FIREFOX
|
||||
from olympia.constants.base import (
|
||||
ADDON_EXTENSION, ADDON_PERSONA, STATUS_PUBLIC)
|
||||
ADDON_EXTENSION,
|
||||
ADDON_PERSONA,
|
||||
STATUS_PUBLIC
|
||||
)
|
||||
from olympia.landfill.collection import generate_collection
|
||||
from olympia.landfill.generators import generate_themes
|
||||
from olympia.files.tests.test_helpers import get_file
|
||||
from olympia.ratings.models import Rating
|
||||
from olympia.users.models import UserProfile
|
||||
from olympia.devhub.tasks import create_version_for_upload
|
||||
|
||||
|
||||
class GenerateAddonsSerializer(serializers.Serializer):
|
||||
|
@ -84,6 +94,46 @@ class GenerateAddonsSerializer(serializers.Serializer):
|
|||
'Created addon {0} for testing successfully'
|
||||
.format(addon.name))
|
||||
|
||||
def create_featured_addon_with_version_for_install(self):
|
||||
"""Creates a custom addon named 'Ui-Addon'.
|
||||
|
||||
This addon will be a featured addon and will have a featured collecton
|
||||
attatched to it. It will belong to the user uitest.
|
||||
|
||||
It has 1 preview, 5 reviews, and 2 authors. The second author is named
|
||||
'ui-tester2'. It has a version number as well as a beta version.
|
||||
|
||||
"""
|
||||
default_icons = [x[0] for x in icons() if x[0].startswith('icon/')]
|
||||
try:
|
||||
addon = Addon.objects.get(guid='@webextension-guid')
|
||||
except Addon.DoesNotExist:
|
||||
addon = addon_factory(
|
||||
status=STATUS_PUBLIC,
|
||||
type=ADDON_EXTENSION,
|
||||
file_kw=False,
|
||||
average_daily_users=5000,
|
||||
users=[UserProfile.objects.get(username='uitest')],
|
||||
average_rating=5,
|
||||
description=u'My Addon description',
|
||||
guid='@webextension-guid',
|
||||
icon_type=random.choice(default_icons),
|
||||
name=u'Ui-Addon-Install',
|
||||
public_stats=True,
|
||||
slug='ui-test-install',
|
||||
summary=u'My Addon summary',
|
||||
tags=['some_tag', 'another_tag', 'ui-testing',
|
||||
'selenium', 'python'],
|
||||
weekly_downloads=9999999,
|
||||
developer_comments='This is a testing addon.',
|
||||
)
|
||||
addon.save()
|
||||
generate_collection(addon, app=FIREFOX)
|
||||
print(
|
||||
'Created addon {0} for testing successfully'
|
||||
.format(addon.name))
|
||||
return addon
|
||||
|
||||
def create_featured_theme(self):
|
||||
"""Creates a custom theme named 'Ui-Test Theme'.
|
||||
|
||||
|
@ -148,3 +198,46 @@ class GenerateAddonsSerializer(serializers.Serializer):
|
|||
for _ in range(6):
|
||||
addon = addon_factory(status=STATUS_PUBLIC, type=ADDON_PERSONA)
|
||||
generate_collection(addon, app=FIREFOX)
|
||||
|
||||
def create_installable_addon(self):
|
||||
activate('en-US')
|
||||
|
||||
# using whatever add-on you already have should work imho, otherwise
|
||||
# fall back to a new one for test purposes
|
||||
addon = self.create_featured_addon_with_version_for_install()
|
||||
|
||||
# the user the add-on gets created with
|
||||
user = UserProfile.objects.get(username='uitest')
|
||||
|
||||
user, _ = UserProfile.objects.get_or_create(
|
||||
pk=settings.TASK_USER_ID,
|
||||
defaults={'email': 'admin@mozilla.com', 'username': 'admin'})
|
||||
|
||||
# generate a proper uploaded file that simulates what django requires
|
||||
# as request.POST
|
||||
file_to_upload = 'webextension_signed_already.xpi'
|
||||
file_path = get_file(file_to_upload)
|
||||
|
||||
# make sure we are not using the file in the source-tree but a
|
||||
# temporary one to avoid the files get moved somewhere else and
|
||||
# deleted from source tree
|
||||
with copy_file_to_temp(file_path) as temporary_path:
|
||||
data = open(temporary_path).read()
|
||||
filedata = SimpleUploadedFile(
|
||||
file_to_upload,
|
||||
data,
|
||||
content_type=mimetypes.guess_type(file_to_upload)[0])
|
||||
|
||||
# now, lets upload the file into the system
|
||||
from olympia.devhub.views import handle_upload
|
||||
|
||||
upload = handle_upload(
|
||||
filedata=filedata,
|
||||
user=user,
|
||||
channel=amo.RELEASE_CHANNEL_LISTED,
|
||||
addon=addon,
|
||||
)
|
||||
|
||||
# And let's create a new version for that upload.
|
||||
create_version_for_upload(
|
||||
upload.addon, upload, amo.RELEASE_CHANNEL_LISTED)
|
||||
|
|
|
@ -11,10 +11,20 @@ from olympia import amo
|
|||
|
||||
|
||||
@pytest.fixture
|
||||
def capabilities(capabilities):
|
||||
# In order to run these tests in Firefox 48, marionette is required
|
||||
capabilities['marionette'] = True
|
||||
return capabilities
|
||||
def firefox_options(firefox_options):
|
||||
firefox_options.set_preference(
|
||||
'extensions.install.requireBuiltInCerts', False)
|
||||
firefox_options.set_preference('xpinstall.signatures.required', False)
|
||||
firefox_options.set_preference('extensions.webapi.testing', True)
|
||||
firefox_options.set_preference('ui.popup.disable_autohide', True)
|
||||
firefox_options.add_argument('-foreground')
|
||||
firefox_options.log.level = 'trace'
|
||||
return firefox_options
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def firefox_notifications(notifications):
|
||||
return notifications
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
|
|
|
@ -17,8 +17,13 @@ class Details(Base):
|
|||
class DescriptionHeader(Region):
|
||||
"""Represents the header of the detail page."""
|
||||
_root_locator = (By.CLASS_NAME, 'addon-description-header')
|
||||
_install_button_locator = (By.CLASS_NAME, 'add')
|
||||
_name_locator = (By.TAG_NAME, 'h1')
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
return self.find_element(*self._name_locator).text
|
||||
|
||||
@property
|
||||
def install_button(self):
|
||||
return self.find_element(*self._install_button_locator)
|
||||
|
|
|
@ -2,5 +2,5 @@
|
|||
addopts = -r=a -vs --showlocals --tb=short
|
||||
sensitive_url = mozilla\.(com|org)
|
||||
xfail_strict = true
|
||||
DJANGO_SETTINGS_MODULE = settings_test
|
||||
base_url = http://olympia.dev:8000
|
||||
DJANGO_SETTINGS_MODULE = settings
|
||||
base_url = http://olympia.dev:80
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
import pytest
|
||||
|
||||
|
||||
from pages.desktop.details import Details
|
||||
|
||||
|
||||
@pytest.mark.nondestructive
|
||||
def test_addon_install(
|
||||
base_url, selenium, firefox, firefox_notifications):
|
||||
"""Test that navigates to an addon and installs it."""
|
||||
selenium.get('{}/firefox/addon/ui-test-install'.format(base_url))
|
||||
addon = Details(selenium, base_url)
|
||||
assert 'Ui-Addon-Install' in addon.description_header.name
|
||||
addon.description_header.install_button.click()
|
||||
firefox.browser.wait_for_notification(
|
||||
firefox_notifications.AddOnInstallBlocked).allow()
|
||||
firefox.browser.wait_for_notification(
|
||||
firefox_notifications.AddOnInstallConfirmation).install()
|
||||
firefox.browser.wait_for_notification(
|
||||
firefox_notifications.AddOnInstallComplete).close()
|
3
tox.ini
3
tox.ini
|
@ -60,9 +60,8 @@ commands =
|
|||
[testenv:ui-tests]
|
||||
commands =
|
||||
make -f Makefile-docker update_deps
|
||||
pip install --no-deps -r requirements/uitests.txt
|
||||
make -f Makefile-docker ui-tests
|
||||
pytest --driver Remote --host selenium-firefox --port 4444 --capability browserName firefox --variables tests/ui/variables.json --self-contained-html tests/ui {posargs}
|
||||
pytest --driver Firefox --variables tests/ui/variables.json --html=ui-test.html --self-contained-html tests/ui {posargs}
|
||||
|
||||
[testenv:assets]
|
||||
commands =
|
||||
|
|
Загрузка…
Ссылка в новой задаче