Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion solvis_graphql_api/color_scale/compute.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,9 @@ def slim(new_intervals, max):
while len(new_intervals) > MAX_LEN:
new_intervals = new_intervals[::2]
new_intervals = sorted(new_intervals)
if new_intervals[-1] < max:
# unreachable: the sole caller passes `max=intervals[0]` (the minimum), so the largest
# element is never < it. Faithfully ported dead branch from the legacy color_scale.py.
if new_intervals[-1] < max: # pragma: no cover
new_intervals.append(max)
return new_intervals

Expand Down
62 changes: 62 additions & 0 deletions tests/test_compute.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
"""Unit tests for the graphene-free colour-scale compute (extracted at the de-graphene cleanup).

Covers the maths and the error/edge branches directly, so the new `color_scale/compute.py`
module is exercised without going through the schema.
"""

import pytest

from solvis_graphql_api.color_scale import compute as C


def test_get_normaliser_log_lin_and_error():
assert C.get_normaliser(10.0, 1.0, "log") is not None
assert C.get_normaliser(10.0, 0.0, "lin") is not None
with pytest.raises(RuntimeError):
C.get_normaliser(10.0, 1.0, "bogus")


@pytest.mark.parametrize(
"vmin, vmax",
[
(1.0e-6, 1.0), # wide multi-decade span -> slim() path
(0.0042171, 0.00967), # narrow span -> interpolate() path
(3.2937376598254063e-18, 0.0008977324469015002), # very wide -> slim + ensure_max
(1.0e-20, 1.0e-11), # slim path where ensure_max appends the boundary
],
)
def test_log_intervals_lengths(vmin, vmax):
iv = C.log_intervals(vmin, vmax)
assert 4 <= len(iv) <= 10
assert iv == sorted(iv)


def test_log_intervals_same_decade():
# min_exponent == max_exponent branch (max_exponent += 1)
iv = C.log_intervals(1.2, 3.4)
assert len(iv) >= 4


def test_compute_colour_scale_log():
res = C.compute_colour_scale("inferno", "log", 1.0, 1.0e-3)
assert res.normalisation == "log"
assert len(res.levels) == len(res.hexrgbs) >= 4
assert all(h.startswith("#") for h in res.hexrgbs)


def test_compute_colour_scale_lin():
res = C.compute_colour_scale("inferno", "lin", 10.0, 0.0)
assert res.normalisation == "lin"
assert len(res.levels) == len(res.hexrgbs)
assert all(h.startswith("#") for h in res.hexrgbs)


def test_compute_colour_scale_unknown_normalisation():
with pytest.raises(RuntimeError):
C.compute_colour_scale("inferno", "bogus", 10.0, 1.0)


def test_get_colour_values_includes_none_sentinel():
vals = list(C.get_colour_values("inferno", 1.0, 1.0e-3, "log", (1.0e-3, 1.0e-2, None)))
assert vals[-1] == "x000000" # None maps to the sentinel, not a hex
assert all(v.startswith("#") for v in vals[:2])
37 changes: 37 additions & 0 deletions tests/test_schema_helpers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
"""Unit coverage for small Strawberry-schema helper branches.

The trivial empty/None branches of the input-coercion helpers and the null-sortby skip aren't
reached by the parity/behavioural queries (which always supply styles, filter_set_options and
non-null sortby items), so exercise them directly.
"""

from solvis_graphql_api.schema import _fso_dict, _style_dict, schema


def test_style_dict_none_returns_empty():
assert _style_dict(None) == {}


def test_fso_dict_falsy_returns_empty():
assert _fso_dict(None) == {}


_FILTER_RUPTURES_NULL_SORTBY = """
query ($model_id: String! $location_ids: [String]! $fault_system: String!) {
filter_ruptures(first: 1 sortby: [null] filter: {
model_id: $model_id fault_system: $fault_system location_ids: $location_ids
radius_km: 5 minimum_mag: 8.3 minimum_rate: 1.0e-6}) {
total_count
}
}
"""


def test_filter_ruptures_skips_null_sortby_item(archive_fixture):
# a null element in the sortby list must be skipped (not crash the resolver)
result = schema.execute_sync(
_FILTER_RUPTURES_NULL_SORTBY,
variable_values={"model_id": "NSHM_v1.0.0", "fault_system": "HIK", "location_ids": ["WLG"]},
)
assert not result.errors
assert result.data["filter_ruptures"]["total_count"] >= 0
Loading