mirror of
https://github.com/DRYTRIX/TimeTracker.git
synced 2026-05-21 13:50:15 -05:00
6cbe869fc1
Bundles four narrow fixes surfaced by the comprehensive CI run after
v5.5.6 enabled SQLite FK enforcement and refreshed test fixtures. Each
fix is independent; bundled here only to keep PR overhead low.
1. tests/test_routes/test_api_v1_expenses_complete.py
- Add missing `User` import. `test_expense_permissions` references
`User.query.filter(...)` but `User` was never imported, causing a
NameError at test runtime.
2. tests/test_client_single_simplification.py
- `Client(...status="active")` failed with TypeError because the
Client model's __init__ does not accept `status` as a keyword
(column default already sets it to "active"). Set the attribute
after construction.
3. tests/test_utils/test_api_auth_enhanced.py
- `User(username=..., is_active=True)` failed because User.__init__
does not accept `is_active`. Set the attribute after construction.
- 9 occurrences of `app.test_request_context(remote_addr="...")`
failed with `TypeError: EnvironBuilder.__init__() got an unexpected
keyword argument 'remote_addr'`. Werkzeug removed the keyword;
replace with `environ_overrides={"REMOTE_ADDR": "..."}` which is
the supported equivalent.
4. app/routes/api_v1_time_entries.py
- DELETE /api/v1/time-entries/<id> returned 415 Unsupported Media
Type when called without an `application/json` Content-Type, even
though the body is optional (only used to capture an audit reason).
Switch to `request.get_json(silent=True)` so the endpoint accepts
DELETE requests with no body. Same change applied to no other
methods; POST/PUT continue to require explicit JSON.
The route file also picked up a black/isort pass from the project
auto-formatter; behaviour is identical to before, only whitespace and
import grouping differ.
Test plan
- pytest tests/test_routes/test_api_v1_expenses_complete.py::TestAPIExpensesComplete::test_expense_permissions
- pytest tests/test_client_single_simplification.py::test_manual_entry_shows_select_when_multiple_clients
- pytest tests/test_utils/test_api_auth_enhanced.py::TestAuthenticateToken
- pytest tests/test_routes/test_api_v1_time_entries_complete.py::TestAPITimeEntriesComplete::test_delete_time_entry_uses_service_layer
65 lines
2.3 KiB
Python
65 lines
2.3 KiB
Python
"""
|
|
Tests for Client Single-Client Simplification (Issue #467).
|
|
|
|
When only one active client exists, the client selection field is pre-filled
|
|
and grayed out across manual time logging, project creation, and similar forms.
|
|
"""
|
|
|
|
import pytest
|
|
from app import db
|
|
from app.models import Client
|
|
from flask import url_for
|
|
|
|
|
|
@pytest.mark.integration
|
|
@pytest.mark.routes
|
|
def test_manual_entry_shows_single_client_prefilled(
|
|
authenticated_client, app, user, test_client
|
|
):
|
|
"""When only one client exists, manual entry form shows pre-filled grayed-out client."""
|
|
with app.app_context():
|
|
# Ensure exactly one active client (test_client from fixture)
|
|
active_count = Client.query.filter_by(status="active").count()
|
|
assert active_count == 1, "Expected exactly 1 active client for this test"
|
|
|
|
response = authenticated_client.get(url_for("timer.manual_entry"))
|
|
assert response.status_code == 200
|
|
html = response.get_data(as_text=True)
|
|
|
|
# Should have hidden input for client_id (single-client mode)
|
|
assert 'name="client_id"' in html
|
|
assert f'value="{test_client.id}"' in html
|
|
# Should have disabled readonly display
|
|
assert "disabled" in html
|
|
assert "readonly" in html
|
|
assert test_client.name in html
|
|
|
|
|
|
@pytest.mark.integration
|
|
@pytest.mark.routes
|
|
def test_manual_entry_shows_select_when_multiple_clients(
|
|
authenticated_client, app, user, test_client
|
|
):
|
|
"""When multiple clients exist, manual entry form shows normal client select."""
|
|
with app.app_context():
|
|
# Add a second client
|
|
second = Client(
|
|
name="Second Client",
|
|
email="second@example.com",
|
|
)
|
|
second.status = "active"
|
|
db.session.add(second)
|
|
db.session.commit()
|
|
|
|
active_count = Client.query.filter_by(status="active").count()
|
|
assert active_count >= 2
|
|
|
|
response = authenticated_client.get(url_for("timer.manual_entry"))
|
|
assert response.status_code == 200
|
|
html = response.get_data(as_text=True)
|
|
|
|
# Should have normal select, not single-client hidden + disabled
|
|
assert "<select" in html
|
|
assert 'id="client_id"' in html or 'name="client_id"' in html
|
|
assert "Select a client" in html or "client" in html.lower()
|