2016-12-02 09:18:22 -05:00
|
|
|
"""
|
|
|
|
Functional tests for the managing sites.
|
|
|
|
|
2017-03-16 08:34:57 -04:00
|
|
|
:copyright: Copyright 2013-2017, Dorian Pula <dorian.pula@amber-penguin-software.ca>
|
2016-12-02 09:18:22 -05:00
|
|
|
:license: AGPL v3+
|
|
|
|
"""
|
|
|
|
|
2017-04-05 17:43:24 -04:00
|
|
|
import http
|
|
|
|
from unittest import mock
|
|
|
|
|
2016-12-02 09:18:22 -05:00
|
|
|
import pytest_bdd as bdd
|
|
|
|
import requests
|
2017-03-14 09:09:16 -04:00
|
|
|
from pytest_bdd import parsers
|
2016-12-02 09:18:22 -05:00
|
|
|
|
2017-03-14 08:46:54 -04:00
|
|
|
from tests import utils
|
2016-12-02 09:18:22 -05:00
|
|
|
|
|
|
|
|
2017-04-05 17:43:24 -04:00
|
|
|
bdd.scenarios('site_creation.feature')
|
|
|
|
bdd.scenarios('site_access.feature')
|
|
|
|
bdd.scenarios('site_modification.feature')
|
|
|
|
bdd.scenarios('site_deletion.feature')
|
|
|
|
|
2016-12-02 09:18:22 -05:00
|
|
|
|
|
|
|
@bdd.given(parsers.parse('I am an {user_role} user'))
|
2017-03-14 08:46:54 -04:00
|
|
|
@bdd.given(parsers.parse('I am a {user_role} user'))
|
2017-04-05 17:43:24 -04:00
|
|
|
def auth_token_headers(user_role, api_base_uri, db_engine):
|
2017-03-14 08:46:54 -04:00
|
|
|
|
|
|
|
user = utils.generate_test_user(role=user_role)
|
|
|
|
utils.save_test_user_in_db(db_engine, user)
|
2017-04-05 17:43:24 -04:00
|
|
|
token = requests.post(
|
2017-03-14 08:46:54 -04:00
|
|
|
url=f'{api_base_uri}/auth',
|
|
|
|
json={
|
|
|
|
'username': user.username,
|
|
|
|
'password': user.password,
|
|
|
|
}
|
|
|
|
).json()['access_token']
|
2017-04-05 17:43:24 -04:00
|
|
|
|
|
|
|
return {'Authorization': f'JWT {token}'}
|
|
|
|
|
|
|
|
|
|
|
|
@bdd.given(parsers.parse('I am a visitor'), target_fixture='auth_token_headers')
|
|
|
|
def no_auth_token_headers():
|
|
|
|
return {}
|
|
|
|
|
|
|
|
|
|
|
|
@bdd.given(parsers.parse('I try to create a site'), target_fixture='site_response')
|
|
|
|
def create_site_response(auth_token_headers, api_base_uri):
|
|
|
|
|
|
|
|
test_site = utils.generate_test_site()
|
|
|
|
site_creation_request = {
|
|
|
|
'name': test_site.site_name,
|
|
|
|
'base_url': test_site.base_url,
|
|
|
|
}
|
|
|
|
|
|
|
|
response = requests.post(
|
|
|
|
url=f'{api_base_uri}/api/sites/',
|
|
|
|
json=site_creation_request,
|
|
|
|
headers=auth_token_headers,
|
|
|
|
)
|
2017-04-05 18:12:06 -04:00
|
|
|
return utils.ResponseSampleBundle(response, test_site)
|
2017-04-05 17:43:24 -04:00
|
|
|
|
|
|
|
|
|
|
|
@bdd.given(parsers.parse('I try to create a site with the same site name'), target_fixture='site_response')
|
|
|
|
def recreate_existing_site_response(site_response, auth_token_headers, api_base_uri):
|
|
|
|
|
2017-04-05 18:12:06 -04:00
|
|
|
test_site = site_response.sample
|
2017-04-05 17:43:24 -04:00
|
|
|
site_creation_request = {
|
|
|
|
'name': test_site.site_name,
|
|
|
|
'base_url': test_site.base_url,
|
|
|
|
}
|
|
|
|
|
|
|
|
response = requests.post(
|
|
|
|
url=f'{api_base_uri}/api/sites/',
|
|
|
|
json=site_creation_request,
|
|
|
|
headers=auth_token_headers,
|
|
|
|
)
|
2017-04-05 18:12:06 -04:00
|
|
|
return utils.ResponseSampleBundle(response, test_site)
|
2017-04-05 17:43:24 -04:00
|
|
|
|
|
|
|
|
|
|
|
@bdd.given(parsers.parse('I try to create a site with a non-json request'), target_fixture='site_response')
|
|
|
|
def invalid_non_json_create_site_response(auth_token_headers, api_base_uri):
|
|
|
|
return requests.post(
|
|
|
|
url=f'{api_base_uri}/api/sites/',
|
|
|
|
data='',
|
|
|
|
headers=auth_token_headers,
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
@bdd.given(parsers.parse('I try to create a site with an empty request'), target_fixture='site_response')
|
|
|
|
def invalid_empty_create_site_response(auth_token_headers, api_base_uri):
|
|
|
|
return requests.post(
|
|
|
|
url=f'{api_base_uri}/api/sites/',
|
|
|
|
json={},
|
|
|
|
headers=auth_token_headers,
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
@bdd.given(parsers.parse('I try to modify the site with a non-json request'), target_fixture='site_response')
|
|
|
|
def invalid_non_json_modify_site_response(site_response, auth_token_headers, api_base_uri):
|
2017-04-05 18:12:06 -04:00
|
|
|
test_site = site_response.sample
|
2017-04-05 17:43:24 -04:00
|
|
|
return requests.put(
|
|
|
|
url=f'{api_base_uri}/api/sites/{test_site.site_name}',
|
|
|
|
data='',
|
|
|
|
headers=auth_token_headers,
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
@bdd.given(parsers.parse('I try to modify the site with an empty request'), target_fixture='site_response')
|
|
|
|
def invalid_empty_modify_site_response(site_response, auth_token_headers, api_base_uri):
|
2017-04-05 18:12:06 -04:00
|
|
|
test_site = site_response.sample
|
2017-04-05 17:43:24 -04:00
|
|
|
return requests.put(
|
|
|
|
url=f'{api_base_uri}/api/sites/{test_site.site_name}',
|
|
|
|
json={},
|
|
|
|
headers=auth_token_headers,
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
@bdd.given(parsers.parse('I get a {state} site'), target_fixture='site_response')
|
|
|
|
def get_site_request(state, auth_token_headers, api_base_uri, db_engine):
|
|
|
|
|
|
|
|
# TODO: Generate a test site by its state
|
|
|
|
test_site = utils.generate_test_site()
|
|
|
|
utils.save_test_site_in_db(db_engine, test_site)
|
|
|
|
|
|
|
|
response = requests.get(
|
|
|
|
url=f'{api_base_uri}/api/sites/{test_site.site_name}',
|
|
|
|
headers=auth_token_headers,
|
|
|
|
)
|
2017-04-05 18:12:06 -04:00
|
|
|
return utils.ResponseSampleBundle(response, test_site)
|
2017-04-05 17:43:24 -04:00
|
|
|
|
|
|
|
|
|
|
|
@bdd.given(parsers.parse('I get a site that does not exist'), target_fixture='site_response')
|
|
|
|
def get_non_existent_site_request(auth_token_headers, api_base_uri):
|
|
|
|
return requests.get(
|
|
|
|
url=f'{api_base_uri}/api/sites/this-does-not-exist',
|
|
|
|
headers=auth_token_headers,
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
@bdd.then(parsers.parse('I get a valid site'))
|
|
|
|
def assert_site_response(site_response, api_base_uri):
|
|
|
|
|
2017-04-05 18:12:06 -04:00
|
|
|
test_site = site_response.sample
|
2017-04-05 17:43:24 -04:00
|
|
|
actual_response = utils.extract_response(site_response)
|
|
|
|
assert actual_response.status_code == http.HTTPStatus.OK
|
|
|
|
|
|
|
|
expected_json = {
|
|
|
|
'name': test_site.site_name,
|
|
|
|
'base_url': test_site.base_url,
|
|
|
|
'urls': mock.ANY,
|
|
|
|
}
|
|
|
|
assert expected_json == actual_response.json()
|
|
|
|
assert f'{api_base_uri}/api/sites/{test_site.site_name}' == actual_response.json()['urls']['self']
|
|
|
|
|
|
|
|
|
|
|
|
@bdd.then(parsers.parse('I get a valid new site'))
|
|
|
|
def assert_new_site_response(site_response, api_base_uri):
|
|
|
|
|
2017-04-05 18:12:06 -04:00
|
|
|
test_site = site_response.sample
|
2017-04-05 17:43:24 -04:00
|
|
|
actual_response = utils.extract_response(site_response)
|
|
|
|
assert actual_response.status_code == http.HTTPStatus.CREATED
|
|
|
|
|
|
|
|
expected_json = {
|
|
|
|
'name': test_site.site_name,
|
|
|
|
'base_url': test_site.base_url,
|
|
|
|
'urls': mock.ANY,
|
|
|
|
}
|
|
|
|
assert expected_json == actual_response.json()
|
|
|
|
assert f'{api_base_uri}/api/sites/{test_site.site_name}' == actual_response.json()['urls']['self']
|
|
|
|
|
|
|
|
|
|
|
|
@bdd.given(parsers.parse('I try to delete the site'), target_fixture='site_response')
|
|
|
|
def delete_site_response(site_response, auth_token_headers, api_base_uri):
|
2017-04-05 18:12:06 -04:00
|
|
|
test_site = site_response.sample
|
2017-04-05 17:43:24 -04:00
|
|
|
response = requests.delete(
|
|
|
|
url=f'{api_base_uri}/api/sites/{test_site.site_name}',
|
|
|
|
headers=auth_token_headers,
|
|
|
|
)
|
2017-04-05 18:12:06 -04:00
|
|
|
return utils.ResponseSampleBundle(response, test_site)
|
2017-04-05 17:43:24 -04:00
|
|
|
|
|
|
|
|
|
|
|
@bdd.given(parsers.parse('I try to delete the deleted site again'), target_fixture='site_response')
|
|
|
|
def delete_deleted_site_response(site_response, auth_token_headers, api_base_uri):
|
|
|
|
return delete_site_response(site_response, auth_token_headers, api_base_uri)
|
|
|
|
|
|
|
|
|
|
|
|
@bdd.given(parsers.parse('I try to modify the site'), target_fixture='site_response')
|
|
|
|
def modify_site_response(site_response, auth_token_headers, api_base_uri):
|
2017-04-05 18:12:06 -04:00
|
|
|
test_site = site_response.sample
|
2017-04-05 17:43:24 -04:00
|
|
|
modified_base_url = f'{test_site.base_url}/new_'
|
|
|
|
modified_site = utils.generate_test_site(test_site.site_name, modified_base_url)
|
|
|
|
site_modification_request = {
|
|
|
|
'name': test_site.site_name,
|
|
|
|
'base_url': modified_base_url,
|
|
|
|
}
|
|
|
|
|
|
|
|
response = requests.put(
|
|
|
|
url=f'{api_base_uri}/api/sites/{test_site.site_name}',
|
|
|
|
json=site_modification_request,
|
|
|
|
headers=auth_token_headers,
|
|
|
|
)
|
2017-04-05 18:12:06 -04:00
|
|
|
return utils.ResponseSampleBundle(response, modified_site)
|
2017-04-05 17:43:24 -04:00
|
|
|
|
|
|
|
|
|
|
|
@bdd.given(parsers.parse('I try to modify a site that does not exist'), target_fixture='site_response')
|
|
|
|
def modify_non_existent_site_request(auth_token_headers, api_base_uri):
|
|
|
|
test_site = utils.generate_test_site()
|
|
|
|
site_modification_request = {
|
|
|
|
'name': 'this-does-not-exist',
|
|
|
|
'base_url': test_site.base_url,
|
|
|
|
}
|
|
|
|
|
|
|
|
return requests.put(
|
|
|
|
url=f'{api_base_uri}/api/sites/this-does-not-exist',
|
|
|
|
json=site_modification_request,
|
|
|
|
headers=auth_token_headers,
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
@bdd.then(parsers.parse('my updates are reflected in the site'))
|
|
|
|
def assert_updated_site_response(site_response, api_base_uri):
|
|
|
|
|
2017-04-05 18:12:06 -04:00
|
|
|
test_site = site_response.sample
|
2017-04-05 17:43:24 -04:00
|
|
|
actual_response = utils.extract_response(site_response)
|
|
|
|
assert actual_response.status_code == http.HTTPStatus.OK
|
|
|
|
|
|
|
|
expected_json = {
|
|
|
|
'name': test_site.site_name,
|
|
|
|
'base_url': test_site.base_url,
|
|
|
|
'urls': mock.ANY,
|
|
|
|
}
|
|
|
|
assert expected_json == actual_response.json()
|
|
|
|
assert f'{api_base_uri}/api/sites/{test_site.site_name}' == actual_response.json()['urls']['self']
|
|
|
|
|
|
|
|
|
|
|
|
@bdd.then(parsers.parse('I get a site can not be found message'))
|
|
|
|
def assert_resource_not_found_response(site_response):
|
|
|
|
actual_response = utils.extract_response(site_response)
|
|
|
|
expected_response_json = {
|
|
|
|
'error': {
|
|
|
|
'status_code': http.HTTPStatus.NOT_FOUND.value,
|
|
|
|
'message': 'Resource not found.',
|
|
|
|
'resource': actual_response.request.url,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
assert actual_response.status_code == http.HTTPStatus.NOT_FOUND
|
|
|
|
assert actual_response.json() == expected_response_json
|
|
|
|
|
|
|
|
|
|
|
|
@bdd.then(parsers.parse('I get an unauthorized response'))
|
|
|
|
def assert_unauthorized_response(site_response):
|
|
|
|
actual_response = utils.extract_response(site_response)
|
|
|
|
expected_response_json = {
|
|
|
|
'error': {
|
|
|
|
'status_code': http.HTTPStatus.UNAUTHORIZED.value,
|
|
|
|
'message': 'Not authorized to access this resource.',
|
|
|
|
'resource': actual_response.request.url,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
assert actual_response.status_code == http.HTTPStatus.UNAUTHORIZED
|
|
|
|
assert actual_response.json() == expected_response_json
|
|
|
|
|
|
|
|
|
|
|
|
@bdd.then(parsers.parse('I get a conflict response about an existing site'))
|
|
|
|
def assert_conflicting_resource_found_response(site_response):
|
|
|
|
actual_response = utils.extract_response(site_response)
|
|
|
|
expected_response_json = {
|
|
|
|
'error': {
|
|
|
|
'status_code': http.HTTPStatus.CONFLICT.value,
|
|
|
|
'message': 'Existing resource already found. PUT to the resource to update it.',
|
|
|
|
'resource': actual_response.request.url,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
assert actual_response.status_code == http.HTTPStatus.CONFLICT
|
|
|
|
assert actual_response.json() == expected_response_json
|
|
|
|
|
|
|
|
|
|
|
|
@bdd.then(parsers.parse('I get a bad request response'))
|
|
|
|
def assert_bad_request_response(site_response):
|
|
|
|
actual_response = utils.extract_response(site_response)
|
|
|
|
expected_response_json = {
|
|
|
|
'error': {
|
|
|
|
'status_code': http.HTTPStatus.BAD_REQUEST.value,
|
|
|
|
'message': mock.ANY,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
assert actual_response.json() == expected_response_json
|
|
|
|
assert actual_response.status_code == http.HTTPStatus.BAD_REQUEST
|
|
|
|
|
|
|
|
|
|
|
|
@bdd.then(parsers.parse('I get a response indicating the deletion was successful'))
|
|
|
|
def assert_resource_deleted_response(site_response):
|
|
|
|
actual_response = utils.extract_response(site_response)
|
|
|
|
assert actual_response.status_code == http.HTTPStatus.NO_CONTENT
|
|
|
|
assert not actual_response.content
|
|
|
|
assert len(actual_response.content) == 0
|