| ============================= test session starts ==============================
|
| platform linux -- Python 3.12.3, pytest-9.0.3, pluggy-1.6.0 -- /home/david/Opyris/.venv/bin/python3
|
| rootdir: /home/david/Opyris
|
| configfile: pyproject.toml
|
| plugins: asyncio-1.4.0, cov-5.0.0, anyio-4.13.0
|
| asyncio: mode=Mode.STRICT, debug=False, asyncio_default_fixture_loop_scope=None, asyncio_default_test_loop_scope=function
|
| collected 673 items
|
|
|
| tests/test_admin_chat_helpers.py ..... [ 0%]
|
| tests/test_app_admin.py ...... [ 1%]
|
| tests/test_app_auth_account.py .... [ 2%]
|
| tests/test_app_core.py .. [ 2%]
|
| tests/test_app_integrations_notifications.py .F..F... [ 3%]
|
| tests/test_app_observability.py ...... [ 4%]
|
| tests/test_app_reports_payroll.py ..F....... [ 6%]
|
| tests/test_app_schedule_flows.py ...F............. [ 8%]
|
| tests/test_app_signup.py ......... [ 9%]
|
| tests/test_app_startup.py ......... [ 11%]
|
| tests/test_auth_router.py .............. [ 13%]
|
| tests/test_config_weather.py ... [ 13%]
|
| tests/test_core_service_helpers.py ....... [ 14%]
|
| tests/test_email_passwords_time_off.py .......... [ 16%]
|
| tests/test_employee_payroll.py ............. [ 18%]
|
| tests/test_employee_schedule_reports.py ..........
|
|
|
| =================================== FAILURES ===================================
|
| _______ test_chat_user_listing_sorts_by_latest_message_and_tracks_unread _______
|
|
|
| client = <starlette.testclient.TestClient object at 0x7e57c4013500>
|
|
|
| def test_chat_user_listing_sorts_by_latest_message_and_tracks_unread(client):
|
| """Chat contact list includes message summaries, date source, and unread state."""
|
| manager_user = register_user(
|
| client,
|
| "manager-chat-list@example.com",
|
| "Secret123!",
|
| UserRole.MANAGER,
|
| )
|
| older_user = register_user(
|
| client,
|
| "older-chat-contact@example.com",
|
| "Secret123!",
|
| UserRole.EMPLOYEE,
|
| )
|
| newer_user = register_user(
|
| client,
|
| "newer-chat-contact@example.com",
|
| "Secret123!",
|
| UserRole.EMPLOYEE,
|
| )
|
| manager_token = login(client, "manager-chat-list@example.com", "Secret123!")
|
| older_token = login(client, "older-chat-contact@example.com", "Secret123!")
|
| newer_token = login(client, "newer-chat-contact@example.com", "Secret123!")
|
|
|
| feature_response = client.put(
|
| "/tenants/me",
|
| json={"feature_flags": {"chats_enabled": True}},
|
| headers=auth_headers(manager_token),
|
| )
|
| assert feature_response.status_code == 200
|
|
|
| older_thread = client.post(
|
| "/chats/threads",
|
| json={"user_id": manager_user["id"]},
|
| headers=auth_headers(older_token),
|
| )
|
| assert older_thread.status_code == 200
|
| older_message = client.post(
|
| f"/chats/threads/{older_thread.json()['thread_id']}/messages",
|
| json={"message": "Older chat message"},
|
| headers=auth_headers(older_token),
|
| )
|
| assert older_message.status_code == 200
|
|
|
| newer_thread = client.post(
|
| "/chats/threads",
|
| json={"user_id": manager_user["id"]},
|
| headers=auth_headers(newer_token),
|
| )
|
| > assert newer_thread.status_code == 200
|
| E assert 404 == 200
|
| E + where 404 = <Response [404 Not Found]>.status_code
|
|
|
| tests/test_app_integrations_notifications.py:155: AssertionError
|
| ----------------------------- Captured stderr call -----------------------------
|
| 2026-06-15 16:18:31,177 INFO request request_id=43135b5206e7495690cd6d9ec0fef021 method=POST path=/auth/register status=201 duration_ms=177.24 tenant=default client=testclient
|
| 2026-06-15 16:18:31,357 INFO request request_id=4e85946188c14f7ebf63445b11ee78fd method=POST path=/auth/register status=201 duration_ms=176.83 tenant=default client=testclient
|
| 2026-06-15 16:18:31,536 INFO request request_id=057f1a6f87a2423c93ae1691ebe50338 method=POST path=/auth/register status=201 duration_ms=175.14 tenant=default client=testclient
|
| 2026-06-15 16:18:31,713 INFO user_login user_id=45 tenant=default method=password
|
| 2026-06-15 16:18:31,715 INFO request request_id=8300db16e1004fe99995b59dfbb25267 method=POST path=/auth/token status=200 duration_ms=174.65 tenant=default client=testclient
|
| 2026-06-15 16:18:31,894 INFO user_login user_id=46 tenant=default method=password
|
| 2026-06-15 16:18:31,895 INFO request request_id=b33d825fbc0c4531bbd611ab2a231977 method=POST path=/auth/token status=200 duration_ms=176.56 tenant=default client=testclient
|
| 2026-06-15 16:18:32,075 INFO user_login user_id=48 tenant=default method=password
|
| 2026-06-15 16:18:32,076 INFO request request_id=a6234c011e0446df8570b79d05563bb5 method=POST path=/auth/token status=200 duration_ms=176.79 tenant=default client=testclient
|
| 2026-06-15 16:18:32,097 INFO request request_id=afc775189c614a1883fcd09d583e5b42 method=PUT path=/tenants/me status=200 duration_ms=17.26 tenant=default client=testclient
|
| 2026-06-15 16:18:32,116 INFO request request_id=7c2c365d63ed4b62874d74d700dd31d8 method=POST path=/chats/threads status=200 duration_ms=15.57 tenant=default client=testclient
|
| 2026-06-15 16:18:32,139 INFO request request_id=172abae097274317b2963d981253eb8c method=POST path=/chats/threads/5/messages status=200 duration_ms=18.23 tenant=default client=testclient
|
| 2026-06-15 16:18:32,150 INFO request request_id=cc94fee4a28f49718e1d5190688294a0 method=POST path=/chats/threads status=404 duration_ms=8.25 tenant=default client=testclient
|
| __ test_external_api_keys_manage_scoped_access_to_external_schedule_endpoints __
|
|
|
| client = <starlette.testclient.TestClient object at 0x7e57c40ecb00>
|
|
|
| def test_external_api_keys_manage_scoped_access_to_external_schedule_endpoints(client):
|
| """Managers should be able to issue scoped external keys for integrations."""
|
| strong_password = "Secret123!"
|
| register_user(
|
| client,
|
| "manager-integrations@example.com",
|
| strong_password,
|
| UserRole.MANAGER,
|
| )
|
| employee_user = register_user(
|
| client,
|
| "employee-integrations@example.com",
|
| strong_password,
|
| UserRole.EMPLOYEE,
|
| )
|
| manager_token = login(client, "manager-integrations@example.com", strong_password)
|
|
|
| with app_database.SessionLocal() as db:
|
| tenant = db.query(Tenant).filter(Tenant.slug == TENANT_SLUG).first()
|
| tenant.country = "Canada"
|
| tenant.region = "ON"
|
| db.commit()
|
|
|
| department = client.post(
|
| "/managers/departments",
|
| json={"name": "Integrations", "description": "External API coverage"},
|
| headers=auth_headers(manager_token),
|
| ).json()
|
|
|
| template = client.post(
|
| "/managers/shift-templates",
|
| json={
|
| "department_id": department["id"],
|
| "name": "Integration Shift",
|
| "shift_type": "Day",
|
| "start_time": "09:00:00",
|
| "end_time": "17:00:00",
|
| "headcount": 1,
|
| "min_experience_level": 1,
|
| "days_of_week": [2],
|
| },
|
| headers=auth_headers(manager_token),
|
| ).json()
|
|
|
| employee_profile = client.post(
|
| "/managers/employees",
|
| json={
|
| "user_id": employee_user["id"],
|
| "employee_name": "Integration Employee",
|
| "employee_identifier": "EMP-INTEGRATION",
|
| "employment_title": "Specialist",
|
| "department_name": "Integrations",
|
| "vacation_days_allotted": 10,
|
| "vacation_days_remaining": 10,
|
| "vacation_days_approved": 0,
|
| "sick_days_allotted": 5,
|
| "sick_days_remaining": 5,
|
| "pay_rate": 30.0,
|
| "experience_level": 2,
|
| "shift_swaps_requested": 0,
|
| "preferred_name": None,
|
| "pronouns": None,
|
| "shift_blackouts": "",
|
| "contact_information": "555-1122",
|
| "vacation_days_requested": 0,
|
| },
|
| headers=auth_headers(manager_token),
|
| ).json()
|
|
|
| shift_date = date(2026, 7, 8)
|
| assignment = client.post(
|
| "/managers/schedule/assignments",
|
| json={
|
| "shift_date": str(shift_date),
|
| "template_id": template["id"],
|
| "employee_id": employee_profile["id"],
|
| },
|
| headers=auth_headers(manager_token),
|
| ).json()
|
|
|
| with app_database.SessionLocal() as db:
|
| tenant = db.query(Tenant).filter(Tenant.slug == TENANT_SLUG).first()
|
| with tenant_session_scope(tenant) as tenant_db:
|
| tenant_db.add_all(
|
| [
|
| ClockEvent(
|
| employee_id=employee_profile["id"],
|
| event_type=ClockEventType.CLOCK_IN,
|
| shift_assignment_id=assignment["id"],
|
| occurred_at=datetime(2026, 7, 8, 9, 0, tzinfo=timezone.utc),
|
| ),
|
| ClockEvent(
|
| employee_id=employee_profile["id"],
|
| !!!!!!!!!!!!!!!!!!!!!!!!!!!!!! KeyboardInterrupt !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
| /home/david/Opyris/.venv/lib/python3.12/site-packages/bcrypt/__init__.py:101: KeyboardInterrupt
|
| (to show a full traceback on KeyboardInterrupt use --full-trace)
|