You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
531 lines
26 KiB
Python
531 lines
26 KiB
Python
"""
|
|
Integration tests for Optimum OH backend.
|
|
All endpoints are sourced from frontend API calls using OPTIMUM_OH_API_URL.
|
|
|
|
Run with:
|
|
pytest src/testing/integration_test.py -v
|
|
"""
|
|
|
|
import pytest
|
|
import requests
|
|
|
|
BASE_URL = "http://100.125.115.116:8000/optimumoh"
|
|
AUTH_BASE_URL = "http://100.125.115.116:8000/auth"
|
|
|
|
OVERHAUL_SESSION_ID = "3704c82c-cfc5-47f7-813a-1661f89b0738"
|
|
SCOPE_JOB_ID = "db590764-72cb-4eb1-a30f-014116df0472"
|
|
CALCULATION_ID = "44f483f3-bfe4-4094-a59f-b97a10f2fea6"
|
|
BUDGET_THRESHOLD = 100000
|
|
RISK_COST = 1
|
|
LOCATION_TAG = "3AL-F501A"
|
|
SCOPE_NAME = "A"
|
|
ASSET_NUM = "A19825"
|
|
EAF_INPUT = 0.85
|
|
DURATION = 17520
|
|
SCOPE_EQUIPMENT_ACTIVITY_ID = "4527eb2b-0bc4-46b3-80a1-e1d2f67882f8"
|
|
ITEMNUM = "206510"
|
|
SPREADSHEET_LINK = "https://docs.google.com/spreadsheets/d/example_spreadsheet_id/edit"
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Users
|
|
# ---------------------------------------------------------------------------
|
|
USER_LIST = [
|
|
{"id": 1, "name": "devmustbeadmin", "pass": "", "email": "", "authorization_token": ""},
|
|
{"id": 2, "name": "devmustbeengineer", "pass": "", "email": "", "authorization_token": ""},
|
|
{"id": 3, "name": "devmustbeapplicationadmin", "pass": "", "email": "", "authorization_token": ""},
|
|
{"id": 4, "name": "devmustbemanagement", "pass": "", "email": "", "authorization_token": ""},
|
|
]
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Role-based access constants
|
|
# ---------------------------------------------------------------------------
|
|
# Endpoints guarded by require_any_role(*ALLOWED_ROLES) block Management entirely.
|
|
# Endpoints with only required_permission(READ) allow Management (has READ in ACL).
|
|
# Endpoints with no guard at all allow every role.
|
|
NON_MANAGEMENT = {"devmustbeadmin", "devmustbeengineer", "devmustbeapplicationadmin"}
|
|
ALL_ALLOWED = {"devmustbeadmin", "devmustbeengineer", "devmustbeapplicationadmin", "devmustbemanagement"}
|
|
|
|
|
|
def user_auth_headers(token: str) -> dict:
|
|
return {"Authorization": f"Bearer {token}", "Content-Type": "application/json"}
|
|
|
|
|
|
def get_csrf_token(path: str, auth_token: str) -> str:
|
|
"""Fetch a one-time CSRF token from be-auth for the given endpoint path.
|
|
|
|
Args:
|
|
path: The endpoint path as seen by be-optimumoh (e.g. "/spareparts").
|
|
Do NOT include the "/optimumoh" Kong prefix.
|
|
auth_token: The raw JWT token string (without "Bearer " prefix).
|
|
|
|
Returns:
|
|
The plain-text CSRF token to send in the X-CSRF-Token header.
|
|
"""
|
|
res = requests.post(
|
|
f"{AUTH_BASE_URL}/csrf-token",
|
|
headers={
|
|
"Authorization": f"Bearer {auth_token}",
|
|
"Content-Type": "application/json",
|
|
"X-Target-Path": path,
|
|
},
|
|
json={
|
|
"_csrf_request": True,
|
|
}
|
|
)
|
|
print(f"Requested CSRF token for {path}, got status {res.status_code}, response: {res.text}")
|
|
assert res.status_code == 200, f"Failed to get CSRF token for {path}: {res.status_code} {res.text}"
|
|
data = res.json()
|
|
# Response shape: {"data": {"csrf_token": "..."}, ...}
|
|
return data["data"]["csrf_token"]
|
|
|
|
|
|
# ─────────────────────────────────────────────
|
|
# Overhaul Schedules
|
|
# ─────────────────────────────────────────────
|
|
|
|
def test_get_overhaul_schedules():
|
|
"""GET /overhaul-schedules — require_any_role blocks Management"""
|
|
for user in USER_LIST:
|
|
res = requests.get(f"{BASE_URL}/overhaul-schedules", headers=user_auth_headers(user["authorization_token"]))
|
|
expected = 200 if user["name"] in NON_MANAGEMENT else 403
|
|
assert res.status_code == expected, f"[{user['name']}] expected {expected}, got {res.status_code}"
|
|
|
|
def test_get_overhaul_schedules_by_id():
|
|
"""GET /overhaul-schedules/{overhaul_session_id} — require_any_role blocks Management"""
|
|
for user in USER_LIST:
|
|
res = requests.get(
|
|
f"{BASE_URL}/overhaul-schedules/{OVERHAUL_SESSION_ID}",
|
|
headers=user_auth_headers(user["authorization_token"]),
|
|
)
|
|
expected = 200 if user["name"] in NON_MANAGEMENT else 403
|
|
assert res.status_code == expected, f"[{user['name']}] expected {expected}, got {res.status_code}: {res.text}"
|
|
|
|
def test_post_overhaul_schedules_update():
|
|
"""POST /overhaul-schedules/update/{scope_id} — require_any_role + EDIT blocks Management
|
|
Payload: duration_oh (optional int), crew_number (optional int), status (optional str)
|
|
"""
|
|
payload = {
|
|
"duration_oh": 720,
|
|
"crew_number": 10,
|
|
"status": "Upcoming",
|
|
}
|
|
for user in USER_LIST:
|
|
csrf_token = get_csrf_token("/overhaul-schedules/update", user["authorization_token"])
|
|
headers = {**user_auth_headers(user["authorization_token"]), "X-CSRF-Token": csrf_token}
|
|
res = requests.post(
|
|
f"{BASE_URL}/overhaul-schedules/update/{OVERHAUL_SESSION_ID}",
|
|
json=payload,
|
|
headers=headers,
|
|
)
|
|
print(f"[{user['name']}], got {res.status_code}, response: {res.text}")
|
|
if user["name"] in NON_MANAGEMENT:
|
|
assert res.status_code in (200, 204, 404), f"[{user['name']}] expected 200/204/404, got {res.status_code}"
|
|
else:
|
|
assert res.status_code == 403, f"[{user['name']}] expected 403, got {res.status_code}"
|
|
|
|
def test_get_overhaul_schedules_history():
|
|
"""GET /overhaul-schedules/history — require_any_role blocks Management"""
|
|
for user in USER_LIST:
|
|
res = requests.get(f"{BASE_URL}/overhaul-schedules/history", headers=user_auth_headers(user["authorization_token"]))
|
|
expected = 200 if user["name"] in NON_MANAGEMENT else 403
|
|
assert res.status_code == expected, f"[{user['name']}] expected {expected}, got {res.status_code}"
|
|
|
|
def test_post_overhaul_schedules_delete():
|
|
"""POST /overhaul-schedules/delete/{scope_id} — require_any_role + DELETE blocks Management
|
|
No body required. CSRF token required in production.
|
|
"""
|
|
for user in USER_LIST:
|
|
csrf_token = get_csrf_token(f"/overhaul-schedules/delete/{OVERHAUL_SESSION_ID}", user["authorization_token"])
|
|
headers = {**user_auth_headers(user["authorization_token"]), "X-CSRF-Token": csrf_token}
|
|
res = requests.post(
|
|
f"{BASE_URL}/overhaul-schedules/delete/{OVERHAUL_SESSION_ID}",
|
|
headers=headers,
|
|
)
|
|
print(f"[{user['name']}], got {res.status_code}, response: {res.text}")
|
|
if user["name"] in NON_MANAGEMENT:
|
|
assert res.status_code in (200, 204, 404), f"[{user['name']}] expected 200/204/404, got {res.status_code}"
|
|
else:
|
|
assert res.status_code == 403, f"[{user['name']}] expected 403, got {res.status_code}"
|
|
|
|
# ─────────────────────────────────────────────
|
|
# Overhauls
|
|
# ─────────────────────────────────────────────
|
|
|
|
def test_get_overhauls():
|
|
"""GET /overhauls — required_permission(READ) only; Management has READ in ACL"""
|
|
for user in USER_LIST:
|
|
res = requests.get(f"{BASE_URL}/overhauls", headers=user_auth_headers(user["authorization_token"]))
|
|
assert res.status_code == 200, f"[{user['name']}] expected 200, got {res.status_code}"
|
|
|
|
# ─────────────────────────────────────────────
|
|
# Overhaul Gantt
|
|
# ─────────────────────────────────────────────
|
|
|
|
def test_get_overhaul_gantt_spreadsheet():
|
|
"""GET /overhaul-gantt/spreadsheet — no role guard; all roles allowed"""
|
|
for user in USER_LIST:
|
|
res = requests.get(
|
|
f"{BASE_URL}/overhaul-gantt/spreadsheet",
|
|
headers=user_auth_headers(user["authorization_token"]),
|
|
)
|
|
assert res.status_code == 200, f"[{user['name']}] expected 200, got {res.status_code}: {res.text}"
|
|
|
|
|
|
|
|
# ─────────────────────────────────────────────
|
|
# Spareparts
|
|
# ─────────────────────────────────────────────
|
|
|
|
def test_get_spareparts():
|
|
"""GET /spareparts — require_any_role blocks Management"""
|
|
for user in USER_LIST:
|
|
res = requests.get(f"{BASE_URL}/spareparts", headers=user_auth_headers(user["authorization_token"]))
|
|
expected = 200 if user["name"] in NON_MANAGEMENT else 403
|
|
assert res.status_code == expected, f"[{user['name']}] expected {expected}, got {res.status_code}"
|
|
|
|
def test_get_equipment_spareparts():
|
|
"""GET /equipment-spareparts/{location_tag} — require_any_role blocks Management"""
|
|
for user in USER_LIST:
|
|
res = requests.get(
|
|
f"{BASE_URL}/equipment-spareparts/{LOCATION_TAG}",
|
|
headers=user_auth_headers(user["authorization_token"]),
|
|
)
|
|
expected = 200 if user["name"] in NON_MANAGEMENT else 403
|
|
assert res.status_code == expected, f"[{user['name']}] expected {expected}, got {res.status_code}"
|
|
|
|
def test_post_spareparts():
|
|
"""POST /spareparts — require_any_role blocks Management
|
|
Payload: itemnum (str), remark (str). CSRF token required.
|
|
"""
|
|
payload = {
|
|
"itemnum": ITEMNUM,
|
|
"remark": "Test remark for integration test",
|
|
}
|
|
for user in USER_LIST:
|
|
csrf_token = get_csrf_token("/spareparts", user["authorization_token"])
|
|
headers = {**user_auth_headers(user["authorization_token"]), "X-CSRF-Token": csrf_token}
|
|
res = requests.post(f"{BASE_URL}/spareparts", json=payload, headers=headers)
|
|
if user["name"] in NON_MANAGEMENT:
|
|
assert res.status_code in (200, 201), f"[{user['name']}] expected 200/201, got {res.status_code}"
|
|
else:
|
|
assert res.status_code == 403, f"[{user['name']}] expected 403, got {res.status_code}"
|
|
|
|
def test_post_overhaul_gantt_spreadsheet():
|
|
"""POST /overhaul-gantt/spreadsheet — no role guard; all roles allowed
|
|
Payload: spreadsheet_link (str). CSRF token required in production.
|
|
"""
|
|
payload = {
|
|
"spreadsheet_link": SPREADSHEET_LINK,
|
|
}
|
|
for user in USER_LIST:
|
|
csrf_token = get_csrf_token("/overhaul-gantt/spreadsheet", user["authorization_token"])
|
|
headers = {**user_auth_headers(user["authorization_token"]), "X-CSRF-Token": csrf_token}
|
|
res = requests.post(
|
|
f"{BASE_URL}/overhaul-gantt/spreadsheet",
|
|
json=payload,
|
|
headers=headers,
|
|
)
|
|
assert res.status_code in (200, 201), f"[{user['name']}] expected 200/201, got {res.status_code}"
|
|
|
|
# ─────────────────────────────────────────────
|
|
# Scope Equipments
|
|
# ─────────────────────────────────────────────
|
|
|
|
def test_get_scope_equipments():
|
|
"""GET /scope-equipments?page=1 — require_any_role blocks Management"""
|
|
for user in USER_LIST:
|
|
res = requests.get(f"{BASE_URL}/scope-equipments?page=1", headers=user_auth_headers(user["authorization_token"]))
|
|
expected = 200 if user["name"] in NON_MANAGEMENT else 403
|
|
assert res.status_code == expected, f"[{user['name']}] expected {expected}, got {res.status_code}"
|
|
|
|
|
|
def test_get_scope_equipments_available():
|
|
"""GET /scope-equipments/available/{scope_name} — require_any_role blocks Management"""
|
|
for user in USER_LIST:
|
|
res = requests.get(
|
|
f"{BASE_URL}/scope-equipments/available/{SCOPE_NAME}",
|
|
headers=user_auth_headers(user["authorization_token"]),
|
|
)
|
|
expected = 200 if user["name"] in NON_MANAGEMENT else 403
|
|
assert res.status_code == expected, f"[{user['name']}] expected {expected}, got {res.status_code}"
|
|
|
|
|
|
# ─────────────────────────────────────────────
|
|
# Overhaul Schedules (additional)
|
|
# ─────────────────────────────────────────────
|
|
|
|
def test_get_overhaul_schedules():
|
|
"""GET /overhaul-schedules — require_any_role blocks Management"""
|
|
for user in USER_LIST:
|
|
res = requests.get(f"{BASE_URL}/overhaul-schedules", headers=user_auth_headers(user["authorization_token"]))
|
|
expected = 200 if user["name"] in NON_MANAGEMENT else 403
|
|
assert res.status_code == expected, f"[{user['name']}] expected {expected}, got {res.status_code}: {res.text}"
|
|
|
|
|
|
def test_get_overhaul_schedules_history():
|
|
"""GET /overhaul-schedules/history — require_any_role blocks Management"""
|
|
for user in USER_LIST:
|
|
res = requests.get(f"{BASE_URL}/overhaul-schedules/history", headers=user_auth_headers(user["authorization_token"]))
|
|
expected = 200 if user["name"] in NON_MANAGEMENT else 403
|
|
assert res.status_code == expected, f"[{user['name']}] expected {expected}, got {res.status_code}: {res.text}"
|
|
|
|
# ─────────────────────────────────────────────
|
|
# Overhauls sub-routes
|
|
# ─────────────────────────────────────────────
|
|
|
|
def test_get_overhauls_system_components():
|
|
"""GET /overhauls/system-components — required_permission(READ); Management has READ"""
|
|
for user in USER_LIST:
|
|
res = requests.get(f"{BASE_URL}/overhauls/system-components", headers=user_auth_headers(user["authorization_token"]))
|
|
assert res.status_code == 200, f"[{user['name']}] expected 200, got {res.status_code}: {res.text}"
|
|
|
|
|
|
# ─────────────────────────────────────────────
|
|
# Workscopes
|
|
# ─────────────────────────────────────────────
|
|
|
|
def test_get_workscopes():
|
|
"""GET /workscopes — no role guard; all roles allowed"""
|
|
for user in USER_LIST:
|
|
res = requests.get(f"{BASE_URL}/workscopes", headers=user_auth_headers(user["authorization_token"]))
|
|
assert res.status_code == 200, f"[{user['name']}] expected 200, got {res.status_code}: {res.text}"
|
|
|
|
def test_get_workscopes_by_id():
|
|
"""GET /workscopes/{scope_equipment_activity_id}?activity_id=... — no role guard; all roles allowed
|
|
"""
|
|
for user in USER_LIST:
|
|
res = requests.get(
|
|
f"{BASE_URL}/workscopes/{SCOPE_EQUIPMENT_ACTIVITY_ID}",
|
|
params={"activity_id": SCOPE_EQUIPMENT_ACTIVITY_ID},
|
|
headers=user_auth_headers(user["authorization_token"]),
|
|
)
|
|
assert res.status_code in (200, 404), f"[{user['name']}] expected 200/404, got {res.status_code}: {res.text}"
|
|
|
|
def test_post_workscopes_update():
|
|
"""POST /workscopes/update/{scope_equipment_activity_id} — no role guard; all roles allowed
|
|
Payload: description (str)
|
|
"""
|
|
payload = {
|
|
"description": "Updated workscope description",
|
|
}
|
|
for user in USER_LIST:
|
|
csrf_token = get_csrf_token("/workscopes/update", user["authorization_token"])
|
|
headers = {**user_auth_headers(user["authorization_token"]), "X-CSRF-Token": csrf_token}
|
|
res = requests.post(
|
|
f"{BASE_URL}/workscopes/update/{SCOPE_EQUIPMENT_ACTIVITY_ID}",
|
|
json=payload,
|
|
params={"activity_id": SCOPE_EQUIPMENT_ACTIVITY_ID},
|
|
headers=headers,
|
|
)
|
|
print(f"[{user['name']}], got {res.status_code}, response: {res.text}")
|
|
assert res.status_code in (200, 404), f"[{user['name']}] expected 200/404, got {res.status_code}"
|
|
|
|
|
|
def test_post_workscopes_delete():
|
|
"""POST /workscopes/delete/{scope_equipment_activity_id} — no role guard; all roles allowed
|
|
No body required.
|
|
"""
|
|
for user in USER_LIST:
|
|
csrf_token = get_csrf_token("/workscopes/delete", user["authorization_token"])
|
|
headers = {**user_auth_headers(user["authorization_token"]), "X-CSRF-Token": csrf_token}
|
|
res = requests.post(
|
|
f"{BASE_URL}/workscopes/delete/{SCOPE_EQUIPMENT_ACTIVITY_ID}",
|
|
params={"activity_id": SCOPE_EQUIPMENT_ACTIVITY_ID},
|
|
headers=headers,
|
|
)
|
|
print(f"[{user['name']}], got {res.status_code}, response: {res.text}")
|
|
assert res.status_code in (200, 204, 404), f"[{user['name']}] expected 200/204/404, got {res.status_code}"
|
|
|
|
# ─────────────────────────────────────────────
|
|
# Overhaul Activity
|
|
# ─────────────────────────────────────────────
|
|
|
|
def test_get_overhaul_activity():
|
|
"""GET /overhaul-activity/{overhaul_session} — require_any_role blocks Management"""
|
|
for user in USER_LIST:
|
|
res = requests.get(
|
|
f"{BASE_URL}/overhaul-activity/{OVERHAUL_SESSION_ID}",
|
|
headers=user_auth_headers(user["authorization_token"]),
|
|
)
|
|
expected = 200 if user["name"] in NON_MANAGEMENT else 403
|
|
assert res.status_code == expected, f"[{user['name']}] expected {expected}, got {res.status_code}"
|
|
|
|
def test_post_overhaul_activity_current():
|
|
"""POST /overhaul-activity/{session_id} — require_any_role blocks Management
|
|
Payload: location_tags (List[str]). CSRF token required.
|
|
"""
|
|
payload = {
|
|
"location_tags": [LOCATION_TAG],
|
|
}
|
|
for user in USER_LIST:
|
|
csrf_token = get_csrf_token("/overhaul-activity", user["authorization_token"])
|
|
headers = {**user_auth_headers(user["authorization_token"]), "X-CSRF-Token": csrf_token}
|
|
res = requests.post(
|
|
f"{BASE_URL}/overhaul-activity/{OVERHAUL_SESSION_ID}",
|
|
json=payload,
|
|
headers=headers,
|
|
)
|
|
if user["name"] in NON_MANAGEMENT:
|
|
assert res.status_code in (200, 201), f"[{user['name']}] expected 200/201, got {res.status_code}"
|
|
else:
|
|
assert res.status_code == 403, f"[{user['name']}] expected 403, got {res.status_code}"
|
|
|
|
def test_delete_overhaul_activity():
|
|
"""POST /overhaul-activity/delete/{overhaul_session}/{location_tag} — require_any_role blocks Management. CSRF required."""
|
|
for user in USER_LIST:
|
|
csrf_token = get_csrf_token(f"/overhaul-activity/delete/{OVERHAUL_SESSION_ID}/{LOCATION_TAG}", user["authorization_token"])
|
|
headers = {**user_auth_headers(user["authorization_token"]), "X-CSRF-Token": csrf_token}
|
|
res = requests.post(
|
|
f"{BASE_URL}/overhaul-activity/delete/{OVERHAUL_SESSION_ID}/{LOCATION_TAG}",
|
|
headers=headers,
|
|
)
|
|
if user["name"] in NON_MANAGEMENT:
|
|
assert res.status_code in (200, 204, 404), f"[{user['name']}] expected 200/204/404, got {res.status_code}"
|
|
else:
|
|
assert res.status_code == 403, f"[{user['name']}] expected 403, got {res.status_code}"
|
|
|
|
|
|
# ─────────────────────────────────────────────
|
|
# Scope Equipments History
|
|
# ─────────────────────────────────────────────
|
|
|
|
def test_get_scope_equipments_history():
|
|
"""GET /scope-equipments/history/{oh_session_id} — require_any_role blocks Management"""
|
|
for user in USER_LIST:
|
|
res = requests.get(
|
|
f"{BASE_URL}/scope-equipments/history/{OVERHAUL_SESSION_ID}",
|
|
headers=user_auth_headers(user["authorization_token"]),
|
|
)
|
|
expected = 200 if user["name"] in NON_MANAGEMENT else 403
|
|
assert res.status_code == expected, f"[{user['name']}] expected {expected}, got {res.status_code}: {res.text}"
|
|
|
|
|
|
# ─────────────────────────────────────────────
|
|
# Equipment Workscopes
|
|
# ─────────────────────────────────────────────
|
|
|
|
def test_get_equipment_workscopes():
|
|
"""GET /equipment-workscopes/{location_tag} — no role guard; all roles allowed
|
|
Query params: scope (optional str)
|
|
"""
|
|
for user in USER_LIST:
|
|
res = requests.get(
|
|
f"{BASE_URL}/equipment-workscopes/{LOCATION_TAG}",
|
|
headers=user_auth_headers(user["authorization_token"]),
|
|
)
|
|
assert res.status_code == 200, f"[{user['name']}] expected 200, got {res.status_code}: {res.text}"
|
|
|
|
|
|
def test_post_equipment_workscopes():
|
|
"""POST /equipment-workscopes/{assetnum} — no role guard; all roles allowed
|
|
Payload: job_ids (List[UUID])
|
|
"""
|
|
payload = {
|
|
"job_ids": [],
|
|
}
|
|
for user in USER_LIST:
|
|
csrf_token = get_csrf_token("/equipment-workscopes", user["authorization_token"])
|
|
headers = {**user_auth_headers(user["authorization_token"]), "X-CSRF-Token": csrf_token}
|
|
res = requests.post(
|
|
f"{BASE_URL}/equipment-workscopes/{ASSET_NUM}",
|
|
json=payload,
|
|
headers=headers,
|
|
)
|
|
print(f"[{user['name']}], got {res.status_code}, response: {res.text}")
|
|
assert res.status_code in (200, 201), f"[{user['name']}] expected 200/201, got {res.status_code}"
|
|
|
|
|
|
# ─────────────────────────────────────────────
|
|
# Calculation — Target Reliability
|
|
# ─────────────────────────────────────────────
|
|
|
|
def test_get_calculation_target_reliability():
|
|
"""GET /calculation/target-reliability — required_permission(READ); Management has READ
|
|
Query params: oh_session_id (required), eaf_input (float), duration (int), simulation_id (optional), cut_hours (optional)
|
|
"""
|
|
for user in USER_LIST:
|
|
res = requests.get(
|
|
f"{BASE_URL}/calculation/target-reliability"
|
|
f"?oh_session_id={OVERHAUL_SESSION_ID}&eaf_input={EAF_INPUT}&duration={DURATION}",
|
|
headers=user_auth_headers(user["authorization_token"]),
|
|
)
|
|
assert res.status_code in (200, 400, 404, 425), f"[{user['name']}] expected 200/400/404/425, got {res.status_code}: {res.text}"
|
|
|
|
|
|
# ─────────────────────────────────────────────
|
|
# Calculation — Time Constraint
|
|
# ─────────────────────────────────────────────
|
|
|
|
def test_get_calculation_time_constraint():
|
|
"""GET /calculation/time-constraint — required_permission(READ); Management has READ"""
|
|
for user in USER_LIST:
|
|
res = requests.get(
|
|
f"{BASE_URL}/calculation/time-constraint",
|
|
headers=user_auth_headers(user["authorization_token"]),
|
|
)
|
|
assert res.status_code == 200, f"[{user['name']}] expected 200, got {res.status_code}: {res.text}"
|
|
|
|
def test_get_calculation_time_constraint_by_id():
|
|
"""GET /calculation/time-constraint/{calculation_id} — required_permission(READ); Management has READ
|
|
Query params: risk_cost (optional int, default 1)
|
|
"""
|
|
for user in USER_LIST:
|
|
res = requests.get(
|
|
f"{BASE_URL}/calculation/time-constraint/{CALCULATION_ID}?risk_cost={RISK_COST}",
|
|
headers=user_auth_headers(user["authorization_token"]),
|
|
)
|
|
assert res.status_code in (200, 404), f"[{user['name']}] expected 200/404, got {res.status_code}: {res.text}"
|
|
|
|
def test_post_calculation_time_constraint_simulation():
|
|
"""POST /calculation/time-constraint/{calculation_id}/simulation — required_permission(READ); Management has READ
|
|
Payload: intervalDays (int)
|
|
"""
|
|
payload = {
|
|
"intervalDays": 365,
|
|
}
|
|
for user in USER_LIST:
|
|
csrf_token = get_csrf_token("/calculation/time-constraint/simulation", user["authorization_token"])
|
|
headers = {**user_auth_headers(user["authorization_token"]), "X-CSRF-Token": csrf_token}
|
|
res = requests.post(
|
|
f"{BASE_URL}/calculation/time-constraint/{CALCULATION_ID}/simulation",
|
|
json=payload,
|
|
headers=headers,
|
|
)
|
|
print(f"[{user['name']}], got {res.status_code}, response: {res.text}")
|
|
assert res.status_code in (200, 201, 404), f"[{user['name']}] expected 200/201/404, got {res.status_code}"
|
|
|
|
def test_post_calculation_time_constraint_update():
|
|
"""POST /calculation/time-constraint/update/{calculation_id} — required_permission(EDIT); Management has no EDIT
|
|
Payload: List of { location_tag (str), name (str), is_included (bool) }. CSRF token required in production.
|
|
"""
|
|
payload = [
|
|
{"location_tag": LOCATION_TAG, "name": "Test Equipment", "is_included": True},
|
|
]
|
|
for user in USER_LIST:
|
|
csrf_token = get_csrf_token(f"/calculation/time-constraint/update/{CALCULATION_ID}", user["authorization_token"])
|
|
headers = {**user_auth_headers(user["authorization_token"]), "X-CSRF-Token": csrf_token}
|
|
res = requests.post(
|
|
f"{BASE_URL}/calculation/time-constraint/update/{CALCULATION_ID}",
|
|
json=payload,
|
|
headers=headers,
|
|
)
|
|
print(f"[{user['name']}], got {res.status_code}, response: {res.text}")
|
|
if user["name"] in NON_MANAGEMENT:
|
|
assert res.status_code in (200, 204, 404), f"[{user['name']}] expected 200/204/404, got {res.status_code}"
|
|
else:
|
|
assert res.status_code == 403, f"[{user['name']}] expected 403, got {res.status_code}"
|
|
|
|
|
|
# ─────────────────────────────────────────────
|
|
# Equipment Activities / Workscopes
|
|
# ─────────────────────────────────────────────
|
|
|
|
def test_get_equipment_workscopes():
|
|
"""GET /equipment-workscopes/{location_tag} — require_any_role blocks Management"""
|
|
for user in USER_LIST:
|
|
res = requests.get(
|
|
f"{BASE_URL}/equipment-workscopes/{LOCATION_TAG}",
|
|
headers=user_auth_headers(user["authorization_token"]),
|
|
)
|
|
assert res.status_code == 200, f"[{user['name']}] expected 200, got {res.status_code}"
|