Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
109 commits
Select commit Hold shift + click to select a range
3f1e986
Add a new favicon with test and static file doco
dbca-serkank Jul 17, 2026
12963d2
Larger favicon without space around
dbca-serkank Jul 17, 2026
f175463
Merge pull request #56 from dbca-wa/feature/favicon
dbca-serkank Jul 17, 2026
67efd23
Fix static files section in doco
dbca-serkank Jul 17, 2026
974769d
Provide hard guidelines for development & doco consolidation
dbca-serkank Jul 17, 2026
025a074
Reorganise test modules with more tests + improve testing doco
dbca-serkank Jul 17, 2026
1b060aa
Fix frontend type check in test
dbca-serkank Jul 17, 2026
706b317
Update bun.lock and lock file rules
dbca-serkank Jul 17, 2026
7eede9c
Add more tests for coverage
dbca-serkank Jul 17, 2026
f09f91c
Convert bun.lock to package-lock.json in CI - Remove package-lock fro…
dbca-serkank Jul 18, 2026
40486e0
Add CHANGELOG entry for the lock files
dbca-serkank Jul 18, 2026
29022ec
Use full path for bun in CI
dbca-serkank Jul 18, 2026
73d3743
Make the `package-json.lock` an artifact from frontend test step
dbca-serkank Jul 18, 2026
5b58a7e
Migrate to `npm` across all environments
dbca-serkank Jul 18, 2026
971c233
Add permalink for new applications
dbca-serkank Jul 20, 2026
c61bc41
Add the "less is more" principle into the guide
dbca-serkank Jul 20, 2026
8dc969f
Implement scrolling to the permalink
dbca-serkank Jul 20, 2026
85acc92
Scroll using `hashchange` event listenner
dbca-serkank Jul 21, 2026
0585dae
Disabled questionnaire tabs when only a single questionnaire
dbca-serkank Jul 21, 2026
9d658fe
Extend frontend unit tests
dbca-serkank Jul 21, 2026
e188441
Add E2E tests for backend sorting order
dbca-serkank Jul 21, 2026
88379a4
Add dedicated E2E test module for "new application" page
dbca-serkank Jul 21, 2026
8451bcf
Fix and activate "user end to end flow" test module
dbca-serkank Jul 21, 2026
80ee825
Fix frontend tests - Enable stricter type checks
dbca-serkank Jul 21, 2026
d62765f
Remove questionnaire `sort_order` from interface - fix tests
dbca-serkank Jul 21, 2026
34a884e
Increase timeout on some E2E tests
dbca-serkank Jul 21, 2026
a38364a
Fix E2E tests waiting on redirection
dbca-serkank Jul 21, 2026
25b6440
Wait for checkbox to be enabled
dbca-serkank Jul 21, 2026
de006f4
Add dummy `TURNSTILE_SITE_KEY` for E2E tests
dbca-serkank Jul 21, 2026
459d2da
Add `TURNSTILE_SITE_KEY` in Azure pipeline
dbca-serkank Jul 21, 2026
cd5ec94
Improve turnstile manager test coverage
dbca-serkank Jul 21, 2026
b89e27e
Merge pull request #60 from dbca-wa/feature/new-application-permalink
dbca-serkank Jul 21, 2026
112dd97
Refactor application status handling and update documentation
dbca-serkank Jul 23, 2026
f62e5ae
Add frontend test suite for the status workflow
dbca-serkank Jul 24, 2026
46f946d
Minor padding styling on the "new application" card
dbca-serkank Jul 24, 2026
2cc2544
Update CHANGELOG
dbca-serkank Jul 24, 2026
be740aa
Implement backend for status workflow with migration
dbca-serkank Jul 24, 2026
7043635
Change version to `1.1.0` MINOR instead of `1.0.4` patch
dbca-serkank Jul 24, 2026
418ee36
Big refactor "Assessor" -> "Reviewer"
dbca-serkank Jul 28, 2026
4c1fcd5
Explain the fronend dev server requirement for E2E tests
dbca-serkank Jul 28, 2026
1811e95
Add CHANGELOG entry
dbca-serkank Jul 28, 2026
cbf7ae7
Merge pull request #64 from dbca-wa/feature/reviewer-refactor
dbca-serkank Jul 28, 2026
e200cc1
Implement core functionality for "Discard" and "Revert" (of applicati…
dbca-serkank Jul 29, 2026
7284806
Alert box for discarded and withdrawn applications
dbca-serkank Jul 29, 2026
7f65154
Implement tab categorisation on "my applications" page
dbca-serkank Jul 29, 2026
ef5eda4
Update CHANELOG and "status workflow" document
dbca-serkank Jul 29, 2026
f602db4
Add test coverage for the extended functionality
dbca-serkank Jul 29, 2026
43d129c
Fix TS lint errors
dbca-serkank Jul 30, 2026
d4ee6b4
Fix and extend the "my applications" page testing
dbca-serkank Jul 30, 2026
d53f508
Organise test file structure
dbca-serkank Jul 30, 2026
72b7c7e
Minor doco fix
dbca-serkank Jul 30, 2026
b835344
Merge pull request #66 from dbca-wa/feature/discard
dbca-serkank Jul 30, 2026
c16483f
Core functionality checkpoint
dbca-serkank Jul 31, 2026
e63db5c
Application card status change highlighting
dbca-serkank Jul 31, 2026
09eed3e
Frontend file extension (ts vs tsx) consistency
dbca-serkank Jul 31, 2026
81e229b
Reset button confirm
dbca-serkank Jul 31, 2026
22f3c8f
Try catch refactor for application cards
dbca-serkank Jul 31, 2026
59d9105
Reset button confirm dialog tweaks
dbca-serkank Jul 31, 2026
6373fcb
Reset draft bugfix and render optimisation
dbca-serkank Jul 31, 2026
f92dcaf
Minor component parameter optimisations
dbca-serkank Jul 31, 2026
203fa0b
Set `submitted_at` to null when sending back to `DRAFT`
dbca-serkank Jul 31, 2026
a620195
Fix tests
dbca-serkank Jul 31, 2026
ed10734
Add comprehensive testing of new features
dbca-serkank Aug 3, 2026
c7ff756
Add "under assessment" confirmation
dbca-serkank Aug 3, 2026
db40fbb
Improve form submission behaviour
dbca-serkank Aug 3, 2026
570986c
Add loading state to submit button and disable during submission
dbca-serkank Aug 3, 2026
c00014f
Add CHANGELOG items
dbca-serkank Aug 3, 2026
6083bdd
Implement audit
dbca-serkank Aug 4, 2026
d76bf14
Improve test coverage for frontend
dbca-serkank Aug 4, 2026
9c2c26a
Merge pull request #68 from dbca-wa/feature/reviewer-draft-button
dbca-serkank Aug 4, 2026
a943999
Update privacy and acknowledge text v1
dbca-serkank Jul 27, 2026
02fca18
Collection notice update v2
dbca-serkank Jul 28, 2026
26983b0
Separate collection notice from privacy policy
dbca-serkank Aug 5, 2026
017bf1d
Refactor the collection notice dialog
dbca-serkank Aug 5, 2026
df23606
Add "scroll for more" indicator
dbca-serkank Aug 6, 2026
72c4060
Fix frontend test
dbca-serkank Aug 6, 2026
136c2f8
Fix TS lint
dbca-serkank Aug 6, 2026
5a27a35
Separate "Privacy Statement"
dbca-serkank Aug 6, 2026
1ab9c94
Merge pull request #63 from dbca-wa/feature/privacy-update
dbca-serkank Aug 7, 2026
b03a94f
Fix table layout and word breaking content display
dbca-serkank Aug 10, 2026
724cc27
Align embedded image file name to centre
dbca-serkank Aug 10, 2026
c6eb8a2
Fix excel file attachments are not displaying icons
dbca-serkank Aug 10, 2026
3ff0e3f
Add "Cross-Tab State Synchronization Issue" document
dbca-serkank Aug 11, 2026
14bd77e
Remove left-over ".bun-version" file
dbca-serkank Aug 11, 2026
6ae8012
Respond with 404 when an attachment was not found in Azure Storage
dbca-serkank Aug 11, 2026
c7cdaa3
Add favicon link to error page
dbca-serkank Aug 11, 2026
60d31e6
Improved handling of missing attachments
dbca-serkank Aug 11, 2026
3d7e4e8
File lookup explicitly based on `LOCAL_MEDIA_STORAGE` setting
dbca-serkank Aug 11, 2026
32eee42
Fix Azure Stoage missing file test
dbca-serkank Aug 11, 2026
397496a
Switch back to `Lax` SESSION_COOKIE_SAMESITE setting
dbca-serkank Aug 12, 2026
cebbe85
Add file size tracking for attachments and display in UI
dbca-serkank Aug 12, 2026
557e7d8
Refactor imports in test files to adhere to PEP 8
dbca-serkank Aug 12, 2026
bb59a62
Fix type check error and more strict checks for TS lint
dbca-serkank Aug 12, 2026
4139ee9
Merge pull request #72 from dbca-wa/feature/pdf-fixes
dbca-serkank Aug 12, 2026
3d16fd8
Add `--no-control-socket` to gunicorn bootup
dbca-serkank Aug 12, 2026
1502927
Add ruff configuration to exclude TOML files from linting
dbca-serkank Aug 12, 2026
85b03fe
Add explicit "DRAFT" label to PDFs that are in draft status
dbca-serkank Aug 12, 2026
bfa5836
Return 404 for non-reviewers on API review endpoint
dbca-serkank Aug 13, 2026
e30c433
Frontend soft 404 for the `/review` route for non-reviewers
dbca-serkank Aug 13, 2026
cc0c4d1
Backend hard 404 for the `/review` for non-reviewers
dbca-serkank Aug 13, 2026
e3d6276
Doco and CHANGELOG update
dbca-serkank Aug 13, 2026
4b90096
Remove dup `_user_is_reviewer` method - minor change in CHANGELOG
dbca-serkank Aug 13, 2026
61b871d
Merge pull request #74 from dbca-wa/feature/hide-unauthorised-urls
dbca-serkank Aug 13, 2026
cc89e87
Upgrade backend dependencies
dbca-serkank Aug 13, 2026
b883a8e
Run E2E tests in parallel
dbca-serkank Aug 13, 2026
63d7035
Fix poetry.lock
dbca-serkank Aug 13, 2026
627f84b
Upgrade frontend dependencies
dbca-serkank Aug 13, 2026
d7ec092
Add "upgrade guideline" doco and CHANGELOG item
dbca-serkank Aug 13, 2026
6481938
Merge pull request #75 from dbca-wa/feature/upgrade-dependencies
dbca-serkank Aug 13, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 35 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,41 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

Entries should be concise, single-sentence summaries without excessive technical detail. Focus on the user-facing impact rather than implementation details.

## [1.1.0] - Unreleased (Requires DB Migration)

### Added

- Added discard and revert functionality allowing applicants to abandon draft applications by moving them to DISCARDED status, with the ability to restore them back to DRAFT for continued editing.
- Added tab-based filtering system for My Applications page enabling applicants to organise applications by status category (Active, Terminated, Finalised), improving visibility of application lifecycle stages.
- Added permanent links to questionnaire types on the new application page, enabling users to share and bookmark direct links to specific application types.
- Added a full privacy statement page with section-by-section expandable content and dedicated contact details. Also updated the "Collection Notice Disclaimer" that we request applicants to acknowledge and agree prior to creating new applications.
- Added a new favicon, replacing the default placeholder.
- Added comprehensive feature development guide ([FEATURE-DEVELOPMENT.md](docs/FEATURE-DEVELOPMENT.md)) consolidating all mandatory best practices, testing requirements, code quality standards, and common commands in a single reference document for AI agents and developers.
- Added new frontend as well as E2E tests for comprehensive coverage of "New application" page functionality.
- Added formal specification of application status workflow ([STATUS-WORKFLOW.md](docs/STATUS-WORKFLOW.md)) documenting all 13 state transitions, permissions, and business rules with comprehensive test coverage across backend API (19 tests), E2E (6 tests), and frontend (10 statuses verified).
- Added submission modal displayed after successful application submission and on page load for read-only applications, providing confirmation and options to download application PDF or exit the application.
- Added technical officers review page workflow actions enabling reviewers to claim applications for review, reset applications to draft for applicant revision, and proceed applications to assessment stage with confirmation dialogs for each action.
- Added audit logging for reviewer and assessor actions, recording every application status change with user, timestamp, and status transition details in an immutable audit log accessible through the Django admin interface for regulatory compliance and investigation purposes.
- Added file size tracking and display for application attachments, automatically capturing file sizes during upload and displaying human-readable sizes (B, KB, MB) in the frontend attachment list and admin interface.

### Changed

- Strengthened review queue access control: non-reviewers now receive 404 responses across frontend menu, route loader, and backend routes when attempting to access the review page.
- Renamed "Assessment" terminology to "Review" throughout the application, including API endpoints (/api/assessment → /api/review), menu navigation ("Assessment Queue" → "Review Queue"), and related components and fixtures, to align with domain conventions.
- Standardised on npm for all frontend package management across development, CI, testing, and production environments to ensure identical dependency versions and predictable builds.
- Disabled questionnaire tabs when only a single questionnaire to prevent user confusion from clicking non-functional tabs.
- Improved handling of missing files and file size display in PDF generation, showing placeholder images for missing attachments and displaying human-readable file sizes alongside filenames for all file types.
- **Dependency upgrades:** Updated 19 backend packages (Django 5.2.17, cryptography 50.0.0, djangorestframework 3.18.0, pytest-django 4.14.0) and 19 frontend packages (axios, eslint, globals, msw, typescript-eslint, and build tooling) with zero codebase modifications. Created [DEPENDENCY-UPGRADE.md](docs/DEPENDENCY-UPGRADE.md) documenting upgrade workflow and breaking-change analysis methodology.

### Fixed

- Fixed submit button allowing duplicate API submissions by adding loading indicator and disabled state during submission process.
- Fixed attachment file-type icons intermittently disappearing (especially Excel) across both draft form editing and reviewer attachment views, which previously caused blank file tiles due to a static asset processing issue in production mode.

### Removed

- Removed `ACTION_REQUIRED` status; applications now use concrete workflow states (DRAFT → SUBMITTED → UNDER_REVIEW → UNDER_ASSESSMENT → decision outcomes) with explicit transition rules and permission boundaries.

## 1.0.3 - 2026-07-16

### Fixed
Expand All @@ -16,7 +51,6 @@ Entries should be concise, single-sentence summaries without excessive technical
### Changed

- Removed redundant CSRF cookie settings (CSRF_COOKIE_NAME, CSRF_COOKIE_SAMESITE, CSRF_COOKIE_SECURE) as the application uses session-based CSRF protection instead.
- Changed SESSION_COOKIE_SAMESITE from "Lax" to "Strict" unconditionally for improved security against cross-site cookie inclusion.

## 1.0.2 - 2026-07-14

Expand Down
16 changes: 7 additions & 9 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,13 @@ FROM node:22-trixie-slim AS builder_frontend
# Build frontend assets in an isolated stage.
WORKDIR /tmp/frontend

# Copy dependency manifest first so dependency install can be cached across code-only changes.
COPY frontend/package.json ./
# Copy dependency manifests for deterministic dependency installation.
# package-lock.json is committed to version control.
COPY frontend/package*.json ./

# Install frontend dependencies.
# `npm ci` is preferred when package-lock.json exists; this project currently tracks bun.lock,
# so `npm install` is used for compatibility while keeping flags conservative:
# - `--no-audit`: skip npm's advisory audit during image builds to avoid extra network work and log noise.
# - `--no-fund`: suppress funding notices so CI/CD logs stay focused on actionable output.
RUN npm install --no-audit --no-fund
# Install frontend dependencies using npm ci for reproducibility.
# Flags: --no-audit (skip advisory audit), --no-fund (suppress funding notices).
RUN npm ci --no-audit --no-fund

# Copy frontend source after dependency install to preserve cache efficiency.
COPY frontend /tmp/frontend/
Expand All @@ -32,7 +30,7 @@ RUN mkdir -p /tmp/backend/applications /tmp/backend/templates
COPY backend/applications/models.py /tmp/backend/applications/
COPY backend/templates/application-pdf-template.html /tmp/backend/templates/

# Build production frontend assets, including hash-free pdf-icons.css.
# Build production frontend assets.
RUN npm run build


Expand Down
8 changes: 7 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ Streamline DBCA authorisation workflows - from Animal Ethics to Section 40/45 -

**Documentation is located in [docs/](docs/README.md).**

**⚠️ Before any feature development, read [docs/FEATURE-DEVELOPMENT.md](docs/FEATURE-DEVELOPMENT.md) — this is the authoritative checklist for all development and must be followed on every session.**

For setup and development instructions, start with [docs/DEVELOPMENT.md](docs/DEVELOPMENT.md).

For testing, see the testing section in [docs/DEVELOPMENT.md](docs/DEVELOPMENT.md) or the comprehensive guide at [docs/TESTING.md](docs/TESTING.md).
Expand All @@ -32,12 +34,16 @@ This system supports DBCA authorisation workflows, including Animal Ethics and S

**Frontend Development:** See [docs/FRONTEND-CONVENTIONS.md](docs/FRONTEND-CONVENTIONS.md) for React, TypeScript, and component guidelines.

**Application Flows:** See [docs/APPLICATION-FLOWS.md](docs/APPLICATION-FLOWS.md) for user journeys, routes, and workflows.
**Application Flows:** See [docs/FRONTEND-API-FLOWS.md](docs/FRONTEND-API-FLOWS.md) for user journeys, routes, and workflows.

**Status Workflow:** See [docs/STATUS-WORKFLOW.md](docs/STATUS-WORKFLOW.md) for application status definitions and business logic.

**File Management:** See [docs/FILE-MANAGEMENT.md](docs/FILE-MANAGEMENT.md) for attachment design and implementation.

**Deployment:** See [docs/DEPLOYMENT.md](docs/DEPLOYMENT.md) for Kubernetes and kustomize configuration.

**Dependencies:** See [docs/DEPENDENCY-UPGRADE.md](docs/DEPENDENCY-UPGRADE.md) for dependency upgrade process and guidelines.

## Writing style

- Use British English spelling in code comments, docs, command names, and developer guidance.
Expand Down
26 changes: 16 additions & 10 deletions THIRD_PARTY_NOTICES.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ attribution obligations, those obligations continue to apply.

| Package | Version reviewed | Licence |
| --- | --- | --- |
| Django | 5.2.14 | BSD-3-Clause |
| Django | 5.2.17 | BSD-3-Clause |
| psycopg | 3.3.4 | LGPL-3.0-only |
| django-vite | 3.1.0 | Apache-2.0 |
| whitenoise | 6.12.0 | MIT |
Expand All @@ -31,12 +31,12 @@ attribution obligations, those obligations continue to apply.
| django-jsonform | 2.23.2 | BSD-3-Clause |
| django-admin-tools | 0.9.3 | MIT |
| frozendict | 2.4.7 | LGPL-3.0-only |
| dbca-utils | 3.0.3 | Apache-2.0 |
| djangorestframework | 3.17.1 | BSD-3-Clause |
| dbca-utils | 3.0.13 | Apache-2.0 |
| djangorestframework | 3.18.0 | BSD-3-Clause |
| pyfsig | 1.1.1 | MIT |
| django-storages | 1.14.6 | BSD-3-Clause |
| django-admin-sortable2 | 2.3.1 | MIT |
| requests | 2.33.1 | Apache-2.0 |
| requests | 2.34.2 | Apache-2.0

### Backend compliance notes

Expand All @@ -53,17 +53,23 @@ attribution obligations, those obligations continue to apply.
| @mui/material | 9.1.2 | MIT |
| @mui/x-data-grid | 9.7.0 | MIT |
| @mui/x-date-pickers | 9.7.0 | MIT |
| @tailwindcss/vite | 4.3.2 | MIT |
| axios | 1.18.1 | MIT |
| @tailwindcss/vite | 4.3.3 | MIT |
| axios | 1.19.0 | MIT |
| dayjs | 1.11.21 | MIT |
| react | 19.2.7 | MIT |
| react-dom | 19.2.7 | MIT |
| eslint | 10.8.1 | MIT |
| globals | 17.11.0 | MIT |
| msw | 2.15.0 | MIT |
| react | 19.2.8 | MIT |
| react-dom | 19.2.8 | MIT |
| react-dropzone | 15.0.0 | MIT |
| react-hook-form | 7.80.0 | MIT |
| react-router | 7.18.1 | MIT |
| tailwindcss | 4.3.2 | MIT |
| react-router | 7.18.2 | MIT |
| tailwindcss | 4.3.3 | MIT |
| typescript | 6.0.3 | Apache-2.0 |
| typescript-eslint | 8.67.0 | BSD-2-Clause |
| underscore | 1.13.8 | MIT |
| uuid | 14.0.1 | MIT |
| vitest | 4.1.10 | MIT |

### Frontend transitive licence notes

Expand Down
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.0.3
1.1.0
3 changes: 2 additions & 1 deletion azure-pipelines.yml
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ stages:
displayName: Install Playwright Chromium browser
- script: |
cd backend
poetry run pytest e2e/tests -v --tb=short --junitxml=e2e-junit.xml --browser chromium --tracing=retain-on-failure --screenshot=only-on-failure --video=retain-on-failure \
poetry run pytest e2e/tests -v --tb=short -n auto --dist loadscope --junitxml=e2e-junit.xml --browser chromium --tracing=retain-on-failure --screenshot=only-on-failure --video=retain-on-failure \
2>&1 | tee "$(Build.ArtifactStagingDirectory)/e2e-debug/logs/pytest-e2e.log"
status=${PIPESTATUS[0]}
if [ "$status" -ne 0 ]; then
Expand All @@ -167,6 +167,7 @@ stages:
DJANGO_SECRET_KEY: $(DJANGO_SECRET_KEY)
DJANGO_VITE_TEST_DEV_MODE: 'false'
DJANGO_VITE_TEST_MANIFEST_PATH: 'static/manifest.json'
TURNSTILE_SITE_KEY: '0x0000000000000000_e2e_test_key'
- script: |
python scripts/collect_e2e_failure_artifacts.py \
--backend-root "$(Build.SourcesDirectory)/backend" \
Expand Down
115 changes: 12 additions & 103 deletions backend/api/tests/conftest.py
Original file line number Diff line number Diff line change
@@ -1,126 +1,35 @@
"""Shared fixtures for API endpoint test modules.

This package-local conftest keeps API-focused factories close to endpoint
behaviour tests while reusing core fixtures from backend/conftest.py.
This module defines API-specific fixtures. Common factories (questionnaire_factory,
application_factory, process_factory) are inherited from backend/conftest.py.
"""

from itertools import count

import pytest
from applications.models import ApplicationAttachment
from django.contrib.auth.models import Group

from applications.models import Application, ApplicationAttachment, ApplicationStatus
from processes.models import AuthorisationProcess
from questionnaires.models import Questionnaire
from django.core.files.uploadedfile import SimpleUploadedFile
from users.models import User


@pytest.fixture
def assessor_group(db):
"""Create the canonical assessor group used in review authorisation tests."""
return Group.objects.create(name="assessors")
def reviewer_group(db):
"""Create the canonical reviewer group used in review authorisation tests."""
return Group.objects.create(name="reviewers")


@pytest.fixture
def assessor_user(db, assessor_group):
"""Create an authenticated assessor user linked to the assessor group."""
from users.models import User

user = User.objects.create_user(username="assessor", password="testpass123")
user.groups.add(assessor_group)
def reviewer_user(db, reviewer_group):
"""Create an authenticated reviewer user linked to the reviewer group."""
user = User.objects.create_user(username="reviewer", password="testpass123")
user.groups.add(reviewer_group)
return user


@pytest.fixture
def process_factory(db):
"""Return a factory that creates authorisation processes with deterministic defaults."""
sequence = count(1)

def _create(**overrides):
index = next(sequence)
values = {
"slug": f"proc-{index}",
"name": f"Process {index}",
"description": f"Process description {index}",
"sort_order": index,
}
values.update(overrides)
return AuthorisationProcess.objects.create(**values)

return _create


@pytest.fixture
def questionnaire_factory(db, process_factory, user):
"""Return a factory that creates questionnaires for list/retrieve and versioning tests."""
sequence = count(1)

def _create(**overrides):
index = next(sequence)
process = overrides.pop("process", process_factory())
values = {
"process": process,
"code": f"form-{index}",
"name": f"Questionnaire {index}",
"description": f"Questionnaire description {index}",
"version": 1,
"document": {
"schema_version": "2025.07-1",
"steps": [
{
"title": "Step 1",
"description": "",
"sections": [
{
"title": "Section 1",
"description": "",
"questions": [
{
"label": "Question 1",
"type": "text",
"is_required": False,
"description": "",
}
],
}
],
}
],
},
"sort_order": index,
"created_by": user,
}
values.update(overrides)
return Questionnaire.objects.create(**values)

return _create


@pytest.fixture
def application_factory(db, user, questionnaire_factory):
"""Return a factory that creates application rows with configurable ownership and status."""

def _create(**overrides):
values = {
"owner": user,
"questionnaire": questionnaire_factory(),
"status": ApplicationStatus.DRAFT,
"document": {
"schema_version": "2025.07-1",
"active_step": 0,
"steps": [{"is_valid": None, "answers": {}}],
},
}
values.update(overrides)
return Application.objects.create(**values)

return _create


@pytest.fixture
def attachment_factory(db, application_factory):
"""Return a factory that creates attachment records bound to application/question pairs."""
from django.core.files.uploadedfile import SimpleUploadedFile

sequence = count(1)

def _create(**overrides):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import pytest
from rest_framework import status

from applications.models import ApplicationStatus
from applications.statuses import ApplicationStatus


pytestmark = [pytest.mark.api, pytest.mark.security]
Expand Down Expand Up @@ -143,3 +143,53 @@ def test_attachment_list_filter_does_not_disclose_foreign_or_unknown_application
assert unknown_response.status_code == status.HTTP_200_OK
assert foreign_response.data == []
assert unknown_response.data == []


@pytest.mark.django_db
def test_reviewer_list_returns_404_for_non_reviewer(
api_client,
user,
reviewer_group,
process_factory,
questionnaire_factory,
application_factory,
):
"""Hide review endpoint from users without reviewer-group permissions by returning 404."""
process = process_factory(slug="review-hidden", sort_order=1)
process.reviewer_groups.add(reviewer_group)
application_factory(
questionnaire=questionnaire_factory(process=process),
status=ApplicationStatus.SUBMITTED,
)

api_client.force_authenticate(user=user)
response = api_client.get("/api/review")

assert response.status_code == status.HTTP_404_NOT_FOUND


@pytest.mark.django_db
def test_reviewer_patch_returns_404_for_non_reviewer(
api_client,
user,
reviewer_group,
process_factory,
questionnaire_factory,
application_factory,
):
"""Prevent non-reviewers from updating reviewer queue by returning 404 on PATCH."""
process = process_factory(slug="review-patch-hidden", sort_order=1)
process.reviewer_groups.add(reviewer_group)
application = application_factory(
questionnaire=questionnaire_factory(process=process),
status=ApplicationStatus.SUBMITTED,
)

api_client.force_authenticate(user=user)
response = api_client.patch(
f"/api/review/{application.key}",
{"status": ApplicationStatus.UNDER_REVIEW},
format="json",
)

assert response.status_code == status.HTTP_404_NOT_FOUND
Loading