A minimal Django app for form submission and review. The Django project lives under efile_app/ with settings in efile_app/efile/.
- Requirements
- Python 3.10+
- uv
-
0) Install uv (one-time)
- macOS (Homebrew):
brew install uv
- Or official installer:
curl -LsSf https://astral.sh/uv/install.sh | sh
- macOS (Homebrew):
-
1) Sync dependencies From the project root (this will create
.venv/and install deps frompyproject.toml):uv sync
-
2) Initialize the database
cd efile_app uv run python manage.py migrate --run-syncdb -
3) Run the development server
uv run python manage.py runserver
Then open http://127.0.0.1:8000/login in your browser.
-
4) Run the document extraction worker In a second terminal, from
efile_app/:uv run python manage.py process_document_extractions
The upload page stores PDFs immediately; this worker analyzes queued lead documents in the background.
uv sync creates .venv/. You can activate it and run Django commands normally:
-
macOS/Linux:
source .venv/bin/activate cd efile_app python manage.py migrate --run-syncdb python manage.py runserver
-
Windows (PowerShell):
.venv\Scripts\Activate.ps1 cd efile_app python manage.py migrate --run-syncdb python manage.py runserver
Deactivate with deactivate when you're done.
-
Create an admin user
- With uv:
uv run python manage.py createsuperuser
Admin will be available at
/admin/after you start the server. - With uv:
-
Static files During development, static files are served automatically. No
collectstaticis needed.
The application uses AWS S3 for document storage and file uploads. Follow these steps to set up your S3 bucket:
- Log into the AWS Console and navigate to S3
- Create a new bucket (e.g.,
litefile-your-suffix) - Choose a region and set
AWS_S3_REGION_NAMEto that same region. - Keep all four "Block public access" settings enabled. Use "Bucket owner enforced" object ownership and do not grant object ACLs.
- Tags can be created to help track ownership of resources and is useful for cost tracking, environment tracking, etc.
- Use the default S3 managed encryption unless you also grant the app access to a customer-managed KMS key.
Create an IAM principal for the application with this policy, replacing YOUR-BUCKET-NAME. The app uploads, downloads, and deletes documents under efile-documents/; its S3 connection check lists only that prefix. A public bucket policy is not needed for presigned URLs.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "ListDocumentsForConnectionCheck",
"Effect": "Allow",
"Action": "s3:ListBucket",
"Resource": "arn:aws:s3:::YOUR-BUCKET-NAME",
"Condition": {"StringLike": {"s3:prefix": "efile-documents/*"}}
},
{
"Sid": "ManageDocuments",
"Effect": "Allow",
"Action": ["s3:PutObject", "s3:GetObject", "s3:DeleteObject", "s3:AbortMultipartUpload"],
"Resource": "arn:aws:s3:::YOUR-BUCKET-NAME/efile-documents/*"
}
]
}Copy the example environment file and update the S3 settings:
cp efile_app/.env.example efile_app/.envEdit efile_app/.env with your AWS credentials:
Remove the AWS_S3_ENDPOINT_URL line from the copied example when using AWS; that endpoint is for LocalStack.
# AWS S3 configuration
AWS_ACCESS_KEY_ID = "your-aws-access-key-id-here"
AWS_SECRET_ACCESS_KEY = "your-aws-secret-access-key-here"
# Set AWS_SESSION_TOKEN too when using temporary credentials.
AWS_S3_BUCKET_NAME = "your-bucket-name-here"
AWS_S3_REGION_NAME = "your-bucket-region"LITEFile generates time-limited presigned URLs that the e-file proxy can retrieve with an ordinary HTTP GET. The signing principal needs s3:GetObject, but the bucket does not need public access or CORS for this server-to-server download. For an existing bucket, remove any PublicReadGetObject statement and confirm all four public access blocks are enabled. Check that an unsigned object URL returns 403 while a fresh presigned URL downloads the file. Do not paste presigned URLs into issue reports or logs; they grant access until they expire.
Ruff is configured in pyproject.toml under [tool.ruff].
- Using uv
- Install dev tools:
uv sync --group dev
- Lint the codebase:
uv run ruff check . uv run djlint .
- Auto-format:
uv run ruff format . - Auto-format HTML, JS, and CSS
uv run djlint --reformat . uv run css-beautify -r efile/static/css/*.css uv run js-beautify -r efile/static/js/*.js
- Install dev tools:
Notes: Ruff targets Python 3.10, line length 120, and excludes Django migrations (**/migrations/*).
Pytest is configured via pyproject.toml to use pytest-django.
-
Install dev deps (once):
uv sync --group dev
-
Run all tests (from project root):
pytest -q
-
Select tests:
pytest efile_app/efile/ -q # only the efile app pytest -k "login and not slow" -q # expression match pytest efile_app/efile/tests/test_smoke.py::test_login_page_renders -q
-
Speed tips:
pytest --reuse-db -q # keep the test DB between runs pytest -n auto -q # run in parallel (pytest-xdist)
-
Coverage (optional):
pytest --cov=efile_app --cov-report=term-missing
Notes:
DJANGO_SETTINGS_MODULEis set toefile.settingsin[tool.pytest.ini_options].- Tests are discovered under
efile_app/. An example smoke test lives atefile_app/efile/tests/test_smoke.py.
Playwright tests are located in efile_app/tests/ and provide browser-based testing of the complete user workflow. These are intended to be run manually and are not part of the CI/CD pipeline because they produce
side-effects (e.g. filing new cases in EFSP) and rely on external APIs (e.g. EFSP again). The tests stop short
of the document upload step as that would touch S3. We also wanted to avoid filing new cases into Tyler as part
of the current end-to-end testing.
-
Install Playwright dependencies (one-time):
cd efile_app npm install npx playwright install -
Environment variables: Create a
.envfile in theefile_app/directory with:# Tyler test-EFM login. The Python test suite reads the same two names. TESTS_TYLER_USERNAME=your_test_email@example.com TESTS_TYLER_PASSWORD=your_test_password E2E_TEST_BASE_URL=http://localhost:8000 # optional, defaults to localhost:8000
The Playwright configuration includes several important settings:
- Global Setup: Automatically loads environment variables and validates credentials before running tests
- Timeout: Extended to 10 minutes (600,000ms) to accommodate form filling and external API calls
- Base URL: Configured for
http://localhost:8000(Django development server) - Retry Strategy: 2 retries on CI, 0 retries locally
- Parallel Execution: Disabled on CI (1 worker) to avoid conflicts with external services
- Browser: Currently configured for Chromium only (Firefox and Safari commented out)
-
Start the Django server first:
cd efile_app uv run python manage.py runserver -
Run all Playwright tests:
cd efile_app npx playwright test
-
Run one spec:
cd efile_app npx playwright test tests/reorganized-filing-matrix.spec.js
-
Run with UI mode (interactive):
cd efile_app npx playwright test --ui
-
Run in headed mode (see browser):
cd efile_app npx playwright test --headed
Note: The global setup automatically validates your .env configuration before running tests. If environment variables are missing, tests will fail with a clear error message.
The Playwright tests use a modular architecture with shared utilities:
tests/setup.js: Global setup that loads environment variables and validates credentials before any tests runtests/test-utils.js: Shared utilities includingloginViaLogout(),loginViaLoginPage(), andgetTestConfig()functionsplaywright.config.js: Playwright configuration with global setup enabled, extended timeout, and CI-specific settings
The test-utils.js module provides two login methods:
loginViaLogout(page, config): Logs in via the/logoutendpoint (ensures clean session) - this is the defaultloginViaLoginPage(page, config): Logs in via the/loginpageloginUser(page, config): Alias forloginViaLogout()for backward compatibility
reorganized-filing-matrix.spec.js: Files one envelope per scenario through the whole workflow -- start a filing, upload a document, confirm the case codes, answer the people and fees screens, submit -- for both new cases and filings into an existing case, across a matrix of Illinois courts and case types.
It really files, in the Tyler test EFSP, so it is skipped unless you ask for it:
cd efile_app
RUN_FILING_MATRIX=1 npx playwright test tests/reorganized-filing-matrix.spec.jsScreenshots are saved to screenshots/ directory and excluded from git via .gitignore.
Ty (a Rust-based type checker) is configured in pyproject.toml under [tool.ty.src].
-
Run a one-off check:
uv run ty check
-
Watch mode (re-run on changes):
uv run ty watch
Pre-commit hooks are configured in .pre-commit-config.yaml to run Ruff, JavaScript ESLint/SonarJS, Prettier, Bandit, and type checking on commits, plus tests on push.
-
Install pre-commit hooks (one-time setup):
uv run pre-commit install uv run pre-commit install --hook-type pre-push
-
Run hooks manually:
uv run pre-commit run --all-files # run all hooks on all files uv run pre-commit run pytest # run just the pytest hook
Note: The pytest hook runs on pre-push stage to keep commits fast. If you skip the pre-push hook installation, tests won't run automatically before pushing.
efile_app/manage.py— Django management scriptefile_app/efile/settings.py— Project settings (uses SQLite by default; DB file atefile_app/db.sqlite3)efile_app/efile/urls.py— URL routingefile_app/efile/templates/— HTML templatesefile_app/efile/static/— Static assets
- Default settings run with
DEBUG=Trueand SQLite for local development.