From 6b6d3c2e3f9f2a7f8bca9d56052781a781188999 Mon Sep 17 00:00:00 2001 From: marlowe-agent <314417787+marlowe-agent@users.noreply.github.com> Date: Wed, 12 Aug 2026 02:40:57 +0300 Subject: [PATCH 1/2] fix: prevent duplicate names in subjects test fixture random_part could be zero-length, so two subjects sharing a prefix/suffix within one batch could get an identical name. Postgres has no defined tie-break for ORDER BY on equal names, causing test_subject_autocompleting to flake on the resulting ambiguous order. Added a per-item unique letter to guarantee distinct names. --- tests/autocomplete/conftest.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/autocomplete/conftest.py b/tests/autocomplete/conftest.py index 403307d4..7b2b22b9 100644 --- a/tests/autocomplete/conftest.py +++ b/tests/autocomplete/conftest.py @@ -107,12 +107,13 @@ def generate_subject_name( faker: Faker, prefix: str, suffix: str, + unique_letter: str, ) -> str: random_part: str = faker.bothify( "?" * faker.random_int(min=0, max=90), letters=quarter_of_ascii_letters_any_case(3), ) - return prefix + random_part + suffix + return prefix + random_part + unique_letter + suffix @pytest.fixture() @@ -125,6 +126,7 @@ async def subjects( odd_subject_name_suffix: str, ) -> AsyncIterator[list[Subject]]: subjects: list[Subject] = [] + unique_letters = quarter_of_ascii_letters_any_case(3) async with active_session(): for i in range(SUBJECT_LIST_SIZE): subjects.append( @@ -137,6 +139,7 @@ async def subjects( if i % 2 == 0 else odd_subject_name_suffix ), + unique_letter=unique_letters[i], ), tutor_id=None if i % 2 == 0 else tutor_user_id, ) From e667e04be59c01e1cd19da0aef4d7a2b09e29f44 Mon Sep 17 00:00:00 2001 From: marlowe-agent <314417787+marlowe-agent@users.noreply.github.com> Date: Wed, 12 Aug 2026 02:41:12 +0300 Subject: [PATCH 2/2] fix: add id tiebreaker to promocode listing order created_at is a client-side timestamp (datetime.now()) with no uniqueness guarantee, so two promocodes created in the same batch could tie. Postgres has no defined tie-break for ORDER BY on equal values, causing test_promocodes_listing to flake on the resulting ambiguous order. Added id as a secondary sort key to the query and the test's own expected-order sort. --- app/subscriptions/routes/promocodes_mub.py | 5 ++++- tests/subscriptions/functional/test_promocodes_list_mub.py | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/app/subscriptions/routes/promocodes_mub.py b/app/subscriptions/routes/promocodes_mub.py index 4875ff3a..7e2c2781 100644 --- a/app/subscriptions/routes/promocodes_mub.py +++ b/app/subscriptions/routes/promocodes_mub.py @@ -23,7 +23,10 @@ async def list_promocodes( limit: Annotated[int, Query(ge=1, le=100)] = 100, ) -> Sequence[Promocode]: return await Promocode.find_paginated_by_kwargs( - offset, limit, Promocode.created_at.desc() + offset, + limit, + Promocode.created_at.desc(), + Promocode.id.desc(), ) diff --git a/tests/subscriptions/functional/test_promocodes_list_mub.py b/tests/subscriptions/functional/test_promocodes_list_mub.py index 0117c4f1..ac030ee4 100644 --- a/tests/subscriptions/functional/test_promocodes_list_mub.py +++ b/tests/subscriptions/functional/test_promocodes_list_mub.py @@ -30,7 +30,10 @@ async def promocodes( for i in range(PROMOCODES_LIST_SIZE) ] - promocodes.sort(key=lambda promocode: promocode.created_at, reverse=True) + promocodes.sort( + key=lambda promocode: (promocode.created_at, promocode.id), + reverse=True, + ) yield promocodes