From 3f37302a12b9891150fb9e4202ca937937465d28 Mon Sep 17 00:00:00 2001 From: Jacob Brown Date: Mon, 3 Nov 2025 17:43:57 -0700 Subject: [PATCH 01/16] WIP: implement well core information feature tests --- tests/features/steps/well-core-information.py | 194 ++++++++++++++++++ 1 file changed, 194 insertions(+) create mode 100644 tests/features/steps/well-core-information.py diff --git a/tests/features/steps/well-core-information.py b/tests/features/steps/well-core-information.py new file mode 100644 index 000000000..02fca377f --- /dev/null +++ b/tests/features/steps/well-core-information.py @@ -0,0 +1,194 @@ +from behave import when, then + + +@when("the user retrieves the well by ID via path parameter") +def step_impl(context): + well_id = 1 + context.response = context.client.get(f"/thing/water-well/{well_id}") + + +@then("the system should return a 200 status code") +def step_impl(context): + assert context.response.status_code == 200 + + +@then("the response should be in JSON format") +def step_impl(context): + assert context.response.headers["Content-Type"] == "application/json" + + +# ------------------------------------------------------------------------------ +# Well names and projects +# ------------------------------------------------------------------------------ + + +@then("the response should include the well name (point ID) (i.e. NM-1234)") +def step_impl(context): + data = context.response.json() + assert data["name"] == "WL-0001" + + +# TODO: this needs to be added to the ThingResponse +@then("the response should include the project(s) or group(s) associated with the well") +def step_impl(context): + data = context.response.json() + assert data["groups"] == ["Collabnet"] + + +# TODO: this needs to be added to the model, schema, and test data +@then( + "the response should include the site name(s) for the well (i.e. John Smith House Well)" +) +def step_impl(context): + data = context.response.json() + assert data["site_name"] == "John Smith House Well" + + +# ------------------------------------------------------------------------------ +# Well Purpose and Status and Monitoring Status +# ------------------------------------------------------------------------------ + + +# TODO: add to test data +@then("the response should include the purpose of the well (current use)") +def step_impl(context): + data = context.response.json() + assert data["well_purposes"] == ["Domestic", "Irrigation"] + + +# TODO: this needs to be added to the ThingResponse and thing_helper via StatusHistory +@then( + "the response should include the well status of the well as the status of the hole in the ground" +) +def step_impl(context): + data = context.response.json() + assert data["well_status"] == "Active" + + +# TODO: this needs to be added to the model, schema, and test data +@then("the response should include the monitoring frequency (new field)") +def step_impl(context): + data = context.response.json() + assert data["monitoring_frequency"] == "Monthly" + + +# TODO: this needs to be added to the model, schema, and test data +@then( + "the response should include whether the well is currently being monitored with status text if applicable (from previous status field)" +) +def step_impl(context): + data = context.response.json() + assert data["is_being_monitored"] == True + assert data["monitoring_status"] == "Active" + + +# ------------------------------------------------------------------------------ +# Data Lifecycle and Public Visibility +# ------------------------------------------------------------------------------ + + +@then("the response should include the release status of the well record") +def step_impl(context): + data = context.response.json() + assert data["release_status"] == "draft" + + +# ------------------------------------------------------------------------------ +# Well Physical Properties +# ------------------------------------------------------------------------------ + + +@then("the response should include the hole depth in feet") +def step_impl(context): + data = context.response.json() + assert data["hole_depth"] == 10 + + +@then("the response should include the well depth in feet") +def step_impl(context): + data = context.response.json() + assert data["well_depth"] == 10 + + +# TODO: this needs to be added to the model, schema, and test data +@then("the response should include the source of the well depth information") +def step_impl(context): + data = context.response.json() + assert data["well_depth_source"] == "Measured" + + +# ------------------------------------------------------------------------------ +# Measuring Point Information +# ------------------------------------------------------------------------------ + +# ------------------------------------------------------------------------------ +# Location Information +# ------------------------------------------------------------------------------ + + +@then( + "the response should include the latitude and longitude in decimal degrees with datum WGS84" +) +def step_impl(context): + data = context.response.json() + assert ( + data["current_location"]["geographic_coordinate_system"]["latitude"] + == 33.809665 + ) + assert ( + data["current_location"]["geographic_coordinate_system"]["longitude"] + == -107.949533 + ) + assert ( + data["current_location"]["geographic_coordinate_system"]["horizontal_datum"] + == "WGS84" + ) + + +@then("the response should include the UTM coordinates with datum NAD83") +def step_impl(context): + data = context.response.json() + assert data["current_location"]["projected_coordinate_system"]["easting"] == 623000 + assert ( + data["current_location"]["projected_coordinate_system"]["northing"] == 3745000 + ) + assert data["current_location"]["projected_coordinate_system"]["utm_zone"] == 13 + assert ( + data["current_location"]["projected_coordinate_system"]["horizontal_datum"] + == "NAD83" + ) + + +@then("the response should include the elevation in feet with vertical datum NAVD88") +def step_impl(context): + data = context.response.json() + assert data["current_location"]["elevation"] == 2464.9 + assert data["current_location"]["vertical_datum"] == "NAVD88" + + +@then( + "the response should include the elevation method (i.e. interpolated from digital elevation model)" +) +def step_impl(context): + data = context.response.json() + assert ( + data["current_location"]["elevation_method"] + == "Interpolated from digital elevation model" + ) + + +# ------------------------------------------------------------------------------ +# Alternate Identifiers +# ------------------------------------------------------------------------------ + + +# TODO: This needs to be added to the model, schema, and test data +@then( + "the response should include any alternate IDs for the well like the USGS site number or the OSE well ID and OSE well tag ID" +) +def step_impl(context): + data = context.response.json() + assert "alternate_ids" in data + assert "usgs_site_number" in data["alternate_ids"] + assert "ose_well_id" in data["alternate_ids"] + assert "ose_well_tag_id" in data["alternate_ids"] From deee08a5ad2c3e7d746fa482472c6e63653248ef Mon Sep 17 00:00:00 2001 From: Jacob Brown Date: Mon, 3 Nov 2025 17:55:03 -0700 Subject: [PATCH 02/16] WIP: add well purposes to feature testing data --- tests/features/steps/api_fixture.py | 7 +++++++ tests/features/steps/well-core-information.py | 12 ++++++------ 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/tests/features/steps/api_fixture.py b/tests/features/steps/api_fixture.py index 041f6ed59..c6ba0eb9e 100644 --- a/tests/features/steps/api_fixture.py +++ b/tests/features/steps/api_fixture.py @@ -36,6 +36,7 @@ LexiconTerm, Group, GroupThingAssociation, + WellPurpose, ) from db.engine import session_ctx, engine @@ -88,6 +89,12 @@ def add_well(location, wid): assoc.effective_start = "2025-02-01T00:00:00Z" session.add(assoc) session.commit() + + for wp in ["Irrigation", "Domestic"]: + well_purpose = WellPurpose(thing=well, purpose=wp) + session.add(well_purpose) + session.commit() + return well diff --git a/tests/features/steps/well-core-information.py b/tests/features/steps/well-core-information.py index 02fca377f..7b4acdd59 100644 --- a/tests/features/steps/well-core-information.py +++ b/tests/features/steps/well-core-information.py @@ -36,6 +36,7 @@ def step_impl(context): # TODO: this needs to be added to the model, schema, and test data +# TODO: how do we rectify this with the name field? Is there a better way to name this? @then( "the response should include the site name(s) for the well (i.e. John Smith House Well)" ) @@ -49,11 +50,10 @@ def step_impl(context): # ------------------------------------------------------------------------------ -# TODO: add to test data @then("the response should include the purpose of the well (current use)") def step_impl(context): data = context.response.json() - assert data["well_purposes"] == ["Domestic", "Irrigation"] + assert sorted(data["well_purposes"]) == sorted(["Domestic", "Irrigation"]) # TODO: this needs to be added to the ThingResponse and thing_helper via StatusHistory @@ -66,6 +66,7 @@ def step_impl(context): # TODO: this needs to be added to the model, schema, and test data +# TODO: the monitoring frequency field needs to be added to lexicon @then("the response should include the monitoring frequency (new field)") def step_impl(context): data = context.response.json() @@ -126,6 +127,7 @@ def step_impl(context): # ------------------------------------------------------------------------------ +# TODO: this needs to be added to the LocationResponse schema @then( "the response should include the latitude and longitude in decimal degrees with datum WGS84" ) @@ -145,6 +147,7 @@ def step_impl(context): ) +# TODO: this needs to be added to the LocationResponse schema @then("the response should include the UTM coordinates with datum NAD83") def step_impl(context): data = context.response.json() @@ -171,10 +174,7 @@ def step_impl(context): ) def step_impl(context): data = context.response.json() - assert ( - data["current_location"]["elevation_method"] - == "Interpolated from digital elevation model" - ) + assert data["current_location"]["elevation_method"] == "Survey-grade GPS" # ------------------------------------------------------------------------------ From 7fdf2df52bde6c6017bcdaf35ccf36e5063392ce Mon Sep 17 00:00:00 2001 From: Jacob Brown Date: Tue, 4 Nov 2025 11:38:44 -0700 Subject: [PATCH 03/16] WIP: well core information behave test development --- tests/features/steps/well-core-information.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/tests/features/steps/well-core-information.py b/tests/features/steps/well-core-information.py index 7b4acdd59..654742e72 100644 --- a/tests/features/steps/well-core-information.py +++ b/tests/features/steps/well-core-information.py @@ -122,6 +122,22 @@ def step_impl(context): # Measuring Point Information # ------------------------------------------------------------------------------ + +# TODO: this needs to be added to the model, schema, and test data +@then("the response should include the description of the measuring point") +def step_impl(context): + data = context.response.json() + assert data["measuring_point_description"] == "Top of Casing" + + +# TODO: this needs to be added to the model, schema, and test data +@then("the response should include the measuring point height in feet") +def step_impl(context): + data = context.response.json() + assert data["measuring_point_height"] == 4 + assert data["measuring_point_height_unit"] == "ft" + + # ------------------------------------------------------------------------------ # Location Information # ------------------------------------------------------------------------------ From 54abcab9a961bfc1e17681b9f4a6dcb64581f5c1 Mon Sep 17 00:00:00 2001 From: Jacob Brown Date: Tue, 4 Nov 2025 11:55:39 -0700 Subject: [PATCH 04/16] WIP: id link testing --- tests/features/steps/well-core-information.py | 20 +++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/tests/features/steps/well-core-information.py b/tests/features/steps/well-core-information.py index 654742e72..584a033f8 100644 --- a/tests/features/steps/well-core-information.py +++ b/tests/features/steps/well-core-information.py @@ -28,6 +28,7 @@ def step_impl(context): assert data["name"] == "WL-0001" +# TODO: a new endpoint named /thing/{thing_id}/group needs to be added to the API # TODO: this needs to be added to the ThingResponse @then("the response should include the project(s) or group(s) associated with the well") def step_impl(context): @@ -103,12 +104,14 @@ def step_impl(context): def step_impl(context): data = context.response.json() assert data["hole_depth"] == 10 + assert data["hole_depth_unit"] == "ft" @then("the response should include the well depth in feet") def step_impl(context): data = context.response.json() assert data["well_depth"] == 10 + assert data["well_depth_unit"] == "ft" # TODO: this needs to be added to the model, schema, and test data @@ -198,13 +201,18 @@ def step_impl(context): # ------------------------------------------------------------------------------ -# TODO: This needs to be added to the model, schema, and test data +# TODO: This needs to be added to the test data +# TODO: id link schema needs to use lexicon enums for relation and alternate_organization @then( "the response should include any alternate IDs for the well like the USGS site number or the OSE well ID and OSE well tag ID" ) def step_impl(context): - data = context.response.json() - assert "alternate_ids" in data - assert "usgs_site_number" in data["alternate_ids"] - assert "ose_well_id" in data["alternate_ids"] - assert "ose_well_tag_id" in data["alternate_ids"] + response = context.client.get("/thing/1/id-link") + data = response.json() + for item in data["items"]: + if item["alternate_organization"] == "USGS": + assert item["relation"] == "same as" + assert item["alternate_id"] == "12345678" + elif item["alternate_organization"] == "NMOSE": + assert item["relation"] == "same as" + assert item["alternate_id"] == "OSE-0001" From 819f7ceebad844fe336581b0f4317dc35306f457 Mon Sep 17 00:00:00 2001 From: Jacob Brown Date: Tue, 4 Nov 2025 12:58:34 -0700 Subject: [PATCH 05/16] WIP: well core information behave test --- tests/features/steps/well-core-information.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/tests/features/steps/well-core-information.py b/tests/features/steps/well-core-information.py index 584a033f8..c38e89812 100644 --- a/tests/features/steps/well-core-information.py +++ b/tests/features/steps/well-core-information.py @@ -7,9 +7,10 @@ def step_impl(context): context.response = context.client.get(f"/thing/water-well/{well_id}") -@then("the system should return a 200 status code") -def step_impl(context): - assert context.response.status_code == 200 +# can only be defined once, but recorded here for reference +# @then("the system should return a 200 status code") +# def step_impl(context): +# assert context.response.status_code == 200 @then("the response should be in JSON format") @@ -181,10 +182,13 @@ def step_impl(context): ) +# TODO: elevation should be returned in ft, not meters, conversion should occur in schema +# TODO: add elevation_unit: str = "ft" to LocationResponse schema @then("the response should include the elevation in feet with vertical datum NAVD88") def step_impl(context): data = context.response.json() assert data["current_location"]["elevation"] == 2464.9 + assert data["current_location"]["elevation_unit"] == "ft" assert data["current_location"]["vertical_datum"] == "NAVD88" From b777dc5b9929764d3b3b2e87648c9717e055ce82 Mon Sep 17 00:00:00 2001 From: Jacob Brown Date: Tue, 4 Nov 2025 13:44:46 -0700 Subject: [PATCH 06/16] WIP: erase and rebuild db each time --- tests/features/steps/api_fixture.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/tests/features/steps/api_fixture.py b/tests/features/steps/api_fixture.py index fe08edd04..b754fea69 100644 --- a/tests/features/steps/api_fixture.py +++ b/tests/features/steps/api_fixture.py @@ -37,7 +37,6 @@ Thing, LocationThingAssociation, Sensor, - LexiconTerm, Group, GroupThingAssociation, WellPurpose, @@ -45,11 +44,11 @@ from db.engine import session_ctx with session_ctx() as session: - if session.query(LexiconTerm).count() == 0: - erase_and_rebuild_db(session) + # TODO: use a test fixture instead of rebuilding the DB here + erase_and_rebuild_db(session) - init_lexicon() - init_parameter() + init_lexicon() + init_parameter() def add_location(lid): From 1486fd953d1c138bc85237874a32ad2c1327e00d Mon Sep 17 00:00:00 2001 From: Jacob Brown Date: Tue, 4 Nov 2025 14:36:26 -0700 Subject: [PATCH 07/16] feat: note reused statements and places for fixtures --- tests/features/steps/well-location.py | 1 + tests/features/steps/well-notes.py | 3 +++ tests/features/steps/well-sensor-deployment.py | 2 ++ 3 files changed, 6 insertions(+) diff --git a/tests/features/steps/well-location.py b/tests/features/steps/well-location.py index 54f228e43..665fcdf3c 100644 --- a/tests/features/steps/well-location.py +++ b/tests/features/steps/well-location.py @@ -17,6 +17,7 @@ from behave.runner import Context +# TODO: should this use fixtures to populate and access data from the database? @given("the system has valid well and location data in the database") def step_impl(context): context.database = { diff --git a/tests/features/steps/well-notes.py b/tests/features/steps/well-notes.py index a85045880..abf65272d 100644 --- a/tests/features/steps/well-notes.py +++ b/tests/features/steps/well-notes.py @@ -26,17 +26,20 @@ def step_impl(context): context.response = context.client.get("thing/water-well/9999") +# TODO: this is a commonly used step, should it be moved to a common steps file? @then("the system should return a 200 status code") def step_impl(context): assert context.response.status_code == 200 +# TODO: this is a commonly used step, should it be moved to a common steps file? @then("the system should return a 404 status code") def step_impl(context): print(context.response.status_code, context.response.text) assert context.response.status_code == 404 +# TODO: this is a commonly used step, should it be moved to a common steps file? @then("the system should return a response in JSON format") def step_impl(context): assert context.response.headers["Content-Type"] == "application/json" diff --git a/tests/features/steps/well-sensor-deployment.py b/tests/features/steps/well-sensor-deployment.py index fef467888..b7d023fdc 100644 --- a/tests/features/steps/well-sensor-deployment.py +++ b/tests/features/steps/well-sensor-deployment.py @@ -25,6 +25,7 @@ # ----------------------------------------------------------------------------- +# TODO: should this use fixtures to populate and access data from the database? @given("the system has valid well and deployment data in the database") def step_impl_valid_data(context: Context): """ @@ -48,6 +49,7 @@ def step_impl_valid_data(context: Context): context.api_connected = True +# TODO: this step could be moved to a common steps file if reused elsewhere @given("the user is authenticated as a field technician") def step_impl_authenticated_user(context: Context): """Simulates user authentication.""" From c2df7aff204af4141029051a8b73a33f5206ad80 Mon Sep 17 00:00:00 2001 From: Jacob Brown Date: Tue, 4 Nov 2025 16:24:28 -0700 Subject: [PATCH 08/16] WIP: note taking for well core information --- tests/features/steps/well-core-information.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/features/steps/well-core-information.py b/tests/features/steps/well-core-information.py index c38e89812..06b86ff6c 100644 --- a/tests/features/steps/well-core-information.py +++ b/tests/features/steps/well-core-information.py @@ -69,6 +69,8 @@ def step_impl(context): # TODO: this needs to be added to the model, schema, and test data # TODO: the monitoring frequency field needs to be added to lexicon +# the monitoring status field from NM_Aquifer contains a multitude of information, like having three codes (6AC), so the transfer and model/schemas will need to take this into account +# could create descriptor table like WellPurpose and CasingMaterial @then("the response should include the monitoring frequency (new field)") def step_impl(context): data = context.response.json() @@ -76,6 +78,8 @@ def step_impl(context): # TODO: this needs to be added to the model, schema, and test data +# the monitoring status field from NM_Aquifer contains a multitude of information, like having three codes (6AC), so the transfer and model/schemas will need to take this into account +# could create descriptor table like WellPurpose and CasingMaterial @then( "the response should include whether the well is currently being monitored with status text if applicable (from previous status field)" ) From e8c944236f89da98e9e03b4d0f823e7d67f1a6c0 Mon Sep 17 00:00:00 2001 From: Jacob Brown Date: Wed, 5 Nov 2025 09:38:48 -0700 Subject: [PATCH 09/16] refactor: address PR comments --- tests/features/steps/well-core-information.py | 93 ++++++++++--------- 1 file changed, 49 insertions(+), 44 deletions(-) diff --git a/tests/features/steps/well-core-information.py b/tests/features/steps/well-core-information.py index 06b86ff6c..489032b12 100644 --- a/tests/features/steps/well-core-information.py +++ b/tests/features/steps/well-core-information.py @@ -1,21 +1,17 @@ from behave import when, then +# TODO: move to commonly used step definitions @when("the user retrieves the well by ID via path parameter") def step_impl(context): well_id = 1 - context.response = context.client.get(f"/thing/water-well/{well_id}") - - -# can only be defined once, but recorded here for reference -# @then("the system should return a 200 status code") -# def step_impl(context): -# assert context.response.status_code == 200 + context.water_well_response = context.client.get(f"/thing/water-well/{well_id}") + context.water_well_data = context.water_well_response.json() @then("the response should be in JSON format") def step_impl(context): - assert context.response.headers["Content-Type"] == "application/json" + assert context.water_well_response["Content-Type"] == "application/json" # ------------------------------------------------------------------------------ @@ -25,16 +21,16 @@ def step_impl(context): @then("the response should include the well name (point ID) (i.e. NM-1234)") def step_impl(context): - data = context.response.json() - assert data["name"] == "WL-0001" + assert "name" in context.water_well_data + assert context.water_well_data["name"] == "WL-0001" # TODO: a new endpoint named /thing/{thing_id}/group needs to be added to the API # TODO: this needs to be added to the ThingResponse @then("the response should include the project(s) or group(s) associated with the well") def step_impl(context): - data = context.response.json() - assert data["groups"] == ["Collabnet"] + assert "groups" in context.water_well_data + assert context.water_well_data["groups"] == ["Collabnet"] # TODO: this needs to be added to the model, schema, and test data @@ -43,8 +39,8 @@ def step_impl(context): "the response should include the site name(s) for the well (i.e. John Smith House Well)" ) def step_impl(context): - data = context.response.json() - assert data["site_name"] == "John Smith House Well" + assert "site_name" in context.water_well_data + assert context.water_well_data["site_name"] == "John Smith House Well" # ------------------------------------------------------------------------------ @@ -54,8 +50,8 @@ def step_impl(context): @then("the response should include the purpose of the well (current use)") def step_impl(context): - data = context.response.json() - assert sorted(data["well_purposes"]) == sorted(["Domestic", "Irrigation"]) + assert "Domestic" in context.water_well_data["well_purposes"] + assert "Irrigation" in context.water_well_data["well_purposes"] # TODO: this needs to be added to the ThingResponse and thing_helper via StatusHistory @@ -63,8 +59,8 @@ def step_impl(context): "the response should include the well status of the well as the status of the hole in the ground" ) def step_impl(context): - data = context.response.json() - assert data["well_status"] == "Active" + assert "well_status" in context.water_well_data + assert context.water_well_data["well_status"] == "Active" # TODO: this needs to be added to the model, schema, and test data @@ -73,8 +69,8 @@ def step_impl(context): # could create descriptor table like WellPurpose and CasingMaterial @then("the response should include the monitoring frequency (new field)") def step_impl(context): - data = context.response.json() - assert data["monitoring_frequency"] == "Monthly" + assert "monitoring_frequency" in context.water_well_data + assert context.water_well_data["monitoring_frequency"] == "Monthly" # TODO: this needs to be added to the model, schema, and test data @@ -84,9 +80,10 @@ def step_impl(context): "the response should include whether the well is currently being monitored with status text if applicable (from previous status field)" ) def step_impl(context): - data = context.response.json() - assert data["is_being_monitored"] == True - assert data["monitoring_status"] == "Active" + assert "is_being_monitored" in context.water_well_data + assert "monitoring_status" in context.water_well_data + assert context.water_well_data["is_being_monitored"] == True + assert context.water_well_data["monitoring_status"] == "Active" # ------------------------------------------------------------------------------ @@ -96,8 +93,8 @@ def step_impl(context): @then("the response should include the release status of the well record") def step_impl(context): - data = context.response.json() - assert data["release_status"] == "draft" + assert "release_status" in context.water_well_data + assert context.water_well_data["release_status"] == "draft" # ------------------------------------------------------------------------------ @@ -107,23 +104,25 @@ def step_impl(context): @then("the response should include the hole depth in feet") def step_impl(context): - data = context.response.json() - assert data["hole_depth"] == 10 - assert data["hole_depth_unit"] == "ft" + assert "hole_depth" in context.water_well_data + assert "hole_depth_unit" in context.water_well_data + assert context.water_well_data["hole_depth"] == 10 + assert context.water_well_data["hole_depth_unit"] == "ft" @then("the response should include the well depth in feet") def step_impl(context): - data = context.response.json() - assert data["well_depth"] == 10 - assert data["well_depth_unit"] == "ft" + assert "well_depth" in context.water_well_data + assert "well_depth_unit" in context.water_well_data + assert context.water_well_data["well_depth"] == 10 + assert context.water_well_data["well_depth_unit"] == "ft" # TODO: this needs to be added to the model, schema, and test data @then("the response should include the source of the well depth information") def step_impl(context): - data = context.response.json() - assert data["well_depth_source"] == "Measured" + assert "well_depth_source" in context.water_well_data + assert context.water_well_data["well_depth_source"] == "Measured" # ------------------------------------------------------------------------------ @@ -134,16 +133,17 @@ def step_impl(context): # TODO: this needs to be added to the model, schema, and test data @then("the response should include the description of the measuring point") def step_impl(context): - data = context.response.json() - assert data["measuring_point_description"] == "Top of Casing" + assert "measuring_point_description" in context.water_well_data + assert context.water_well_data["measuring_point_description"] == "Top of Casing" # TODO: this needs to be added to the model, schema, and test data @then("the response should include the measuring point height in feet") def step_impl(context): - data = context.response.json() - assert data["measuring_point_height"] == 4 - assert data["measuring_point_height_unit"] == "ft" + assert "measuring_point_height" in context.water_well_data + assert "measuring_point_height_unit" in context.water_well_data + assert context.water_well_data["measuring_point_height"] == 4 + assert context.water_well_data["measuring_point_height_unit"] == "ft" # ------------------------------------------------------------------------------ @@ -190,18 +190,23 @@ def step_impl(context): # TODO: add elevation_unit: str = "ft" to LocationResponse schema @then("the response should include the elevation in feet with vertical datum NAVD88") def step_impl(context): - data = context.response.json() - assert data["current_location"]["elevation"] == 2464.9 - assert data["current_location"]["elevation_unit"] == "ft" - assert data["current_location"]["vertical_datum"] == "NAVD88" + assert "elevation" in context.water_well_data["current_location"] + assert "elevation_unit" in context.water_well_data["current_location"] + assert "vertical_datum" in context.water_well_data["current_location"] + assert context.water_well_data["current_location"]["elevation"] == 2464.9 + assert context.water_well_data["current_location"]["elevation_unit"] == "ft" + assert context.water_well_data["current_location"]["vertical_datum"] == "NAVD88" @then( "the response should include the elevation method (i.e. interpolated from digital elevation model)" ) def step_impl(context): - data = context.response.json() - assert data["current_location"]["elevation_method"] == "Survey-grade GPS" + assert "elevation_method" in context.water_well_data["current_location"] + assert ( + context.water_well_data["current_location"]["elevation_method"] + == "Survey-grade GPS" + ) # ------------------------------------------------------------------------------ From 6ee07192094ed064a44ba50076c86a3b9741f8b4 Mon Sep 17 00:00:00 2001 From: Jacob Brown Date: Wed, 5 Nov 2025 13:40:05 -0700 Subject: [PATCH 10/16] refactor: update behave tests per PR feedback --- tests/features/steps/well-core-information.py | 61 +++++++++++-------- 1 file changed, 34 insertions(+), 27 deletions(-) diff --git a/tests/features/steps/well-core-information.py b/tests/features/steps/well-core-information.py index 489032b12..b00b3cc20 100644 --- a/tests/features/steps/well-core-information.py +++ b/tests/features/steps/well-core-information.py @@ -156,46 +156,53 @@ def step_impl(context): "the response should include the latitude and longitude in decimal degrees with datum WGS84" ) def step_impl(context): - data = context.response.json() - assert ( - data["current_location"]["geographic_coordinate_system"]["latitude"] - == 33.809665 - ) - assert ( - data["current_location"]["geographic_coordinate_system"]["longitude"] - == -107.949533 - ) - assert ( - data["current_location"]["geographic_coordinate_system"]["horizontal_datum"] - == "WGS84" - ) + assert "current_location" in context.water_well_data + assert "geometry" in context.water_well_data["current_location"] + assert context.water_well_data["current_location"]["geometry"] == { + "type": "Point", + "coordinates": [33.809665, -107.949533], + } # TODO: this needs to be added to the LocationResponse schema @then("the response should include the UTM coordinates with datum NAD83") def step_impl(context): - data = context.response.json() - assert data["current_location"]["projected_coordinate_system"]["easting"] == 623000 - assert ( - data["current_location"]["projected_coordinate_system"]["northing"] == 3745000 - ) - assert data["current_location"]["projected_coordinate_system"]["utm_zone"] == 13 + assert "current_location" in context.water_well_data + assert "properties" in context.water_well_data["current_location"] assert ( - data["current_location"]["projected_coordinate_system"]["horizontal_datum"] - == "NAD83" + "utm_coordinates" in context.water_well_data["current_location"]["properties"] ) + assert context.water_well_data["current_location"]["properties"][ + "utm_coordinates" + ] == { + "easting": 623000, + "northing": 3745000, + "utm_zone": 13, + "horizontal_datum": "NAD83", + } # TODO: elevation should be returned in ft, not meters, conversion should occur in schema # TODO: add elevation_unit: str = "ft" to LocationResponse schema @then("the response should include the elevation in feet with vertical datum NAVD88") def step_impl(context): - assert "elevation" in context.water_well_data["current_location"] - assert "elevation_unit" in context.water_well_data["current_location"] - assert "vertical_datum" in context.water_well_data["current_location"] - assert context.water_well_data["current_location"]["elevation"] == 2464.9 - assert context.water_well_data["current_location"]["elevation_unit"] == "ft" - assert context.water_well_data["current_location"]["vertical_datum"] == "NAVD88" + assert "current_location" in context.water_well_data + assert "properties" in context.water_well_data["current_location"] + assert "elevation" in context.water_well_data["current_location"]["properties"] + assert "elevation_unit" in context.water_well_data["current_location"]["properties"] + assert "vertical_datum" in context.water_well_data["current_location"]["properties"] + + assert ( + context.water_well_data["current_location"]["properties"]["elevation"] == 2464.9 + ) + assert ( + context.water_well_data["current_location"]["properties"]["elevation_unit"] + == "ft" + ) + assert ( + context.water_well_data["current_location"]["properties"]["vertical_datum"] + == "NAVD88" + ) @then( From 5e3a106e5dcb4967e8d11367e96de9b46a754763 Mon Sep 17 00:00:00 2001 From: Jacob Brown Date: Wed, 5 Nov 2025 14:04:51 -0700 Subject: [PATCH 11/16] refactor: update feature tests per PR feedback --- tests/features/steps/well-core-information.py | 94 +++++++++++-------- 1 file changed, 54 insertions(+), 40 deletions(-) diff --git a/tests/features/steps/well-core-information.py b/tests/features/steps/well-core-information.py index b00b3cc20..21ae94265 100644 --- a/tests/features/steps/well-core-information.py +++ b/tests/features/steps/well-core-information.py @@ -14,6 +14,15 @@ def step_impl(context): assert context.water_well_response["Content-Type"] == "application/json" +@then( + "null values in the response should be represented as JSON null (not placeholder strings)" +) +def step_impl(context): + for key, value in context.water_well_data.items(): + if value is None: + assert value is None # JSON null is represented as None in Python + + # ------------------------------------------------------------------------------ # Well names and projects # ------------------------------------------------------------------------------ @@ -33,16 +42,6 @@ def step_impl(context): assert context.water_well_data["groups"] == ["Collabnet"] -# TODO: this needs to be added to the model, schema, and test data -# TODO: how do we rectify this with the name field? Is there a better way to name this? -@then( - "the response should include the site name(s) for the well (i.e. John Smith House Well)" -) -def step_impl(context): - assert "site_name" in context.water_well_data - assert context.water_well_data["site_name"] == "John Smith House Well" - - # ------------------------------------------------------------------------------ # Well Purpose and Status and Monitoring Status # ------------------------------------------------------------------------------ @@ -151,49 +150,40 @@ def step_impl(context): # ------------------------------------------------------------------------------ -# TODO: this needs to be added to the LocationResponse schema -@then( - "the response should include the latitude and longitude in decimal degrees with datum WGS84" -) +@then("the response should include location information in GeoJSON format") def step_impl(context): assert "current_location" in context.water_well_data + assert "type" in context.water_well_data["current_location"] assert "geometry" in context.water_well_data["current_location"] - assert context.water_well_data["current_location"]["geometry"] == { - "type": "Point", - "coordinates": [33.809665, -107.949533], - } + assert "properties" in context.water_well_data["current_location"] + assert context.water_well_data["current_location"]["type"] == "Feature" -# TODO: this needs to be added to the LocationResponse schema -@then("the response should include the UTM coordinates with datum NAD83") + +# TODO: the LocationResponse schema needs to be updated +@then( + 'the response should include a geometry object with type "Point" and coordinates array [longitude, latitude, elevation] in decimal degrees with datum WGS84' +) def step_impl(context): - assert "current_location" in context.water_well_data - assert "properties" in context.water_well_data["current_location"] - assert ( - "utm_coordinates" in context.water_well_data["current_location"]["properties"] - ) - assert context.water_well_data["current_location"]["properties"][ - "utm_coordinates" - ] == { - "easting": 623000, - "northing": 3745000, - "utm_zone": 13, - "horizontal_datum": "NAD83", + assert context.water_well_data["current_location"]["geometry"] == { + "type": "Point", + "coordinates": [33.809665, -107.949533, 2464.9], } # TODO: elevation should be returned in ft, not meters, conversion should occur in schema # TODO: add elevation_unit: str = "ft" to LocationResponse schema -@then("the response should include the elevation in feet with vertical datum NAVD88") +@then( + "the response should include the elevation in feet with vertical datum NAVD88 in the properties" +) def step_impl(context): - assert "current_location" in context.water_well_data - assert "properties" in context.water_well_data["current_location"] assert "elevation" in context.water_well_data["current_location"]["properties"] assert "elevation_unit" in context.water_well_data["current_location"]["properties"] assert "vertical_datum" in context.water_well_data["current_location"]["properties"] assert ( - context.water_well_data["current_location"]["properties"]["elevation"] == 2464.9 + context.water_well_data["current_location"]["properties"]["elevation"] + == 2464.9 * 3.28084 ) assert ( context.water_well_data["current_location"]["properties"]["elevation_unit"] @@ -206,16 +196,37 @@ def step_impl(context): @then( - "the response should include the elevation method (i.e. interpolated from digital elevation model)" + "the response should include the elevation method (i.e. interpolated from digital elevation model) in the properties" ) def step_impl(context): - assert "elevation_method" in context.water_well_data["current_location"] assert ( - context.water_well_data["current_location"]["elevation_method"] + "elevation_method" in context.water_well_data["current_location"]["properties"] + ) + assert ( + context.water_well_data["current_location"]["properties"]["elevation_method"] == "Survey-grade GPS" ) +# TODO: this needs to be added to the LocationResponse schema +@then( + "the response should include the UTM coordinates with datum NAD83 in the properties" +) +def step_impl(context): + + assert ( + "utm_coordinates" in context.water_well_data["current_location"]["properties"] + ) + assert context.water_well_data["current_location"]["properties"][ + "utm_coordinates" + ] == { + "easting": 623000, + "northing": 3745000, + "utm_zone": 13, + "horizontal_datum": "NAD83", + } + + # ------------------------------------------------------------------------------ # Alternate Identifiers # ------------------------------------------------------------------------------ @@ -224,7 +235,7 @@ def step_impl(context): # TODO: This needs to be added to the test data # TODO: id link schema needs to use lexicon enums for relation and alternate_organization @then( - "the response should include any alternate IDs for the well like the USGS site number or the OSE well ID and OSE well tag ID" + "the response should include any alternate IDs for the well like the NMBGMR site_name (i.e. John Smith Well), USGS site number, or the OSE well ID and OSE well tag ID" ) def step_impl(context): response = context.client.get("/thing/1/id-link") @@ -236,3 +247,6 @@ def step_impl(context): elif item["alternate_organization"] == "NMOSE": assert item["relation"] == "same as" assert item["alternate_id"] == "OSE-0001" + elif item["alternate_organization"] == "NMBGMR": + assert item["relation"] == "same as" + assert item["alternate_id"] == "John Smith Well" From c504b279e0a789542f56603976c49e73a4e31a7a Mon Sep 17 00:00:00 2001 From: Jacob Brown Date: Thu, 6 Nov 2025 09:02:30 -0700 Subject: [PATCH 12/16] refactor: revert to context.response for the single request --- tests/features/steps/well-core-information.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/features/steps/well-core-information.py b/tests/features/steps/well-core-information.py index 21ae94265..ae16588f4 100644 --- a/tests/features/steps/well-core-information.py +++ b/tests/features/steps/well-core-information.py @@ -5,8 +5,8 @@ @when("the user retrieves the well by ID via path parameter") def step_impl(context): well_id = 1 - context.water_well_response = context.client.get(f"/thing/water-well/{well_id}") - context.water_well_data = context.water_well_response.json() + context.response = context.water_well_response + context.water_well_data = context.response.json() @then("the response should be in JSON format") From 995d6b1eb023bc89293d7b44ad4f95b21e5372b7 Mon Sep 17 00:00:00 2001 From: Jacob Brown Date: Thu, 6 Nov 2025 12:54:11 -0700 Subject: [PATCH 13/16] refactor: use context objects to get well id for get request --- tests/features/steps/well-core-information.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/features/steps/well-core-information.py b/tests/features/steps/well-core-information.py index ae16588f4..07a132436 100644 --- a/tests/features/steps/well-core-information.py +++ b/tests/features/steps/well-core-information.py @@ -4,8 +4,8 @@ # TODO: move to commonly used step definitions @when("the user retrieves the well by ID via path parameter") def step_impl(context): - well_id = 1 - context.response = context.water_well_response + well_id = context.objects["wells"][0].id + context.response = context.client.get(f"/thing/water-well/{well_id}") context.water_well_data = context.response.json() From 87dba2be09cda9fd203ada70d36f698c0d528a74 Mon Sep 17 00:00:00 2001 From: Jacob Brown Date: Thu, 6 Nov 2025 15:19:21 -0700 Subject: [PATCH 14/16] feat: update tests --- tests/features/environment.py | 79 +++++++++++++ tests/features/steps/well-core-information.py | 110 ++++++++++++++---- 2 files changed, 165 insertions(+), 24 deletions(-) diff --git a/tests/features/environment.py b/tests/features/environment.py index ac97355c1..dfcfde370 100644 --- a/tests/features/environment.py +++ b/tests/features/environment.py @@ -29,6 +29,7 @@ Parameter, Deployment, TransducerObservationBlock, + StatusHistory, ) from db.engine import session_ctx @@ -187,6 +188,36 @@ def add_block(context, session, parameter): return block +@add_context_object_container("status_histories") +def add_status_history( + context, + session, + status_type, + status_value, + start_date, + end_date, + reason, + statusable_id, + statusable_type, +): + status_history = StatusHistory( + status_type=status_type, + status_value=status_value, + start_date=start_date, + end_date=end_date, + reason=reason, + statusable_id=statusable_id, + statusable_type=statusable_type, + ) + + session.add(status_history) + session.commit() + session.refresh(status_history) + + context.objects["status_histories"].append(status_history) + return status_history + + def before_all(context): context.objects = {} @@ -209,6 +240,54 @@ def before_all(context): sensor_1 = add_sensor(context, session, well_1.id) deployment = add_deployment(context, session, well_1.id, sensor_1.id) + well_status_1 = add_status_history( + context, + session, + status_type="well_status", + status_value="Active, pumping well", + start_date=datetime(2020, 1, 1), + end_date=datetime(2021, 1, 1), + reason="Initial status", + statusable_id=well_1.id, + statusable_type="Thing", + ) + + well_status_2 = add_status_history( + context, + session, + status_type="well_status", + status_value="Destroyed, exists but not usable", + start_date=datetime(2021, 1, 1), + end_date=None, + reason="Roving bovine", + statusable_id=well_1.id, + statusable_type="Thing", + ) + + monitoring_status_1 = add_status_history( + context, + session, + status_type="monitoring_status", + status_value="currently monitored", + start_date=datetime(2020, 1, 1), + end_date=datetime(2021, 1, 1), + reason="Initial monitoring status", + statusable_id=well_1.id, + statusable_type="Thing", + ) + + monitoring_status_2 = add_status_history( + context, + session, + status_type="monitoring_status", + status_value="not monitored", + start_date=datetime(2021, 1, 1), + end_date=None, + reason="Roving bovine destroyed well", + statusable_id=well_1.id, + statusable_type="Thing", + ) + # parameter ID can be hardcoded because init_parameter always creates the same one parameter = session.get(Parameter, 1) add_obs = add_block(context, session, parameter) diff --git a/tests/features/steps/well-core-information.py b/tests/features/steps/well-core-information.py index 07a132436..a892285a6 100644 --- a/tests/features/steps/well-core-information.py +++ b/tests/features/steps/well-core-information.py @@ -1,3 +1,5 @@ +from constants import SRID_WGS84, SRID_UTM_ZONE_13N +from services.util import transform_srid from behave import when, then @@ -11,7 +13,7 @@ def step_impl(context): @then("the response should be in JSON format") def step_impl(context): - assert context.water_well_response["Content-Type"] == "application/json" + assert context.response["Content-Type"] == "application/json" @then( @@ -31,14 +33,15 @@ def step_impl(context): @then("the response should include the well name (point ID) (i.e. NM-1234)") def step_impl(context): assert "name" in context.water_well_data - assert context.water_well_data["name"] == "WL-0001" + assert context.water_well_data["name"] == context.objects["wells"][0].name -# TODO: a new endpoint named /thing/{thing_id}/group needs to be added to the API -# TODO: this needs to be added to the ThingResponse + +# TODO: model schema, and test data need to be udpated @then("the response should include the project(s) or group(s) associated with the well") def step_impl(context): assert "groups" in context.water_well_data + assert context.water_well_data["groups"] == ["Collabnet"] @@ -52,14 +55,28 @@ def step_impl(context): assert "Domestic" in context.water_well_data["well_purposes"] assert "Irrigation" in context.water_well_data["well_purposes"] + assert ( + context.water_well_data["well_purposes"][0] + == context.objects.wells[0].well_purposes[0].purpose + ) + assert ( + context.water_well_data["well_purposes"][1] + == context.objects.wells[0].well_purposes[1].purpose + ) + # TODO: this needs to be added to the ThingResponse and thing_helper via StatusHistory @then( - "the response should include the well status of the well as the status of the hole in the ground" + "the response should include the well hole status of the well as the status of the hole in the ground (from previous Status field)" ) def step_impl(context): assert "well_status" in context.water_well_data - assert context.water_well_data["well_status"] == "Active" + + status_history = context.objects["wells"][0].status_history + well_status = [sh for sh in status_history if sh.status_type == "well_status"] + well_status_sorted = sorted(well_status, key=lambda sh: sh.start_date, reverse=True) + + assert context.water_well_data["well_status"] == well_status_sorted[0].status_value # TODO: this needs to be added to the model, schema, and test data @@ -69,6 +86,7 @@ def step_impl(context): @then("the response should include the monitoring frequency (new field)") def step_impl(context): assert "monitoring_frequency" in context.water_well_data + assert context.water_well_data["monitoring_frequency"] == "Monthly" @@ -76,13 +94,23 @@ def step_impl(context): # the monitoring status field from NM_Aquifer contains a multitude of information, like having three codes (6AC), so the transfer and model/schemas will need to take this into account # could create descriptor table like WellPurpose and CasingMaterial @then( - "the response should include whether the well is currently being monitored with status text if applicable (from previous status field)" + "the response should include whether the well is currently being monitored with status text if applicable (from previous MonitoringStatus field)" ) def step_impl(context): - assert "is_being_monitored" in context.water_well_data assert "monitoring_status" in context.water_well_data - assert context.water_well_data["is_being_monitored"] == True - assert context.water_well_data["monitoring_status"] == "Active" + + status_history = context.objects["wells"][0].status_history + monitoring_status = [ + sh for sh in status_history if sh.status_type == "monitoring_status" + ] + monitoring_status_sorted = sorted( + monitoring_status, key=lambda sh: sh.start_date, reverse=True + ) + + assert ( + context.water_well_data["monitoring_status"] + == monitoring_status_sorted[0].status_value + ) # ------------------------------------------------------------------------------ @@ -93,7 +121,11 @@ def step_impl(context): @then("the response should include the release status of the well record") def step_impl(context): assert "release_status" in context.water_well_data - assert context.water_well_data["release_status"] == "draft" + + assert ( + context.water_well_data["release_status"] + == context.objects["wells"][0].release_status + ) # ------------------------------------------------------------------------------ @@ -105,7 +137,10 @@ def step_impl(context): def step_impl(context): assert "hole_depth" in context.water_well_data assert "hole_depth_unit" in context.water_well_data - assert context.water_well_data["hole_depth"] == 10 + + assert ( + context.water_well_data["hole_depth"] == context.objects["wells"][0].hole_depth + ) assert context.water_well_data["hole_depth_unit"] == "ft" @@ -113,7 +148,10 @@ def step_impl(context): def step_impl(context): assert "well_depth" in context.water_well_data assert "well_depth_unit" in context.water_well_data - assert context.water_well_data["well_depth"] == 10 + + assert ( + context.water_well_data["well_depth"] == context.objects["wells"][0].well_depth + ) assert context.water_well_data["well_depth_unit"] == "ft" @@ -121,7 +159,11 @@ def step_impl(context): @then("the response should include the source of the well depth information") def step_impl(context): assert "well_depth_source" in context.water_well_data - assert context.water_well_data["well_depth_source"] == "Measured" + + assert ( + context.water_well_data["well_depth_source"] + == context.objects["wells"][0].well_depth_source + ) # ------------------------------------------------------------------------------ @@ -133,7 +175,11 @@ def step_impl(context): @then("the response should include the description of the measuring point") def step_impl(context): assert "measuring_point_description" in context.water_well_data - assert context.water_well_data["measuring_point_description"] == "Top of Casing" + + assert ( + context.water_well_data["measuring_point_description"] + == context.objects["wells"][0].measuring_point_description + ) # TODO: this needs to be added to the model, schema, and test data @@ -141,7 +187,11 @@ def step_impl(context): def step_impl(context): assert "measuring_point_height" in context.water_well_data assert "measuring_point_height_unit" in context.water_well_data - assert context.water_well_data["measuring_point_height"] == 4 + + assert ( + context.water_well_data["measuring_point_height"] + == context.objects["wells"][0].measuring_point_height + ) assert context.water_well_data["measuring_point_height_unit"] == "ft" @@ -165,9 +215,13 @@ def step_impl(context): 'the response should include a geometry object with type "Point" and coordinates array [longitude, latitude, elevation] in decimal degrees with datum WGS84' ) def step_impl(context): + latitude = context.objects["locations"][0].point.y + longitude = context.objects["locations"][0].point.x + elevation_m = context.objects["locations"][0].elevation + assert context.water_well_data["current_location"]["geometry"] == { "type": "Point", - "coordinates": [33.809665, -107.949533, 2464.9], + "coordinates": [longitude, latitude, elevation_m], } @@ -181,9 +235,11 @@ def step_impl(context): assert "elevation_unit" in context.water_well_data["current_location"]["properties"] assert "vertical_datum" in context.water_well_data["current_location"]["properties"] + elevation_ft = context.objects["locations"][0].elevation * 3.28084 + assert ( context.water_well_data["current_location"]["properties"]["elevation"] - == 2464.9 * 3.28084 + == elevation_ft ) assert ( context.water_well_data["current_location"]["properties"]["elevation_unit"] @@ -204,7 +260,7 @@ def step_impl(context): ) assert ( context.water_well_data["current_location"]["properties"]["elevation_method"] - == "Survey-grade GPS" + == context.objects["locations"][0].elevation_method ) @@ -217,11 +273,16 @@ def step_impl(context): assert ( "utm_coordinates" in context.water_well_data["current_location"]["properties"] ) + + point_utm_zone_13 = transform_srid( + context.objects["locations"][0].point, SRID_WGS84, SRID_UTM_ZONE_13N + ) + assert context.water_well_data["current_location"]["properties"][ "utm_coordinates" ] == { - "easting": 623000, - "northing": 3745000, + "easting": point_utm_zone_13.x, + "northing": point_utm_zone_13.y, "utm_zone": 13, "horizontal_datum": "NAD83", } @@ -238,9 +299,10 @@ def step_impl(context): "the response should include any alternate IDs for the well like the NMBGMR site_name (i.e. John Smith Well), USGS site number, or the OSE well ID and OSE well tag ID" ) def step_impl(context): - response = context.client.get("/thing/1/id-link") - data = response.json() - for item in data["items"]: + assert "alternate_ids" in context.water_well_data + + assert len(context.water_well_data["alternate_ids"]) == 3 + for item in context.water_well_data["alternate_ids"]: if item["alternate_organization"] == "USGS": assert item["relation"] == "same as" assert item["alternate_id"] == "12345678" From 077dacdad449e019d6be4b2c8657b9e056e863f6 Mon Sep 17 00:00:00 2001 From: Jacob Brown Date: Thu, 6 Nov 2025 15:28:15 -0700 Subject: [PATCH 15/16] feat: add id links to pseudo fixtures --- tests/features/environment.py | 46 +++++++++++++++++++ tests/features/steps/well-core-information.py | 12 ++--- 2 files changed, 52 insertions(+), 6 deletions(-) diff --git a/tests/features/environment.py b/tests/features/environment.py index dfcfde370..05d5c3afb 100644 --- a/tests/features/environment.py +++ b/tests/features/environment.py @@ -30,6 +30,7 @@ Deployment, TransducerObservationBlock, StatusHistory, + ThingIdLink, ) from db.engine import session_ctx @@ -218,6 +219,24 @@ def add_status_history( return status_history +@add_context_object_container("id_links") +def add_id_link( + context, session, thing, relation, alternate_id, alternate_organization +): + id_link = ThingIdLink( + thing_id=thing.id, + relation=relation, + alternate_id=alternate_id, + alternate_organization=alternate_organization, + ) + session.add(id_link) + session.commit() + session.refresh(id_link) + + context.objects["id_links"].append(id_link) + return id_link + + def before_all(context): context.objects = {} @@ -288,6 +307,33 @@ def before_all(context): statusable_type="Thing", ) + id_link_1 = add_id_link( + context, + session, + thing=well_1, + relation="same_as", + alternate_id="12345678", + alternate_organization="USGS", + ) + + id_link_2 = add_id_link( + context, + session, + thing=well_1, + relation="same_as", + alternate_id="OSE-0001", + alternate_organization="NMOSE", + ) + + id_link_3 = add_id_link( + context, + session, + thing=well_1, + relation="same_as", + alternate_id="Roving Bovine Ranch Well #1", + alternate_organization="NMBGMR", + ) + # parameter ID can be hardcoded because init_parameter always creates the same one parameter = session.get(Parameter, 1) add_obs = add_block(context, session, parameter) diff --git a/tests/features/steps/well-core-information.py b/tests/features/steps/well-core-information.py index a892285a6..79c857532 100644 --- a/tests/features/steps/well-core-information.py +++ b/tests/features/steps/well-core-information.py @@ -304,11 +304,11 @@ def step_impl(context): assert len(context.water_well_data["alternate_ids"]) == 3 for item in context.water_well_data["alternate_ids"]: if item["alternate_organization"] == "USGS": - assert item["relation"] == "same as" - assert item["alternate_id"] == "12345678" + assert item["relation"] == context.objects["id_links"][0].relation + assert item["alternate_id"] == context.objects["id_links"][0].alternate_id elif item["alternate_organization"] == "NMOSE": - assert item["relation"] == "same as" - assert item["alternate_id"] == "OSE-0001" + assert item["relation"] == context.objects["id_links"][1].relation + assert item["alternate_id"] == context.objects["id_links"][1].alternate_id elif item["alternate_organization"] == "NMBGMR": - assert item["relation"] == "same as" - assert item["alternate_id"] == "John Smith Well" + assert item["relation"] == context.objects["id_links"][2].relation + assert item["alternate_id"] == context.objects["id_links"][2].alternate_id From 2ce6f5cdd0816deab282591528acba3de61ca866 Mon Sep 17 00:00:00 2001 From: Jacob Brown Date: Thu, 6 Nov 2025 17:00:52 -0700 Subject: [PATCH 16/16] refactor: update groups in testing data --- tests/features/environment.py | 4 +++- tests/features/steps/well-core-information.py | 16 ++++++++++++++-- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/tests/features/environment.py b/tests/features/environment.py index 05d5c3afb..61ee82709 100644 --- a/tests/features/environment.py +++ b/tests/features/environment.py @@ -144,7 +144,9 @@ def add_sensor(context, session, sid): @add_context_object_container("groups") def add_group(context, session, wells, gid): - group = Group(name="Collabnet") + group = Group( + name="Collabnet", description="Healy Collaborative Network", project_area=None + ) for w in wells: assoc = GroupThingAssociation(group=group, thing=w) session.add(assoc) diff --git a/tests/features/steps/well-core-information.py b/tests/features/steps/well-core-information.py index 79c857532..5e773b73f 100644 --- a/tests/features/steps/well-core-information.py +++ b/tests/features/steps/well-core-information.py @@ -42,7 +42,18 @@ def step_impl(context): def step_impl(context): assert "groups" in context.water_well_data - assert context.water_well_data["groups"] == ["Collabnet"] + assert ( + context.water_well_data["groups"][0]["description"] + == context.objects["groups"][0].description + ) + assert ( + context.water_well_data["groups"][0]["name"] + == context.objects["groups"][0].name + ) + assert ( + context.water_well_data["groups"][0]["project_area"] + == context.objects["groups"][0].project_area + ) # ------------------------------------------------------------------------------ @@ -85,7 +96,8 @@ def step_impl(context): # could create descriptor table like WellPurpose and CasingMaterial @then("the response should include the monitoring frequency (new field)") def step_impl(context): - assert "monitoring_frequency" in context.water_well_data + for group in context.water_well_data["groups"]: + assert "monitoring_frequency" in group assert context.water_well_data["monitoring_frequency"] == "Monthly"