Skip to content
This repository has been archived by the owner on Aug 22, 2022. It is now read-only.

Commit

Permalink
Merge pull request #707 from open-craft/arjun/bb-3585-e2e-setup
Browse files Browse the repository at this point in the history
[BB-3585] Add initial setup for e2e tests
  • Loading branch information
arjunsinghy96 committed Feb 18, 2021
2 parents 7644ebe + c66807b commit 0e7de5d
Show file tree
Hide file tree
Showing 17 changed files with 1,133 additions and 198 deletions.
32 changes: 32 additions & 0 deletions .env.e2e
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
E2E_TESTS=true
FIREFOX_BINARY_PATH='/usr/local/bin/firefox'
DEBUG=true
SECRET_KEY='tests'
DATABASE_URL='postgres://localhost/opencraft'
DEFAULT_INSTANCE_MYSQL_URL='mysql://root@127.0.0.1'
DEFAULT_INSTANCE_MONGO_URL='mongodb://127.0.0.1'
HUEY_ALWAYS_EAGER=true
OPENSTACK_USER='test'
OPENSTACK_PASSWORD='pass'
OPENSTACK_TENANT='test-tenant'
OPENSTACK_AUTH_URL='http://example.com/auth/url'
OPENSTACK_REGION='test-region'
DEFAULT_INSTANCE_BASE_DOMAIN='example.com'
GANDI_API_KEY='TEST_GANDI_API_KEY'
GITHUB_ACCESS_TOKEN='test-token'
BASE_HANDLERS='["file"]'
BACKUP_SWIFT_ENABLED=true
PRELIMINARY_PAGE_SERVER_IP='47.11.08.15'
DEFAULT_LOAD_BALANCING_SERVER='ubuntu@haproxy-test.fake.domain'
LOAD_BALANCER_FRAGMENT_NAME_PREFIX='opencraft-'
DEFAULT_RABBITMQ_API_URL='https://admin:password@rabbitmq.example.com:15671'
DEFAULT_INSTANCE_RABBITMQ_URL='amqps://rabbitmq.example.com:5671'
CONSUL_ENABLED=false
CONSUL_SERVERS=haproxy-integration.net.opencraft.hosting
DISABLE_LOAD_BALANCER_CONFIGURATION=false
MAILCHIMP_ENABLED=false
MAILCHIMP_API_KEY='deadc0dedeadc0dedeadc0dedeadc0de-us7'
MAILCHIMP_LIST_ID_FOR_TRIAL_USERS='badc0de'
INSTANCE_STORAGE_TYPE='s3'
AWS_ACCESS_KEY_ID='1234'
AWS_SECRET_ACCESS_KEY='5678'
13 changes: 13 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

# Any configuration variable can be overridden with `VARIABLE = VALUE` in a git-ignored `private.mk` file.

API_CLIENT_PATH := frontend/packages/api_client
.DEFAULT_GOAL := help
HELP_SPACING ?= 30
COVERAGE_THRESHOLD ?= 90
Expand All @@ -27,6 +28,7 @@ WORKERS_LOW_PRIORITY ?= 3
SHELL ?= /bin/bash
HONCHO_MANAGE := honcho run python3 manage.py
HONCHO_MANAGE_TESTS := honcho -e .env.test run python3 manage.py
HONCHO_MANAGE_E2E_TESTS := honcho -e .env.e2e run python3 manage.py e2e_test
HONCHO_COVERAGE_TEST := honcho -e .env.test run coverage run --branch --parallel-mode ./manage.py test --noinput -v2
HONCHO_COVERAGE_INTEGRATION := honcho -e .env.integration run coverage run --branch --parallel-mode ./manage.py test --noinput -v2
COVERAGE := coverage run --branch --parallel-mode ./manage.py test --noinput -v2
Expand Down Expand Up @@ -168,6 +170,17 @@ test: clean test.quality test.unit test.migrations_missing test.js test.browser
test.one: clean
$(HONCHO_MANAGE_TESTS) test $(RUN_ARGS)

frontend.build: install_frontend_dependencies
@echo "\nBuilding frontend application\n"
rm -rf frontend/build
rm -rf $(API_CLIENT_PATH)/dist
npm install --prefix=$(API_CLIENT_PATH)
npm run build --prefix=$(API_CLIENT_PATH)
npm run build --prefix frontend

test.e2e: clean frontend.build
$(HONCHO_MANAGE_E2E_TESTS)

docs:
mkdocs build -f mkdocs.yml

Expand Down
2 changes: 1 addition & 1 deletion bin/install-supported-firefox
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

set -e

FIREFOX_RELEASE="47.0.2"
FIREFOX_RELEASE="85.0"
FIREFOX_BIN="/usr/local/bin/firefox"

sudo curl -O "https://ftp.mozilla.org/pub/firefox/releases/$FIREFOX_RELEASE/linux-x86_64/en-US/firefox-$FIREFOX_RELEASE.tar.bz2"
Expand Down
85 changes: 85 additions & 0 deletions circle.yml
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,90 @@ jobs:
paths:
- coverage

e2e-tests:
docker:
- image: circleci/python:3.6-stretch-node-browsers
environment:
DEBUG: 'true'
DEFAULT_FORK: 'open-craft/edx-platform'
LOAD_BALANCER_FRAGMENT_NAME_PREFIX: 'integration-'
- image: redis
- image: mongo:3.2-jessie
- image: "circleci/mysql:5"
environment:
MYSQL_ALLOW_EMPTY_PASSWORD: True
- image: circleci/postgres:10.1-alpine
environment:
PG_HOST: 127.0.0.1
POSTGRES_USER: circleci
POSTGRES_DB: circle_test
environment:
REACT_APP_OCIM_API_BASE: http://localhost:5000
steps:
- checkout
- restore_cache:
key: dependencies-{{ checksum "requirements.txt" }}
- run:
name: Wait for Redis
command: dockerize -wait tcp://localhost:6379 -timeout 10s
- run:
name: Wait for Postgres
command: dockerize -wait tcp://localhost:5432 -timeout 10s
- run:
name: Wait for MySQL
command: dockerize -wait tcp://localhost:3306 -timeout 10s
- run:
name: Wait for MongoDB
command: dockerize -wait tcp://localhost:27017 -timeout 10s
- run:
name: Install Dependencies
command: |
sed -i 's/libmysqlclient/default-libmysqlclient/' debian_packages.lst
make install_system_dependencies
sudo ln -s /usr/lib/x86_64-linux-gnu/libmysqlclient.so /usr/lib/x86_64-linux-gnu/libmysqlclient.so.18
bin/install-supported-firefox
python3 -m venv venv
. venv/bin/activate
pip install --upgrade pip
pip install --upgrade virtualenv
pip install -r requirements.txt
pip install -r cleanup_utils/requirements.txt
npm install
- run:
name: Run Consul
command: |
sudo wget -P /tmp https://releases.hashicorp.com/consul/1.2.1/consul_1.2.1_linux_amd64.zip
sudo unzip /tmp/consul_1.2.1_linux_amd64.zip -d /usr/local/bin
mkdir -p /tmp/consul-data
consul agent -dev
background: true
- save_cache:
key: dependencies-{{ checksum "requirements.txt" }}
paths:
- "venv"
- run:
name: Create Database
command: make create_db
- run:
name: Run Tests
command: |
. venv/bin/activate
mkdir -p /tmp/coverage
make test.e2e
if [ -e .coverage.* ]; then
cp -v .coverage.* /tmp/coverage/.
fi
if [ -d coverage ]; then
cp -vR coverage/* /tmp/coverage/.
fi
no_output_timeout: 2h
environment:
ANSIBLE_HOST_KEY_CHECKING: False
- persist_to_workspace:
root: /tmp
paths:
- coverage

coverage:
docker:
- image: circleci/python:3.6-stretch-node
Expand Down Expand Up @@ -297,6 +381,7 @@ workflows:
name: browser_tests
tests_group: 0
tests_type: clean test.browser
- e2e-tests
- build:
name: js_tests
tests_group: 0
Expand Down
Empty file added e2e_tests/__init__.py
Empty file.
99 changes: 99 additions & 0 deletions e2e_tests/frontend_server.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
# -*- coding: utf-8 -*-
#
# OpenCraft -- tools to aid developing and hosting free software projects
# Copyright (C) 2015-2020 OpenCraft <xavier@opencraft.com>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
"""
Utility functions related to frontend server for e2e testing.
"""
import http.server
import os

from urllib.parse import urlparse
from threading import Thread


# Functions #################################################################

def start_react_server(
build_path="./frontend/build",
hostname="localhost",
port=3000
):
"""
Start a react server in different thread.
"""
build_path = os.path.abspath(build_path)
handler = RequestHandler
httpd = http.server.HTTPServer((hostname, port), handler, False)

httpd.server_bind()
address = "http://%s:%d" % (httpd.server_name, httpd.server_port)

print("Server starting at:", address)
httpd.server_activate()

def serve_forever(httpd):
# Switch to the frontend build directory
os.chdir(build_path)
with httpd: # to make sure httpd.server_close is called
print("Frontend server started (infinite request loop):", build_path)
httpd.serve_forever()
print("Shutting down frontend server")

thread = Thread(target=serve_forever, args=(httpd, ))
thread.setDaemon(True)
thread.start()

return httpd, address


# Classes ################################################################

class RequestHandler(http.server.SimpleHTTPRequestHandler):
"""
RequestHandler for react frontend server. We send the index file
instead of 404.
"""

INDEXFILE = "index.html"

def log_message(self, format, *args): # pylint: disable=redefined-builtin
"""
Override to supress logs of accessed paths.
"""

def do_GET(self): # noqa
"""
Override get method to send the INDEXFILE when the requested file is not found.
"""
parsed_params = urlparse(self.path)

try:
# See if the file requested exists and accessible
if os.access('.' + os.sep + parsed_params.path, os.R_OK):
http.server.SimpleHTTPRequestHandler.do_GET(self)
else:
# send index.html, but don't redirect
index_file = os.path.join(os.getcwd(), self.INDEXFILE)
self.send_response(200)
self.send_header('Content-Type', 'text/html')
self.end_headers()
with open(index_file, 'rb') as fin:
self.copyfile(fin, self.wfile)
except BrokenPipeError:
# The client closed connection. We can ignore the exception here.
pass
Empty file.
Empty file.
40 changes: 40 additions & 0 deletions e2e_tests/management/commands/e2e_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# -*- coding: utf-8 -*-
#
# OpenCraft -- tools to aid developing and hosting free software projects
# Copyright (C) 2015-2019 OpenCraft <contact@opencraft.com>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
"""
Django Command e2e_test for running e2e_tests
"""

from django.core.management.commands import test

from e2e_tests.frontend_server import start_react_server


class Command(test.Command):
"""
Management command to run the e2e test.
Start the frontend server and run the tests in e2e application.
"""
def handle(self, *args, **options):
httpd, _ = start_react_server()
args = (*args, 'e2e_tests')
try:
super(Command, self).handle(*args, **options)
finally:
httpd.shutdown()
Empty file added e2e_tests/tests/__init__.py
Empty file.
Loading

0 comments on commit 0e7de5d

Please sign in to comment.