Playwright-based helpers for DHIS2 UI automation.
Project description
dhis2w-browser
Playwright-based helpers for DHIS2 UI automation. Separate from dhis2w-client so API-only callers never pull in Chromium.
Install
uv add 'dhis2w-cli[browser]' # pulls dhis2w-browser alongside the main CLI
playwright install chromium # one-off; pulls the actual browser driver
Library-only consumers (no CLI) can install dhis2w-browser on its own.
Surface
The CLI lives on the main dhis2 entry point as a plugin; there's no separate dhis2w-browser binary. Workflows mount under dhis2 browser <subcommand>:
dhis2 browser pat --url http://localhost:8080 --username admin --password district
dhis2 browser dashboard screenshot --output-dir /tmp/out --only <uid>
dhis2 browser viz screenshot --output-dir /tmp/out --only <uid>
dhis2 browser map screenshot --output-dir /tmp/out --only <uid>
Library callers import from dhis2w_browser directly:
| Entry point | Purpose |
|---|---|
dhis2w_browser.logged_in_page(url, username, password) |
Async context manager yielding a (BrowserContext, Page) tuple logged into DHIS2 via the React login form. |
dhis2w_browser.session_from_cookie(url, jsessionid) |
Fast-path variant — inject a pre-minted JSESSIONID instead of driving the login form. |
dhis2w_browser.create_pat(url, username, password, options=...) |
Mint a Personal Access Token V2 (POST /api/apiToken) through an authenticated browser session. Returns the d2p_... token string. DHIS2 only returns the token value once — store it immediately. |
dhis2w_browser.drive_oauth2_login(profile_name, *, username, password) |
Run dhis2 profile login <name> --no-browser end-to-end — spawns the CLI, reads the authorize URL from its stderr, and drives Chromium through the DHIS2 React login + Spring AS consent screen + loopback redirect. Returns an OAuth2LoginResult model. |
dhis2w_browser.drive_login_form(auth_url, *, username, password) |
Lower-level companion to drive_oauth2_login — navigates Chromium to an already-built authorize URL, fills the login form + consent screen, waits for the loopback redirect. For wiring Playwright into an in-process OAuth2Auth.redirect_capturer. |
dhis2w_browser.capture_dashboard(...) / capture_visualization(...) / capture_map(...) |
Render a DHIS2 dashboard / chart / map as a PNG via the respective web app. Banner + background-trim helpers available for report-friendly output. |
Headless vs headful
Headless by default. Two ways to flip to visible:
- Env var:
DHIS2_HEADFUL=1(ortrue/yes/on) — applies to every Playwright entry point in this package. - Explicit kwarg:
logged_in_page(..., headless=False)— overrides env.
The dhis2 browser pat CLI command defaults to headful (--headful) so first-time users can watch the login; pass --headless to flip.
Why: automation wants headless for speed; humans debugging a flow want to see it. One env var covers every caller (CLI, library, tests) uniformly. See docs/decisions.md 2026-04-17.
Example
import asyncio
from dhis2w_browser import PatOptions, create_pat
async def main() -> None:
token = await create_pat(
"http://localhost:8080",
"admin",
"district",
options=PatOptions(
name="automation-bot",
expires_in_days=90,
allowed_methods=["GET", "POST"],
),
)
print(token) # d2p_...
asyncio.run(main())
Architecture
See docs/architecture/browser.md for the longer write-up: why PAT creation has to go through a browser (DHIS2 gates /api/apiToken behind a session cookie), how logged_in_page drives the React login form, and what's on the roadmap.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file dhis2w_browser-0.6.0.tar.gz.
File metadata
- Download URL: dhis2w_browser-0.6.0.tar.gz
- Upload date:
- Size: 14.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
bdac5fb20a5a8924664ae14a3d5087a2d13fa1e3c947d4d858f5f85b7bef01e1
|
|
| MD5 |
992386eed069f6e24dae28e0220a740c
|
|
| BLAKE2b-256 |
1f7a8362bb3be2fcfe11a3eebb4ad029c2b82b90d794eed8f440b12ae0f806f2
|
Provenance
The following attestation bundles were made for dhis2w_browser-0.6.0.tar.gz:
Publisher:
pypi-publish.yml on winterop-com/dhis2w-utils
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
dhis2w_browser-0.6.0.tar.gz -
Subject digest:
bdac5fb20a5a8924664ae14a3d5087a2d13fa1e3c947d4d858f5f85b7bef01e1 - Sigstore transparency entry: 1479182549
- Sigstore integration time:
-
Permalink:
winterop-com/dhis2w-utils@5b91d5c51b0f02362c53fa46ffef7ba3abb476d3 -
Branch / Tag:
refs/tags/v0.6.0 - Owner: https://github.com/winterop-com
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
pypi-publish.yml@5b91d5c51b0f02362c53fa46ffef7ba3abb476d3 -
Trigger Event:
push
-
Statement type:
File details
Details for the file dhis2w_browser-0.6.0-py3-none-any.whl.
File metadata
- Download URL: dhis2w_browser-0.6.0-py3-none-any.whl
- Upload date:
- Size: 20.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6f358bf15f3178299332b539a33c08d5e1aa0725942e1c3a03adc93bc53b833b
|
|
| MD5 |
a71c98cfb7a45d188635e1a97c96f16a
|
|
| BLAKE2b-256 |
30e7c723b8aa491c3045cfb2a9797665d8721757e919745ba96579fdf7fa3f81
|
Provenance
The following attestation bundles were made for dhis2w_browser-0.6.0-py3-none-any.whl:
Publisher:
pypi-publish.yml on winterop-com/dhis2w-utils
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
dhis2w_browser-0.6.0-py3-none-any.whl -
Subject digest:
6f358bf15f3178299332b539a33c08d5e1aa0725942e1c3a03adc93bc53b833b - Sigstore transparency entry: 1479184144
- Sigstore integration time:
-
Permalink:
winterop-com/dhis2w-utils@5b91d5c51b0f02362c53fa46ffef7ba3abb476d3 -
Branch / Tag:
refs/tags/v0.6.0 - Owner: https://github.com/winterop-com
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
pypi-publish.yml@5b91d5c51b0f02362c53fa46ffef7ba3abb476d3 -
Trigger Event:
push
-
Statement type: