New paste Repaste Download
============================= 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)
Filename: None. Size: 10kb. View raw, , hex, or download this file.

This paste expires on 2026-06-22 20:19:15.557257+00:00. Pasted through deprecated-web.