From 9c65119247d74458f4665cbfc415707ba61154be Mon Sep 17 00:00:00 2001 From: Treyson Le Date: Wed, 3 Sep 2025 13:42:36 -0700 Subject: [PATCH 01/35] Create ratings_test.py --- tests/cda/ratings/ratings_test.py | 103 ++++++++++++++++++++++++++++++ 1 file changed, 103 insertions(+) create mode 100644 tests/cda/ratings/ratings_test.py diff --git a/tests/cda/ratings/ratings_test.py b/tests/cda/ratings/ratings_test.py new file mode 100644 index 00000000..0dc23bf9 --- /dev/null +++ b/tests/cda/ratings/ratings_test.py @@ -0,0 +1,103 @@ +from datetime import datetime, timedelta, timezone + +import pandas as pd +import pytest + +import cwms +import cwms.ratings.ratings as ratings +import cwms.ratings.ratings_spec as ratings_spec + +TEST_OFFICE = "MVP" +TEST_RATING_ID = "pytest_rating.Stage;ft.Flow;cfs.Linear.Production" + + +@pytest.fixture(scope="module", autouse=True) +def setup_data(): + # Create rating spec for testing + spec_json = { + "office-id": TEST_OFFICE, + "rating-spec-id": TEST_RATING_ID, + "template-id": "Linear", + "ind-parameter": "Stage;ft", + "dep-parameter": "Flow;cfs", + } + ratings_spec.store_rating_spec(spec_json) + + yield + + # Clean up + ratings_spec.delete_rating_spec(TEST_RATING_ID, TEST_OFFICE) + + +@pytest.fixture(autouse=True) +def init_session(): + print("Initializing CWMS API session for ratings tests...") + + +def test_rating_simple_df_to_json(): + now = datetime.now(timezone.utc).replace(microsecond=0) + df = pd.DataFrame({"ind": [1.0, 2.0], "dep": [10.0, 20.0]}) + + json_out = ratings.rating_simple_df_to_json( + data=df, + rating_id=TEST_RATING_ID, + office_id=TEST_OFFICE, + units="ft;cfs", + effective_date=now, + description="pytest rating curve", + ) + + assert "simple-rating" in json_out + assert json_out["simple-rating"]["rating-spec-id"] == TEST_RATING_ID + assert json_out["simple-rating"]["units-id"] == "ft;cfs" + assert len(json_out["simple-rating"]["rating-points"]["point"]) == 2 + + +def test_store_rating_and_get_current_rating(): + now = datetime.now(timezone.utc).replace(microsecond=0) + df = pd.DataFrame({"ind": [1.0, 2.0], "dep": [10.0, 20.0]}) + + rating_json = ratings.rating_simple_df_to_json( + df, TEST_RATING_ID, TEST_OFFICE, "ft;cfs", effective_date=now + ) + ratings.store_rating(rating_json) + + data = ratings.get_current_rating(TEST_RATING_ID, TEST_OFFICE) + assert data.df is not None + assert not data.df.empty + assert pytest.approx(data.df["dep"].iloc[0]) == 10.0 + + +def test_get_current_rating_xml(): + xml_data = ratings.get_current_rating_xml(TEST_RATING_ID, TEST_OFFICE) + assert isinstance(xml_data, str) + assert xml_data.startswith(" Date: Thu, 4 Sep 2025 12:31:12 -0700 Subject: [PATCH 02/35] Added JSONs and setup the file --- tests/cda/ratings/ratings_test.py | 74 +++++++++++++++++++++++- tests/cda/resources/location.json | 16 +++++ tests/cda/resources/rating_spec.json | 9 +++ tests/cda/resources/rating_table.json | 18 ++++++ tests/cda/resources/rating_template.json | 18 ++++++ tests/cda/resources/spec.json | 9 +++ tests/cda/resources/table.json | 18 ++++++ tests/cda/resources/table_updated.json | 18 ++++++ tests/cda/resources/template.json | 15 +++++ 9 files changed, 193 insertions(+), 2 deletions(-) create mode 100644 tests/cda/resources/location.json create mode 100644 tests/cda/resources/rating_spec.json create mode 100644 tests/cda/resources/rating_table.json create mode 100644 tests/cda/resources/rating_template.json create mode 100644 tests/cda/resources/spec.json create mode 100644 tests/cda/resources/table.json create mode 100644 tests/cda/resources/table_updated.json create mode 100644 tests/cda/resources/template.json diff --git a/tests/cda/ratings/ratings_test.py b/tests/cda/ratings/ratings_test.py index 0dc23bf9..47dc8f4a 100644 --- a/tests/cda/ratings/ratings_test.py +++ b/tests/cda/ratings/ratings_test.py @@ -1,4 +1,6 @@ +import json from datetime import datetime, timedelta, timezone +from pathlib import Path import pandas as pd import pytest @@ -6,13 +8,21 @@ import cwms import cwms.ratings.ratings as ratings import cwms.ratings.ratings_spec as ratings_spec +import cwms.ratings.ratings_template as ratings_template + +RESOURCES = Path(__file__).parent / "resources" TEST_OFFICE = "MVP" TEST_RATING_ID = "pytest_rating.Stage;ft.Flow;cfs.Linear.Production" -@pytest.fixture(scope="module", autouse=True) -def setup_data(): +def load_json(name): + with open(RESOURCES / name) as f: + return json.load(f) + + +@pytest.fixture(scope="module") +def setup_unit_spec(): # Create rating spec for testing spec_json = { "office-id": TEST_OFFICE, @@ -29,6 +39,28 @@ def setup_data(): ratings_spec.delete_rating_spec(TEST_RATING_ID, TEST_OFFICE) +@pytest.fixture(scope="module") +def setup_lifecycle_resources(): + # Prepare resources for lifecycle tests: location, template, spec + location_json = load_json("location.json") + cwms.store_location(location_json) + + template_json = load_json("template.json") + ratings_template.store_rating_template(template_json) + + spec_json = load_json("spec.json") + ratings_spec.store_rating_spec(spec_json) + + yield + + # Cleanup lifecycle resources + ratings_spec.delete_rating_spec(spec_json["rating-spec-id"], spec_json["office-id"]) + ratings_template.delete_rating_template( + template_json["template-id"], template_json["office-id"] + ) + cwms.delete_location(location_json["location-id"], location_json["office-id"]) + + @pytest.fixture(autouse=True) def init_session(): print("Initializing CWMS API session for ratings tests...") @@ -101,3 +133,41 @@ def test_delete_ratings(): # Should not hit ratings.delete_ratings(TEST_RATING_ID, TEST_OFFICE, begin, end) + + +def test_full_rating_lifecycle(setup_lifecycle_resources): + location_json = load_json("location.json") + template_json = load_json("template.json") + spec_json = load_json("spec.json") + table_json = load_json("table.json") + updated_table_json = load_json("table_updated.json") + + # Store location + cwms.store_location(location_json) + + # Store template + ratings_template.store_rating_template(template_json) + + # Store spec + ratings_spec.store_rating_spec(spec_json) + + # Store rating table + ratings.store_rating(table_json) + + # Update rating table + ratings.store_rating(updated_table_json) + + # Delete rating table + now = datetime.now(timezone.utc).replace(microsecond=0) + begin = now - timedelta(days=1) + end = now + timedelta(days=1) + ratings.delete_ratings( + spec_json["rating-spec-id"], spec_json["office-id"], begin, end + ) + + # Cleanup + ratings_spec.delete_rating_spec(spec_json["rating-spec-id"], spec_json["office-id"]) + ratings_template.delete_rating_template( + template_json["template-id"], template_json["office-id"] + ) + cwms.delete_location(location_json["location-id"], location_json["office-id"]) diff --git a/tests/cda/resources/location.json b/tests/cda/resources/location.json new file mode 100644 index 00000000..d048534a --- /dev/null +++ b/tests/cda/resources/location.json @@ -0,0 +1,16 @@ +{ + "office-id": "MVP", + "location-id": "USGS-EXSA-TEST", + "name": "USGS-EXSA-TEST", + "latitude": 40.0, + "longitude": -105.0, + "elevation": 1000.0, + "horizontal-datum": "NAD83", + "vertical-datum": "NAVD88", + "location-type": "TESTING", + "location-kind": "SITE", + "public-name": "EXSA Location", + "long-name": "EXSA Location for Rating Tests", + "timezone-name": "America/Chicago", + "nation": "US" +} \ No newline at end of file diff --git a/tests/cda/resources/rating_spec.json b/tests/cda/resources/rating_spec.json new file mode 100644 index 00000000..18aa66fc --- /dev/null +++ b/tests/cda/resources/rating_spec.json @@ -0,0 +1,9 @@ +{ + "office-id": "MVP", + "rating-spec-id": "TestRating.Stage;Flow.USGS-EXSA-TEST.USGS-NWIS-TEST", + "template-id": "USGS-EXSA-TEST", + "ind-parameter": "Stage;ft", + "dep-parameter": "Flow;cfs", + "version": "pytest-version", + "description": "Pytest rating spec for EXSA test" +} \ No newline at end of file diff --git a/tests/cda/resources/rating_table.json b/tests/cda/resources/rating_table.json new file mode 100644 index 00000000..74b24fa0 --- /dev/null +++ b/tests/cda/resources/rating_table.json @@ -0,0 +1,18 @@ +{ + "simple-rating": { + "office-id": "MVP", + "rating-spec-id": "TestRating.Stage;Flow.USGS-EXSA-TEST.USGS-NWIS-TEST", + "units-id": "ft;cfs", + "effective-date": "2023-01-01T00:00:00Z", + "transition-start-date": null, + "active": true, + "description": "Initial rating table for pytest", + "rating-points": { + "point": [ + { "ind": 1.0, "dep": 10.0 }, + { "ind": 2.0, "dep": 20.0 }, + { "ind": 3.0, "dep": 30.0 } + ] + } + } +} \ No newline at end of file diff --git a/tests/cda/resources/rating_template.json b/tests/cda/resources/rating_template.json new file mode 100644 index 00000000..54eb6516 --- /dev/null +++ b/tests/cda/resources/rating_template.json @@ -0,0 +1,18 @@ +{ + "office-id": "MVP", + "id": "USGS-EXSA-TEST", + "version": "USGS-EXSA-TEST", + "description": "Expanded, Shift-Adjusted Stream Rating Template", + "dependent-parameter": "Flow", + "independent-parameter-specs": [ + { + "parameter": "Stage", + "in-range-method": "LINEAR", + "out-range-low-method": "LINEAR", + "out-range-high-method": "LINEAR" + } + ], + "rating-ids": [ + "TestRating.Stage;Flow.USGS-EXSA-TEST.USGS-NWIS-TEST" + ] +} \ No newline at end of file diff --git a/tests/cda/resources/spec.json b/tests/cda/resources/spec.json new file mode 100644 index 00000000..18aa66fc --- /dev/null +++ b/tests/cda/resources/spec.json @@ -0,0 +1,9 @@ +{ + "office-id": "MVP", + "rating-spec-id": "TestRating.Stage;Flow.USGS-EXSA-TEST.USGS-NWIS-TEST", + "template-id": "USGS-EXSA-TEST", + "ind-parameter": "Stage;ft", + "dep-parameter": "Flow;cfs", + "version": "pytest-version", + "description": "Pytest rating spec for EXSA test" +} \ No newline at end of file diff --git a/tests/cda/resources/table.json b/tests/cda/resources/table.json new file mode 100644 index 00000000..74b24fa0 --- /dev/null +++ b/tests/cda/resources/table.json @@ -0,0 +1,18 @@ +{ + "simple-rating": { + "office-id": "MVP", + "rating-spec-id": "TestRating.Stage;Flow.USGS-EXSA-TEST.USGS-NWIS-TEST", + "units-id": "ft;cfs", + "effective-date": "2023-01-01T00:00:00Z", + "transition-start-date": null, + "active": true, + "description": "Initial rating table for pytest", + "rating-points": { + "point": [ + { "ind": 1.0, "dep": 10.0 }, + { "ind": 2.0, "dep": 20.0 }, + { "ind": 3.0, "dep": 30.0 } + ] + } + } +} \ No newline at end of file diff --git a/tests/cda/resources/table_updated.json b/tests/cda/resources/table_updated.json new file mode 100644 index 00000000..a43aa86c --- /dev/null +++ b/tests/cda/resources/table_updated.json @@ -0,0 +1,18 @@ +{ + "simple-rating": { + "office-id": "MVP", + "rating-spec-id": "TestRating.Stage;Flow.USGS-EXSA-TEST.USGS-NWIS-TEST", + "units-id": "ft;cfs", + "effective-date": "2024-01-01T00:00:00Z", + "transition-start-date": null, + "active": true, + "description": "Updated rating table for pytest", + "rating-points": { + "point": [ + { "ind": 1.0, "dep": 11.0 }, + { "ind": 2.0, "dep": 22.0 }, + { "ind": 3.0, "dep": 33.0 } + ] + } + } +} \ No newline at end of file diff --git a/tests/cda/resources/template.json b/tests/cda/resources/template.json new file mode 100644 index 00000000..6e009b88 --- /dev/null +++ b/tests/cda/resources/template.json @@ -0,0 +1,15 @@ +{ + "office-id": "MVP", + "template-id": "USGS-EXSA-TEST", + "version": "USGS-EXSA-TEST", + "description": "Expanded, Shift-Adjusted Stream Rating Template", + "dependent-parameter": "Flow", + "independent-parameter-specs": [ + { + "parameter": "Stage", + "in-range-method": "LINEAR", + "out-range-low-method": "LINEAR", + "out-range-high-method": "LINEAR" + } + ] +} \ No newline at end of file From bf18b8ea4beb784a3fab5777f7270c4f65bb6385 Mon Sep 17 00:00:00 2001 From: Treyson Le Date: Fri, 5 Sep 2025 17:26:56 -0700 Subject: [PATCH 03/35] Update ratings_CDA_test.py --- tests/cda/ratings/{ratings_test.py => ratings_CDA_test.py} | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) rename tests/cda/ratings/{ratings_test.py => ratings_CDA_test.py} (97%) diff --git a/tests/cda/ratings/ratings_test.py b/tests/cda/ratings/ratings_CDA_test.py similarity index 97% rename from tests/cda/ratings/ratings_test.py rename to tests/cda/ratings/ratings_CDA_test.py index 47dc8f4a..bb07020b 100644 --- a/tests/cda/ratings/ratings_test.py +++ b/tests/cda/ratings/ratings_CDA_test.py @@ -10,10 +10,10 @@ import cwms.ratings.ratings_spec as ratings_spec import cwms.ratings.ratings_template as ratings_template -RESOURCES = Path(__file__).parent / "resources" +RESOURCES = Path(__file__).parent.parent / "resources" TEST_OFFICE = "MVP" -TEST_RATING_ID = "pytest_rating.Stage;ft.Flow;cfs.Linear.Production" +TEST_RATING_ID = "pytest_rating.Stage;ft.Flow;cfs.Linear" def load_json(name): From 411cdc43e0b8a4458bc664cfd84d3c29f5bd3d52 Mon Sep 17 00:00:00 2001 From: Treyson Le Date: Fri, 5 Sep 2025 17:46:33 -0700 Subject: [PATCH 04/35] Update location.json --- tests/cda/resources/location.json | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tests/cda/resources/location.json b/tests/cda/resources/location.json index d048534a..b1576fcc 100644 --- a/tests/cda/resources/location.json +++ b/tests/cda/resources/location.json @@ -1,16 +1,15 @@ { - "office-id": "MVP", - "location-id": "USGS-EXSA-TEST", "name": "USGS-EXSA-TEST", + "office-id": "MVP", "latitude": 40.0, "longitude": -105.0, "elevation": 1000.0, "horizontal-datum": "NAD83", "vertical-datum": "NAVD88", "location-type": "TESTING", - "location-kind": "SITE", "public-name": "EXSA Location", "long-name": "EXSA Location for Rating Tests", "timezone-name": "America/Chicago", + "location-kind": "SITE", "nation": "US" } \ No newline at end of file From 38e6079622cb9110cb920b3b63fa27c54aed47f1 Mon Sep 17 00:00:00 2001 From: Treyson Le Date: Fri, 5 Sep 2025 18:01:06 -0700 Subject: [PATCH 05/35] fix --- tests/cda/ratings/ratings_CDA_test.py | 26 +++++++++++------------- tests/cda/resources/rating_template.json | 14 ++++++------- tests/cda/resources/template.json | 11 ++++++---- 3 files changed, 26 insertions(+), 25 deletions(-) diff --git a/tests/cda/ratings/ratings_CDA_test.py b/tests/cda/ratings/ratings_CDA_test.py index bb07020b..3cdc417d 100644 --- a/tests/cda/ratings/ratings_CDA_test.py +++ b/tests/cda/ratings/ratings_CDA_test.py @@ -9,6 +9,7 @@ import cwms.ratings.ratings as ratings import cwms.ratings.ratings_spec as ratings_spec import cwms.ratings.ratings_template as ratings_template +from cwms.api import ApiError RESOURCES = Path(__file__).parent.parent / "resources" @@ -46,7 +47,13 @@ def setup_lifecycle_resources(): cwms.store_location(location_json) template_json = load_json("template.json") - ratings_template.store_rating_template(template_json) + try: + ratings_template.store_rating_template(template_json) + except ApiError: + # If the backend rejects this custom template, try falling back to a known template + # Update spec to use the standard 'Linear' template which is commonly available + if "template-id" in template_json and template_json["template-id"] != "Linear": + pass # We'll rely on spec.json to point at 'Linear' if needed spec_json = load_json("spec.json") ratings_spec.store_rating_spec(spec_json) @@ -66,7 +73,7 @@ def init_session(): print("Initializing CWMS API session for ratings tests...") -def test_rating_simple_df_to_json(): +def test_rating_simple_df_to_json(setup_unit_spec): now = datetime.now(timezone.utc).replace(microsecond=0) df = pd.DataFrame({"ind": [1.0, 2.0], "dep": [10.0, 20.0]}) @@ -85,7 +92,7 @@ def test_rating_simple_df_to_json(): assert len(json_out["simple-rating"]["rating-points"]["point"]) == 2 -def test_store_rating_and_get_current_rating(): +def test_store_rating_and_get_current_rating(setup_unit_spec): now = datetime.now(timezone.utc).replace(microsecond=0) df = pd.DataFrame({"ind": [1.0, 2.0], "dep": [10.0, 20.0]}) @@ -100,13 +107,13 @@ def test_store_rating_and_get_current_rating(): assert pytest.approx(data.df["dep"].iloc[0]) == 10.0 -def test_get_current_rating_xml(): +def test_get_current_rating_xml(setup_unit_spec): xml_data = ratings.get_current_rating_xml(TEST_RATING_ID, TEST_OFFICE) assert isinstance(xml_data, str) assert xml_data.startswith(" Date: Fri, 5 Sep 2025 18:12:18 -0700 Subject: [PATCH 06/35] fix --- tests/cda/ratings/ratings_CDA_test.py | 6 ++++-- tests/cda/resources/spec.json | 10 +++++----- tests/cda/resources/table.json | 2 +- tests/cda/resources/table_updated.json | 2 +- 4 files changed, 11 insertions(+), 9 deletions(-) diff --git a/tests/cda/ratings/ratings_CDA_test.py b/tests/cda/ratings/ratings_CDA_test.py index 3cdc417d..c7045deb 100644 --- a/tests/cda/ratings/ratings_CDA_test.py +++ b/tests/cda/ratings/ratings_CDA_test.py @@ -29,8 +29,10 @@ def setup_unit_spec(): "office-id": TEST_OFFICE, "rating-spec-id": TEST_RATING_ID, "template-id": "Linear", - "ind-parameter": "Stage;ft", - "dep-parameter": "Flow;cfs", + "ind-parameter": {"parameter": "Stage", "unit": "ft"}, + "dep-parameter": {"parameter": "Flow", "unit": "cfs"}, + "version": "pytest-version", + "description": "Pytest rating spec for tests", } ratings_spec.store_rating_spec(spec_json) diff --git a/tests/cda/resources/spec.json b/tests/cda/resources/spec.json index 18aa66fc..ac4fe7f0 100644 --- a/tests/cda/resources/spec.json +++ b/tests/cda/resources/spec.json @@ -1,9 +1,9 @@ { "office-id": "MVP", - "rating-spec-id": "TestRating.Stage;Flow.USGS-EXSA-TEST.USGS-NWIS-TEST", - "template-id": "USGS-EXSA-TEST", - "ind-parameter": "Stage;ft", - "dep-parameter": "Flow;cfs", + "rating-spec-id": "pytest_rating.Stage;ft.Flow;cfs.Linear", + "template-id": "Linear", + "ind-parameter": {"parameter": "Stage", "unit": "ft"}, + "dep-parameter": {"parameter": "Flow", "unit": "cfs"}, "version": "pytest-version", - "description": "Pytest rating spec for EXSA test" + "description": "Pytest rating spec for tests" } \ No newline at end of file diff --git a/tests/cda/resources/table.json b/tests/cda/resources/table.json index 74b24fa0..1856d474 100644 --- a/tests/cda/resources/table.json +++ b/tests/cda/resources/table.json @@ -1,7 +1,7 @@ { "simple-rating": { "office-id": "MVP", - "rating-spec-id": "TestRating.Stage;Flow.USGS-EXSA-TEST.USGS-NWIS-TEST", + "rating-spec-id": "pytest_rating.Stage;ft.Flow;cfs.Linear", "units-id": "ft;cfs", "effective-date": "2023-01-01T00:00:00Z", "transition-start-date": null, diff --git a/tests/cda/resources/table_updated.json b/tests/cda/resources/table_updated.json index a43aa86c..857d1061 100644 --- a/tests/cda/resources/table_updated.json +++ b/tests/cda/resources/table_updated.json @@ -1,7 +1,7 @@ { "simple-rating": { "office-id": "MVP", - "rating-spec-id": "TestRating.Stage;Flow.USGS-EXSA-TEST.USGS-NWIS-TEST", + "rating-spec-id": "pytest_rating.Stage;ft.Flow;cfs.Linear", "units-id": "ft;cfs", "effective-date": "2024-01-01T00:00:00Z", "transition-start-date": null, From da1303a7ab5936221cc3de1aa9b58761cdf1e0f2 Mon Sep 17 00:00:00 2001 From: Treyson Le Date: Tue, 9 Sep 2025 17:30:34 -0700 Subject: [PATCH 07/35] added changes --- tests/cda/ratings/ratings_CDA_test.py | 212 +++++++++----------------- tests/cda/resources/location.json | 6 +- 2 files changed, 72 insertions(+), 146 deletions(-) diff --git a/tests/cda/ratings/ratings_CDA_test.py b/tests/cda/ratings/ratings_CDA_test.py index c7045deb..a181c6c8 100644 --- a/tests/cda/ratings/ratings_CDA_test.py +++ b/tests/cda/ratings/ratings_CDA_test.py @@ -6,7 +6,6 @@ import pytest import cwms -import cwms.ratings.ratings as ratings import cwms.ratings.ratings_spec as ratings_spec import cwms.ratings.ratings_template as ratings_template from cwms.api import ApiError @@ -14,160 +13,87 @@ RESOURCES = Path(__file__).parent.parent / "resources" TEST_OFFICE = "MVP" -TEST_RATING_ID = "pytest_rating.Stage;ft.Flow;cfs.Linear" +TEST_LOCATION_ID = "pytest_template_group" +TEST_TEMPLATE_ID = "pytest_template.Linear" -def load_json(name): - with open(RESOURCES / name) as f: - return json.load(f) - - -@pytest.fixture(scope="module") -def setup_unit_spec(): - # Create rating spec for testing - spec_json = { +@pytest.fixture(scope="module", autouse=True) +def setup_data(): + location = { "office-id": TEST_OFFICE, - "rating-spec-id": TEST_RATING_ID, - "template-id": "Linear", - "ind-parameter": {"parameter": "Stage", "unit": "ft"}, - "dep-parameter": {"parameter": "Flow", "unit": "cfs"}, - "version": "pytest-version", - "description": "Pytest rating spec for tests", + "location-id": TEST_LOCATION_ID, + "location-name": "Pytest Template Location", + "location-type": "OTHER", + "latitude": 40.0, + "longitude": -90.0, + "elevation": 100.0, + "horizontal-datum": "NAD83", + "vertical-datum": "NAVD88", } - ratings_spec.store_rating_spec(spec_json) - + cwms.store_location(location) yield + cwms.delete_location(TEST_LOCATION_ID, TEST_OFFICE, cascade_delete=True) + + +@pytest.fixture(autouse=True) +def init_session(): + print("Initializing CWMS API session for template tests...") + + +def test_store_template(): + template_json = json.load(open(RESOURCES / "template.json")) + ratings_template.store_rating_template(template_json) + fetched = ratings_template.get_rating_template(TEST_TEMPLATE_ID, TEST_OFFICE) + assert fetched["template-id"] == TEST_TEMPLATE_ID + assert fetched["office-id"] == TEST_OFFICE - # Clean up - ratings_spec.delete_rating_spec(TEST_RATING_ID, TEST_OFFICE) +def test_get_template(): + fetched = ratings_template.get_rating_template(TEST_TEMPLATE_ID, TEST_OFFICE) + assert fetched["template-id"] == TEST_TEMPLATE_ID + assert fetched["office-id"] == TEST_OFFICE -@pytest.fixture(scope="module") -def setup_lifecycle_resources(): - # Prepare resources for lifecycle tests: location, template, spec - location_json = load_json("location.json") - cwms.store_location(location_json) - template_json = load_json("template.json") - try: - ratings_template.store_rating_template(template_json) - except ApiError: - # If the backend rejects this custom template, try falling back to a known template - # Update spec to use the standard 'Linear' template which is commonly available - if "template-id" in template_json and template_json["template-id"] != "Linear": - pass # We'll rely on spec.json to point at 'Linear' if needed +def test_update_template(): + template_json = json.load(open(RESOURCES / "template.json")) + template_json["description"] = template_json.get("description", "") + " - updated" + ratings_template.store_rating_template(template_json) + fetched = ratings_template.get_rating_template(TEST_TEMPLATE_ID, TEST_OFFICE) + assert fetched["description"].endswith(" - updated") - spec_json = load_json("spec.json") + +def test_delete_template(): + ratings_template.delete_rating_template(TEST_TEMPLATE_ID, TEST_OFFICE) + with pytest.raises(ApiError): + ratings_template.get_rating_template(TEST_TEMPLATE_ID, TEST_OFFICE) + + +# Rating specs +def test_store_rating_spec(): + spec_json = json.load(open(RESOURCES / "spec.json")) ratings_spec.store_rating_spec(spec_json) + fetched = ratings_spec.get_rating_spec(spec_json["rating-spec-id"], TEST_OFFICE) + assert fetched["rating-spec-id"] == spec_json["rating-spec-id"] + assert fetched["office-id"] == TEST_OFFICE - yield - # Cleanup lifecycle resources - ratings_spec.delete_rating_spec(spec_json["rating-spec-id"], spec_json["office-id"]) - ratings_template.delete_rating_template( - template_json["template-id"], template_json["office-id"] - ) - cwms.delete_location(location_json["location-id"], location_json["office-id"]) +def test_get_rating_spec(): + spec_json = json.load(open(RESOURCES / "spec.json")) + fetched = ratings_spec.get_rating_spec(spec_json["rating-spec-id"], TEST_OFFICE) + assert fetched["rating-spec-id"] == spec_json["rating-spec-id"] + assert fetched["office-id"] == TEST_OFFICE -@pytest.fixture(autouse=True) -def init_session(): - print("Initializing CWMS API session for ratings tests...") - - -def test_rating_simple_df_to_json(setup_unit_spec): - now = datetime.now(timezone.utc).replace(microsecond=0) - df = pd.DataFrame({"ind": [1.0, 2.0], "dep": [10.0, 20.0]}) - - json_out = ratings.rating_simple_df_to_json( - data=df, - rating_id=TEST_RATING_ID, - office_id=TEST_OFFICE, - units="ft;cfs", - effective_date=now, - description="pytest rating curve", - ) - - assert "simple-rating" in json_out - assert json_out["simple-rating"]["rating-spec-id"] == TEST_RATING_ID - assert json_out["simple-rating"]["units-id"] == "ft;cfs" - assert len(json_out["simple-rating"]["rating-points"]["point"]) == 2 - - -def test_store_rating_and_get_current_rating(setup_unit_spec): - now = datetime.now(timezone.utc).replace(microsecond=0) - df = pd.DataFrame({"ind": [1.0, 2.0], "dep": [10.0, 20.0]}) - - rating_json = ratings.rating_simple_df_to_json( - df, TEST_RATING_ID, TEST_OFFICE, "ft;cfs", effective_date=now - ) - ratings.store_rating(rating_json) - - data = ratings.get_current_rating(TEST_RATING_ID, TEST_OFFICE) - assert data.df is not None - assert not data.df.empty - assert pytest.approx(data.df["dep"].iloc[0]) == 10.0 - - -def test_get_current_rating_xml(setup_unit_spec): - xml_data = ratings.get_current_rating_xml(TEST_RATING_ID, TEST_OFFICE) - assert isinstance(xml_data, str) - assert xml_data.startswith(" Date: Wed, 10 Sep 2025 13:33:48 -0700 Subject: [PATCH 08/35] update --- tests/cda/ratings/ratings_CDA_test.py | 12 +----------- tests/cda/resources/rating_spec.json | 4 ++-- tests/cda/resources/spec.json | 2 +- 3 files changed, 4 insertions(+), 14 deletions(-) diff --git a/tests/cda/ratings/ratings_CDA_test.py b/tests/cda/ratings/ratings_CDA_test.py index a181c6c8..52b7b82a 100644 --- a/tests/cda/ratings/ratings_CDA_test.py +++ b/tests/cda/ratings/ratings_CDA_test.py @@ -19,17 +19,7 @@ @pytest.fixture(scope="module", autouse=True) def setup_data(): - location = { - "office-id": TEST_OFFICE, - "location-id": TEST_LOCATION_ID, - "location-name": "Pytest Template Location", - "location-type": "OTHER", - "latitude": 40.0, - "longitude": -90.0, - "elevation": 100.0, - "horizontal-datum": "NAD83", - "vertical-datum": "NAVD88", - } + location = json.load(open(RESOURCES / "location.json")) cwms.store_location(location) yield cwms.delete_location(TEST_LOCATION_ID, TEST_OFFICE, cascade_delete=True) diff --git a/tests/cda/resources/rating_spec.json b/tests/cda/resources/rating_spec.json index 18aa66fc..86c379f2 100644 --- a/tests/cda/resources/rating_spec.json +++ b/tests/cda/resources/rating_spec.json @@ -1,7 +1,7 @@ { "office-id": "MVP", - "rating-spec-id": "TestRating.Stage;Flow.USGS-EXSA-TEST.USGS-NWIS-TEST", - "template-id": "USGS-EXSA-TEST", + "rating-spec-id": "pytest_template_group.Stage;Flow.pytest_template.Linear.pytest-version", + "template-id": "pytest_template.Linear", "ind-parameter": "Stage;ft", "dep-parameter": "Flow;cfs", "version": "pytest-version", diff --git a/tests/cda/resources/spec.json b/tests/cda/resources/spec.json index ac4fe7f0..873e1256 100644 --- a/tests/cda/resources/spec.json +++ b/tests/cda/resources/spec.json @@ -1,6 +1,6 @@ { "office-id": "MVP", - "rating-spec-id": "pytest_rating.Stage;ft.Flow;cfs.Linear", + "rating-spec-id": "pytest_rating.Stage;ft.Flow;cfs.Linear.pytest-version", "template-id": "Linear", "ind-parameter": {"parameter": "Stage", "unit": "ft"}, "dep-parameter": {"parameter": "Flow", "unit": "cfs"}, From 621d7e2827c38ca1636f84c11699ad045e89b553 Mon Sep 17 00:00:00 2001 From: Treyson Le Date: Wed, 10 Sep 2025 13:44:09 -0700 Subject: [PATCH 09/35] update --- tests/cda/resources/location.json | 1 + tests/cda/resources/spec.json | 4 ++-- tests/cda/resources/template.json | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/tests/cda/resources/location.json b/tests/cda/resources/location.json index cbac56d4..c6a78914 100644 --- a/tests/cda/resources/location.json +++ b/tests/cda/resources/location.json @@ -1,6 +1,7 @@ { "name": "TestRating", "office-id": "MVP", + "location-id": "pytest_template_group", "latitude": 40.0, "longitude": -105.0, "elevation": 1000.0, diff --git a/tests/cda/resources/spec.json b/tests/cda/resources/spec.json index 873e1256..017bac6b 100644 --- a/tests/cda/resources/spec.json +++ b/tests/cda/resources/spec.json @@ -1,7 +1,7 @@ { "office-id": "MVP", - "rating-spec-id": "pytest_rating.Stage;ft.Flow;cfs.Linear.pytest-version", - "template-id": "Linear", + "rating-spec-id": "pytest_template_group.Stage;Flow.pytest_template.Linear.pytest-version", + "template-id": "pytest_template.Linear", "ind-parameter": {"parameter": "Stage", "unit": "ft"}, "dep-parameter": {"parameter": "Flow", "unit": "cfs"}, "version": "pytest-version", diff --git a/tests/cda/resources/template.json b/tests/cda/resources/template.json index 373c4a3b..c19a3e36 100644 --- a/tests/cda/resources/template.json +++ b/tests/cda/resources/template.json @@ -1,6 +1,6 @@ { "office-id": "MVP", - "template-id": "Linear", + "template-id": "pytest_template.Linear", "description": "Linear stage-to-flow template", "dependent-parameter": { "parameter": "Flow", From 3215c57297e6672c0df3df01ac8e08594032117b Mon Sep 17 00:00:00 2001 From: Treyson Le Date: Wed, 10 Sep 2025 14:54:29 -0700 Subject: [PATCH 10/35] Update location.json --- tests/cda/resources/location.json | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tests/cda/resources/location.json b/tests/cda/resources/location.json index c6a78914..ecfb4f9f 100644 --- a/tests/cda/resources/location.json +++ b/tests/cda/resources/location.json @@ -1,16 +1,15 @@ { "name": "TestRating", - "office-id": "MVP", - "location-id": "pytest_template_group", "latitude": 40.0, "longitude": -105.0, "elevation": 1000.0, "horizontal-datum": "NAD83", "vertical-datum": "NAVD88", + "office-id": "MVP", "location-type": "TESTING", + "location-kind": "pytest_template_group", "public-name": "Test Location", "long-name": "Test Location for Rating Tests", "timezone-name": "America/Chicago", - "location-kind": "SITE", "nation": "US" } \ No newline at end of file From 7a9f23047848adc79bc7c39cfcdfa1ea87c10976 Mon Sep 17 00:00:00 2001 From: Treyson Le Date: Thu, 11 Sep 2025 16:19:04 -0700 Subject: [PATCH 11/35] Switching to XML --- tests/cda/ratings/ratings_CDA_test.py | 61 ++++++++++++++++++--------- tests/cda/resources/spec.json | 9 ---- tests/cda/resources/spec.xml | 20 +++++++++ tests/cda/resources/template.json | 18 -------- tests/cda/resources/template.xml | 15 +++++++ 5 files changed, 75 insertions(+), 48 deletions(-) delete mode 100644 tests/cda/resources/spec.json create mode 100644 tests/cda/resources/spec.xml delete mode 100644 tests/cda/resources/template.json create mode 100644 tests/cda/resources/template.xml diff --git a/tests/cda/ratings/ratings_CDA_test.py b/tests/cda/ratings/ratings_CDA_test.py index 52b7b82a..c72a66aa 100644 --- a/tests/cda/ratings/ratings_CDA_test.py +++ b/tests/cda/ratings/ratings_CDA_test.py @@ -31,8 +31,8 @@ def init_session(): def test_store_template(): - template_json = json.load(open(RESOURCES / "template.json")) - ratings_template.store_rating_template(template_json) + template_xml = (RESOURCES / "template.xml").read_text() + ratings_template.store_rating_template(template_xml) fetched = ratings_template.get_rating_template(TEST_TEMPLATE_ID, TEST_OFFICE) assert fetched["template-id"] == TEST_TEMPLATE_ID assert fetched["office-id"] == TEST_OFFICE @@ -45,11 +45,11 @@ def test_get_template(): def test_update_template(): - template_json = json.load(open(RESOURCES / "template.json")) - template_json["description"] = template_json.get("description", "") + " - updated" - ratings_template.store_rating_template(template_json) fetched = ratings_template.get_rating_template(TEST_TEMPLATE_ID, TEST_OFFICE) - assert fetched["description"].endswith(" - updated") + fetched["description"] = fetched.get("description", "") + " - updated" + ratings_template.store_rating_template(fetched) + updated = ratings_template.get_rating_template(TEST_TEMPLATE_ID, TEST_OFFICE) + assert updated["description"].endswith(" - updated") def test_delete_template(): @@ -60,30 +60,49 @@ def test_delete_template(): # Rating specs def test_store_rating_spec(): - spec_json = json.load(open(RESOURCES / "spec.json")) - ratings_spec.store_rating_spec(spec_json) - fetched = ratings_spec.get_rating_spec(spec_json["rating-spec-id"], TEST_OFFICE) - assert fetched["rating-spec-id"] == spec_json["rating-spec-id"] + spec_xml = (RESOURCES / "spec.xml").read_text() + ratings_spec.store_rating_spec(spec_xml) + # Parse spec_xml to get rating-spec-id for fetching + # If spec_xml contains element, parse it: + import xml.etree.ElementTree as ET + + root = ET.fromstring(spec_xml) + rating_spec_id = root.findtext("rating-spec-id") + fetched = ratings_spec.get_rating_spec(rating_spec_id, TEST_OFFICE) + assert fetched["rating-spec-id"] == rating_spec_id assert fetched["office-id"] == TEST_OFFICE def test_get_rating_spec(): - spec_json = json.load(open(RESOURCES / "spec.json")) - fetched = ratings_spec.get_rating_spec(spec_json["rating-spec-id"], TEST_OFFICE) - assert fetched["rating-spec-id"] == spec_json["rating-spec-id"] + spec_xml = (RESOURCES / "spec.xml").read_text() + import xml.etree.ElementTree as ET + + root = ET.fromstring(spec_xml) + rating_spec_id = root.findtext("rating-spec-id") + fetched = ratings_spec.get_rating_spec(rating_spec_id, TEST_OFFICE) + assert fetched["rating-spec-id"] == rating_spec_id assert fetched["office-id"] == TEST_OFFICE def test_update_rating_spec(): - spec_json = json.load(open(RESOURCES / "spec.json")) - spec_json["description"] = spec_json.get("description", "") + " - updated" - ratings_spec.store_rating_spec(spec_json) - fetched = ratings_spec.get_rating_spec(spec_json["rating-spec-id"], TEST_OFFICE) - assert fetched["description"].endswith(" - updated") + spec_xml = (RESOURCES / "spec.xml").read_text() + import xml.etree.ElementTree as ET + + root = ET.fromstring(spec_xml) + rating_spec_id = root.findtext("rating-spec-id") + fetched = ratings_spec.get_rating_spec(rating_spec_id, TEST_OFFICE) + fetched["description"] = fetched.get("description", "") + " - updated" + ratings_spec.store_rating_spec(fetched) + updated = ratings_spec.get_rating_spec(rating_spec_id, TEST_OFFICE) + assert updated["description"].endswith(" - updated") def test_delete_rating_spec(): - spec_json = json.load(open(RESOURCES / "spec.json")) - ratings_spec.delete_rating_spec(spec_json["rating-spec-id"], TEST_OFFICE) + spec_xml = (RESOURCES / "spec.xml").read_text() + import xml.etree.ElementTree as ET + + root = ET.fromstring(spec_xml) + rating_spec_id = root.findtext("rating-spec-id") + ratings_spec.delete_rating_spec(rating_spec_id, TEST_OFFICE) with pytest.raises(ApiError): - ratings_spec.get_rating_spec(spec_json["rating-spec-id"], TEST_OFFICE) + ratings_spec.get_rating_spec(rating_spec_id, TEST_OFFICE) diff --git a/tests/cda/resources/spec.json b/tests/cda/resources/spec.json deleted file mode 100644 index 017bac6b..00000000 --- a/tests/cda/resources/spec.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "office-id": "MVP", - "rating-spec-id": "pytest_template_group.Stage;Flow.pytest_template.Linear.pytest-version", - "template-id": "pytest_template.Linear", - "ind-parameter": {"parameter": "Stage", "unit": "ft"}, - "dep-parameter": {"parameter": "Flow", "unit": "cfs"}, - "version": "pytest-version", - "description": "Pytest rating spec for tests" -} \ No newline at end of file diff --git a/tests/cda/resources/spec.xml b/tests/cda/resources/spec.xml new file mode 100644 index 00000000..ff3e4a30 --- /dev/null +++ b/tests/cda/resources/spec.xml @@ -0,0 +1,20 @@ + + + TestRating.Stage;Flow.TEST.Spec-test + Stage;Flow.TEST + TestRating + Spec-test + USGS + LINEAR + NEAREST + NEAREST + true + true + true + true + + 2223456782 + + 2222233332 + TESTing rating spec + \ No newline at end of file diff --git a/tests/cda/resources/template.json b/tests/cda/resources/template.json deleted file mode 100644 index c19a3e36..00000000 --- a/tests/cda/resources/template.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "office-id": "MVP", - "template-id": "pytest_template.Linear", - "description": "Linear stage-to-flow template", - "dependent-parameter": { - "parameter": "Flow", - "unit": "cfs" - }, - "independent-parameter-specs": [ - { - "parameter": "Stage", - "unit": "ft", - "in-range-method": "LINEAR", - "out-range-low-method": "LINEAR", - "out-range-high-method": "LINEAR" - } - ] -} \ No newline at end of file diff --git a/tests/cda/resources/template.xml b/tests/cda/resources/template.xml new file mode 100644 index 00000000..cd117cfe --- /dev/null +++ b/tests/cda/resources/template.xml @@ -0,0 +1,15 @@ + + +Stage;Flow +TEST\ + + + Stage + LINEAR + LINEAR + LINEAR + + + Flow + Expanded, Shift-Adjusted Stream Rating + \ No newline at end of file From 02ad2ac1393216c31a9d2d4f829281b1977b0b9c Mon Sep 17 00:00:00 2001 From: Treyson Le Date: Tue, 16 Sep 2025 13:09:34 -0700 Subject: [PATCH 12/35] Update ratings_CDA_test.py --- tests/cda/ratings/ratings_CDA_test.py | 33 +++++++++++++++------------ 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/tests/cda/ratings/ratings_CDA_test.py b/tests/cda/ratings/ratings_CDA_test.py index c72a66aa..b5d30fbc 100644 --- a/tests/cda/ratings/ratings_CDA_test.py +++ b/tests/cda/ratings/ratings_CDA_test.py @@ -22,7 +22,10 @@ def setup_data(): location = json.load(open(RESOURCES / "location.json")) cwms.store_location(location) yield - cwms.delete_location(TEST_LOCATION_ID, TEST_OFFICE, cascade_delete=True) + try: + cwms.delete_location(TEST_LOCATION_ID, TEST_OFFICE, cascade_delete=True) + except ApiError: + pass @pytest.fixture(autouse=True) @@ -34,26 +37,26 @@ def test_store_template(): template_xml = (RESOURCES / "template.xml").read_text() ratings_template.store_rating_template(template_xml) fetched = ratings_template.get_rating_template(TEST_TEMPLATE_ID, TEST_OFFICE) - assert fetched["template-id"] == TEST_TEMPLATE_ID - assert fetched["office-id"] == TEST_OFFICE + assert fetched.template_id == TEST_TEMPLATE_ID + assert fetched.office_id == TEST_OFFICE def test_get_template(): fetched = ratings_template.get_rating_template(TEST_TEMPLATE_ID, TEST_OFFICE) - assert fetched["template-id"] == TEST_TEMPLATE_ID - assert fetched["office-id"] == TEST_OFFICE + assert fetched.template_id == TEST_TEMPLATE_ID + assert fetched.office_id == TEST_OFFICE def test_update_template(): fetched = ratings_template.get_rating_template(TEST_TEMPLATE_ID, TEST_OFFICE) - fetched["description"] = fetched.get("description", "") + " - updated" + fetched.description = (fetched.description or "") + " - updated" ratings_template.store_rating_template(fetched) updated = ratings_template.get_rating_template(TEST_TEMPLATE_ID, TEST_OFFICE) - assert updated["description"].endswith(" - updated") + assert updated.description.endswith(" - updated") def test_delete_template(): - ratings_template.delete_rating_template(TEST_TEMPLATE_ID, TEST_OFFICE) + ratings_template.delete_rating_template(TEST_TEMPLATE_ID, TEST_OFFICE, "DELETE") with pytest.raises(ApiError): ratings_template.get_rating_template(TEST_TEMPLATE_ID, TEST_OFFICE) @@ -69,8 +72,8 @@ def test_store_rating_spec(): root = ET.fromstring(spec_xml) rating_spec_id = root.findtext("rating-spec-id") fetched = ratings_spec.get_rating_spec(rating_spec_id, TEST_OFFICE) - assert fetched["rating-spec-id"] == rating_spec_id - assert fetched["office-id"] == TEST_OFFICE + assert fetched.rating_spec_id == rating_spec_id + assert fetched.office_id == TEST_OFFICE def test_get_rating_spec(): @@ -80,8 +83,8 @@ def test_get_rating_spec(): root = ET.fromstring(spec_xml) rating_spec_id = root.findtext("rating-spec-id") fetched = ratings_spec.get_rating_spec(rating_spec_id, TEST_OFFICE) - assert fetched["rating-spec-id"] == rating_spec_id - assert fetched["office-id"] == TEST_OFFICE + assert fetched.rating_spec_id == rating_spec_id + assert fetched.office_id == TEST_OFFICE def test_update_rating_spec(): @@ -91,10 +94,10 @@ def test_update_rating_spec(): root = ET.fromstring(spec_xml) rating_spec_id = root.findtext("rating-spec-id") fetched = ratings_spec.get_rating_spec(rating_spec_id, TEST_OFFICE) - fetched["description"] = fetched.get("description", "") + " - updated" + fetched.description = (fetched.description or "") + " - updated" ratings_spec.store_rating_spec(fetched) updated = ratings_spec.get_rating_spec(rating_spec_id, TEST_OFFICE) - assert updated["description"].endswith(" - updated") + assert updated.description.endswith(" - updated") def test_delete_rating_spec(): @@ -103,6 +106,6 @@ def test_delete_rating_spec(): root = ET.fromstring(spec_xml) rating_spec_id = root.findtext("rating-spec-id") - ratings_spec.delete_rating_spec(rating_spec_id, TEST_OFFICE) + ratings_spec.delete_rating_spec(rating_spec_id, TEST_OFFICE, "DELETE") with pytest.raises(ApiError): ratings_spec.get_rating_spec(rating_spec_id, TEST_OFFICE) From 5a1bd952c5f142c88ea7b5a3d29e1bd848692753 Mon Sep 17 00:00:00 2001 From: Treyson Le Date: Tue, 16 Sep 2025 13:17:17 -0700 Subject: [PATCH 13/35] Update ratings_CDA_test.py --- tests/cda/ratings/ratings_CDA_test.py | 32 +++++++++++++++++---------- 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/tests/cda/ratings/ratings_CDA_test.py b/tests/cda/ratings/ratings_CDA_test.py index b5d30fbc..a52ba4e9 100644 --- a/tests/cda/ratings/ratings_CDA_test.py +++ b/tests/cda/ratings/ratings_CDA_test.py @@ -34,17 +34,20 @@ def init_session(): def test_store_template(): + from cwms.ratings import RatingTemplate + template_xml = (RESOURCES / "template.xml").read_text() - ratings_template.store_rating_template(template_xml) + template = RatingTemplate.from_xml(template_xml) + ratings_template.store_rating_template(template) fetched = ratings_template.get_rating_template(TEST_TEMPLATE_ID, TEST_OFFICE) - assert fetched.template_id == TEST_TEMPLATE_ID - assert fetched.office_id == TEST_OFFICE + assert fetched.id == TEST_TEMPLATE_ID + assert fetched.office == TEST_OFFICE def test_get_template(): fetched = ratings_template.get_rating_template(TEST_TEMPLATE_ID, TEST_OFFICE) - assert fetched.template_id == TEST_TEMPLATE_ID - assert fetched.office_id == TEST_OFFICE + assert fetched.id == TEST_TEMPLATE_ID + assert fetched.office == TEST_OFFICE def test_update_template(): @@ -56,15 +59,18 @@ def test_update_template(): def test_delete_template(): - ratings_template.delete_rating_template(TEST_TEMPLATE_ID, TEST_OFFICE, "DELETE") + ratings_template.delete_rating_template(TEST_TEMPLATE_ID, TEST_OFFICE, "DELETE_ALL") with pytest.raises(ApiError): ratings_template.get_rating_template(TEST_TEMPLATE_ID, TEST_OFFICE) # Rating specs def test_store_rating_spec(): + from cwms.ratings import RatingSpec + spec_xml = (RESOURCES / "spec.xml").read_text() - ratings_spec.store_rating_spec(spec_xml) + spec = RatingSpec.from_xml(spec_xml) + ratings_spec.store_rating_spec(spec) # Parse spec_xml to get rating-spec-id for fetching # If spec_xml contains element, parse it: import xml.etree.ElementTree as ET @@ -72,8 +78,8 @@ def test_store_rating_spec(): root = ET.fromstring(spec_xml) rating_spec_id = root.findtext("rating-spec-id") fetched = ratings_spec.get_rating_spec(rating_spec_id, TEST_OFFICE) - assert fetched.rating_spec_id == rating_spec_id - assert fetched.office_id == TEST_OFFICE + assert fetched.id == rating_spec_id + assert fetched.office == TEST_OFFICE def test_get_rating_spec(): @@ -83,11 +89,13 @@ def test_get_rating_spec(): root = ET.fromstring(spec_xml) rating_spec_id = root.findtext("rating-spec-id") fetched = ratings_spec.get_rating_spec(rating_spec_id, TEST_OFFICE) - assert fetched.rating_spec_id == rating_spec_id - assert fetched.office_id == TEST_OFFICE + assert fetched.id == rating_spec_id + assert fetched.office == TEST_OFFICE def test_update_rating_spec(): + from cwms.ratings import RatingSpec + spec_xml = (RESOURCES / "spec.xml").read_text() import xml.etree.ElementTree as ET @@ -106,6 +114,6 @@ def test_delete_rating_spec(): root = ET.fromstring(spec_xml) rating_spec_id = root.findtext("rating-spec-id") - ratings_spec.delete_rating_spec(rating_spec_id, TEST_OFFICE, "DELETE") + ratings_spec.delete_rating_spec(rating_spec_id, TEST_OFFICE, "DELETE_ALL") with pytest.raises(ApiError): ratings_spec.get_rating_spec(rating_spec_id, TEST_OFFICE) From 98e33d63742823d42c26d3f467f9d566baf2d049 Mon Sep 17 00:00:00 2001 From: Treyson Le Date: Tue, 16 Sep 2025 13:51:02 -0700 Subject: [PATCH 14/35] Update ratings_CDA_test.py --- tests/cda/ratings/ratings_CDA_test.py | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/tests/cda/ratings/ratings_CDA_test.py b/tests/cda/ratings/ratings_CDA_test.py index a52ba4e9..49d99829 100644 --- a/tests/cda/ratings/ratings_CDA_test.py +++ b/tests/cda/ratings/ratings_CDA_test.py @@ -34,11 +34,8 @@ def init_session(): def test_store_template(): - from cwms.ratings import RatingTemplate - template_xml = (RESOURCES / "template.xml").read_text() - template = RatingTemplate.from_xml(template_xml) - ratings_template.store_rating_template(template) + ratings_template.store_rating_template(template_xml) fetched = ratings_template.get_rating_template(TEST_TEMPLATE_ID, TEST_OFFICE) assert fetched.id == TEST_TEMPLATE_ID assert fetched.office == TEST_OFFICE @@ -53,7 +50,7 @@ def test_get_template(): def test_update_template(): fetched = ratings_template.get_rating_template(TEST_TEMPLATE_ID, TEST_OFFICE) fetched.description = (fetched.description or "") + " - updated" - ratings_template.store_rating_template(fetched) + ratings_template.store_rating_template(fetched.json) updated = ratings_template.get_rating_template(TEST_TEMPLATE_ID, TEST_OFFICE) assert updated.description.endswith(" - updated") @@ -66,11 +63,8 @@ def test_delete_template(): # Rating specs def test_store_rating_spec(): - from cwms.ratings import RatingSpec - spec_xml = (RESOURCES / "spec.xml").read_text() - spec = RatingSpec.from_xml(spec_xml) - ratings_spec.store_rating_spec(spec) + ratings_spec.store_rating_spec(spec_xml) # Parse spec_xml to get rating-spec-id for fetching # If spec_xml contains element, parse it: import xml.etree.ElementTree as ET @@ -94,8 +88,6 @@ def test_get_rating_spec(): def test_update_rating_spec(): - from cwms.ratings import RatingSpec - spec_xml = (RESOURCES / "spec.xml").read_text() import xml.etree.ElementTree as ET From cfa8131f30a177ec30e607ca60cf3ec0e2dc1fed Mon Sep 17 00:00:00 2001 From: Treyson Le Date: Thu, 18 Sep 2025 13:09:42 -0700 Subject: [PATCH 15/35] Updated compatability --- tests/cda/ratings/ratings_CDA_test.py | 15 ++++++++------- tests/cda/resources/spec.xml | 2 +- tests/cda/resources/template.xml | 1 + 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/tests/cda/ratings/ratings_CDA_test.py b/tests/cda/ratings/ratings_CDA_test.py index 49d99829..6885c40d 100644 --- a/tests/cda/ratings/ratings_CDA_test.py +++ b/tests/cda/ratings/ratings_CDA_test.py @@ -72,8 +72,8 @@ def test_store_rating_spec(): root = ET.fromstring(spec_xml) rating_spec_id = root.findtext("rating-spec-id") fetched = ratings_spec.get_rating_spec(rating_spec_id, TEST_OFFICE) - assert fetched.id == rating_spec_id - assert fetched.office == TEST_OFFICE + assert fetched.json["rating-spec-id"] == rating_spec_id + assert fetched.json["office-id"] == TEST_OFFICE def test_get_rating_spec(): @@ -83,8 +83,8 @@ def test_get_rating_spec(): root = ET.fromstring(spec_xml) rating_spec_id = root.findtext("rating-spec-id") fetched = ratings_spec.get_rating_spec(rating_spec_id, TEST_OFFICE) - assert fetched.id == rating_spec_id - assert fetched.office == TEST_OFFICE + assert fetched.json["rating-spec-id"] == rating_spec_id + assert fetched.json["office-id"] == TEST_OFFICE def test_update_rating_spec(): @@ -94,10 +94,11 @@ def test_update_rating_spec(): root = ET.fromstring(spec_xml) rating_spec_id = root.findtext("rating-spec-id") fetched = ratings_spec.get_rating_spec(rating_spec_id, TEST_OFFICE) - fetched.description = (fetched.description or "") + " - updated" - ratings_spec.store_rating_spec(fetched) + fetched_json = fetched.json + fetched_json["description"] = (fetched_json.get("description") or "") + " - updated" + ratings_spec.store_rating_spec(fetched_json) updated = ratings_spec.get_rating_spec(rating_spec_id, TEST_OFFICE) - assert updated.description.endswith(" - updated") + assert updated.json["description"].endswith(" - updated") def test_delete_rating_spec(): diff --git a/tests/cda/resources/spec.xml b/tests/cda/resources/spec.xml index ff3e4a30..37d247f0 100644 --- a/tests/cda/resources/spec.xml +++ b/tests/cda/resources/spec.xml @@ -1,7 +1,7 @@ TestRating.Stage;Flow.TEST.Spec-test - Stage;Flow.TEST + pytest_template.Linear TestRating Spec-test USGS diff --git a/tests/cda/resources/template.xml b/tests/cda/resources/template.xml index cd117cfe..efe96409 100644 --- a/tests/cda/resources/template.xml +++ b/tests/cda/resources/template.xml @@ -1,5 +1,6 @@ +pytest_template.Linear Stage;Flow TEST\ From d695d5c69c9917bc12e8fa3422be0914a3a3672b Mon Sep 17 00:00:00 2001 From: Treyson Le Date: Thu, 18 Sep 2025 13:43:24 -0700 Subject: [PATCH 16/35] Update ratings_CDA_test.py --- tests/cda/ratings/ratings_CDA_test.py | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/tests/cda/ratings/ratings_CDA_test.py b/tests/cda/ratings/ratings_CDA_test.py index 6885c40d..19f2ef00 100644 --- a/tests/cda/ratings/ratings_CDA_test.py +++ b/tests/cda/ratings/ratings_CDA_test.py @@ -37,22 +37,23 @@ def test_store_template(): template_xml = (RESOURCES / "template.xml").read_text() ratings_template.store_rating_template(template_xml) fetched = ratings_template.get_rating_template(TEST_TEMPLATE_ID, TEST_OFFICE) - assert fetched.id == TEST_TEMPLATE_ID - assert fetched.office == TEST_OFFICE + assert fetched.json["template-id"] == TEST_TEMPLATE_ID + assert fetched.json["office-id"] == TEST_OFFICE def test_get_template(): fetched = ratings_template.get_rating_template(TEST_TEMPLATE_ID, TEST_OFFICE) - assert fetched.id == TEST_TEMPLATE_ID - assert fetched.office == TEST_OFFICE + assert fetched.json["template-id"] == TEST_TEMPLATE_ID + assert fetched.json["office-id"] == TEST_OFFICE def test_update_template(): fetched = ratings_template.get_rating_template(TEST_TEMPLATE_ID, TEST_OFFICE) - fetched.description = (fetched.description or "") + " - updated" - ratings_template.store_rating_template(fetched.json) + fetched_json = fetched.json + fetched_json["description"] = (fetched_json.get("description") or "") + " - updated" + ratings_template.store_rating_template(fetched_json) updated = ratings_template.get_rating_template(TEST_TEMPLATE_ID, TEST_OFFICE) - assert updated.description.endswith(" - updated") + assert updated.json["description"].endswith(" - updated") def test_delete_template(): From b4a2ff4caca1444da8181010af5a568b4cd2fbd2 Mon Sep 17 00:00:00 2001 From: Treyson Le Date: Thu, 18 Sep 2025 13:44:15 -0700 Subject: [PATCH 17/35] Update ratings_CDA_test.py --- tests/cda/ratings/ratings_CDA_test.py | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/tests/cda/ratings/ratings_CDA_test.py b/tests/cda/ratings/ratings_CDA_test.py index 19f2ef00..52edd505 100644 --- a/tests/cda/ratings/ratings_CDA_test.py +++ b/tests/cda/ratings/ratings_CDA_test.py @@ -89,17 +89,29 @@ def test_get_rating_spec(): def test_update_rating_spec(): - spec_xml = (RESOURCES / "spec.xml").read_text() import xml.etree.ElementTree as ET - root = ET.fromstring(spec_xml) + # Parse the original spec XML + spec_path = RESOURCES / "spec.xml" + tree = ET.parse(spec_path) + root = tree.getroot() + + # Update or create the element + desc = root.find("description") + if desc is None: + desc = ET.SubElement(root, "description") + desc.text = (desc.text or "") + " - updated" + + # Convert tree back to string with XML declaration + updated_xml = ET.tostring(root, encoding="unicode", xml_declaration=True) + + # Store the updated rating spec + ratings_spec.store_rating_spec(updated_xml) + + # Fetch and assert the description was updated rating_spec_id = root.findtext("rating-spec-id") fetched = ratings_spec.get_rating_spec(rating_spec_id, TEST_OFFICE) - fetched_json = fetched.json - fetched_json["description"] = (fetched_json.get("description") or "") + " - updated" - ratings_spec.store_rating_spec(fetched_json) - updated = ratings_spec.get_rating_spec(rating_spec_id, TEST_OFFICE) - assert updated.json["description"].endswith(" - updated") + assert fetched.json["description"].endswith(" - updated") def test_delete_rating_spec(): From 1a28641b2dfa1d0e1bc64d24218b2ef0569f023f Mon Sep 17 00:00:00 2001 From: Treyson Le Date: Thu, 18 Sep 2025 16:00:52 -0700 Subject: [PATCH 18/35] reset the tests --- tests/cda/ratings/ratings_CDA_test.py | 90 ++++++++++++--------------- tests/cda/resources/spec.xml | 2 +- tests/cda/resources/template.xml | 1 - 3 files changed, 41 insertions(+), 52 deletions(-) diff --git a/tests/cda/ratings/ratings_CDA_test.py b/tests/cda/ratings/ratings_CDA_test.py index 52edd505..fea5655b 100644 --- a/tests/cda/ratings/ratings_CDA_test.py +++ b/tests/cda/ratings/ratings_CDA_test.py @@ -1,4 +1,5 @@ import json +import xml.etree.ElementTree as ET from datetime import datetime, timedelta, timezone from pathlib import Path @@ -13,8 +14,22 @@ RESOURCES = Path(__file__).parent.parent / "resources" TEST_OFFICE = "MVP" -TEST_LOCATION_ID = "pytest_template_group" -TEST_TEMPLATE_ID = "pytest_template.Linear" + +# Parse template.xml to construct template ID +template_xml = (RESOURCES / "template.xml").read_text() +template_root = ET.fromstring(template_xml) +parameters_id = template_root.findtext("parameters-id") +template_version = template_root.findtext("version") + +TEST_TEMPLATE_ID = f"{parameters_id}.{template_version}" # Stage;Flow.TEST + +# Parse spec.xml to get rating-spec-id +spec_xml = (RESOURCES / "spec.xml").read_text() +spec_root = ET.fromstring(spec_xml) + +TEST_RATING_SPEC_ID = spec_root.findtext( + "rating-spec-id" +) # TestRating.Stage;Flow.TEST.Spec-test @pytest.fixture(scope="module", autouse=True) @@ -23,18 +38,19 @@ def setup_data(): cwms.store_location(location) yield try: - cwms.delete_location(TEST_LOCATION_ID, TEST_OFFICE, cascade_delete=True) + cwms.delete_location( + spec_root.findtext("location-id"), TEST_OFFICE, cascade_delete=True + ) except ApiError: pass @pytest.fixture(autouse=True) def init_session(): - print("Initializing CWMS API session for template tests...") + print("Initializing CWMS API session for ratings tests...") def test_store_template(): - template_xml = (RESOURCES / "template.xml").read_text() ratings_template.store_rating_template(template_xml) fetched = ratings_template.get_rating_template(TEST_TEMPLATE_ID, TEST_OFFICE) assert fetched.json["template-id"] == TEST_TEMPLATE_ID @@ -48,10 +64,14 @@ def test_get_template(): def test_update_template(): - fetched = ratings_template.get_rating_template(TEST_TEMPLATE_ID, TEST_OFFICE) - fetched_json = fetched.json - fetched_json["description"] = (fetched_json.get("description") or "") + " - updated" - ratings_template.store_rating_template(fetched_json) + template_root = ET.fromstring(template_xml) + desc = template_root.find("description") + if desc is None: + desc = ET.SubElement(template_root, "description") + desc.text = (desc.text or "") + " - updated" + + updated_xml = ET.tostring(template_root, encoding="unicode", xml_declaration=True) + ratings_template.store_rating_template(updated_xml) updated = ratings_template.get_rating_template(TEST_TEMPLATE_ID, TEST_OFFICE) assert updated.json["description"].endswith(" - updated") @@ -64,62 +84,32 @@ def test_delete_template(): # Rating specs def test_store_rating_spec(): - spec_xml = (RESOURCES / "spec.xml").read_text() ratings_spec.store_rating_spec(spec_xml) - # Parse spec_xml to get rating-spec-id for fetching - # If spec_xml contains element, parse it: - import xml.etree.ElementTree as ET - - root = ET.fromstring(spec_xml) - rating_spec_id = root.findtext("rating-spec-id") - fetched = ratings_spec.get_rating_spec(rating_spec_id, TEST_OFFICE) - assert fetched.json["rating-spec-id"] == rating_spec_id + fetched = ratings_spec.get_rating_spec(TEST_RATING_SPEC_ID, TEST_OFFICE) + assert fetched.json["rating-spec-id"] == TEST_RATING_SPEC_ID assert fetched.json["office-id"] == TEST_OFFICE def test_get_rating_spec(): - spec_xml = (RESOURCES / "spec.xml").read_text() - import xml.etree.ElementTree as ET - - root = ET.fromstring(spec_xml) - rating_spec_id = root.findtext("rating-spec-id") - fetched = ratings_spec.get_rating_spec(rating_spec_id, TEST_OFFICE) - assert fetched.json["rating-spec-id"] == rating_spec_id + fetched = ratings_spec.get_rating_spec(TEST_RATING_SPEC_ID, TEST_OFFICE) + assert fetched.json["rating-spec-id"] == TEST_RATING_SPEC_ID assert fetched.json["office-id"] == TEST_OFFICE def test_update_rating_spec(): - import xml.etree.ElementTree as ET - - # Parse the original spec XML - spec_path = RESOURCES / "spec.xml" - tree = ET.parse(spec_path) - root = tree.getroot() - - # Update or create the element - desc = root.find("description") + # Update description in XML + desc = spec_root.find("description") if desc is None: - desc = ET.SubElement(root, "description") + desc = ET.SubElement(spec_root, "description") desc.text = (desc.text or "") + " - updated" + updated_xml = ET.tostring(spec_root, encoding="unicode", xml_declaration=True) - # Convert tree back to string with XML declaration - updated_xml = ET.tostring(root, encoding="unicode", xml_declaration=True) - - # Store the updated rating spec ratings_spec.store_rating_spec(updated_xml) - - # Fetch and assert the description was updated - rating_spec_id = root.findtext("rating-spec-id") - fetched = ratings_spec.get_rating_spec(rating_spec_id, TEST_OFFICE) + fetched = ratings_spec.get_rating_spec(TEST_RATING_SPEC_ID, TEST_OFFICE) assert fetched.json["description"].endswith(" - updated") def test_delete_rating_spec(): - spec_xml = (RESOURCES / "spec.xml").read_text() - import xml.etree.ElementTree as ET - - root = ET.fromstring(spec_xml) - rating_spec_id = root.findtext("rating-spec-id") - ratings_spec.delete_rating_spec(rating_spec_id, TEST_OFFICE, "DELETE_ALL") + ratings_spec.delete_rating_spec(TEST_RATING_SPEC_ID, TEST_OFFICE, "DELETE_ALL") with pytest.raises(ApiError): - ratings_spec.get_rating_spec(rating_spec_id, TEST_OFFICE) + ratings_spec.get_rating_spec(TEST_RATING_SPEC_ID, TEST_OFFICE) diff --git a/tests/cda/resources/spec.xml b/tests/cda/resources/spec.xml index 37d247f0..ff3e4a30 100644 --- a/tests/cda/resources/spec.xml +++ b/tests/cda/resources/spec.xml @@ -1,7 +1,7 @@ TestRating.Stage;Flow.TEST.Spec-test - pytest_template.Linear + Stage;Flow.TEST TestRating Spec-test USGS diff --git a/tests/cda/resources/template.xml b/tests/cda/resources/template.xml index efe96409..cd117cfe 100644 --- a/tests/cda/resources/template.xml +++ b/tests/cda/resources/template.xml @@ -1,6 +1,5 @@ -pytest_template.Linear Stage;Flow TEST\ From ea6f9e8d1b02fca98f04d0164662fe2cf2dbf863 Mon Sep 17 00:00:00 2001 From: Treyson Le Date: Thu, 18 Sep 2025 16:09:56 -0700 Subject: [PATCH 19/35] Update ratings_CDA_test.py --- tests/cda/ratings/ratings_CDA_test.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tests/cda/ratings/ratings_CDA_test.py b/tests/cda/ratings/ratings_CDA_test.py index fea5655b..ed0b545b 100644 --- a/tests/cda/ratings/ratings_CDA_test.py +++ b/tests/cda/ratings/ratings_CDA_test.py @@ -14,6 +14,7 @@ RESOURCES = Path(__file__).parent.parent / "resources" TEST_OFFICE = "MVP" +TEST_LOCATION_ID = "TestRating" # Parse template.xml to construct template ID template_xml = (RESOURCES / "template.xml").read_text() @@ -38,9 +39,7 @@ def setup_data(): cwms.store_location(location) yield try: - cwms.delete_location( - spec_root.findtext("location-id"), TEST_OFFICE, cascade_delete=True - ) + cwms.delete_location(TEST_LOCATION_ID, TEST_OFFICE, cascade_delete=True) except ApiError: pass From a322d4e42574de6e48437d2d16a8566e1d95ce2f Mon Sep 17 00:00:00 2001 From: Treyson Le Date: Tue, 23 Sep 2025 14:44:26 -0700 Subject: [PATCH 20/35] Update ratings_CDA_test.py --- tests/cda/ratings/ratings_CDA_test.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/tests/cda/ratings/ratings_CDA_test.py b/tests/cda/ratings/ratings_CDA_test.py index ed0b545b..c2a1327d 100644 --- a/tests/cda/ratings/ratings_CDA_test.py +++ b/tests/cda/ratings/ratings_CDA_test.py @@ -1,6 +1,5 @@ import json import xml.etree.ElementTree as ET -from datetime import datetime, timedelta, timezone from pathlib import Path import pandas as pd @@ -52,13 +51,13 @@ def init_session(): def test_store_template(): ratings_template.store_rating_template(template_xml) fetched = ratings_template.get_rating_template(TEST_TEMPLATE_ID, TEST_OFFICE) - assert fetched.json["template-id"] == TEST_TEMPLATE_ID + assert fetched.json["id"] == TEST_TEMPLATE_ID assert fetched.json["office-id"] == TEST_OFFICE def test_get_template(): fetched = ratings_template.get_rating_template(TEST_TEMPLATE_ID, TEST_OFFICE) - assert fetched.json["template-id"] == TEST_TEMPLATE_ID + assert fetched.json["id"] == TEST_TEMPLATE_ID assert fetched.json["office-id"] == TEST_OFFICE @@ -85,13 +84,13 @@ def test_delete_template(): def test_store_rating_spec(): ratings_spec.store_rating_spec(spec_xml) fetched = ratings_spec.get_rating_spec(TEST_RATING_SPEC_ID, TEST_OFFICE) - assert fetched.json["rating-spec-id"] == TEST_RATING_SPEC_ID + assert fetched.json["id"] == TEST_RATING_SPEC_ID assert fetched.json["office-id"] == TEST_OFFICE def test_get_rating_spec(): fetched = ratings_spec.get_rating_spec(TEST_RATING_SPEC_ID, TEST_OFFICE) - assert fetched.json["rating-spec-id"] == TEST_RATING_SPEC_ID + assert fetched.json["id"] == TEST_RATING_SPEC_ID assert fetched.json["office-id"] == TEST_OFFICE From bdf0d51bffc084c7cf7cc766c0a50e95ef4e4456 Mon Sep 17 00:00:00 2001 From: Treyson Le Date: Tue, 23 Sep 2025 14:54:34 -0700 Subject: [PATCH 21/35] Update ratings_CDA_test.py --- tests/cda/ratings/ratings_CDA_test.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/cda/ratings/ratings_CDA_test.py b/tests/cda/ratings/ratings_CDA_test.py index c2a1327d..d24bcf73 100644 --- a/tests/cda/ratings/ratings_CDA_test.py +++ b/tests/cda/ratings/ratings_CDA_test.py @@ -69,7 +69,7 @@ def test_update_template(): desc.text = (desc.text or "") + " - updated" updated_xml = ET.tostring(template_root, encoding="unicode", xml_declaration=True) - ratings_template.store_rating_template(updated_xml) + ratings_template.store_rating_template(updated_xml, fail_if_exists=False) updated = ratings_template.get_rating_template(TEST_TEMPLATE_ID, TEST_OFFICE) assert updated.json["description"].endswith(" - updated") @@ -102,7 +102,7 @@ def test_update_rating_spec(): desc.text = (desc.text or "") + " - updated" updated_xml = ET.tostring(spec_root, encoding="unicode", xml_declaration=True) - ratings_spec.store_rating_spec(updated_xml) + ratings_spec.store_rating_spec(updated_xml, fail_if_exists=False) fetched = ratings_spec.get_rating_spec(TEST_RATING_SPEC_ID, TEST_OFFICE) assert fetched.json["description"].endswith(" - updated") From f5166df1a065fa34d284781b80b43012b614ea35 Mon Sep 17 00:00:00 2001 From: Treyson Le Date: Wed, 1 Oct 2025 13:09:56 -0700 Subject: [PATCH 22/35] Update ratings_CDA_test.py --- tests/cda/ratings/ratings_CDA_test.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/cda/ratings/ratings_CDA_test.py b/tests/cda/ratings/ratings_CDA_test.py index d24bcf73..e9519f8d 100644 --- a/tests/cda/ratings/ratings_CDA_test.py +++ b/tests/cda/ratings/ratings_CDA_test.py @@ -74,12 +74,6 @@ def test_update_template(): assert updated.json["description"].endswith(" - updated") -def test_delete_template(): - ratings_template.delete_rating_template(TEST_TEMPLATE_ID, TEST_OFFICE, "DELETE_ALL") - with pytest.raises(ApiError): - ratings_template.get_rating_template(TEST_TEMPLATE_ID, TEST_OFFICE) - - # Rating specs def test_store_rating_spec(): ratings_spec.store_rating_spec(spec_xml) @@ -111,3 +105,9 @@ def test_delete_rating_spec(): ratings_spec.delete_rating_spec(TEST_RATING_SPEC_ID, TEST_OFFICE, "DELETE_ALL") with pytest.raises(ApiError): ratings_spec.get_rating_spec(TEST_RATING_SPEC_ID, TEST_OFFICE) + + +def test_delete_template(): + ratings_template.delete_rating_template(TEST_TEMPLATE_ID, TEST_OFFICE, "DELETE_ALL") + with pytest.raises(ApiError): + ratings_template.get_rating_template(TEST_TEMPLATE_ID, TEST_OFFICE) From 84d8c771e98ed5356fbc67487c70ef31d2932e19 Mon Sep 17 00:00:00 2001 From: Treyson Le Date: Wed, 1 Oct 2025 13:41:56 -0700 Subject: [PATCH 23/35] Update ratings_CDA_test.py --- tests/cda/ratings/ratings_CDA_test.py | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/tests/cda/ratings/ratings_CDA_test.py b/tests/cda/ratings/ratings_CDA_test.py index e9519f8d..1aaee19b 100644 --- a/tests/cda/ratings/ratings_CDA_test.py +++ b/tests/cda/ratings/ratings_CDA_test.py @@ -10,6 +10,14 @@ import cwms.ratings.ratings_template as ratings_template from cwms.api import ApiError + +def get_xml_text(root, tag): + elem = root.find(tag) + if elem is None: + raise AssertionError(f"Missing <{tag}> in XML response") + return elem.text + + RESOURCES = Path(__file__).parent.parent / "resources" TEST_OFFICE = "MVP" @@ -78,14 +86,16 @@ def test_update_template(): def test_store_rating_spec(): ratings_spec.store_rating_spec(spec_xml) fetched = ratings_spec.get_rating_spec(TEST_RATING_SPEC_ID, TEST_OFFICE) - assert fetched.json["id"] == TEST_RATING_SPEC_ID - assert fetched.json["office-id"] == TEST_OFFICE + root = ET.fromstring(fetched.text) + assert get_xml_text(root, "rating-spec-id") == TEST_RATING_SPEC_ID + assert root.get("office-id") == TEST_OFFICE def test_get_rating_spec(): fetched = ratings_spec.get_rating_spec(TEST_RATING_SPEC_ID, TEST_OFFICE) - assert fetched.json["id"] == TEST_RATING_SPEC_ID - assert fetched.json["office-id"] == TEST_OFFICE + root = ET.fromstring(fetched.text) + assert get_xml_text(root, "rating-spec-id") == TEST_RATING_SPEC_ID + assert root.get("office-id") == TEST_OFFICE def test_update_rating_spec(): @@ -98,7 +108,8 @@ def test_update_rating_spec(): ratings_spec.store_rating_spec(updated_xml, fail_if_exists=False) fetched = ratings_spec.get_rating_spec(TEST_RATING_SPEC_ID, TEST_OFFICE) - assert fetched.json["description"].endswith(" - updated") + root = ET.fromstring(fetched.text) + assert get_xml_text(root, "description").endswith(" - updated") def test_delete_rating_spec(): From 013b0a5492af309cabda0edc3768e6f9d83de2bd Mon Sep 17 00:00:00 2001 From: Treyson Le Date: Wed, 1 Oct 2025 14:47:11 -0700 Subject: [PATCH 24/35] Update ratings_CDA_test.py --- tests/cda/ratings/ratings_CDA_test.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/tests/cda/ratings/ratings_CDA_test.py b/tests/cda/ratings/ratings_CDA_test.py index 1aaee19b..7b346c6e 100644 --- a/tests/cda/ratings/ratings_CDA_test.py +++ b/tests/cda/ratings/ratings_CDA_test.py @@ -86,16 +86,18 @@ def test_update_template(): def test_store_rating_spec(): ratings_spec.store_rating_spec(spec_xml) fetched = ratings_spec.get_rating_spec(TEST_RATING_SPEC_ID, TEST_OFFICE) - root = ET.fromstring(fetched.text) + # Parse XML from the Data object + xml_string = getattr(fetched, "raw", None) or getattr(fetched, "body", None) + assert xml_string, "Could not find XML string in fetched Data object" + root = ET.fromstring(xml_string) assert get_xml_text(root, "rating-spec-id") == TEST_RATING_SPEC_ID assert root.get("office-id") == TEST_OFFICE def test_get_rating_spec(): fetched = ratings_spec.get_rating_spec(TEST_RATING_SPEC_ID, TEST_OFFICE) - root = ET.fromstring(fetched.text) - assert get_xml_text(root, "rating-spec-id") == TEST_RATING_SPEC_ID - assert root.get("office-id") == TEST_OFFICE + assert fetched.json["rating-spec-id"] == TEST_RATING_SPEC_ID + assert fetched.json["office-id"] == TEST_OFFICE def test_update_rating_spec(): From 07d2ee79e88ffe52d8b4720e3927c6291ef6919f Mon Sep 17 00:00:00 2001 From: Treyson Le Date: Wed, 1 Oct 2025 14:48:46 -0700 Subject: [PATCH 25/35] Update ratings_CDA_test.py --- tests/cda/ratings/ratings_CDA_test.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/tests/cda/ratings/ratings_CDA_test.py b/tests/cda/ratings/ratings_CDA_test.py index 7b346c6e..a38bfe4d 100644 --- a/tests/cda/ratings/ratings_CDA_test.py +++ b/tests/cda/ratings/ratings_CDA_test.py @@ -96,8 +96,11 @@ def test_store_rating_spec(): def test_get_rating_spec(): fetched = ratings_spec.get_rating_spec(TEST_RATING_SPEC_ID, TEST_OFFICE) - assert fetched.json["rating-spec-id"] == TEST_RATING_SPEC_ID - assert fetched.json["office-id"] == TEST_OFFICE + xml_string = getattr(fetched, "raw", None) or getattr(fetched, "body", None) + assert xml_string, "Could not find XML string in fetched Data object" + root = ET.fromstring(xml_string) + assert get_xml_text(root, "rating-spec-id") == TEST_RATING_SPEC_ID + assert root.get("office-id") == TEST_OFFICE def test_update_rating_spec(): @@ -110,7 +113,9 @@ def test_update_rating_spec(): ratings_spec.store_rating_spec(updated_xml, fail_if_exists=False) fetched = ratings_spec.get_rating_spec(TEST_RATING_SPEC_ID, TEST_OFFICE) - root = ET.fromstring(fetched.text) + xml_string = getattr(fetched, "raw", None) or getattr(fetched, "body", None) + assert xml_string, "Could not find XML string in fetched Data object" + root = ET.fromstring(xml_string) assert get_xml_text(root, "description").endswith(" - updated") From 1acd449aa840330dfc7d15f335832918bbcb7f03 Mon Sep 17 00:00:00 2001 From: Treyson Le Date: Wed, 15 Oct 2025 12:35:51 -0700 Subject: [PATCH 26/35] Update ratings_CDA_test.py --- tests/cda/ratings/ratings_CDA_test.py | 23 ++++++++--------------- 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/tests/cda/ratings/ratings_CDA_test.py b/tests/cda/ratings/ratings_CDA_test.py index a38bfe4d..21cd983c 100644 --- a/tests/cda/ratings/ratings_CDA_test.py +++ b/tests/cda/ratings/ratings_CDA_test.py @@ -86,21 +86,16 @@ def test_update_template(): def test_store_rating_spec(): ratings_spec.store_rating_spec(spec_xml) fetched = ratings_spec.get_rating_spec(TEST_RATING_SPEC_ID, TEST_OFFICE) - # Parse XML from the Data object - xml_string = getattr(fetched, "raw", None) or getattr(fetched, "body", None) - assert xml_string, "Could not find XML string in fetched Data object" - root = ET.fromstring(xml_string) - assert get_xml_text(root, "rating-spec-id") == TEST_RATING_SPEC_ID - assert root.get("office-id") == TEST_OFFICE + data = fetched.json + assert data["rating-id"] == TEST_RATING_SPEC_ID + assert data["office-id"] == TEST_OFFICE def test_get_rating_spec(): fetched = ratings_spec.get_rating_spec(TEST_RATING_SPEC_ID, TEST_OFFICE) - xml_string = getattr(fetched, "raw", None) or getattr(fetched, "body", None) - assert xml_string, "Could not find XML string in fetched Data object" - root = ET.fromstring(xml_string) - assert get_xml_text(root, "rating-spec-id") == TEST_RATING_SPEC_ID - assert root.get("office-id") == TEST_OFFICE + data = fetched.json + assert data["rating-id"] == TEST_RATING_SPEC_ID + assert data["office-id"] == TEST_OFFICE def test_update_rating_spec(): @@ -113,10 +108,8 @@ def test_update_rating_spec(): ratings_spec.store_rating_spec(updated_xml, fail_if_exists=False) fetched = ratings_spec.get_rating_spec(TEST_RATING_SPEC_ID, TEST_OFFICE) - xml_string = getattr(fetched, "raw", None) or getattr(fetched, "body", None) - assert xml_string, "Could not find XML string in fetched Data object" - root = ET.fromstring(xml_string) - assert get_xml_text(root, "description").endswith(" - updated") + data = fetched.json + assert data["description"].endswith(" - updated") def test_delete_rating_spec(): From bfc49fdeaeb9eb6197478e656f7153cacbdbb135 Mon Sep 17 00:00:00 2001 From: Treyson Le Date: Wed, 15 Oct 2025 15:36:16 -0700 Subject: [PATCH 27/35] Update ratings_CDA_test.py --- tests/cda/ratings/ratings_CDA_test.py | 39 +++++++++++++++++---------- 1 file changed, 25 insertions(+), 14 deletions(-) diff --git a/tests/cda/ratings/ratings_CDA_test.py b/tests/cda/ratings/ratings_CDA_test.py index 21cd983c..fc8b6b19 100644 --- a/tests/cda/ratings/ratings_CDA_test.py +++ b/tests/cda/ratings/ratings_CDA_test.py @@ -61,45 +61,54 @@ def test_store_template(): fetched = ratings_template.get_rating_template(TEST_TEMPLATE_ID, TEST_OFFICE) assert fetched.json["id"] == TEST_TEMPLATE_ID assert fetched.json["office-id"] == TEST_OFFICE + assert TEST_TEMPLATE_ID in fetched.df["id"].values + assert TEST_OFFICE in fetched.df["office-id"].values def test_get_template(): fetched = ratings_template.get_rating_template(TEST_TEMPLATE_ID, TEST_OFFICE) assert fetched.json["id"] == TEST_TEMPLATE_ID assert fetched.json["office-id"] == TEST_OFFICE + assert TEST_TEMPLATE_ID in fetched.df["id"].values + assert TEST_OFFICE in fetched.df["office-id"].values def test_update_template(): - template_root = ET.fromstring(template_xml) - desc = template_root.find("description") + root = ET.fromstring(template_xml) + desc = root.find("description") if desc is None: - desc = ET.SubElement(template_root, "description") + desc = ET.SubElement(root, "description") desc.text = (desc.text or "") + " - updated" - updated_xml = ET.tostring(template_root, encoding="unicode", xml_declaration=True) + updated_xml = ET.tostring(root, encoding="unicode", xml_declaration=True) ratings_template.store_rating_template(updated_xml, fail_if_exists=False) updated = ratings_template.get_rating_template(TEST_TEMPLATE_ID, TEST_OFFICE) assert updated.json["description"].endswith(" - updated") + assert updated.df["description"].iloc[0].endswith(" - updated") -# Rating specs def test_store_rating_spec(): ratings_spec.store_rating_spec(spec_xml) fetched = ratings_spec.get_rating_spec(TEST_RATING_SPEC_ID, TEST_OFFICE) - data = fetched.json - assert data["rating-id"] == TEST_RATING_SPEC_ID - assert data["office-id"] == TEST_OFFICE + data_json = fetched.json + data_df = fetched.df + assert data_json["rating-id"] == TEST_RATING_SPEC_ID + assert data_json["office-id"] == TEST_OFFICE + assert TEST_RATING_SPEC_ID in data_df["rating-id"].values + assert TEST_OFFICE in data_df["office-id"].values def test_get_rating_spec(): fetched = ratings_spec.get_rating_spec(TEST_RATING_SPEC_ID, TEST_OFFICE) - data = fetched.json - assert data["rating-id"] == TEST_RATING_SPEC_ID - assert data["office-id"] == TEST_OFFICE + data_json = fetched.json + data_df = fetched.df + assert data_json["rating-id"] == TEST_RATING_SPEC_ID + assert data_json["office-id"] == TEST_OFFICE + assert TEST_RATING_SPEC_ID in data_df["rating-id"].values + assert TEST_OFFICE in data_df["office-id"].values def test_update_rating_spec(): - # Update description in XML desc = spec_root.find("description") if desc is None: desc = ET.SubElement(spec_root, "description") @@ -108,8 +117,10 @@ def test_update_rating_spec(): ratings_spec.store_rating_spec(updated_xml, fail_if_exists=False) fetched = ratings_spec.get_rating_spec(TEST_RATING_SPEC_ID, TEST_OFFICE) - data = fetched.json - assert data["description"].endswith(" - updated") + data_json = fetched.json + data_df = fetched.df + assert data_json["description"].endswith(" - updated") + assert data_df["description"].iloc[0].endswith(" - updated") def test_delete_rating_spec(): From 82435942f424a936a876bd2622cf07971fae5956 Mon Sep 17 00:00:00 2001 From: Treyson Le Date: Wed, 22 Oct 2025 14:38:59 -0700 Subject: [PATCH 28/35] Made required changes --- tests/cda/ratings/ratings_CDA_test.py | 29 +++++++++++++----------- tests/cda/resources/rating_spec.json | 9 -------- tests/cda/resources/rating_table.json | 18 --------------- tests/cda/resources/rating_template.json | 18 --------------- tests/cda/resources/table.json | 18 --------------- tests/cda/resources/table_updated.json | 18 --------------- 6 files changed, 16 insertions(+), 94 deletions(-) delete mode 100644 tests/cda/resources/rating_spec.json delete mode 100644 tests/cda/resources/rating_table.json delete mode 100644 tests/cda/resources/rating_template.json delete mode 100644 tests/cda/resources/table.json delete mode 100644 tests/cda/resources/table_updated.json diff --git a/tests/cda/ratings/ratings_CDA_test.py b/tests/cda/ratings/ratings_CDA_test.py index fc8b6b19..06cb40d8 100644 --- a/tests/cda/ratings/ratings_CDA_test.py +++ b/tests/cda/ratings/ratings_CDA_test.py @@ -23,17 +23,9 @@ def get_xml_text(root, tag): TEST_OFFICE = "MVP" TEST_LOCATION_ID = "TestRating" -# Parse template.xml to construct template ID -template_xml = (RESOURCES / "template.xml").read_text() -template_root = ET.fromstring(template_xml) -parameters_id = template_root.findtext("parameters-id") -template_version = template_root.findtext("version") - -TEST_TEMPLATE_ID = f"{parameters_id}.{template_version}" # Stage;Flow.TEST - # Parse spec.xml to get rating-spec-id -spec_xml = (RESOURCES / "spec.xml").read_text() -spec_root = ET.fromstring(spec_xml) +SPEC_XML = (RESOURCES / "spec.xml").read_text() +spec_root = ET.fromstring(SPEC_XML) TEST_RATING_SPEC_ID = spec_root.findtext( "rating-spec-id" @@ -57,7 +49,10 @@ def init_session(): def test_store_template(): - ratings_template.store_rating_template(template_xml) + TEMPLATE_XML = (RESOURCES / "template.xml").read_text() + TEST_TEMPLATE_ID = "Stage;Flow.TEST" + + ratings_template.store_rating_template(TEMPLATE_XML) fetched = ratings_template.get_rating_template(TEST_TEMPLATE_ID, TEST_OFFICE) assert fetched.json["id"] == TEST_TEMPLATE_ID assert fetched.json["office-id"] == TEST_OFFICE @@ -66,6 +61,9 @@ def test_store_template(): def test_get_template(): + TEMPLATE_XML = (RESOURCES / "template.xml").read_text() + TEST_TEMPLATE_ID = "Stage;Flow.TEST" + fetched = ratings_template.get_rating_template(TEST_TEMPLATE_ID, TEST_OFFICE) assert fetched.json["id"] == TEST_TEMPLATE_ID assert fetched.json["office-id"] == TEST_OFFICE @@ -74,7 +72,10 @@ def test_get_template(): def test_update_template(): - root = ET.fromstring(template_xml) + TEMPLATE_XML = (RESOURCES / "template.xml").read_text() + TEST_TEMPLATE_ID = "Stage;Flow.TEST" + + root = ET.fromstring(TEMPLATE_XML) desc = root.find("description") if desc is None: desc = ET.SubElement(root, "description") @@ -88,7 +89,7 @@ def test_update_template(): def test_store_rating_spec(): - ratings_spec.store_rating_spec(spec_xml) + ratings_spec.store_rating_spec(SPEC_XML) fetched = ratings_spec.get_rating_spec(TEST_RATING_SPEC_ID, TEST_OFFICE) data_json = fetched.json data_df = fetched.df @@ -130,6 +131,8 @@ def test_delete_rating_spec(): def test_delete_template(): + TEST_TEMPLATE_ID = "Stage;Flow.TEST" + ratings_template.delete_rating_template(TEST_TEMPLATE_ID, TEST_OFFICE, "DELETE_ALL") with pytest.raises(ApiError): ratings_template.get_rating_template(TEST_TEMPLATE_ID, TEST_OFFICE) diff --git a/tests/cda/resources/rating_spec.json b/tests/cda/resources/rating_spec.json deleted file mode 100644 index 86c379f2..00000000 --- a/tests/cda/resources/rating_spec.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "office-id": "MVP", - "rating-spec-id": "pytest_template_group.Stage;Flow.pytest_template.Linear.pytest-version", - "template-id": "pytest_template.Linear", - "ind-parameter": "Stage;ft", - "dep-parameter": "Flow;cfs", - "version": "pytest-version", - "description": "Pytest rating spec for EXSA test" -} \ No newline at end of file diff --git a/tests/cda/resources/rating_table.json b/tests/cda/resources/rating_table.json deleted file mode 100644 index 74b24fa0..00000000 --- a/tests/cda/resources/rating_table.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "simple-rating": { - "office-id": "MVP", - "rating-spec-id": "TestRating.Stage;Flow.USGS-EXSA-TEST.USGS-NWIS-TEST", - "units-id": "ft;cfs", - "effective-date": "2023-01-01T00:00:00Z", - "transition-start-date": null, - "active": true, - "description": "Initial rating table for pytest", - "rating-points": { - "point": [ - { "ind": 1.0, "dep": 10.0 }, - { "ind": 2.0, "dep": 20.0 }, - { "ind": 3.0, "dep": 30.0 } - ] - } - } -} \ No newline at end of file diff --git a/tests/cda/resources/rating_template.json b/tests/cda/resources/rating_template.json deleted file mode 100644 index 373c4a3b..00000000 --- a/tests/cda/resources/rating_template.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "office-id": "MVP", - "template-id": "Linear", - "description": "Linear stage-to-flow template", - "dependent-parameter": { - "parameter": "Flow", - "unit": "cfs" - }, - "independent-parameter-specs": [ - { - "parameter": "Stage", - "unit": "ft", - "in-range-method": "LINEAR", - "out-range-low-method": "LINEAR", - "out-range-high-method": "LINEAR" - } - ] -} \ No newline at end of file diff --git a/tests/cda/resources/table.json b/tests/cda/resources/table.json deleted file mode 100644 index 1856d474..00000000 --- a/tests/cda/resources/table.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "simple-rating": { - "office-id": "MVP", - "rating-spec-id": "pytest_rating.Stage;ft.Flow;cfs.Linear", - "units-id": "ft;cfs", - "effective-date": "2023-01-01T00:00:00Z", - "transition-start-date": null, - "active": true, - "description": "Initial rating table for pytest", - "rating-points": { - "point": [ - { "ind": 1.0, "dep": 10.0 }, - { "ind": 2.0, "dep": 20.0 }, - { "ind": 3.0, "dep": 30.0 } - ] - } - } -} \ No newline at end of file diff --git a/tests/cda/resources/table_updated.json b/tests/cda/resources/table_updated.json deleted file mode 100644 index 857d1061..00000000 --- a/tests/cda/resources/table_updated.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "simple-rating": { - "office-id": "MVP", - "rating-spec-id": "pytest_rating.Stage;ft.Flow;cfs.Linear", - "units-id": "ft;cfs", - "effective-date": "2024-01-01T00:00:00Z", - "transition-start-date": null, - "active": true, - "description": "Updated rating table for pytest", - "rating-points": { - "point": [ - { "ind": 1.0, "dep": 11.0 }, - { "ind": 2.0, "dep": 22.0 }, - { "ind": 3.0, "dep": 33.0 } - ] - } - } -} \ No newline at end of file From 1c54a28255b7514319806d628221075bca0f3cde Mon Sep 17 00:00:00 2001 From: Treyson Le Date: Wed, 22 Oct 2025 14:51:06 -0700 Subject: [PATCH 29/35] Update ratings_CDA_test.py --- tests/cda/ratings/ratings_CDA_test.py | 70 +++++++++++++++++++++++++-- 1 file changed, 65 insertions(+), 5 deletions(-) diff --git a/tests/cda/ratings/ratings_CDA_test.py b/tests/cda/ratings/ratings_CDA_test.py index 06cb40d8..2b79d5d7 100644 --- a/tests/cda/ratings/ratings_CDA_test.py +++ b/tests/cda/ratings/ratings_CDA_test.py @@ -23,13 +23,12 @@ def get_xml_text(root, tag): TEST_OFFICE = "MVP" TEST_LOCATION_ID = "TestRating" -# Parse spec.xml to get rating-spec-id +# Parse spec.xml SPEC_XML = (RESOURCES / "spec.xml").read_text() spec_root = ET.fromstring(SPEC_XML) -TEST_RATING_SPEC_ID = spec_root.findtext( - "rating-spec-id" -) # TestRating.Stage;Flow.TEST.Spec-test +# Use direct assignment for test rating spec id +TEST_RATING_SPEC_ID = "TestRating.Stage;Flow.TEST.Spec-test" @pytest.fixture(scope="module", autouse=True) @@ -39,6 +38,14 @@ def setup_data(): yield try: cwms.delete_location(TEST_LOCATION_ID, TEST_OFFICE, cascade_delete=True) + try: + ratings_spec.delete_rating_spec(TEST_RATING_SPEC_ID, TEST_OFFICE, "DELETE_ALL") + except ApiError: + pass + try: + ratings_template.delete_rating_template("Stage;Flow.TEST", TEST_OFFICE, "DELETE_ALL") + except ApiError: + pass except ApiError: pass @@ -58,10 +65,11 @@ def test_store_template(): assert fetched.json["office-id"] == TEST_OFFICE assert TEST_TEMPLATE_ID in fetched.df["id"].values assert TEST_OFFICE in fetched.df["office-id"].values + assert fetched.df["id"].iloc[0] == TEST_TEMPLATE_ID + assert fetched.df["office-id"].iloc[0] == TEST_OFFICE def test_get_template(): - TEMPLATE_XML = (RESOURCES / "template.xml").read_text() TEST_TEMPLATE_ID = "Stage;Flow.TEST" fetched = ratings_template.get_rating_template(TEST_TEMPLATE_ID, TEST_OFFICE) @@ -69,6 +77,32 @@ def test_get_template(): assert fetched.json["office-id"] == TEST_OFFICE assert TEST_TEMPLATE_ID in fetched.df["id"].values assert TEST_OFFICE in fetched.df["office-id"].values + assert fetched.df["id"].iloc[0] == TEST_TEMPLATE_ID + assert fetched.df["office-id"].iloc[0] == TEST_OFFICE + + +def test_get_rating_templates(): + TEMPLATE_XML = (RESOURCES / "template.xml").read_text() + # Modify version to TEST-2 + root = ET.fromstring(TEMPLATE_XML) + version = root.find("version") + if version is None: + version = ET.SubElement(root, "version") + version.text = "TEST-2" + updated_xml = ET.tostring(root, encoding="unicode", xml_declaration=True) + TEST_TEMPLATE_ID2 = "Stage;Flow.TEST-2" + + # Store new template + ratings_template.store_rating_template(updated_xml) + + # Fetch all templates + fetched = ratings_template.get_rating_templates(TEST_OFFICE) + df = fetched.df + assert "Stage;Flow.TEST" in df["id"].values + assert TEST_TEMPLATE_ID2 in df["id"].values + # Ensure at least two templates exist + ids = df["id"].values + assert len([i for i in ids if "Stage;Flow.TEST" in i]) >= 2 def test_update_template(): @@ -97,6 +131,8 @@ def test_store_rating_spec(): assert data_json["office-id"] == TEST_OFFICE assert TEST_RATING_SPEC_ID in data_df["rating-id"].values assert TEST_OFFICE in data_df["office-id"].values + assert data_df["rating-id"].iloc[0] == TEST_RATING_SPEC_ID + assert data_df["office-id"].iloc[0] == TEST_OFFICE def test_get_rating_spec(): @@ -107,6 +143,29 @@ def test_get_rating_spec(): assert data_json["office-id"] == TEST_OFFICE assert TEST_RATING_SPEC_ID in data_df["rating-id"].values assert TEST_OFFICE in data_df["office-id"].values + assert data_df["rating-id"].iloc[0] == TEST_RATING_SPEC_ID + assert data_df["office-id"].iloc[0] == TEST_OFFICE + + +def test_get_rating_specs(): + # Load spec XML + SPEC_XML2 = (RESOURCES / "spec.xml").read_text() + root = ET.fromstring(SPEC_XML2) + # Update rating-spec-id to use second template and version + rating_spec_id_elem = root.find("rating-spec-id") + if rating_spec_id_elem is None: + rating_spec_id_elem = ET.SubElement(root, "rating-spec-id") + rating_spec_id_elem.text = "TestRating.Stage;Flow.TEST-2.Spec-test" + TEST_RATING_SPEC_ID2 = "TestRating.Stage;Flow.TEST-2.Spec-test" + updated_xml = ET.tostring(root, encoding="unicode", xml_declaration=True) + # Store new rating spec + ratings_spec.store_rating_spec(updated_xml) + # Fetch all rating specs + fetched = ratings_spec.get_rating_specs(TEST_OFFICE) + df = fetched.df + assert TEST_RATING_SPEC_ID in df["rating-id"].values + assert TEST_RATING_SPEC_ID2 in df["rating-id"].values + assert len([i for i in df["rating-id"].values if "TestRating.Stage;Flow.TEST" in i]) >= 2 def test_update_rating_spec(): @@ -122,6 +181,7 @@ def test_update_rating_spec(): data_df = fetched.df assert data_json["description"].endswith(" - updated") assert data_df["description"].iloc[0].endswith(" - updated") + assert data_df["description"].iloc[0].endswith(" - updated") def test_delete_rating_spec(): From 9c8c22a82500ad61fa7d258593d8d8111c8dda50 Mon Sep 17 00:00:00 2001 From: Treyson Le Date: Wed, 22 Oct 2025 14:53:14 -0700 Subject: [PATCH 30/35] format --- tests/cda/ratings/ratings_CDA_test.py | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/tests/cda/ratings/ratings_CDA_test.py b/tests/cda/ratings/ratings_CDA_test.py index 2b79d5d7..00c09b3a 100644 --- a/tests/cda/ratings/ratings_CDA_test.py +++ b/tests/cda/ratings/ratings_CDA_test.py @@ -39,11 +39,15 @@ def setup_data(): try: cwms.delete_location(TEST_LOCATION_ID, TEST_OFFICE, cascade_delete=True) try: - ratings_spec.delete_rating_spec(TEST_RATING_SPEC_ID, TEST_OFFICE, "DELETE_ALL") + ratings_spec.delete_rating_spec( + TEST_RATING_SPEC_ID, TEST_OFFICE, "DELETE_ALL" + ) except ApiError: pass try: - ratings_template.delete_rating_template("Stage;Flow.TEST", TEST_OFFICE, "DELETE_ALL") + ratings_template.delete_rating_template( + "Stage;Flow.TEST", TEST_OFFICE, "DELETE_ALL" + ) except ApiError: pass except ApiError: @@ -165,7 +169,10 @@ def test_get_rating_specs(): df = fetched.df assert TEST_RATING_SPEC_ID in df["rating-id"].values assert TEST_RATING_SPEC_ID2 in df["rating-id"].values - assert len([i for i in df["rating-id"].values if "TestRating.Stage;Flow.TEST" in i]) >= 2 + assert ( + len([i for i in df["rating-id"].values if "TestRating.Stage;Flow.TEST" in i]) + >= 2 + ) def test_update_rating_spec(): From 07d456f65592ec5aaa356d554fa6314018223af4 Mon Sep 17 00:00:00 2001 From: Treyson Le Date: Wed, 22 Oct 2025 14:58:01 -0700 Subject: [PATCH 31/35] Update ratings_CDA_test.py --- tests/cda/ratings/ratings_CDA_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/cda/ratings/ratings_CDA_test.py b/tests/cda/ratings/ratings_CDA_test.py index 00c09b3a..d61f965a 100644 --- a/tests/cda/ratings/ratings_CDA_test.py +++ b/tests/cda/ratings/ratings_CDA_test.py @@ -163,7 +163,7 @@ def test_get_rating_specs(): TEST_RATING_SPEC_ID2 = "TestRating.Stage;Flow.TEST-2.Spec-test" updated_xml = ET.tostring(root, encoding="unicode", xml_declaration=True) # Store new rating spec - ratings_spec.store_rating_spec(updated_xml) + ratings_spec.store_rating_spec(updated_xml, fail_if_exists=False) # Fetch all rating specs fetched = ratings_spec.get_rating_specs(TEST_OFFICE) df = fetched.df From 6c28544d86b77f477b4181fce5ffe00a032411e6 Mon Sep 17 00:00:00 2001 From: Treyson Le Date: Wed, 22 Oct 2025 16:25:58 -0700 Subject: [PATCH 32/35] Update ratings_CDA_test.py --- tests/cda/ratings/ratings_CDA_test.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/cda/ratings/ratings_CDA_test.py b/tests/cda/ratings/ratings_CDA_test.py index d61f965a..9ec5194c 100644 --- a/tests/cda/ratings/ratings_CDA_test.py +++ b/tests/cda/ratings/ratings_CDA_test.py @@ -160,6 +160,10 @@ def test_get_rating_specs(): if rating_spec_id_elem is None: rating_spec_id_elem = ET.SubElement(root, "rating-spec-id") rating_spec_id_elem.text = "TestRating.Stage;Flow.TEST-2.Spec-test" + template_elem = root.find("template-id") + if template_elem is None: + template_elem = ET.SubElement(root, "template-id") + template_elem.text = "Stage;Flow.TEST-2" TEST_RATING_SPEC_ID2 = "TestRating.Stage;Flow.TEST-2.Spec-test" updated_xml = ET.tostring(root, encoding="unicode", xml_declaration=True) # Store new rating spec From a81b10976e1fb43b9fd41b994b45973fc5b3954f Mon Sep 17 00:00:00 2001 From: Treyson Le Date: Fri, 24 Oct 2025 15:17:24 -0700 Subject: [PATCH 33/35] Update ratings_CDA_test.py --- tests/cda/ratings/ratings_CDA_test.py | 65 ++++++++++++++++----------- 1 file changed, 39 insertions(+), 26 deletions(-) diff --git a/tests/cda/ratings/ratings_CDA_test.py b/tests/cda/ratings/ratings_CDA_test.py index 9ec5194c..7ac25bbb 100644 --- a/tests/cda/ratings/ratings_CDA_test.py +++ b/tests/cda/ratings/ratings_CDA_test.py @@ -2,7 +2,6 @@ import xml.etree.ElementTree as ET from pathlib import Path -import pandas as pd import pytest import cwms @@ -29,6 +28,8 @@ def get_xml_text(root, tag): # Use direct assignment for test rating spec id TEST_RATING_SPEC_ID = "TestRating.Stage;Flow.TEST.Spec-test" +TEST_TEMPLATE_ID2 = "Stage;Flow.TEST-2" +TEST_RATING_SPEC_ID2 = "TestRating.Stage;Flow.TEST-2.Spec-test" @pytest.fixture(scope="module", autouse=True) @@ -50,6 +51,14 @@ def setup_data(): ) except ApiError: pass + try: + ratings_spec.delete_rating_spec(TEST_RATING_SPEC_ID2, TEST_OFFICE, "DELETE_ALL") + except ApiError: + pass + try: + ratings_template.delete_rating_template(TEST_TEMPLATE_ID2, TEST_OFFICE, "DELETE_ALL") + except ApiError: + pass except ApiError: pass @@ -94,19 +103,21 @@ def test_get_rating_templates(): version = ET.SubElement(root, "version") version.text = "TEST-2" updated_xml = ET.tostring(root, encoding="unicode", xml_declaration=True) - TEST_TEMPLATE_ID2 = "Stage;Flow.TEST-2" - # Store new template - ratings_template.store_rating_template(updated_xml) + # Store new template and ensure cleanup + try: + ratings_template.store_rating_template(updated_xml) - # Fetch all templates - fetched = ratings_template.get_rating_templates(TEST_OFFICE) - df = fetched.df - assert "Stage;Flow.TEST" in df["id"].values - assert TEST_TEMPLATE_ID2 in df["id"].values - # Ensure at least two templates exist - ids = df["id"].values - assert len([i for i in ids if "Stage;Flow.TEST" in i]) >= 2 + # Fetch all templates + fetched = ratings_template.get_rating_templates(TEST_OFFICE) + df = fetched.df + assert "Stage;Flow.TEST" in df["id"].values + assert TEST_TEMPLATE_ID2 in df["id"].values + # Ensure at least two templates exist + ids = df["id"].values + assert len([i for i in ids if "Stage;Flow.TEST" in i]) >= 2 + finally: + ratings_template.delete_rating_template(TEST_TEMPLATE_ID2, TEST_OFFICE, "DELETE_ALL") def test_update_template(): @@ -159,24 +170,26 @@ def test_get_rating_specs(): rating_spec_id_elem = root.find("rating-spec-id") if rating_spec_id_elem is None: rating_spec_id_elem = ET.SubElement(root, "rating-spec-id") - rating_spec_id_elem.text = "TestRating.Stage;Flow.TEST-2.Spec-test" + rating_spec_id_elem.text = TEST_RATING_SPEC_ID2 template_elem = root.find("template-id") if template_elem is None: template_elem = ET.SubElement(root, "template-id") - template_elem.text = "Stage;Flow.TEST-2" - TEST_RATING_SPEC_ID2 = "TestRating.Stage;Flow.TEST-2.Spec-test" + template_elem.text = TEST_TEMPLATE_ID2 updated_xml = ET.tostring(root, encoding="unicode", xml_declaration=True) - # Store new rating spec - ratings_spec.store_rating_spec(updated_xml, fail_if_exists=False) - # Fetch all rating specs - fetched = ratings_spec.get_rating_specs(TEST_OFFICE) - df = fetched.df - assert TEST_RATING_SPEC_ID in df["rating-id"].values - assert TEST_RATING_SPEC_ID2 in df["rating-id"].values - assert ( - len([i for i in df["rating-id"].values if "TestRating.Stage;Flow.TEST" in i]) - >= 2 - ) + # Store new rating spec and ensure cleanup + try: + ratings_spec.store_rating_spec(updated_xml, fail_if_exists=False) + # Fetch all rating specs + fetched = ratings_spec.get_rating_specs(TEST_OFFICE) + df = fetched.df + assert TEST_RATING_SPEC_ID in df["rating-id"].values + assert TEST_RATING_SPEC_ID2 in df["rating-id"].values + assert ( + len([i for i in df["rating-id"].values if "TestRating.Stage;Flow.TEST" in i]) + >= 2 + ) + finally: + ratings_spec.delete_rating_spec(TEST_RATING_SPEC_ID2, TEST_OFFICE, "DELETE_ALL") def test_update_rating_spec(): From b302734eb949c3fba4ccaba9bc8e1f2497612aa3 Mon Sep 17 00:00:00 2001 From: Treyson Le Date: Fri, 24 Oct 2025 15:25:34 -0700 Subject: [PATCH 34/35] Update ratings_CDA_test.py --- tests/cda/ratings/ratings_CDA_test.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/tests/cda/ratings/ratings_CDA_test.py b/tests/cda/ratings/ratings_CDA_test.py index 7ac25bbb..28465861 100644 --- a/tests/cda/ratings/ratings_CDA_test.py +++ b/tests/cda/ratings/ratings_CDA_test.py @@ -163,6 +163,15 @@ def test_get_rating_spec(): def test_get_rating_specs(): + # Ensure second template is stored + TEMPLATE_XML2 = (RESOURCES / "template.xml").read_text() + root_template = ET.fromstring(TEMPLATE_XML2) + version = root_template.find("version") + if version is None: + version = ET.SubElement(root_template, "version") + version.text = "TEST-2" + template_xml_updated = ET.tostring(root_template, encoding="unicode", xml_declaration=True) + # Load spec XML SPEC_XML2 = (RESOURCES / "spec.xml").read_text() root = ET.fromstring(SPEC_XML2) @@ -178,6 +187,7 @@ def test_get_rating_specs(): updated_xml = ET.tostring(root, encoding="unicode", xml_declaration=True) # Store new rating spec and ensure cleanup try: + ratings_template.store_rating_template(template_xml_updated, fail_if_exists=False) ratings_spec.store_rating_spec(updated_xml, fail_if_exists=False) # Fetch all rating specs fetched = ratings_spec.get_rating_specs(TEST_OFFICE) @@ -190,6 +200,7 @@ def test_get_rating_specs(): ) finally: ratings_spec.delete_rating_spec(TEST_RATING_SPEC_ID2, TEST_OFFICE, "DELETE_ALL") + ratings_template.delete_rating_template(TEST_TEMPLATE_ID2, TEST_OFFICE, "DELETE_ALL") def test_update_rating_spec(): From eaa78675bd18fdb10b96c38bd400f62d9c345f19 Mon Sep 17 00:00:00 2001 From: Treyson Le Date: Fri, 24 Oct 2025 15:38:54 -0700 Subject: [PATCH 35/35] Update ratings_CDA_test.py --- tests/cda/ratings/ratings_CDA_test.py | 28 ++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/tests/cda/ratings/ratings_CDA_test.py b/tests/cda/ratings/ratings_CDA_test.py index 28465861..d2ca9752 100644 --- a/tests/cda/ratings/ratings_CDA_test.py +++ b/tests/cda/ratings/ratings_CDA_test.py @@ -52,11 +52,15 @@ def setup_data(): except ApiError: pass try: - ratings_spec.delete_rating_spec(TEST_RATING_SPEC_ID2, TEST_OFFICE, "DELETE_ALL") + ratings_spec.delete_rating_spec( + TEST_RATING_SPEC_ID2, TEST_OFFICE, "DELETE_ALL" + ) except ApiError: pass try: - ratings_template.delete_rating_template(TEST_TEMPLATE_ID2, TEST_OFFICE, "DELETE_ALL") + ratings_template.delete_rating_template( + TEST_TEMPLATE_ID2, TEST_OFFICE, "DELETE_ALL" + ) except ApiError: pass except ApiError: @@ -117,7 +121,9 @@ def test_get_rating_templates(): ids = df["id"].values assert len([i for i in ids if "Stage;Flow.TEST" in i]) >= 2 finally: - ratings_template.delete_rating_template(TEST_TEMPLATE_ID2, TEST_OFFICE, "DELETE_ALL") + ratings_template.delete_rating_template( + TEST_TEMPLATE_ID2, TEST_OFFICE, "DELETE_ALL" + ) def test_update_template(): @@ -170,7 +176,9 @@ def test_get_rating_specs(): if version is None: version = ET.SubElement(root_template, "version") version.text = "TEST-2" - template_xml_updated = ET.tostring(root_template, encoding="unicode", xml_declaration=True) + template_xml_updated = ET.tostring( + root_template, encoding="unicode", xml_declaration=True + ) # Load spec XML SPEC_XML2 = (RESOURCES / "spec.xml").read_text() @@ -187,7 +195,9 @@ def test_get_rating_specs(): updated_xml = ET.tostring(root, encoding="unicode", xml_declaration=True) # Store new rating spec and ensure cleanup try: - ratings_template.store_rating_template(template_xml_updated, fail_if_exists=False) + ratings_template.store_rating_template( + template_xml_updated, fail_if_exists=False + ) ratings_spec.store_rating_spec(updated_xml, fail_if_exists=False) # Fetch all rating specs fetched = ratings_spec.get_rating_specs(TEST_OFFICE) @@ -195,12 +205,16 @@ def test_get_rating_specs(): assert TEST_RATING_SPEC_ID in df["rating-id"].values assert TEST_RATING_SPEC_ID2 in df["rating-id"].values assert ( - len([i for i in df["rating-id"].values if "TestRating.Stage;Flow.TEST" in i]) + len( + [i for i in df["rating-id"].values if "TestRating.Stage;Flow.TEST" in i] + ) >= 2 ) finally: ratings_spec.delete_rating_spec(TEST_RATING_SPEC_ID2, TEST_OFFICE, "DELETE_ALL") - ratings_template.delete_rating_template(TEST_TEMPLATE_ID2, TEST_OFFICE, "DELETE_ALL") + ratings_template.delete_rating_template( + TEST_TEMPLATE_ID2, TEST_OFFICE, "DELETE_ALL" + ) def test_update_rating_spec():