Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 2 additions & 0 deletions MANIFEST.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
recursive-include contracts *.json *.md
include tests/conftest.py
6 changes: 5 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
PYTHON ?= python3.14
SOURCES = energy_tracker_api/ tests/ scripts/ example.py

.PHONY: help install install-dev clean test coverage lint format type-check build check-dist upload upload-test venv all
.PHONY: help install install-dev clean test test-contracts coverage lint format type-check build check-dist upload upload-test venv all

help:
@echo "Available commands:"
Expand All @@ -10,6 +10,7 @@ help:
@echo " make install-dev - Install package with development dependencies"
@echo " make clean - Remove build artifacts and cache files"
@echo " make test - Run tests"
@echo " make test-contracts - Run shared API contract cases"
@echo " make coverage - Run tests with coverage report"
@echo " make lint - Run code linting (black check + isort check)"
@echo " make format - Format code with black and isort"
Expand Down Expand Up @@ -54,6 +55,9 @@ clean:
test: .install-dev-stamp
venv/bin/python -m pytest tests/ -v

test-contracts: .install-dev-stamp
venv/bin/python -m pytest tests/test_contracts.py -v

coverage: .install-dev-stamp
venv/bin/python -m pytest tests/ --cov=energy_tracker_api --cov-report=html --cov-report=term --cov-report=xml

Expand Down
57 changes: 57 additions & 0 deletions contracts/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# Shared SDK contract cases

Language-independent examples for the Energy Tracker Python and TypeScript clients.
Run the Python adapter with `make test-contracts`; the cases also run in the normal
test and release checks. No API token, live backend or sibling checkout is needed.

## Format and execution

`schema.json` defines fixture format version 1. Each file in `cases/` contains a
`schemaVersion` and an array of cases with globally unique IDs.

- `operation` and `input` describe a public SDK call. Bind these to the target
language's API; they do not prescribe method names or classes. Reading values
are decimal strings, environment values are JSON numbers, dates are offset ISO
timestamps. Missing optional inputs mean omitted arguments.
- `request` specifies the method, API-relative path, decoded query parameters,
required headers and body. Preserve a base URL's `/public-api/` prefix. Compare
header names case-insensitively; additional transport headers are allowed.
Query key order and JSON object key order are irrelevant; extra query/body
fields and duplicate query keys are not allowed.
- `response` is the local server's synthetic HTTP response. Bodies use exactly
one of `json`, UTF-8 `text`, or `base64`; `{}` means no body. A `json: null`
body is distinct from no body. Base64 preserves exact CSV bytes, including BOM
and line endings.
- `expected` contains either a normalized `result` or an `error`. Results use
camelCase DTO fields, decimal strings, and `{ "base64": "..." }` for bytes.
Void results and absent optional DTO fields are normalized to `null`.
Errors specify a semantic category, HTTP status, API message list and, when
present, `retryAfter` in seconds. Exception class names and local wording are
language-specific. Assert exactly one request, including on errors/redirects.

Compare `timestamp`, `date`, `lastUpdatedAt`, `from`, `to`, `updatedAfter` and
`updatedBefore` as offset-aware instants. `Z` and equivalent offsets/fractional
spellings are interchangeable. Do not round to calendar boundaries. Compare
all other values directly, preserving decimal precision and list order.

The wire examples were checked against the Public API controllers and DTOs in
[energy-tracker-core at fcc269a06184426caf64c882291d4209be57a723](https://github.com/StefaniOSApps/energy-tracker-core/tree/fcc269a06184426caf64c882291d4209be57a723/backend/src/app/public-api).
Error/redirect/malformed-response cases additionally specify SDK behavior; their
messages are illustrative, not fixed backend wording. These mocked responses
do not verify server calculations, validation rules or authorization scopes.
Timeouts, session lifecycle and language-specific input validation remain in
each SDK's own tests.

## Reuse and versioning

This directory is the fixture source. Pin an immutable Git commit of this
repository when consuming it; do not fetch a moving `main` in SDK CI. Export
with `git archive <commit> LICENSE contracts`, retain the repository's MIT license, and
record the source commit alongside the imported files. A TypeScript repository
can vendor that snapshot and run its own HTTP test adapter entirely offline.
Update the source fixtures here and import updates explicitly into consumers.

`schemaVersion` versions the fixture format, independently of Python releases.
The pinned Git commit identifies the exact case revision. Unknown schema
versions and operations must fail rather than be skipped. Fixtures are included
in the source distribution, but are not a runtime dependency or part of the wheel.
Loading