751 lines
19 KiB
Python
751 lines
19 KiB
Python
import pytest
|
|
from django.test import Client
|
|
|
|
from rest_framework.reverse import reverse
|
|
|
|
|
|
|
|
class MetadataAttributesFunctionalBase:
|
|
""" Functional Tests for API, HTTP/Options Method
|
|
|
|
These tests ensure that **ALL** serializers include the metaclass that adds the required
|
|
data to the HTTP Options method.
|
|
|
|
Metaclass adds data required for the UI to function correctly.
|
|
"""
|
|
|
|
app_namespace: str = None
|
|
|
|
url_name: str = None
|
|
|
|
viewset_type: str = 'list'
|
|
|
|
|
|
def test_method_options_request_list_ok(self):
|
|
"""Test HTTP/Options Method
|
|
|
|
Ensure the request returns `OK`.
|
|
"""
|
|
|
|
client = Client()
|
|
client.force_login(self.view_user)
|
|
|
|
if getattr(self, 'url_kwargs', None):
|
|
|
|
url = reverse(self.app_namespace + ':' + self.url_name + '-' + self.viewset_type, kwargs = self.url_kwargs)
|
|
|
|
else:
|
|
|
|
url = reverse(self.app_namespace + ':' + self.url_name + '-' + self.viewset_type)
|
|
|
|
response = client.options( url, content_type='application/json' )
|
|
|
|
assert response.status_code == 200
|
|
|
|
|
|
def test_method_options_request_list_data_returned(self):
|
|
"""Test HTTP/Options Method
|
|
|
|
Ensure the request returns data.
|
|
"""
|
|
|
|
client = Client()
|
|
client.force_login(self.view_user)
|
|
|
|
if getattr(self, 'url_kwargs', None):
|
|
|
|
url = reverse(self.app_namespace + ':' + self.url_name + '-' + self.viewset_type, kwargs = self.url_kwargs)
|
|
|
|
else:
|
|
|
|
url = reverse(self.app_namespace + ':' + self.url_name + '-' + self.viewset_type)
|
|
|
|
response = client.options( url, content_type='application/json' )
|
|
|
|
assert response.data is not None
|
|
|
|
|
|
def test_method_options_request_list_data_type(self):
|
|
"""Test HTTP/Options Method
|
|
|
|
Ensure the request data returned is of type `dict`
|
|
"""
|
|
|
|
client = Client()
|
|
client.force_login(self.view_user)
|
|
|
|
if getattr(self, 'url_kwargs', None):
|
|
|
|
url = reverse(self.app_namespace + ':' + self.url_name + '-' + self.viewset_type, kwargs = self.url_kwargs)
|
|
|
|
else:
|
|
|
|
url = reverse(self.app_namespace + ':' + self.url_name + '-' + self.viewset_type)
|
|
|
|
response = client.options( url, content_type='application/json' )
|
|
|
|
assert type(response.data) is dict
|
|
|
|
|
|
def test_method_options_request_detail_ok(self):
|
|
"""Test HTTP/Options Method
|
|
|
|
Ensure the request returns `OK`.
|
|
"""
|
|
|
|
client = Client()
|
|
client.force_login(self.view_user)
|
|
|
|
if getattr(self, 'url_kwargs', None):
|
|
|
|
url = reverse(self.app_namespace + ':' + self.url_name + '-' + self.viewset_type, kwargs = self.url_kwargs)
|
|
|
|
else:
|
|
|
|
url = reverse(self.app_namespace + ':' + self.url_name + '-' + self.viewset_type)
|
|
|
|
response = client.options( url, content_type='application/json' )
|
|
|
|
assert response.status_code == 200
|
|
|
|
|
|
def test_method_options_request_detail_data_returned(self):
|
|
"""Test HTTP/Options Method
|
|
|
|
Ensure the request returns data.
|
|
"""
|
|
|
|
client = Client()
|
|
client.force_login(self.view_user)
|
|
|
|
response = client.options(
|
|
reverse(
|
|
self.app_namespace + ':' + self.url_name + '-detail',
|
|
kwargs=self.url_view_kwargs
|
|
),
|
|
content_type='application/json'
|
|
)
|
|
|
|
assert response.data is not None
|
|
|
|
|
|
def test_method_options_request_detail_data_type(self):
|
|
"""Test HTTP/Options Method
|
|
|
|
Ensure the request data returned is of type `dict`
|
|
"""
|
|
|
|
client = Client()
|
|
client.force_login(self.view_user)
|
|
|
|
response = client.options(
|
|
reverse(
|
|
self.app_namespace + ':' + self.url_name + '-detail',
|
|
kwargs=self.url_view_kwargs
|
|
),
|
|
content_type='application/json'
|
|
)
|
|
|
|
assert type(response.data) is dict
|
|
|
|
|
|
|
|
def test_method_options_request_detail_data_has_key_urls(self):
|
|
"""Test HTTP/Options Method
|
|
|
|
Ensure the request data returned has key `urls`
|
|
"""
|
|
|
|
client = Client()
|
|
client.force_login(self.view_user)
|
|
|
|
response = client.options(
|
|
reverse(
|
|
self.app_namespace + ':' + self.url_name + '-detail',
|
|
kwargs=self.url_view_kwargs
|
|
),
|
|
content_type='application/json'
|
|
)
|
|
|
|
assert 'urls' in response.data
|
|
|
|
|
|
def test_method_options_request_detail_data_key_urls_is_dict(self):
|
|
"""Test HTTP/Options Method
|
|
|
|
Ensure the request data key `urls` is dict
|
|
"""
|
|
|
|
client = Client()
|
|
client.force_login(self.view_user)
|
|
|
|
response = client.options(
|
|
reverse(
|
|
self.app_namespace + ':' + self.url_name + '-detail',
|
|
kwargs=self.url_view_kwargs
|
|
),
|
|
content_type='application/json'
|
|
)
|
|
|
|
assert type(response.data['urls']) is dict
|
|
|
|
|
|
|
|
def test_method_options_request_detail_data_has_key_urls_self(self):
|
|
"""Test HTTP/Options Method
|
|
|
|
Ensure the request data returned has key `urls.self`
|
|
"""
|
|
|
|
client = Client()
|
|
client.force_login(self.view_user)
|
|
|
|
response = client.options(
|
|
reverse(
|
|
self.app_namespace + ':' + self.url_name + '-detail',
|
|
kwargs=self.url_view_kwargs
|
|
),
|
|
content_type='application/json'
|
|
)
|
|
|
|
assert 'urls' in response.data
|
|
|
|
|
|
def test_method_options_request_detail_data_key_urls_self_is_str(self):
|
|
"""Test HTTP/Options Method
|
|
|
|
Ensure the request data key `urls.self` is a string
|
|
"""
|
|
|
|
client = Client()
|
|
client.force_login(self.view_user)
|
|
|
|
response = client.options(
|
|
reverse(
|
|
self.app_namespace + ':' + self.url_name + '-detail',
|
|
kwargs=self.url_view_kwargs
|
|
),
|
|
content_type='application/json'
|
|
)
|
|
|
|
assert type(response.data['urls']['self']) is str
|
|
|
|
|
|
@pytest.mark.skip(reason='to be written')
|
|
def test_method_options_no_field_is_generic(self):
|
|
"""Test HTTP/Options Method
|
|
|
|
Fields are used for the UI to setup inputs correctly.
|
|
|
|
Ensure all fields at path `.actions.<METHOD>.<name>.type` do not have `GenericField` as the value.
|
|
"""
|
|
|
|
pass
|
|
|
|
|
|
|
|
class MetadataAttributesFunctionalTable:
|
|
"""Test cases for Metadata
|
|
|
|
These test cases are for models that are expected to
|
|
be rendered in a table.
|
|
"""
|
|
|
|
|
|
def test_method_options_request_list_data_has_key_table_fields(self):
|
|
"""Test HTTP/Options Method
|
|
|
|
Ensure the request data returned has key `table_fields`
|
|
"""
|
|
|
|
client = Client()
|
|
client.force_login(self.view_user)
|
|
|
|
if getattr(self, 'url_kwargs', None):
|
|
|
|
url = reverse(self.app_namespace + ':' + self.url_name + '-' + self.viewset_type, kwargs = self.url_kwargs)
|
|
|
|
else:
|
|
|
|
url = reverse(self.app_namespace + ':' + self.url_name + '-' + self.viewset_type)
|
|
|
|
response = client.options( url, content_type='application/json' )
|
|
|
|
assert 'table_fields' in response.data
|
|
|
|
|
|
def test_method_options_request_list_data_key_table_fields_is_list(self):
|
|
"""Test HTTP/Options Method
|
|
|
|
Ensure the request data['table_fields'] is of type `list`
|
|
"""
|
|
|
|
client = Client()
|
|
client.force_login(self.view_user)
|
|
|
|
if getattr(self, 'url_kwargs', None):
|
|
|
|
url = reverse(self.app_namespace + ':' + self.url_name + '-' + self.viewset_type, kwargs = self.url_kwargs)
|
|
|
|
else:
|
|
|
|
url = reverse(self.app_namespace + ':' + self.url_name + '-' + self.viewset_type)
|
|
|
|
response = client.options( url, content_type='application/json' )
|
|
|
|
assert type(response.data['table_fields']) is list
|
|
|
|
|
|
def test_method_options_request_list_data_key_table_fields_is_list_of_str(self):
|
|
"""Test HTTP/Options Method
|
|
|
|
Ensure the request data['table_fields'] list is of `str`
|
|
"""
|
|
|
|
client = Client()
|
|
client.force_login(self.view_user)
|
|
|
|
if getattr(self, 'url_kwargs', None):
|
|
|
|
url = reverse(self.app_namespace + ':' + self.url_name + '-' + self.viewset_type, kwargs = self.url_kwargs)
|
|
|
|
else:
|
|
|
|
url = reverse(self.app_namespace + ':' + self.url_name + '-' + self.viewset_type)
|
|
|
|
response = client.options( url, content_type='application/json' )
|
|
|
|
all_string = True
|
|
|
|
for item in response.data['table_fields']:
|
|
|
|
if type(item) is not str:
|
|
|
|
all_string = False
|
|
|
|
|
|
assert all_string
|
|
|
|
|
|
|
|
class MetadataAttributesFunctionalEndpoint:
|
|
"""Test cases for Metadata
|
|
|
|
These test cases are for models that will have an
|
|
endpoint. i.e. A Detail view
|
|
"""
|
|
|
|
|
|
def test_method_options_request_detail_data_has_key_page_layout(self):
|
|
"""Test HTTP/Options Method
|
|
|
|
Ensure the request data returned has key `layout`
|
|
"""
|
|
|
|
client = Client()
|
|
client.force_login(self.view_user)
|
|
|
|
response = client.options(
|
|
reverse(
|
|
self.app_namespace + ':' + self.url_name + '-detail',
|
|
kwargs=self.url_view_kwargs
|
|
),
|
|
content_type='application/json'
|
|
)
|
|
|
|
assert 'layout' in response.data
|
|
|
|
|
|
def test_method_options_request_detail_data_key_page_layout_is_list(self):
|
|
"""Test HTTP/Options Method
|
|
|
|
Ensure the request data['layout'] is of type `list`
|
|
"""
|
|
|
|
client = Client()
|
|
client.force_login(self.view_user)
|
|
|
|
response = client.options(
|
|
reverse(
|
|
self.app_namespace + ':' + self.url_name + '-detail',
|
|
kwargs=self.url_view_kwargs
|
|
),
|
|
content_type='application/json'
|
|
)
|
|
|
|
assert type(response.data['layout']) is list
|
|
|
|
|
|
def test_method_options_request_detail_data_key_page_layout_is_list_of_dict(self):
|
|
"""Test HTTP/Options Method
|
|
|
|
Ensure the request data['layout'] list is of `dict`
|
|
"""
|
|
|
|
client = Client()
|
|
client.force_login(self.view_user)
|
|
|
|
response = client.options(
|
|
reverse(
|
|
self.app_namespace + ':' + self.url_name + '-detail',
|
|
kwargs=self.url_view_kwargs
|
|
),
|
|
content_type='application/json'
|
|
)
|
|
|
|
all_dict = True
|
|
|
|
for item in response.data['layout']:
|
|
|
|
if type(item) is not dict:
|
|
|
|
all_dict = False
|
|
|
|
|
|
assert all_dict
|
|
|
|
|
|
def test_method_options_request_detail_data_key_page_layout_dicts_key_exists_name(self):
|
|
"""Test HTTP/Options Method
|
|
|
|
Ensure the request data['layout'].x has key `name`
|
|
"""
|
|
|
|
client = Client()
|
|
client.force_login(self.view_user)
|
|
|
|
response = client.options(
|
|
reverse(
|
|
self.app_namespace + ':' + self.url_name + '-detail',
|
|
kwargs=self.url_view_kwargs
|
|
),
|
|
content_type='application/json'
|
|
)
|
|
|
|
has_key = True
|
|
|
|
for item in response.data['layout']:
|
|
|
|
if 'name' not in item:
|
|
|
|
has_key = False
|
|
|
|
|
|
assert has_key
|
|
|
|
|
|
def test_method_options_request_detail_data_key_page_layout_dicts_key_type_name(self):
|
|
"""Test HTTP/Options Method
|
|
|
|
Ensure the request data['layout'].x.[name] is of type `str`
|
|
"""
|
|
|
|
client = Client()
|
|
client.force_login(self.view_user)
|
|
|
|
response = client.options(
|
|
reverse(
|
|
self.app_namespace + ':' + self.url_name + '-detail',
|
|
kwargs=self.url_view_kwargs
|
|
),
|
|
content_type='application/json'
|
|
)
|
|
|
|
all_are_str = True
|
|
|
|
for item in response.data['layout']:
|
|
|
|
if type(item['name']) is not str:
|
|
|
|
all_are_str = False
|
|
|
|
|
|
assert all_are_str
|
|
|
|
|
|
def test_method_options_request_detail_data_key_page_layout_dicts_key_exists_sections(self):
|
|
"""Test HTTP/Options Method
|
|
|
|
Ensure the request data['layout'].x has key `sections`
|
|
"""
|
|
|
|
client = Client()
|
|
client.force_login(self.view_user)
|
|
|
|
response = client.options(
|
|
reverse(
|
|
self.app_namespace + ':' + self.url_name + '-detail',
|
|
kwargs=self.url_view_kwargs
|
|
),
|
|
content_type='application/json'
|
|
)
|
|
|
|
has_key = True
|
|
|
|
for item in response.data['layout']:
|
|
|
|
if 'sections' not in item:
|
|
|
|
has_key = False
|
|
|
|
|
|
assert has_key
|
|
|
|
|
|
def test_method_options_request_detail_data_key_page_layout_dicts_key_type_sections(self):
|
|
"""Test HTTP/Options Method
|
|
|
|
Ensure the request data['layout'].x.[sections] is of type `list`
|
|
"""
|
|
|
|
client = Client()
|
|
client.force_login(self.view_user)
|
|
|
|
response = client.options(
|
|
reverse(
|
|
self.app_namespace + ':' + self.url_name + '-detail',
|
|
kwargs=self.url_view_kwargs
|
|
),
|
|
content_type='application/json'
|
|
)
|
|
|
|
all_are_str = True
|
|
|
|
for item in response.data['layout']:
|
|
|
|
if type(item['sections']) is not list:
|
|
|
|
all_are_str = False
|
|
|
|
|
|
assert all_are_str
|
|
|
|
|
|
|
|
class MetadataAttributesFunctional(
|
|
MetadataAttributesFunctionalEndpoint,
|
|
MetadataAttributesFunctionalTable,
|
|
MetadataAttributesFunctionalBase,
|
|
):
|
|
|
|
pass
|
|
|
|
|
|
|
|
class MetaDataNavigationEntriesFunctional:
|
|
""" Test cases for the Navigation menu
|
|
|
|
Navigation menu is rendered as part of the API when a HTTP/OPTIONS
|
|
request has been made. Each menu entry requires that a user has View
|
|
permissions for that entry to be visible.
|
|
|
|
**No** menu entry is to be returned for **any** user whom does not
|
|
have the corresponding view permission.
|
|
|
|
These test cases are for any model that has a navigation menu entry.
|
|
|
|
## Tests
|
|
|
|
- Ensure add user does not have menu entry
|
|
- Ensure change user does not have menu entry
|
|
- Ensure delete user does not have menu entry
|
|
- Ensure the view user has menu entry
|
|
- No menu to return without pages for add user
|
|
- No menu to return without pages for change user
|
|
- No menu to return without pages for delete user
|
|
- No menu to return without pages for view user
|
|
"""
|
|
|
|
menu_id: str = None
|
|
""" Name of the Menu entry
|
|
|
|
Match for .navigation[i][name]
|
|
"""
|
|
|
|
menu_entry_id: str = None
|
|
"""Name of the menu entry
|
|
|
|
Match for .navigation[i][pages][i][name]
|
|
"""
|
|
|
|
app_namespace:str = None
|
|
"""application namespace"""
|
|
|
|
url_name: str = None
|
|
"""url name"""
|
|
|
|
url_kwargs: dict = None
|
|
"""View URL kwargs"""
|
|
|
|
add_user = None
|
|
""" User with add permission"""
|
|
|
|
change_user = None
|
|
""" User with change permission"""
|
|
|
|
delete_user = None
|
|
""" User with delete permission"""
|
|
|
|
view_user = None
|
|
""" User with view permission"""
|
|
|
|
|
|
|
|
def test_navigation_entry_add_user(self):
|
|
"""Test HTTP/Options Method Navigation Entry
|
|
|
|
Ensure that a user with add permission, does not
|
|
have the menu entry within navigation
|
|
"""
|
|
|
|
client = Client()
|
|
client.force_login(self.add_user)
|
|
|
|
|
|
if getattr(self, 'url_kwargs', None):
|
|
|
|
url = reverse(self.app_namespace + ':' + self.url_name + '-list', kwargs = self.url_kwargs)
|
|
|
|
else:
|
|
|
|
url = reverse(self.app_namespace + ':' + self.url_name + '-list')
|
|
|
|
response = client.options(
|
|
url,
|
|
content_type='application/json'
|
|
)
|
|
|
|
assert response.status_code == 403
|
|
|
|
|
|
|
|
def test_navigation_entry_change_user(self):
|
|
"""Test HTTP/Options Method Navigation Entry
|
|
|
|
Ensure that a user with change permission, does not
|
|
have the menu entry within navigation
|
|
"""
|
|
|
|
client = Client()
|
|
client.force_login(self.change_user)
|
|
|
|
if getattr(self, 'url_kwargs', None):
|
|
|
|
url = reverse(self.app_namespace + ':' + self.url_name + '-list', kwargs = self.url_kwargs)
|
|
|
|
else:
|
|
|
|
url = reverse(self.app_namespace + ':' + self.url_name + '-list')
|
|
|
|
response = client.options(
|
|
url,
|
|
content_type='application/json'
|
|
)
|
|
|
|
|
|
assert response.status_code == 403
|
|
|
|
|
|
|
|
def test_navigation_entry_delete_user(self):
|
|
"""Test HTTP/Options Method Navigation Entry
|
|
|
|
Ensure that a user with delete permission, does not
|
|
have the menu entry within navigation
|
|
"""
|
|
|
|
client = Client()
|
|
client.force_login(self.delete_user)
|
|
|
|
if getattr(self, 'url_kwargs', None):
|
|
|
|
url = reverse(self.app_namespace + ':' + self.url_name + '-list', kwargs = self.url_kwargs)
|
|
|
|
else:
|
|
|
|
url = reverse(self.app_namespace + ':' + self.url_name + '-list')
|
|
|
|
response = client.options(
|
|
url,
|
|
content_type='application/json'
|
|
)
|
|
|
|
|
|
assert response.status_code == 403
|
|
|
|
|
|
|
|
def test_navigation_entry_view_user(self):
|
|
"""Test HTTP/Options Method Navigation Entry
|
|
|
|
Ensure that a user with view permission,
|
|
has the menu entry within navigation
|
|
"""
|
|
|
|
client = Client()
|
|
client.force_login(self.view_user)
|
|
|
|
if getattr(self, 'url_kwargs', None):
|
|
|
|
url = reverse(self.app_namespace + ':' + self.url_name + '-list', kwargs = self.url_kwargs)
|
|
|
|
else:
|
|
|
|
url = reverse(self.app_namespace + ':' + self.url_name + '-list')
|
|
|
|
response = client.options(
|
|
url,
|
|
content_type='application/json'
|
|
)
|
|
|
|
menu_entry_found: bool = False
|
|
|
|
for nav_menu in response.data['navigation']:
|
|
|
|
if nav_menu['name'] == self.menu_id:
|
|
|
|
for menu_entry in nav_menu['pages']:
|
|
|
|
if menu_entry['name'] == self.menu_entry_id:
|
|
|
|
menu_entry_found = True
|
|
|
|
assert menu_entry_found
|
|
|
|
|
|
|
|
def test_navigation_no_empty_menu_view_user(self):
|
|
"""Test HTTP/Options Method Navigation Entry
|
|
|
|
Ensure that a user with view permission, does not
|
|
have any nave menu without pages
|
|
"""
|
|
|
|
client = Client()
|
|
client.force_login(self.view_user)
|
|
|
|
if getattr(self, 'url_kwargs', None):
|
|
|
|
url = reverse(self.app_namespace + ':' + self.url_name + '-list', kwargs = self.url_kwargs)
|
|
|
|
else:
|
|
|
|
url = reverse(self.app_namespace + ':' + self.url_name + '-list')
|
|
|
|
response = client.options(
|
|
url,
|
|
content_type='application/json'
|
|
)
|
|
|
|
no_empty_menu_found: bool = True
|
|
|
|
for nav_menu in response.data['navigation']:
|
|
|
|
if len(nav_menu['pages']) == 0:
|
|
|
|
no_empty_menu_found = False
|
|
|
|
assert no_empty_menu_found
|
|
|
|
|