11
.github/workflows/ci.yaml
vendored
11
.github/workflows/ci.yaml
vendored
@ -46,6 +46,17 @@ jobs:
|
|||||||
WORKFLOW_TOKEN: ${{ secrets.WORKFLOW_TOKEN }}
|
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:
|
gitlab-mirror:
|
||||||
if: ${{ github.repository == 'nofusscomputing/centurion_erp' }}
|
if: ${{ github.repository == 'nofusscomputing/centurion_erp' }}
|
||||||
runs-on: ubuntu-latest
|
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.",
|
"audit_models: Selects Audit models.",
|
||||||
"centurion_models: Selects Centurion models",
|
"centurion_models: Selects Centurion models",
|
||||||
"functional: Selects all Functional tests.",
|
"functional: Selects all Functional tests.",
|
||||||
|
"integration: Selects all Integration tests.",
|
||||||
"meta_models: Selects Meta models",
|
"meta_models: Selects Meta models",
|
||||||
"mixin: Selects all mixin test cases.",
|
"mixin: Selects all mixin test cases.",
|
||||||
"mixin_centurion: Selects all centurion mixin test cases.",
|
"mixin_centurion: Selects all centurion mixin test cases.",
|
||||||
|
Reference in New Issue
Block a user