2016-09-21 17:13:26 +01:00
|
|
|
from contextlib import contextmanager
|
2016-01-07 17:31:17 +00:00
|
|
|
import os
|
2016-02-16 15:25:46 +00:00
|
|
|
|
2017-11-22 17:54:59 +00:00
|
|
|
from flask import Flask
|
2016-01-07 17:31:17 +00:00
|
|
|
from alembic.command import upgrade
|
|
|
|
|
from alembic.config import Config
|
2017-08-23 14:46:40 +01:00
|
|
|
import pytest
|
2017-08-24 13:54:16 +01:00
|
|
|
import sqlalchemy
|
2016-02-16 15:25:46 +00:00
|
|
|
|
2016-01-07 17:31:17 +00:00
|
|
|
from app import create_app, db
|
2019-11-11 16:09:15 +00:00
|
|
|
from app.dao.provider_details_dao import get_provider_details_by_identifier
|
2015-12-11 16:57:00 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.fixture(scope='session')
|
2016-11-04 10:11:09 +00:00
|
|
|
def notify_api():
|
2017-11-22 17:54:59 +00:00
|
|
|
app = Flask('test')
|
|
|
|
|
create_app(app)
|
2016-11-04 10:11:09 +00:00
|
|
|
|
|
|
|
|
# deattach server-error error handlers - error_handler_spec looks like:
|
|
|
|
|
# {'blueprint_name': {
|
|
|
|
|
# status_code: [error_handlers],
|
2017-08-18 15:39:39 +01:00
|
|
|
# None: { ExceptionClass: error_handler }
|
2016-11-04 10:11:09 +00:00
|
|
|
# }}
|
|
|
|
|
for error_handlers in app.error_handler_spec.values():
|
|
|
|
|
error_handlers.pop(500, None)
|
|
|
|
|
if None in error_handlers:
|
2017-08-18 15:39:39 +01:00
|
|
|
error_handlers[None] = {
|
|
|
|
|
exc_class: error_handler
|
|
|
|
|
for exc_class, error_handler in error_handlers[None].items()
|
|
|
|
|
if exc_class != Exception
|
|
|
|
|
}
|
2016-11-04 10:11:09 +00:00
|
|
|
if error_handlers[None] == []:
|
|
|
|
|
error_handlers.pop(None)
|
|
|
|
|
|
2015-12-11 16:57:00 +00:00
|
|
|
ctx = app.app_context()
|
|
|
|
|
ctx.push()
|
|
|
|
|
|
2016-11-04 10:11:09 +00:00
|
|
|
yield app
|
2015-12-11 16:57:00 +00:00
|
|
|
|
2016-11-04 10:11:09 +00:00
|
|
|
ctx.pop()
|
2015-12-11 16:57:00 +00:00
|
|
|
|
|
|
|
|
|
2016-08-30 11:18:30 +01:00
|
|
|
@pytest.fixture(scope='function')
|
2016-08-30 10:41:23 +01:00
|
|
|
def client(notify_api):
|
|
|
|
|
with notify_api.test_request_context(), notify_api.test_client() as client:
|
|
|
|
|
yield client
|
|
|
|
|
|
|
|
|
|
|
2017-08-23 14:46:40 +01:00
|
|
|
def create_test_db(database_uri):
|
2017-08-24 13:54:16 +01:00
|
|
|
# get the
|
|
|
|
|
db_uri_parts = database_uri.split('/')
|
|
|
|
|
postgres_db_uri = '/'.join(db_uri_parts[:-1] + ['postgres'])
|
|
|
|
|
|
|
|
|
|
postgres_db = sqlalchemy.create_engine(
|
|
|
|
|
postgres_db_uri,
|
|
|
|
|
echo=False,
|
|
|
|
|
isolation_level='AUTOCOMMIT',
|
|
|
|
|
client_encoding='utf8'
|
|
|
|
|
)
|
2017-08-23 14:46:40 +01:00
|
|
|
try:
|
2017-08-24 13:54:16 +01:00
|
|
|
result = postgres_db.execute(sqlalchemy.sql.text('CREATE DATABASE {}'.format(db_uri_parts[-1])))
|
|
|
|
|
result.close()
|
|
|
|
|
except sqlalchemy.exc.ProgrammingError:
|
|
|
|
|
# database "test_notification_api_master" already exists
|
2017-08-23 14:46:40 +01:00
|
|
|
pass
|
|
|
|
|
finally:
|
2017-08-24 13:54:16 +01:00
|
|
|
postgres_db.dispose()
|
2017-08-23 14:46:40 +01:00
|
|
|
|
|
|
|
|
|
2016-01-07 17:31:17 +00:00
|
|
|
@pytest.fixture(scope='session')
|
2017-08-23 14:46:40 +01:00
|
|
|
def notify_db(notify_api, worker_id):
|
|
|
|
|
assert 'test_notification_api' in db.engine.url.database, 'dont run tests against main db'
|
|
|
|
|
|
|
|
|
|
# create a database for this worker thread -
|
|
|
|
|
from flask import current_app
|
|
|
|
|
current_app.config['SQLALCHEMY_DATABASE_URI'] += '_{}'.format(worker_id)
|
|
|
|
|
create_test_db(current_app.config['SQLALCHEMY_DATABASE_URI'])
|
|
|
|
|
|
2016-04-08 16:13:10 +01:00
|
|
|
BASE_DIR = os.path.dirname(os.path.dirname(__file__))
|
|
|
|
|
ALEMBIC_CONFIG = os.path.join(BASE_DIR, 'migrations')
|
|
|
|
|
config = Config(ALEMBIC_CONFIG + '/alembic.ini')
|
|
|
|
|
config.set_main_option("script_location", ALEMBIC_CONFIG)
|
|
|
|
|
|
|
|
|
|
with notify_api.app_context():
|
|
|
|
|
upgrade(config, 'head')
|
|
|
|
|
|
2016-11-04 10:11:09 +00:00
|
|
|
yield db
|
2016-04-08 16:13:10 +01:00
|
|
|
|
2016-11-04 10:11:09 +00:00
|
|
|
db.session.remove()
|
|
|
|
|
db.get_engine(notify_api).dispose()
|
2016-01-07 17:31:17 +00:00
|
|
|
|
|
|
|
|
|
2016-01-08 12:18:12 +00:00
|
|
|
@pytest.fixture(scope='function')
|
2019-11-11 16:09:15 +00:00
|
|
|
def sms_providers(notify_db):
|
|
|
|
|
"""
|
|
|
|
|
In production we randomly choose which provider to use based on their priority. To guarantee tests run the same each
|
|
|
|
|
time, make sure we always choose mmg. You'll need to override them in your tests if you wish to do something
|
|
|
|
|
different.
|
|
|
|
|
"""
|
|
|
|
|
get_provider_details_by_identifier('mmg').priority = 100
|
|
|
|
|
get_provider_details_by_identifier('firetext').priority = 0
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.fixture(scope='function')
|
|
|
|
|
def notify_db_session(notify_db, sms_providers):
|
2016-11-04 10:11:09 +00:00
|
|
|
yield notify_db
|
2016-01-08 12:18:12 +00:00
|
|
|
|
2016-11-04 10:11:09 +00:00
|
|
|
notify_db.session.remove()
|
|
|
|
|
for tbl in reversed(notify_db.metadata.sorted_tables):
|
2017-01-13 12:14:34 +00:00
|
|
|
if tbl.name not in ["provider_details",
|
|
|
|
|
"key_types",
|
|
|
|
|
"branding_type",
|
|
|
|
|
"job_status",
|
|
|
|
|
"provider_details_history",
|
2017-04-21 12:39:42 +01:00
|
|
|
"template_process_type",
|
2017-05-11 15:22:58 +01:00
|
|
|
"notification_status_types",
|
2019-07-24 16:37:23 +01:00
|
|
|
"organisation_types",
|
2017-10-30 11:53:55 +00:00
|
|
|
"service_permission_types",
|
2018-02-19 17:14:01 +00:00
|
|
|
"auth_type",
|
2018-07-10 11:31:18 +01:00
|
|
|
"invite_status_type",
|
2018-07-17 16:15:57 +01:00
|
|
|
"service_callback_type"]:
|
2016-11-04 10:11:09 +00:00
|
|
|
notify_db.engine.execute(tbl.delete())
|
|
|
|
|
notify_db.session.commit()
|
2016-01-08 12:18:12 +00:00
|
|
|
|
|
|
|
|
|
2016-12-08 12:12:45 +00:00
|
|
|
@pytest.fixture
|
|
|
|
|
def os_environ():
|
|
|
|
|
"""
|
|
|
|
|
clear os.environ, and restore it after the test runs
|
|
|
|
|
"""
|
|
|
|
|
# for use whenever you expect code to edit environment variables
|
|
|
|
|
old_env = os.environ.copy()
|
2017-07-11 15:41:44 +01:00
|
|
|
|
|
|
|
|
class EnvironDict(dict):
|
|
|
|
|
def __setitem__(self, key, value):
|
|
|
|
|
assert type(value) == str
|
|
|
|
|
super().__setitem__(key, value)
|
|
|
|
|
|
|
|
|
|
os.environ = EnvironDict()
|
2016-12-08 12:12:45 +00:00
|
|
|
yield
|
|
|
|
|
os.environ = old_env
|
2016-02-03 13:16:19 +00:00
|
|
|
|
|
|
|
|
|
2016-07-18 12:02:27 +01:00
|
|
|
def pytest_generate_tests(metafunc):
|
|
|
|
|
# Copied from https://gist.github.com/pfctdayelise/5719730
|
2018-10-26 17:54:53 +01:00
|
|
|
idparametrize = metafunc.definition.get_closest_marker('idparametrize')
|
2016-07-18 12:02:27 +01:00
|
|
|
if idparametrize:
|
|
|
|
|
argnames, testdata = idparametrize.args
|
|
|
|
|
ids, argvalues = zip(*sorted(testdata.items()))
|
|
|
|
|
metafunc.parametrize(argnames, argvalues, ids=ids)
|
2016-09-21 17:13:26 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
@contextmanager
|
|
|
|
|
def set_config(app, name, value):
|
|
|
|
|
old_val = app.config.get(name)
|
|
|
|
|
app.config[name] = value
|
2018-03-27 17:41:05 +01:00
|
|
|
try:
|
|
|
|
|
yield
|
|
|
|
|
finally:
|
|
|
|
|
app.config[name] = old_val
|
2017-02-13 15:46:06 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
@contextmanager
|
|
|
|
|
def set_config_values(app, dict):
|
|
|
|
|
old_values = {}
|
|
|
|
|
|
|
|
|
|
for key in dict:
|
|
|
|
|
old_values[key] = app.config.get(key)
|
|
|
|
|
app.config[key] = dict[key]
|
|
|
|
|
|
2018-03-27 17:41:05 +01:00
|
|
|
try:
|
|
|
|
|
yield
|
|
|
|
|
finally:
|
|
|
|
|
for key in dict:
|
|
|
|
|
app.config[key] = old_values[key]
|
2018-07-17 15:27:43 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
class Matcher:
|
|
|
|
|
def __init__(self, description, key):
|
|
|
|
|
self.description = description
|
|
|
|
|
self.key = key
|
|
|
|
|
|
|
|
|
|
def __eq__(self, other):
|
|
|
|
|
return self.key(other)
|
|
|
|
|
|
|
|
|
|
def __repr__(self):
|
|
|
|
|
return '<Matcher: {}>'.format(self.description)
|