11
.github/workflows/ci.yaml
vendored
11
.github/workflows/ci.yaml
vendored
@ -46,6 +46,17 @@ jobs:
|
||||
WORKFLOW_TOKEN: ${{ secrets.WORKFLOW_TOKEN }}
|
||||
|
||||
|
||||
integration-test:
|
||||
name: 'Integration Test'
|
||||
uses: nofusscomputing/action_python/.github/workflows/python-integration.yaml@development
|
||||
needs:
|
||||
- docker
|
||||
with:
|
||||
PYTHON_VERSION: '3.11'
|
||||
secrets:
|
||||
WORKFLOW_TOKEN: ${{ secrets.WORKFLOW_TOKEN }}
|
||||
|
||||
|
||||
gitlab-mirror:
|
||||
if: ${{ github.repository == 'nofusscomputing/centurion_erp' }}
|
||||
runs-on: ubuntu-latest
|
||||
|
182
app/centurion/tests/integration/test_integration_list_urls.py
Normal file
182
app/centurion/tests/integration/test_integration_list_urls.py
Normal file
@ -0,0 +1,182 @@
|
||||
|
||||
import pytest
|
||||
import re
|
||||
import requests
|
||||
|
||||
from django.urls import get_resolver, URLPattern, URLResolver
|
||||
|
||||
|
||||
|
||||
def list_urls(urlpatterns, parent_pattern=''):
|
||||
|
||||
urls = []
|
||||
|
||||
for entry in urlpatterns:
|
||||
|
||||
if isinstance(entry, URLPattern):
|
||||
urls.append(parent_pattern + str(entry.pattern))
|
||||
|
||||
elif isinstance(entry, URLResolver):
|
||||
urls.extend(list_urls(entry.url_patterns, parent_pattern + str(entry.pattern)))
|
||||
|
||||
filtered = [
|
||||
re.sub(r"\^([a-z\-]+)\$$", r"\1", u).rstrip('/') for u in urls if (
|
||||
re.sub(r"\^([a-z\-]+)\$$", r"\1", u).startswith('api/')
|
||||
and '(' not in re.sub(r"\^([a-z\-]+)\$$", r"\1", u).rstrip('/')
|
||||
and '<' not in re.sub(r"\^([a-z\-]+)\$$", r"\1", u).rstrip('/')
|
||||
and '$' not in re.sub(r"\^([a-z\-]+)\$$", r"\1", u).rstrip('/')
|
||||
)
|
||||
]
|
||||
|
||||
return filtered
|
||||
|
||||
|
||||
no_auth_urls = [
|
||||
'api/v2/auth/login',
|
||||
'api/v2/docs',
|
||||
'api/v2/schema',
|
||||
]
|
||||
|
||||
urls_list_view_auth_required_excluded = [
|
||||
'api/v2/auth/logout',
|
||||
|
||||
]
|
||||
|
||||
urls_list_view_auth_required_authenticated_excluded = [
|
||||
'api/v2/itam/inventory',
|
||||
'api/v2/auth/logout',
|
||||
]
|
||||
|
||||
@pytest.mark.integration
|
||||
@pytest.mark.regression
|
||||
class URLChecksPyTest:
|
||||
|
||||
|
||||
|
||||
@pytest.fixture(scope="class")
|
||||
def auto_login_client(self):
|
||||
session = requests.Session()
|
||||
|
||||
login_page_url = "http://127.0.0.1:8003/api/v2/auth/login"
|
||||
login_post_url = "http://127.0.0.1:8003/api/v2/auth/login"
|
||||
|
||||
resp = session.get(login_page_url)
|
||||
resp.raise_for_status()
|
||||
# Extract CSRF token from cookies (Django sets csrftoken cookie)
|
||||
csrf_token = session.cookies.get("csrftoken")
|
||||
if not csrf_token:
|
||||
raise RuntimeError("CSRF token cookie not found")
|
||||
|
||||
login_data = {
|
||||
"username": "admin",
|
||||
"password": "admin",
|
||||
"csrfmiddlewaretoken": csrf_token,
|
||||
}
|
||||
|
||||
headers = {
|
||||
"Referer": login_page_url,
|
||||
"X-CSRFToken": csrf_token, # Include CSRF token header
|
||||
}
|
||||
|
||||
resp = session.post(login_post_url, data=login_data, headers=headers, allow_redirects=True)
|
||||
resp.raise_for_status()
|
||||
|
||||
|
||||
class Client:
|
||||
def __init__(self, session):
|
||||
self._session = session
|
||||
|
||||
self._unauth_session = requests.Session()
|
||||
|
||||
resp = self._unauth_session.get(login_page_url)
|
||||
resp.raise_for_status()
|
||||
self._headers = csrf_token = {
|
||||
"Referer": login_page_url,
|
||||
"X-CSRFToken": self._unauth_session.cookies.get("csrftoken"),
|
||||
}
|
||||
|
||||
def request(self, method, url, auth = False, **kwargs):
|
||||
|
||||
if auth:
|
||||
session = self._session
|
||||
else:
|
||||
session = self._unauth_session
|
||||
|
||||
return session.request(method, url, headers=self._headers, **kwargs)
|
||||
|
||||
@property
|
||||
def cookies(self):
|
||||
return self._session.cookies
|
||||
|
||||
return Client(session)
|
||||
|
||||
|
||||
list_view_urls = list_urls(urlpatterns = get_resolver().url_patterns)
|
||||
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
argnames = "url_path",
|
||||
argvalues = [
|
||||
url for url in list_view_urls if( url in no_auth_urls )
|
||||
],
|
||||
ids = [
|
||||
re.sub(r'[^\w_\-.:]', '_', url) for url in list_view_urls if( url in no_auth_urls )
|
||||
],
|
||||
)
|
||||
def test_urls_no_auth_required(self, url_path, auto_login_client):
|
||||
url = f"http://127.0.0.1:8003/{url_path}"
|
||||
|
||||
response = auto_login_client.request("GET", url)
|
||||
|
||||
assert response.status_code == 200
|
||||
|
||||
|
||||
|
||||
@pytest.mark.permissions
|
||||
@pytest.mark.parametrize(
|
||||
argnames = "url_path",
|
||||
argvalues = [
|
||||
url for url in list_view_urls if(
|
||||
url not in no_auth_urls
|
||||
and url not in urls_list_view_auth_required_excluded
|
||||
)
|
||||
],
|
||||
ids = [
|
||||
re.sub(r'[^\w_\-.:]', '_', url) for url in list_view_urls if(
|
||||
url not in no_auth_urls
|
||||
and url not in urls_list_view_auth_required_excluded
|
||||
)
|
||||
],
|
||||
)
|
||||
def test_urls_list_view_auth_required(self, url_path, auto_login_client):
|
||||
url = f"http://127.0.0.1:8003/{url_path}"
|
||||
|
||||
response = auto_login_client.request("GET", url)
|
||||
|
||||
assert response.status_code == 401
|
||||
|
||||
|
||||
|
||||
@pytest.mark.permissions
|
||||
@pytest.mark.parametrize(
|
||||
argnames = "url_path",
|
||||
argvalues = [
|
||||
url for url in list_view_urls if(
|
||||
url not in no_auth_urls
|
||||
and url not in urls_list_view_auth_required_authenticated_excluded
|
||||
)
|
||||
],
|
||||
ids = [
|
||||
re.sub(r'[^\w_\-.:]', '_', url) for url in list_view_urls if(
|
||||
url not in no_auth_urls
|
||||
and url not in urls_list_view_auth_required_authenticated_excluded
|
||||
)
|
||||
],
|
||||
)
|
||||
def test_urls_list_view_auth_required_authenticated(self, url_path, auto_login_client):
|
||||
url = f"http://127.0.0.1:8003/{url_path}"
|
||||
|
||||
response = auto_login_client.request(method = "GET", url = url, auth = True)
|
||||
|
||||
assert response.status_code == 200
|
@ -1100,6 +1100,7 @@ markers = [
|
||||
"audit_models: Selects Audit models.",
|
||||
"centurion_models: Selects Centurion models",
|
||||
"functional: Selects all Functional tests.",
|
||||
"integration: Selects all Integration tests.",
|
||||
"meta_models: Selects Meta models",
|
||||
"mixin: Selects all mixin test cases.",
|
||||
"mixin_centurion: Selects all centurion mixin test cases.",
|
||||
|
Reference in New Issue
Block a user