70 lines
2.7 KiB
Python
70 lines
2.7 KiB
Python
from contextlib import contextmanager
|
|
import pytest
|
|
from fastapi import FastAPI, HTTPException
|
|
from fastapi.testclient import TestClient
|
|
from app.workflows import decisions
|
|
|
|
|
|
@pytest.fixture
|
|
def api(monkeypatch):
|
|
app = FastAPI()
|
|
app.include_router(decisions.router)
|
|
app.dependency_overrides[decisions.edit_access] = lambda: {'id': 4, 'permissions': []}
|
|
app.dependency_overrides[decisions.view_access] = lambda: {'id': 4}
|
|
state = {'entry': {'id': 1, 'workflow_revision': 3, 'status': 'draft'},
|
|
'previous': {'id': 2, 'status': 'decided', 'manual_override': True}, 'writes': []}
|
|
class Cursor:
|
|
def execute(self, sql, params=None):
|
|
self.sql = sql
|
|
if not sql.startswith('SELECT'):
|
|
state['writes'].append(sql)
|
|
def fetchone(self):
|
|
if 'FROM tmodule_times' in self.sql:
|
|
return state['entry']
|
|
return state['previous']
|
|
def fetchall(self):
|
|
return []
|
|
@contextmanager
|
|
def transaction():
|
|
yield Cursor()
|
|
monkeypatch.setattr(decisions.service, 'transaction', transaction)
|
|
return TestClient(app), state
|
|
|
|
|
|
def test_recalculate_preserves_manual_override_without_writes(api):
|
|
client, state = api
|
|
result = client.post('/timetracking/time/1/workflow-recalculate', json={})
|
|
assert result.status_code == 200
|
|
assert result.json()['preserved_override'] is True
|
|
assert not state['writes']
|
|
|
|
|
|
def test_reset_requires_admin_permission(api):
|
|
client, state = api
|
|
result = client.post('/timetracking/time/1/workflow-recalculate', json={'reset_override': True, 'reason': 'Ny aftale'})
|
|
assert result.status_code == 403
|
|
assert not state['writes']
|
|
|
|
|
|
@pytest.mark.parametrize('field,value', [('status', 'approved'), ('status', 'billed'), ('economy_settled_at', 'now'), ('economy_order_draft_id', 24), ('exported_at', 'now')])
|
|
def test_settled_or_exported_cannot_recompute(api, field, value):
|
|
client, state = api
|
|
state['entry'][field] = value
|
|
result = client.post('/timetracking/time/1/workflow-recalculate', json={})
|
|
assert result.status_code == 409
|
|
assert not state['writes']
|
|
|
|
|
|
def test_unauthenticated_cannot_override():
|
|
app = FastAPI()
|
|
app.include_router(decisions.router)
|
|
response = TestClient(app).post('/timetracking/time/1/workflow-override', json={'method': 'invoice', 'reason': 'Ny aftale'})
|
|
assert response.status_code == 401
|
|
|
|
|
|
def test_not_active_customer_rejected(monkeypatch):
|
|
monkeypatch.setattr(decisions, 'active_for_customer', lambda _: False)
|
|
with pytest.raises(HTTPException) as exc:
|
|
decisions._require_active({'customer_id': '24'})
|
|
assert exc.value.status_code == 409
|