mirror of
https://github.com/DRYTRIX/TimeTracker.git
synced 2026-05-18 12:19:18 -05:00
ef9b66f5e7
Global search referenced Client.company, which is not a column on Client, so client matches failed at runtime. Legacy and v1 search, plus search_clients(), now filter on name, email, description, and contact_person; result descriptions use the same fields. Legacy /api/search returns count: 0 for queries shorter than two characters so responses stay consistent. OpenAPI info.version is taken from get_version_from_setup(), with a config fallback when the resolved version is unknown. get_version_from_setup() also honors TIMETRACKER_VERSION and APP_VERSION for CI and container builds. Client.__init__ accepts custom_fields. ClientService no longer passes status= into Client(), which the initializer does not support. Tests add HTTP route contract checks and OpenAPI version alignment, fix subcontractor search fixtures (Client/Task construction and v1 client fixture naming), and update related API integration tests.
48 lines
1.7 KiB
Python
48 lines
1.7 KiB
Python
"""Contract checks: curated HTTP paths exist on the Flask url map; OpenAPI version matches app version."""
|
|
|
|
import pytest
|
|
from werkzeug.exceptions import MethodNotAllowed, NotFound
|
|
|
|
pytestmark = [pytest.mark.api, pytest.mark.integration]
|
|
|
|
# Paths exercised by tests after drift cleanup; extend when adding stable API coverage.
|
|
CONTRACT_ROUTES = (
|
|
("/api/v1/info", "GET"),
|
|
("/api/v1/health", "GET"),
|
|
("/api/timer/status", "GET"),
|
|
("/api/timer/stop", "POST"),
|
|
("/api/openapi.json", "GET"),
|
|
("/api/analytics/hours-by-day", "GET"),
|
|
("/api/analytics/hours-by-project", "GET"),
|
|
("/api/tasks/create", "POST"),
|
|
("/projects/create", "GET"),
|
|
("/api/reports/scheduled", "GET"),
|
|
)
|
|
|
|
|
|
def test_contract_routes_registered(app):
|
|
"""Each curated path must resolve against the application's url map."""
|
|
server_name = app.config.get("SERVER_NAME") or "localhost"
|
|
adapter = app.url_map.bind(server_name)
|
|
for path, method in CONTRACT_ROUTES:
|
|
try:
|
|
adapter.match(path, method=method)
|
|
except NotFound:
|
|
pytest.fail(f"No route registered for {method} {path!r}")
|
|
except MethodNotAllowed as exc:
|
|
pytest.fail(f"Method not allowed for {method} {path!r}: {exc!s}")
|
|
|
|
|
|
def test_openapi_info_version_matches_app_version(app, client):
|
|
"""OpenAPI info.version must follow setup.py / env (same as get_version_from_setup)."""
|
|
from app.config.analytics_defaults import get_version_from_setup
|
|
|
|
expected = get_version_from_setup()
|
|
if expected == "unknown":
|
|
expected = app.config.get("APP_VERSION", "1.0.0")
|
|
|
|
response = client.get("/api/openapi.json")
|
|
assert response.status_code == 200
|
|
data = response.get_json()
|
|
assert data.get("info", {}).get("version") == expected
|