Repository navigation
Add a Django test harness and initial REST API tests #388
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
tpanajott
merged 18 commits into
NSPManager:devel
from
jamesmulcahy:feat/django-test-harness
Oct 17, 2026
+2,600
−667
Merged
Changes from all commits
Commits
Show all changes
18 commits
Select commit
Hold shift + click to select a range
8d249cc
Add a Django test harness and initial REST API tests
jamesmulcahy 9d3f54f
Expand Django test coverage
jamesmulcahy 024e4df
Make the MQTTManager settings endpoint's banned-key check case-insens…
jamesmulcahy 23e8d28
Tell MQTTManager to reload after deletes and edits that skipped it
jamesmulcahy 833a65a
Make /rest/rooms create and delete match the UI's room views
jamesmulcahy c9cf90d
Apply PUT /rest/rooms/<id>/entities/order atomically
jamesmulcahy 3bb0972
Validate where entities and scenes are placed on a page
jamesmulcahy bd6f3ed
Reject entities and scenes MQTTManager cannot load
jamesmulcahy d3d7952
Only allow 4, 8 and 12 entity pages, and do not strand entities on sh…
jamesmulcahy cf0ede1
Reject non-PUT requests to the thermostat and scene entity endpoints
jamesmulcahy a44657a
Fix three small REST bugs: settings 500, scene filter, missing checksums
jamesmulcahy 08c05f6
Fix api/get_nspanel_config and remove two dead htmx partials
jamesmulcahy f303838
Update tests for the React first page (#391)
jamesmulcahy 328186a
Remove the leftover htmx setup wizard that 500s every page on a fresh…
jamesmulcahy 16ce94c
Make the wizard test settings a module constant (ruff RUF012)
jamesmulcahy 58e7ac8
Report Django test results in the GitHub Actions job summary
jamesmulcahy 6fb9b63
Test adding Home Assistant scripts as scenes
jamesmulcahy 83350d7
Address review feedback on the Django test harness
jamesmulcahy File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,53 @@ | ||
| name: "Django tests" | ||
|
|
||
| on: | ||
| pull_request: | ||
| paths: | ||
| - "docker/web/**" | ||
| - ".github/workflows/django-tests.yml" | ||
| push: | ||
| branches: | ||
| - "main" | ||
|
tpanajott marked this conversation as resolved.
|
||
| - "devel" | ||
|
tpanajott marked this conversation as resolved.
|
||
| - "beta" | ||
| paths: | ||
| - "docker/web/**" | ||
| - ".github/workflows/django-tests.yml" | ||
|
|
||
| # Fork pull requests already get a read-only token and no repository secrets; this keeps | ||
| # same-repo runs read-only too. Don't switch to pull_request_target or add a workflow_run | ||
| # follow-up without reviewing what code it checks out: those run with secrets. | ||
| permissions: | ||
| contents: read | ||
|
|
||
| jobs: | ||
| test: | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
|
|
||
| - uses: actions/setup-python@v5 | ||
| with: | ||
| python-version: "3.12" # Matches the python:3.12 base image in docker/Dockerfile | ||
| cache: pip | ||
| cache-dependency-path: docker/web/requirements.txt | ||
|
|
||
| - name: Install dependencies | ||
| run: pip install -r docker/web/requirements.txt unittest-xml-reporting | ||
|
|
||
| - name: Run tests | ||
| run: docker/web/run_tests.sh -v 2 | ||
| env: | ||
| NSPM_TEST_JUNIT_DIR: ${{ github.workspace }}/test-results | ||
|
|
||
| # annotate_only writes the job summary and failure annotations without creating a | ||
| # check run, which needs checks: write and so fails on pull requests from forks. | ||
| - name: Report test results | ||
| if: ${{ !cancelled() }} | ||
| uses: mikepenz/action-junit-report@v6 | ||
| with: | ||
| report_paths: test-results/*.xml | ||
| annotate_only: true | ||
| detailed_summary: true | ||
| include_passed: true | ||
| require_tests: true | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| """ | ||
| Settings used when running the Django test suite (see docker/web/run_tests.sh). | ||
|
|
||
| Identical to the production settings except that persistent data (the secret key) | ||
| is written to a throw-away directory instead of /data. The Django test runner | ||
| automatically uses an in-memory SQLite database, so the real database is never touched. | ||
| """ | ||
|
|
||
| import os | ||
| import tempfile | ||
|
|
||
| os.environ.setdefault("NSPM_DATA_DIR", tempfile.mkdtemp(prefix="nspm-test-")) | ||
|
|
||
| from .settings import * | ||
|
|
||
| MEDIA_ROOT = os.path.join(DATA_DIR, "media") | ||
|
|
||
| # Hashing speed is irrelevant for tests. | ||
| PASSWORD_HASHERS = ["django.contrib.auth.hashers.MD5PasswordHasher"] | ||
|
|
||
| # Many views log full tracebacks when rejecting bad input, which the tests do on purpose. | ||
| # Set NSPM_TEST_LOG_LEVEL=INFO (or DEBUG) to see them when debugging a failing test. | ||
| LOGGING["root"]["level"] = os.environ.get("NSPM_TEST_LOG_LEVEL", "CRITICAL") | ||
| LOGGING["loggers"] = {"django.request": {"level": os.environ.get("NSPM_TEST_LOG_LEVEL", "CRITICAL")}} | ||
|
|
||
| # CI sets NSPM_TEST_JUNIT_DIR to also write JUnit XML results (needs unittest-xml-reporting). | ||
| if os.environ.get("NSPM_TEST_JUNIT_DIR"): | ||
| TEST_RUNNER = "xmlrunner.extra.djangotestrunner.XMLTestRunner" | ||
| TEST_OUTPUT_DIR = os.environ["NSPM_TEST_JUNIT_DIR"] | ||
| TEST_OUTPUT_FILE_NAME = "django-tests.xml" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.