94 lines
3.4 KiB
Python
94 lines
3.4 KiB
Python
from __future__ import annotations
|
|
|
|
import json
|
|
from dataclasses import replace
|
|
from decimal import Decimal
|
|
from pathlib import Path
|
|
|
|
from adaptive_pricing_core.pricing_models import (
|
|
AssuranceClaim,
|
|
load_pricing_models as load_core_pricing_models,
|
|
validate_pricing_catalog,
|
|
validate_pricing_model,
|
|
)
|
|
from observatory.load import load_pricing_models
|
|
|
|
DATA_DIR = Path(__file__).resolve().parent.parent / "data"
|
|
|
|
|
|
def test_coulomb_pricing_catalog_validates() -> None:
|
|
models = load_pricing_models(DATA_DIR)
|
|
assert validate_pricing_catalog(models) == {}
|
|
|
|
|
|
def test_hybrid_model_preserves_usage_component_and_tuning_metadata() -> None:
|
|
models = load_pricing_models(DATA_DIR)
|
|
model = next(item for item in models if item.id == "membership-plus-overage")
|
|
|
|
usage_component = next(component for component in model.charge_components if component.kind == "usage")
|
|
|
|
assert usage_component.meter == "openrouter_tokens"
|
|
assert usage_component.included_units == Decimal("100000")
|
|
assert usage_component.unit_price == Decimal("0.002")
|
|
assert any(parameter.parameter_class == "customer_tunable" for parameter in model.tunable_parameters)
|
|
|
|
|
|
def test_flat_model_still_exposes_access_fee_compatibility_fields() -> None:
|
|
models = load_pricing_models(DATA_DIR)
|
|
model = next(item for item in models if item.id == "flat-899-eur-monthly")
|
|
|
|
assert model.access_fee_amount == Decimal("8.99")
|
|
assert model.access_fee_cadence == "monthly"
|
|
assert len(model.charge_components) == 1
|
|
|
|
|
|
def test_assurance_claim_schema_is_optional_and_typed() -> None:
|
|
model = next(
|
|
item for item in load_pricing_models(DATA_DIR) if item.id == "flat-899-eur-monthly"
|
|
)
|
|
assert model.assurance_claims == ()
|
|
|
|
invalid = replace(
|
|
model,
|
|
assurance_claims=(
|
|
AssuranceClaim(
|
|
id="retention",
|
|
kind="retention",
|
|
customer_wording="Deleted data is gone.",
|
|
minimum_levels={"R": True, "P": 1},
|
|
delivering_service="",
|
|
evidence_ref="",
|
|
maximum_erasure_horizon_days=0,
|
|
erasure_mechanism="magic",
|
|
),
|
|
),
|
|
)
|
|
issues = validate_pricing_model(invalid)
|
|
|
|
assert any("invalid R level" in issue for issue in issues)
|
|
assert any("requires delivering_service" in issue for issue in issues)
|
|
assert any("requires evidence_ref" in issue for issue in issues)
|
|
assert any("invalid maximum erasure horizon" in issue for issue in issues)
|
|
assert any("unsupported erasure_mechanism" in issue for issue in issues)
|
|
|
|
|
|
def test_assurance_claim_loads_from_json_catalog(tmp_path: Path) -> None:
|
|
catalog = json.loads((DATA_DIR / "pricing-models.json").read_text(encoding="utf-8"))
|
|
catalog["models"][0]["assurance_claims"] = [
|
|
{
|
|
"id": "availability-tier",
|
|
"kind": "availability",
|
|
"customer_wording": "Survives a zone loss.",
|
|
"minimum_levels": {"V": "3"},
|
|
"delivering_service": "railiance-platform",
|
|
"evidence_ref": "evidence/zone-failover.json",
|
|
}
|
|
]
|
|
catalog_path = tmp_path / "pricing-models.json"
|
|
catalog_path.write_text(json.dumps(catalog), encoding="utf-8")
|
|
|
|
models = load_core_pricing_models(catalog_path)
|
|
claim = models[0].assurance_claims[0]
|
|
|
|
assert claim.id == "availability-tier"
|
|
assert claim.minimum_levels == {"V": 3}
|