Skip to content

Commit

Permalink
Merge branch 'main' into add_links_to_xrays
Browse files Browse the repository at this point in the history
  • Loading branch information
nas-tabchiche committed Feb 28, 2024
2 parents ef4fd62 + a5bf729 commit 2b0ebcf
Show file tree
Hide file tree
Showing 116 changed files with 16,586 additions and 8,277 deletions.
8 changes: 7 additions & 1 deletion .github/workflows/backend-api-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -57,4 +57,10 @@ jobs:
working-directory: ${{env.working-directory}}
run: |
export $(grep -v '^#' .env | xargs)
pytest app_tests/api
pytest app_tests/api --html=pytest-report.html --self-contained-html
- uses: actions/upload-artifact@v4
if: always()
with:
name: api-tests-report
path: ${{ env.working-directory }}/pytest-report.html
retention-days: 5
2 changes: 0 additions & 2 deletions .github/workflows/functional-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@ on:
pull_request:
branches: [main, develop]
types: [opened, synchronize]
paths:
- 'frontend/tests/**'
workflow_dispatch:

env:
Expand Down
25 changes: 23 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ Read the [full article](https://intuitem.com/blog/we-are-going-open-source/) abo
- CMMC v2
- PSPF

Checkout the [library](/library/libraries/) for the Domain Specific Language used and how you can define your own.
Checkout the [library](/library/libraries/) and [tools](/tools/) for the Domain Specific Language used and how you can define your own.

### Coming soon

Expand Down Expand Up @@ -75,6 +75,8 @@ You can then reach CISO Assistant using your web brower at [https://localhost:84

For the following executions, use "docker-compose up" directly.

If you want to restart a fresh install, simply delete the db directory, where the database is stored.

## Setting up CISO Assistant for development

### Requirements
Expand Down Expand Up @@ -132,7 +134,7 @@ export EMAIL_HOST_USER_RESCUE=<XXX>
export EMAIL_HOST_PASSWORD_RESCUE=<XXX>
export EMAIL_USE_TLS_RESCUE=True

# You can define the email of the first superuser, useful for automation
# You can define the email of the first superuser, useful for automation. A mail is sent to the superuser for password initlization
export CISO_SUPERUSER_EMAIL=<XXX>

# By default, Django secret key is generated randomly at each start of CISO Assistant. This is convenient for quick test,
Expand Down Expand Up @@ -267,6 +269,25 @@ python manage.py migrate

These migration files should be tracked by version control.

## Test harness

To run API tests on the backend, simply type "pytest" in a shell in the backend folder.

To run functional tests on the frontend, do the following actions:
- in the backend folder, launch the following commands:
```shell
[email protected] DJANGO_SUPERUSER_PASSWORD=1234 python manage.py createsuperuser --noinput
CISO_ASSISTANT_URL=http://localhost:4173 python manage.py runserver
```
- in parallel, in the frontend folder, launch the following command:
```shell
PUBLIC_BACKEND_API_URL=http://localhost:8000/api npx playwright test
```

For tests requiring mail sending, it is necessary to launch mailhog in a separate terminal.

The goal of the test harness is to prevent any regression, i.e. all the tests shall be successful. This is achieved for API tests, and will be soon achieved for functional tests.

## Built With

- [Django](https://www.djangoproject.com/) - Python Web Development Framework
Expand Down
2 changes: 2 additions & 0 deletions backend/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ __pycache__
*.DS_Store
*~$*
staticfiles/*
static/
*.mo
.env
.vscode
Expand All @@ -16,3 +17,4 @@ db/django_secret_key
db/pg_password.txt
./db/
.coverage
pytest-report.html
73 changes: 47 additions & 26 deletions backend/app_tests/api/test_api_assets.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
from core.models import Asset
from iam.models import Folder

from test_api import EndpointTestsQueries
from test_vars import GROUPS_PERMISSIONS
from test_utils import EndpointTestsQueries

# Generic asset data for tests
ASSET_NAME = "Test Asset"
Expand Down Expand Up @@ -78,31 +79,41 @@ def test_delete_assets(self):


@pytest.mark.django_db
@pytest.mark.parametrize(
"test",
GROUPS_PERMISSIONS.keys(),
ids=[GROUPS_PERMISSIONS[key]["name"] for key in GROUPS_PERMISSIONS.keys()],
indirect=True,
)
class TestAssetsAuthenticated:
"""Perform tests on Assets API endpoint with authentication"""

def test_get_assets(self, authenticated_client):
def test_get_assets(self, test):
"""test to get assets from the API with authentication"""

EndpointTestsQueries.Auth.get_object(
authenticated_client,
test.client,
"Assets",
Asset,
{
"name": ASSET_NAME,
"description": ASSET_DESCRIPTION,
"business_value": ASSET_BUSINESS_VALUE,
"type": ASSET_TYPE[0],
"folder": Folder.get_root_folder(),
"folder": test.folder,
},
{"folder": {"str": Folder.get_root_folder().name}, "type": ASSET_TYPE[1]},
{
"folder": {"id": str(test.folder.id), "str": test.folder.name},
"type": ASSET_TYPE[1],
},
user_group=test.user_group,
)

def test_create_assets(self, authenticated_client):
"""test to create assets with the API with authentication"""
def test_create_assets(self, test):
"""test to create assets without a parent asset the API with authentication"""

EndpointTestsQueries.Auth.create_object(
authenticated_client,
test.client,
"Assets",
Asset,
{
Expand All @@ -111,23 +122,27 @@ def test_create_assets(self, authenticated_client):
"business_value": ASSET_BUSINESS_VALUE,
"type": ASSET_TYPE[0],
"parent_assets": [],
"folder": str(Folder.get_root_folder().id),
"folder": str(test.folder.id),
},
{
"folder": {"id": str(test.folder.id), "str": test.folder.name},
"type": ASSET_TYPE[1],
},
{"folder": {"str": Folder.get_root_folder().name}, "type": ASSET_TYPE[1]},
user_group=test.user_group,
)

def test_create_assets2(self, authenticated_client):
"""test to create assets with the API with authentication"""
def test_create_assets_with_parent(self, test):
"""test to create assets with a parent asset with the API with authentication"""

root_asset = Asset.objects.create(
name="root",
description=ASSET_DESCRIPTION,
type=ASSET_TYPE[0],
folder=Folder.get_root_folder(),
folder=test.folder,
)

EndpointTestsQueries.Auth.create_object(
authenticated_client,
test.client,
"Assets",
Asset,
{
Expand All @@ -136,31 +151,32 @@ def test_create_assets2(self, authenticated_client):
"business_value": ASSET_BUSINESS_VALUE,
"type": ASSET_TYPE2[0],
"parent_assets": [str(root_asset.id)],
"folder": str(Folder.get_root_folder().id),
"folder": str(test.folder.id),
},
{
"folder": {"str": Folder.get_root_folder().name},
"folder": {"id": str(test.folder.id), "str": test.folder.name},
"type": ASSET_TYPE2[1],
"parent_assets": [{"id": str(root_asset.id), "str": root_asset.name}],
},
base_count=1,
user_group=test.user_group,
)

def test_update_assets(self, authenticated_client):
def test_update_assets(self, test):
"""test to update assets with the API with authentication"""

folder = Folder.objects.create(name="test")
folder = Folder.objects.create(name="test2")

EndpointTestsQueries.Auth.update_object(
authenticated_client,
test.client,
"Assets",
Asset,
{
"name": ASSET_NAME,
"description": ASSET_DESCRIPTION,
"business_value": ASSET_BUSINESS_VALUE,
"type": ASSET_TYPE[0],
"folder": Folder.get_root_folder(),
"folder": test.folder,
},
{
"name": "new " + ASSET_NAME,
Expand All @@ -169,22 +185,27 @@ def test_update_assets(self, authenticated_client):
"type": ASSET_TYPE2[0],
"folder": str(folder.id),
},
{"folder": {"str": Folder.get_root_folder().name}, "type": ASSET_TYPE[1]},
{
"folder": {"id": str(test.folder.id), "str": test.folder.name},
"type": ASSET_TYPE[1],
},
user_group=test.user_group,
)

def test_delete_assets(self, authenticated_client):
def test_delete_assets(self, test):
"""test to delete assets with the API with authentication"""

EndpointTestsQueries.Auth.delete_object(
authenticated_client,
test.client,
"Assets",
Asset,
{"name": ASSET_NAME, "folder": Folder.get_root_folder()},
{"name": ASSET_NAME, "folder": test.folder},
user_group=test.user_group,
)

def test_get_type_choices(self, authenticated_client):
def test_get_type_choices(self, test):
"""test to get type choices from the API with authentication"""

EndpointTestsQueries.Auth.get_object_options(
authenticated_client, "Assets", "type", Asset.Type.choices
test.client, "Assets", "type", Asset.Type.choices
)
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
from core.models import Project
from iam.models import Folder

from test_api import EndpointTestsQueries
from test_vars import GROUPS_PERMISSIONS
from test_utils import EndpointTestsQueries

# Generic compliance assessment data for tests
COMPLIANCE_ASSESSMENT_NAME = "Test Compliance Assessment"
Expand Down Expand Up @@ -96,19 +97,23 @@ def test_delete_compliance_assessments(self, authenticated_client):


@pytest.mark.django_db
@pytest.mark.parametrize(
"test",
GROUPS_PERMISSIONS.keys(),
ids=[GROUPS_PERMISSIONS[key]["name"] for key in GROUPS_PERMISSIONS.keys()],
indirect=True,
)
class TestComplianceAssessmentsAuthenticated:
"""Perform tests on ComplianceAssessments API endpoint with authentication"""

def test_get_compliance_assessments(self, authenticated_client):
def test_get_compliance_assessments(self, test):
"""test to get compliance assessments from the API with authentication"""

EndpointTestsQueries.Auth.import_object(authenticated_client, "Framework")
project = Project.objects.create(
name="test", folder=Folder.objects.create(name="test")
)
EndpointTestsQueries.Auth.import_object(test.admin_client, "Framework")
project = Project.objects.create(name="test", folder=test.folder)

EndpointTestsQueries.Auth.get_object(
authenticated_client,
test.client,
"Compliance Assessments",
ComplianceAssessment,
{
Expand All @@ -125,18 +130,17 @@ def test_get_compliance_assessments(self, authenticated_client):
"str": str(Framework.objects.all()[0]),
},
},
user_group=test.user_group,
)

def test_create_compliance_assessments(self, authenticated_client):
def test_create_compliance_assessments(self, test):
"""test to create compliance assessments with the API with authentication"""

EndpointTestsQueries.Auth.import_object(authenticated_client, "Framework")
project = Project.objects.create(
name="test", folder=Folder.objects.create(name="test")
)
EndpointTestsQueries.Auth.import_object(test.admin_client, "Framework")
project = Project.objects.create(name="test", folder=test.folder)

EndpointTestsQueries.Auth.create_object(
authenticated_client,
test.client,
"Compliance Assessments",
ComplianceAssessment,
{
Expand All @@ -153,23 +157,22 @@ def test_create_compliance_assessments(self, authenticated_client):
"str": str(Framework.objects.all()[0]),
},
},
user_group=test.user_group,
)

def test_update_compliance_assessments(self, authenticated_client):
def test_update_compliance_assessments(self, test):
"""test to update compliance assessments with the API with authentication"""

EndpointTestsQueries.Auth.import_object(authenticated_client, "Documents")
EndpointTestsQueries.Auth.import_object(authenticated_client, "Framework")
EndpointTestsQueries.Auth.import_object(authenticated_client, "Framework2")
project = Project.objects.create(
name="test", folder=Folder.objects.create(name="test")
)
EndpointTestsQueries.Auth.import_object(test.admin_client, "Documents")
EndpointTestsQueries.Auth.import_object(test.admin_client, "Framework")
EndpointTestsQueries.Auth.import_object(test.admin_client, "Framework2")
project = Project.objects.create(name="test", folder=test.folder)
project2 = Project.objects.create(
name="test2", folder=Folder.objects.create(name="test2")
)

EndpointTestsQueries.Auth.update_object(
authenticated_client,
test.client,
"Compliance Assessments",
ComplianceAssessment,
{
Expand All @@ -193,23 +196,23 @@ def test_update_compliance_assessments(self, authenticated_client):
"str": str(Framework.objects.all()[0]),
},
},
user_group=test.user_group,
)

def test_delete_compliance_assessments(self, authenticated_client):
def test_delete_compliance_assessments(self, test):
"""test to delete compliance assessments with the API with authentication"""

EndpointTestsQueries.Auth.import_object(authenticated_client, "Framework")
project = Project.objects.create(
name="test", folder=Folder.objects.create(name="test")
)
EndpointTestsQueries.Auth.import_object(test.admin_client, "Framework")
project = Project.objects.create(name="test", folder=test.folder)

EndpointTestsQueries.Auth.delete_object(
authenticated_client,
test.client,
"Compliance Assessments",
ComplianceAssessment,
{
"name": COMPLIANCE_ASSESSMENT_NAME,
"project": project,
"framework": Framework.objects.all()[0],
},
user_group=test.user_group,
)
Loading

0 comments on commit 2b0ebcf

Please sign in to comment.