From 06d8db551e5a3238167900dbcafc293d59009660 Mon Sep 17 00:00:00 2001 From: maxachis Date: Mon, 5 Jan 2026 13:21:22 -0500 Subject: [PATCH] Set up initial draft --- .../annotate/all/get/queries/core.py | 3 +- .../endpoints/annotate/anonymous/get/query.py | 10 ++- src/api/endpoints/annotate/routes.py | 51 +++++++++++-- .../api/_helpers/RequestValidator.py | 14 ++-- .../api/annotate/all/test_happy_path.py | 10 ++- .../api/annotate/all/test_not_found.py | 2 +- .../api/annotate/all/test_offset.py | 38 ++++++++++ .../annotate/all/test_post_batch_filtering.py | 2 +- .../all/test_post_return_no_annotation.py | 63 ++++++++++++++++ .../api/annotate/all/test_url_filtering.py | 2 +- .../api/annotate/all/test_validation_error.py | 2 +- .../api/annotate/anonymous/helper.py | 33 +++++++-- .../api/annotate/anonymous/test_core.py | 4 +- .../api/annotate/anonymous/test_offset.py | 37 ++++++++++ .../test_post_return_no_annotation.py | 74 +++++++++++++++++++ 15 files changed, 312 insertions(+), 33 deletions(-) create mode 100644 tests/automated/integration/api/annotate/all/test_offset.py create mode 100644 tests/automated/integration/api/annotate/all/test_post_return_no_annotation.py create mode 100644 tests/automated/integration/api/annotate/anonymous/test_offset.py create mode 100644 tests/automated/integration/api/annotate/anonymous/test_post_return_no_annotation.py diff --git a/src/api/endpoints/annotate/all/get/queries/core.py b/src/api/endpoints/annotate/all/get/queries/core.py index a382f0b4..ad578253 100644 --- a/src/api/endpoints/annotate/all/get/queries/core.py +++ b/src/api/endpoints/annotate/all/get/queries/core.py @@ -22,7 +22,8 @@ def __init__( self, batch_id: int | None, user_id: int, - url_id: int | None = None + url_id: int | None = None, + offset: int | None = None ): super().__init__() self.batch_id = batch_id diff --git a/src/api/endpoints/annotate/anonymous/get/query.py b/src/api/endpoints/annotate/anonymous/get/query.py index c53726e1..f3dcaad9 100644 --- a/src/api/endpoints/annotate/anonymous/get/query.py +++ b/src/api/endpoints/annotate/anonymous/get/query.py @@ -23,10 +23,12 @@ class GetNextURLForAnonymousAnnotationQueryBuilder(QueryBuilderBase): def __init__( self, - session_id: UUID + session_id: UUID, + offset: int | None = None ): super().__init__() self.session_id = session_id + self.offset = offset async def run(self, session: AsyncSession) -> GetNextURLForAnonymousAnnotationResponse: base_cte = select( @@ -66,11 +68,17 @@ async def run(self, session: AsyncSession) -> GetNextURLForAnonymousAnnotationRe ) query = add_common_where_conditions(query) query = add_load_options(query) + if self.offset is not None: + offset = 0 + else: + offset = self.offset + query = ( # Sorting Priority query.order_by( *common_sorts(base_cte) ) + .offset(offset) # Limit to 1 result .limit(1) ) diff --git a/src/api/endpoints/annotate/routes.py b/src/api/endpoints/annotate/routes.py index 0af2afcb..61708d8b 100644 --- a/src/api/endpoints/annotate/routes.py +++ b/src/api/endpoints/annotate/routes.py @@ -1,7 +1,8 @@ import uuid +from http import HTTPStatus from uuid import UUID -from fastapi import APIRouter, Depends, Query +from fastapi import APIRouter, Depends, Query, HTTPException from src.api.dependencies import get_async_core from src.api.endpoints.annotate.all.get.models.agency import AgencyAnnotationResponseOuterInfo @@ -40,7 +41,11 @@ @annotate_router.get("/anonymous") async def get_next_url_for_all_annotations_anonymous( async_core: AsyncCore = Depends(get_async_core), - session_id: UUID | None = Query(description="The session id of the anonymous user.", default=None) + session_id: UUID | None = Query(description="The session id of the anonymous user.", default=None), + offset: int | None = Query( + description="Offset for annotation", + default=None + ) ) -> GetNextURLForAnonymousAnnotationResponse: # If session_id is not provided, generate new UUID if session_id is None: @@ -49,16 +54,23 @@ async def get_next_url_for_all_annotations_anonymous( ) return await async_core.adb_client.run_query_builder( - GetNextURLForAnonymousAnnotationQueryBuilder(session_id=session_id) + GetNextURLForAnonymousAnnotationQueryBuilder( + session_id=session_id, + offset=offset + ) ) @annotate_router.post("/anonymous/{url_id}") -async def annotate_url_for_all_annotations_and_get_next_url_anonymous( +async def annotate_url_for_all_annotations( url_id: int, all_annotation_post_info: AllAnnotationPostInfo, async_core: AsyncCore = Depends(get_async_core), - session_id: UUID = Query(description="The session id of the anonymous user") + session_id: UUID = Query(description="The session id of the anonymous user"), + get_next_url: bool = Query( + description="Get next URL after submitting this URL", + default=True + ) ) -> GetNextURLForAnonymousAnnotationResponse: await async_core.adb_client.run_query_builder( AddAnonymousAnnotationsToURLQueryBuilder( @@ -67,6 +79,11 @@ async def annotate_url_for_all_annotations_and_get_next_url_anonymous( session_id=session_id ) ) + if not get_next_url: + return GetNextURLForAnonymousAnnotationResponse( + next_annotation=None, + session_id=session_id + ) return await async_core.adb_client.run_query_builder( GetNextURLForAnonymousAnnotationQueryBuilder( @@ -81,8 +98,17 @@ async def get_next_url_for_all_annotations( access_info: AccessInfo = Depends(get_standard_user_access_info), async_core: AsyncCore = Depends(get_async_core), batch_id: int | None = batch_query, - anno_url_id: int | None = url_id_query + anno_url_id: int | None = url_id_query, + offset: int | None = Query( + description="Offset for annotation", + default=None + ) ) -> GetNextURLForAllAnnotationResponse: + if anno_url_id is not None and offset is not None: + raise HTTPException( + status_code=HTTPStatus.BAD_REQUEST, + detail="anno_url_id and offset query arguments cannot both be defined" + ) return await async_core.adb_client.get_next_url_for_all_annotations( batch_id=batch_id, user_id=access_info.user_id, @@ -90,13 +116,17 @@ async def get_next_url_for_all_annotations( ) @annotate_router.post("/all/{url_id}") -async def annotate_url_for_all_annotations_and_get_next_url( +async def annotate_url_for_all_annotations( url_id: int, all_annotation_post_info: AllAnnotationPostInfo, async_core: AsyncCore = Depends(get_async_core), access_info: AccessInfo = Depends(get_standard_user_access_info), batch_id: int | None = batch_query, - anno_url_id: int | None = url_id_query + anno_url_id: int | None = url_id_query, + get_next_url: bool = Query( + description="Get next URL after submitting this URL", + default=True + ) ) -> GetNextURLForAllAnnotationResponse: """ Post URL annotation and get next URL to annotate @@ -109,6 +139,11 @@ async def annotate_url_for_all_annotations_and_get_next_url( ) ) + if not get_next_url: + return GetNextURLForAllAnnotationResponse( + next_annotation=None + ) + return await async_core.adb_client.get_next_url_for_all_annotations( batch_id=batch_id, user_id=access_info.user_id, diff --git a/tests/automated/integration/api/_helpers/RequestValidator.py b/tests/automated/integration/api/_helpers/RequestValidator.py index b1bfbf20..704f55ae 100644 --- a/tests/automated/integration/api/_helpers/RequestValidator.py +++ b/tests/automated/integration/api/_helpers/RequestValidator.py @@ -396,14 +396,16 @@ async def get_current_task_status(self) -> GetTaskStatusResponseInfo: async def get_next_url_for_all_annotations( self, batch_id: int | None = None, - anno_url_id: int | None = None + anno_url_id: int | None = None, + offset: int | None = None ) -> GetNextURLForAllAnnotationResponse: params = {} update_if_not_none( target=params, source={ "batch_id": batch_id, - "anno_url_id": anno_url_id + "anno_url_id": anno_url_id, + "offset": offset } ) data = self.get( @@ -412,19 +414,21 @@ async def get_next_url_for_all_annotations( ) return GetNextURLForAllAnnotationResponse(**data) - async def post_all_annotations_and_get_next( + async def post_all_annotations( self, url_id: int, all_annotations_post_info: AllAnnotationPostInfo, batch_id: int | None = None, - anno_url_id: int | None = None + anno_url_id: int | None = None, + get_next_url: bool = True ) -> GetNextURLForAllAnnotationResponse: params = {} update_if_not_none( target=params, source={ "batch_id": batch_id, - "anno_url_id": anno_url_id + "anno_url_id": anno_url_id, + "get_next_url": get_next_url } ) data = self.post( diff --git a/tests/automated/integration/api/annotate/all/test_happy_path.py b/tests/automated/integration/api/annotate/all/test_happy_path.py index 8a62c3e8..996cdb61 100644 --- a/tests/automated/integration/api/annotate/all/test_happy_path.py +++ b/tests/automated/integration/api/annotate/all/test_happy_path.py @@ -15,15 +15,17 @@ from src.db.models.impl.annotation.record_type.user.user import AnnotationRecordTypeUser from src.db.models.impl.annotation.url_type.user.sqlalchemy import AnnotationURLTypeUser from src.db.models.impl.flag.url_validated.enums import URLType +from tests.helpers.api_test_helper import APITestHelper +from tests.helpers.data_creator.models.creation_info.county import CountyCreationInfo from tests.helpers.data_creator.models.creation_info.us_state import USStateCreationInfo from tests.helpers.setup.final_review.core import setup_for_get_next_url_for_final_review @pytest.mark.asyncio async def test_annotate_all( - api_test_helper, + api_test_helper: APITestHelper, pennsylvania: USStateCreationInfo, - allegheny_county: USStateCreationInfo, + allegheny_county: CountyCreationInfo, california: USStateCreationInfo, test_agency_id: int ): @@ -63,7 +65,7 @@ async def test_annotate_all( # Annotate the first and submit agency_id = await ath.db_data_creator.agency() - post_response_1 = await ath.request_validator.post_all_annotations_and_get_next( + post_response_1 = await ath.request_validator.post_all_annotations( url_id=url_mapping_1.url_id, all_annotations_post_info=AllAnnotationPostInfo( suggested_status=URLType.DATA_SOURCE, @@ -86,7 +88,7 @@ async def test_annotate_all( assert post_response_1.next_annotation.url_info.url_id == url_mapping_2.url_id # Upon submitting the second, confirm that no more URLs are returned through either POST or GET - post_response_2 = await ath.request_validator.post_all_annotations_and_get_next( + post_response_2 = await ath.request_validator.post_all_annotations( url_id=url_mapping_2.url_id, all_annotations_post_info=AllAnnotationPostInfo( suggested_status=URLType.NOT_RELEVANT, diff --git a/tests/automated/integration/api/annotate/all/test_not_found.py b/tests/automated/integration/api/annotate/all/test_not_found.py index 251b4c0e..534cf37f 100644 --- a/tests/automated/integration/api/annotate/all/test_not_found.py +++ b/tests/automated/integration/api/annotate/all/test_not_found.py @@ -24,7 +24,7 @@ async def test_not_found( db_data_creator=ath.db_data_creator, include_user_annotations=True ) - post_response_1 = await ath.request_validator.post_all_annotations_and_get_next( + post_response_1 = await ath.request_validator.post_all_annotations( url_id=setup_info_1.url_mapping.url_id, all_annotations_post_info=AllAnnotationPostInfo( suggested_status=URLType.DATA_SOURCE, diff --git a/tests/automated/integration/api/annotate/all/test_offset.py b/tests/automated/integration/api/annotate/all/test_offset.py new file mode 100644 index 00000000..48754e9b --- /dev/null +++ b/tests/automated/integration/api/annotate/all/test_offset.py @@ -0,0 +1,38 @@ +import pytest + +from src.api.endpoints.annotate.all.get.models.response import GetNextURLForAllAnnotationResponse +from src.db.dtos.url.mapping_.simple import SimpleURLMapping +from tests.helpers.api_test_helper import APITestHelper +from tests.helpers.setup.final_review.core import setup_for_get_next_url_for_final_review +from tests.helpers.setup.final_review.model import FinalReviewSetupInfo + + +@pytest.mark.asyncio +async def test_offset( + api_test_helper: APITestHelper, +): + """ + Test that offset functionality works as expected when getting + user annotations + """ + + ath = api_test_helper + + # Set up URLs + setup_info_1: FinalReviewSetupInfo = await setup_for_get_next_url_for_final_review( + db_data_creator=ath.db_data_creator, include_user_annotations=True + ) + url_mapping_1: SimpleURLMapping = setup_info_1.url_mapping + setup_info_2: FinalReviewSetupInfo = await setup_for_get_next_url_for_final_review( + db_data_creator=ath.db_data_creator, include_user_annotations=True + ) + url_mapping_2: SimpleURLMapping = setup_info_2.url_mapping + + + get_response_1: GetNextURLForAllAnnotationResponse = await ath.request_validator.get_next_url_for_all_annotations( + offset=1 + ) + + # Check that response is the second URL, rather than the first + assert get_response_1.next_annotation.url_info.url_id == url_mapping_2.url_id + diff --git a/tests/automated/integration/api/annotate/all/test_post_batch_filtering.py b/tests/automated/integration/api/annotate/all/test_post_batch_filtering.py index a770329d..f7812321 100644 --- a/tests/automated/integration/api/annotate/all/test_post_batch_filtering.py +++ b/tests/automated/integration/api/annotate/all/test_post_batch_filtering.py @@ -27,7 +27,7 @@ async def test_annotate_all_post_batch_filtering(api_test_helper): url_mapping_3 = setup_info_3.url_mapping # Submit the first annotation, using the third batch id, and receive the third URL - post_response_1 = await ath.request_validator.post_all_annotations_and_get_next( + post_response_1 = await ath.request_validator.post_all_annotations( url_id=url_mapping_1.url_id, batch_id=setup_info_3.batch_id, all_annotations_post_info=AllAnnotationPostInfo( diff --git a/tests/automated/integration/api/annotate/all/test_post_return_no_annotation.py b/tests/automated/integration/api/annotate/all/test_post_return_no_annotation.py new file mode 100644 index 00000000..548b7438 --- /dev/null +++ b/tests/automated/integration/api/annotate/all/test_post_return_no_annotation.py @@ -0,0 +1,63 @@ +import pytest + +from src.api.endpoints.annotate.all.post.models.agency import AnnotationPostAgencyInfo +from src.api.endpoints.annotate.all.post.models.location import AnnotationPostLocationInfo +from src.api.endpoints.annotate.all.post.models.name import AnnotationPostNameInfo +from src.api.endpoints.annotate.all.post.models.request import AllAnnotationPostInfo +from src.core.enums import RecordType +from src.db.models.impl.annotation.url_type.user.sqlalchemy import AnnotationURLTypeUser +from src.db.models.impl.flag.url_validated.enums import URLType +from tests.helpers.api_test_helper import APITestHelper +from tests.helpers.data_creator.models.creation_info.us_state import USStateCreationInfo +from tests.helpers.setup.final_review.core import setup_for_get_next_url_for_final_review + + +@pytest.mark.asyncio +async def test_post_annotate_return_no_annotation( + api_test_helper: APITestHelper, + pennsylvania: USStateCreationInfo, + test_agency_id: int +): + """ + If the `return_new_annotation` query arg is false, + do not return a new annotation. + """ + ath = api_test_helper + adb_client = ath.adb_client() + + # Set up URLs + setup_info_1 = await setup_for_get_next_url_for_final_review( + db_data_creator=ath.db_data_creator, include_user_annotations=True + ) + url_mapping_1 = setup_info_1.url_mapping + setup_info_2 = await setup_for_get_next_url_for_final_review( + db_data_creator=ath.db_data_creator, include_user_annotations=True + ) + url_mapping_2 = setup_info_2.url_mapping + + post_response_1 = await ath.request_validator.post_all_annotations( + url_id=url_mapping_1.url_id, + all_annotations_post_info=AllAnnotationPostInfo( + suggested_status=URLType.DATA_SOURCE, + record_type=RecordType.ACCIDENT_REPORTS, + agency_info=AnnotationPostAgencyInfo(agency_ids=[test_agency_id]), + location_info=AnnotationPostLocationInfo( + location_ids=[ + pennsylvania.location_id, + ] + ), + name_info=AnnotationPostNameInfo( + new_name="New Name" + ) + ), + get_next_url=False + ) + assert post_response_1.next_annotation is None + + # Check annotation still posted to DB + # Check URL Type Suggestions + all_relevance_suggestions: list[AnnotationURLTypeUser] = await adb_client.get_all(AnnotationURLTypeUser) + assert len(all_relevance_suggestions) == 3 + suggested_types: set[URLType] = {sugg.type for sugg in all_relevance_suggestions} + assert suggested_types == {URLType.DATA_SOURCE, URLType.NOT_RELEVANT} + diff --git a/tests/automated/integration/api/annotate/all/test_url_filtering.py b/tests/automated/integration/api/annotate/all/test_url_filtering.py index 6ca36cb5..233640f3 100644 --- a/tests/automated/integration/api/annotate/all/test_url_filtering.py +++ b/tests/automated/integration/api/annotate/all/test_url_filtering.py @@ -33,7 +33,7 @@ async def test_annotate_all_post_batch_filtering(api_test_helper: APITestHelper) ) assert get_response_2.next_annotation.url_info.url_id == url_mapping_3.url_id - post_response_3 = await ath.request_validator.post_all_annotations_and_get_next( + post_response_3 = await ath.request_validator.post_all_annotations( url_id=url_mapping_1.url_id, anno_url_id=url_mapping_3.url_id, all_annotations_post_info=AllAnnotationPostInfo( diff --git a/tests/automated/integration/api/annotate/all/test_validation_error.py b/tests/automated/integration/api/annotate/all/test_validation_error.py index db9e336a..56718555 100644 --- a/tests/automated/integration/api/annotate/all/test_validation_error.py +++ b/tests/automated/integration/api/annotate/all/test_validation_error.py @@ -21,7 +21,7 @@ async def test_annotate_all_validation_error(api_test_helper): url_mapping_1 = setup_info_1.url_mapping with pytest.raises(FailedValidationException) as e: - response = await ath.request_validator.post_all_annotations_and_get_next( + response = await ath.request_validator.post_all_annotations( url_id=url_mapping_1.url_id, all_annotations_post_info=AllAnnotationPostInfo( suggested_status=URLType.NOT_RELEVANT, diff --git a/tests/automated/integration/api/annotate/anonymous/helper.py b/tests/automated/integration/api/annotate/anonymous/helper.py index cb892091..92084764 100644 --- a/tests/automated/integration/api/annotate/anonymous/helper.py +++ b/tests/automated/integration/api/annotate/anonymous/helper.py @@ -2,19 +2,28 @@ from src.api.endpoints.annotate.all.post.models.request import AllAnnotationPostInfo from src.api.endpoints.annotate.anonymous.get.response import GetNextURLForAnonymousAnnotationResponse +from src.util.helper_functions import update_if_not_none from tests.automated.integration.api._helpers.RequestValidator import RequestValidator async def get_next_url_for_anonymous_annotation( request_validator: RequestValidator, - session_id: UUID | None = None + session_id: UUID | None = None, + offset: int | None = None, ) -> GetNextURLForAnonymousAnnotationResponse: url = "/annotate/anonymous" - if session_id is not None: - url += f"?session_id={session_id}" + params = {} + update_if_not_none( + target=params, + source={ + "session_id": session_id, + "offset": offset + } + ) data = request_validator.get( - url=url + url=url, + params=params ) return GetNextURLForAnonymousAnnotationResponse(**data) @@ -22,11 +31,21 @@ async def post_and_get_next_url_for_anonymous_annotation( request_validator: RequestValidator, url_id: int, all_annotation_post_info: AllAnnotationPostInfo, - session_id: UUID + session_id: UUID, + get_next_url: bool = True ) -> GetNextURLForAnonymousAnnotationResponse: - url = f"/annotate/anonymous/{url_id}?session_id={session_id}" + url = f"/annotate/anonymous/{url_id}" + params = {} + update_if_not_none( + target=params, + source={ + "session_id": session_id, + "get_next_url": get_next_url + } + ) data = request_validator.post( url=url, - json=all_annotation_post_info.model_dump(mode='json') + json=all_annotation_post_info.model_dump(mode='json'), + params=params ) return GetNextURLForAnonymousAnnotationResponse(**data) \ No newline at end of file diff --git a/tests/automated/integration/api/annotate/anonymous/test_core.py b/tests/automated/integration/api/annotate/anonymous/test_core.py index 65f18965..8fd71aef 100644 --- a/tests/automated/integration/api/annotate/anonymous/test_core.py +++ b/tests/automated/integration/api/annotate/anonymous/test_core.py @@ -166,6 +166,4 @@ async def test_annotate_anonymous( name_suggestions: list[AnnotationNameUserEndorsement] = await ddc.adb_client.get_all(AnnotationNameUserEndorsement) assert len(name_suggestions) == 1 annotation_name: AnnotationNameUserEndorsement = name_suggestions[0] - assert annotation_name.user_id == MOCK_USER_ID - - + assert annotation_name.user_id == MOCK_USER_ID \ No newline at end of file diff --git a/tests/automated/integration/api/annotate/anonymous/test_offset.py b/tests/automated/integration/api/annotate/anonymous/test_offset.py new file mode 100644 index 00000000..85c934dd --- /dev/null +++ b/tests/automated/integration/api/annotate/anonymous/test_offset.py @@ -0,0 +1,37 @@ +import pytest + +from src.api.endpoints.annotate.anonymous.get.response import GetNextURLForAnonymousAnnotationResponse +from src.db.dtos.url.mapping_.simple import SimpleURLMapping +from tests.automated.integration.api.annotate.anonymous.helper import get_next_url_for_anonymous_annotation +from tests.helpers.setup.final_review.core import setup_for_get_next_url_for_final_review +from tests.helpers.setup.final_review.model import FinalReviewSetupInfo + + +@pytest.mark.asyncio +async def test_offset( + api_test_helper, +): + + ath = api_test_helper + rv = ath.request_validator + + # Set up URLs + setup_info_1 = await setup_for_get_next_url_for_final_review( + db_data_creator=ath.db_data_creator, include_user_annotations=True + ) + url_mapping_1: SimpleURLMapping = setup_info_1.url_mapping + setup_info_2: FinalReviewSetupInfo = await setup_for_get_next_url_for_final_review( + db_data_creator=ath.db_data_creator, include_user_annotations=True + ) + url_mapping_2: SimpleURLMapping = setup_info_2.url_mapping + + get_response_1: GetNextURLForAnonymousAnnotationResponse = await get_next_url_for_anonymous_annotation( + rv, + offset=1 + ) + + # Check URL is second URL and not first + assert get_response_1.next_annotation.url_info.url_id == url_mapping_1.url_id + + + diff --git a/tests/automated/integration/api/annotate/anonymous/test_post_return_no_annotation.py b/tests/automated/integration/api/annotate/anonymous/test_post_return_no_annotation.py new file mode 100644 index 00000000..429ed6c1 --- /dev/null +++ b/tests/automated/integration/api/annotate/anonymous/test_post_return_no_annotation.py @@ -0,0 +1,74 @@ +import pytest + +from src.api.endpoints.annotate.all.post.models.agency import AnnotationPostAgencyInfo +from src.api.endpoints.annotate.all.post.models.location import AnnotationPostLocationInfo +from src.api.endpoints.annotate.all.post.models.name import AnnotationPostNameInfo +from src.api.endpoints.annotate.all.post.models.request import AllAnnotationPostInfo +from src.api.endpoints.annotate.anonymous.get.response import GetNextURLForAnonymousAnnotationResponse +from src.core.enums import RecordType +from src.db.dtos.url.mapping_.simple import SimpleURLMapping +from src.db.models.impl.annotation.url_type.user.sqlalchemy import AnnotationURLTypeUser +from src.db.models.impl.flag.url_validated.enums import URLType +from tests.automated.integration.api.annotate.anonymous.helper import get_next_url_for_anonymous_annotation, \ + post_and_get_next_url_for_anonymous_annotation +from tests.automated.integration.conftest import MOCK_USER_ID +from tests.helpers.data_creator.models.creation_info.us_state import USStateCreationInfo +from tests.helpers.setup.final_review.core import setup_for_get_next_url_for_final_review +from tests.helpers.setup.final_review.model import FinalReviewSetupInfo + + +@pytest.mark.asyncio +async def test_post_annotate_return_no_annotation( + api_test_helper, + pennsylvania: USStateCreationInfo, + test_agency_id: int +): + """ + If the `return_new_annotation` query arg is false, + do not return a new annotation. + """ + ath = api_test_helper + ddc = ath.db_data_creator + rv = ath.request_validator + + # Set up URLs + setup_info_1 = await setup_for_get_next_url_for_final_review( + db_data_creator=ath.db_data_creator, include_user_annotations=True + ) + url_mapping_1: SimpleURLMapping = setup_info_1.url_mapping + setup_info_2: FinalReviewSetupInfo = await setup_for_get_next_url_for_final_review( + db_data_creator=ath.db_data_creator, include_user_annotations=True + ) + url_mapping_2: SimpleURLMapping = setup_info_2.url_mapping + + get_response_1: GetNextURLForAnonymousAnnotationResponse = await get_next_url_for_anonymous_annotation(rv) + session_id = get_response_1.session_id + + post_response_1: GetNextURLForAnonymousAnnotationResponse = await post_and_get_next_url_for_anonymous_annotation( + rv, + url_mapping_1.url_id, + AllAnnotationPostInfo( + suggested_status=URLType.DATA_SOURCE, + record_type=RecordType.ACCIDENT_REPORTS, + agency_info=AnnotationPostAgencyInfo(agency_ids=[test_agency_id]), + location_info=AnnotationPostLocationInfo( + location_ids=[ + pennsylvania.location_id, + ] + ), + name_info=AnnotationPostNameInfo( + new_name="New Name" + ) + ), + session_id=session_id, + get_next_url=False + ) + + assert post_response_1.next_annotation is None + + url_types: list[AnnotationURLTypeUser] = await ddc.adb_client.get_all(AnnotationURLTypeUser) + assert len(url_types) == 3 + annotation_url_type: AnnotationURLTypeUser = url_types[-1] + assert annotation_url_type.user_id == MOCK_USER_ID + assert annotation_url_type.url_id == get_response_1.next_annotation.url_info.url_id + assert annotation_url_type.type == URLType.DATA_SOURCE