Skip to content

Commit 4cf00bb

Browse files
committed
Add tests for badge expiry parsing and logic
1 parent 40346bb commit 4cf00bb

1 file changed

Lines changed: 190 additions & 0 deletions

File tree

tests/test_versioning.py

Lines changed: 190 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,16 @@
33
import pytest
44

55
from great_docs._versioning import (
6+
BADGE_EXPIRY_NEVER,
7+
BadgeExpiry,
68
VersionEntry,
79
build_version_map,
810
evaluate_version_expr,
911
extract_page_versions,
1012
get_latest_version,
13+
is_badge_expired,
1114
page_matches_version,
15+
parse_badge_expiry,
1216
parse_versions_config,
1317
process_version_fences,
1418
)
@@ -639,3 +643,189 @@ def test_prerelease_and_eol_flags(self):
639643
# Non-flagged version should not have the keys
640644
assert "prerelease" not in result["versions"][1]
641645
assert "eol" not in result["versions"][1]
646+
647+
648+
# ---------------------------------------------------------------------------
649+
# parse_badge_expiry
650+
# ---------------------------------------------------------------------------
651+
652+
653+
class TestParseBadgeExpiry:
654+
def test_none(self):
655+
assert parse_badge_expiry(None) is BADGE_EXPIRY_NEVER
656+
657+
def test_never_string(self):
658+
result = parse_badge_expiry("never")
659+
assert result.mode == "never"
660+
661+
def test_never_case_insensitive(self):
662+
assert parse_badge_expiry("Never").mode == "never"
663+
664+
def test_releases(self):
665+
result = parse_badge_expiry("3 releases")
666+
assert result.mode == "releases"
667+
assert result.value == 3
668+
669+
def test_release_singular(self):
670+
result = parse_badge_expiry("1 release")
671+
assert result.mode == "releases"
672+
assert result.value == 1
673+
674+
def test_minor_releases(self):
675+
result = parse_badge_expiry("2 minor releases")
676+
assert result.mode == "minor_releases"
677+
assert result.value == 2
678+
679+
def test_days(self):
680+
result = parse_badge_expiry("180 days")
681+
assert result.mode == "days"
682+
assert result.value == 180
683+
684+
def test_day_singular(self):
685+
result = parse_badge_expiry("1 day")
686+
assert result.mode == "days"
687+
assert result.value == 1
688+
689+
def test_iso_date(self):
690+
result = parse_badge_expiry("2026-06-01")
691+
assert result.mode == "date"
692+
assert result.value == "2026-06-01"
693+
694+
def test_version_tag(self):
695+
result = parse_badge_expiry("0.8")
696+
assert result.mode == "version"
697+
assert result.value == "0.8"
698+
699+
def test_version_tag_with_v_prefix(self):
700+
result = parse_badge_expiry("v1.2")
701+
assert result.mode == "version"
702+
assert result.value == "v1.2"
703+
704+
705+
# ---------------------------------------------------------------------------
706+
# is_badge_expired
707+
# ---------------------------------------------------------------------------
708+
709+
710+
class TestIsBadgeExpired:
711+
@pytest.fixture
712+
def versions(self) -> list[VersionEntry]:
713+
return parse_versions_config(
714+
[
715+
{"tag": "dev", "label": "dev", "prerelease": True},
716+
{"tag": "0.7", "label": "0.7.0"},
717+
{"tag": "0.6", "label": "0.6.0"},
718+
{"tag": "0.5", "label": "0.5.0"},
719+
{"tag": "0.4", "label": "0.4.0"},
720+
{"tag": "0.3", "label": "0.3.0"},
721+
]
722+
)
723+
724+
def test_never_not_expired(self, versions):
725+
assert is_badge_expired("0.3", versions[1], versions, BADGE_EXPIRY_NEVER) is False
726+
727+
# --- releases mode ---
728+
729+
def test_releases_not_expired_same_version(self, versions):
730+
expiry = BadgeExpiry(mode="releases", value=3)
731+
target = versions[5] # 0.3
732+
assert is_badge_expired("0.3", target, versions, expiry) is False
733+
734+
def test_releases_not_expired_within_window(self, versions):
735+
expiry = BadgeExpiry(mode="releases", value=3)
736+
target = versions[3] # 0.5 — 2 releases after 0.3
737+
assert is_badge_expired("0.3", target, versions, expiry) is False
738+
739+
def test_releases_expired_at_boundary(self, versions):
740+
expiry = BadgeExpiry(mode="releases", value=3)
741+
target = versions[2] # 0.6 — 3 releases after 0.3
742+
assert is_badge_expired("0.3", target, versions, expiry) is True
743+
744+
def test_releases_expired_past_boundary(self, versions):
745+
expiry = BadgeExpiry(mode="releases", value=3)
746+
target = versions[1] # 0.7 — 4 releases after 0.3
747+
assert is_badge_expired("0.3", target, versions, expiry) is True
748+
749+
# --- minor_releases mode ---
750+
751+
def test_minor_releases_skips_prerelease(self, versions):
752+
# dev is prerelease, so only 0.7-0.3 count
753+
expiry = BadgeExpiry(mode="minor_releases", value=3)
754+
target = versions[2] # 0.6 — 3 non-pre releases after 0.3
755+
assert is_badge_expired("0.3", target, versions, expiry) is True
756+
757+
def test_minor_releases_not_expired(self, versions):
758+
expiry = BadgeExpiry(mode="minor_releases", value=3)
759+
target = versions[3] # 0.5 — 2 non-pre releases after 0.3
760+
assert is_badge_expired("0.3", target, versions, expiry) is False
761+
762+
def test_minor_releases_prerelease_target_falls_back_to_latest(self, versions):
763+
# dev (prerelease) should behave like the latest non-prerelease (0.7)
764+
expiry = BadgeExpiry(mode="minor_releases", value=3)
765+
target_dev = versions[0] # dev
766+
target_07 = versions[1] # 0.7
767+
assert is_badge_expired("0.3", target_dev, versions, expiry) == is_badge_expired(
768+
"0.3", target_07, versions, expiry
769+
)
770+
771+
# --- version mode ---
772+
773+
def test_version_not_expired_before_threshold(self, versions):
774+
expiry = BadgeExpiry(mode="version", value="0.6")
775+
target = versions[3] # 0.5
776+
assert is_badge_expired("0.3", target, versions, expiry) is False
777+
778+
def test_version_expired_at_threshold(self, versions):
779+
expiry = BadgeExpiry(mode="version", value="0.6")
780+
target = versions[2] # 0.6
781+
assert is_badge_expired("0.3", target, versions, expiry) is True
782+
783+
def test_version_expired_after_threshold(self, versions):
784+
expiry = BadgeExpiry(mode="version", value="0.6")
785+
target = versions[1] # 0.7
786+
assert is_badge_expired("0.3", target, versions, expiry) is True
787+
788+
# --- date mode ---
789+
790+
def test_date_not_expired_future(self, versions):
791+
expiry = BadgeExpiry(mode="date", value="2099-01-01")
792+
assert is_badge_expired("0.3", versions[1], versions, expiry) is False
793+
794+
def test_date_expired_past(self, versions):
795+
expiry = BadgeExpiry(mode="date", value="2020-01-01")
796+
assert is_badge_expired("0.3", versions[1], versions, expiry) is True
797+
798+
# --- days mode ---
799+
800+
def test_days_no_released_date(self, versions):
801+
expiry = BadgeExpiry(mode="days", value=90)
802+
# No released date → fail open
803+
assert is_badge_expired("0.3", versions[1], versions, expiry) is False
804+
805+
def test_days_expired(self):
806+
versions = parse_versions_config(
807+
[
808+
{"tag": "0.5", "label": "0.5.0"},
809+
{"tag": "0.3", "label": "0.3.0", "released": "2020-01-01"},
810+
]
811+
)
812+
expiry = BadgeExpiry(mode="days", value=90)
813+
assert is_badge_expired("0.3", versions[0], versions, expiry) is True
814+
815+
def test_days_not_expired(self):
816+
versions = parse_versions_config(
817+
[
818+
{"tag": "0.5", "label": "0.5.0"},
819+
{"tag": "0.3", "label": "0.3.0", "released": "2099-01-01"},
820+
]
821+
)
822+
expiry = BadgeExpiry(mode="days", value=90)
823+
assert is_badge_expired("0.3", versions[0], versions, expiry) is False
824+
825+
# --- unknown badge version ---
826+
827+
def test_unknown_badge_version(self, versions):
828+
expiry = BadgeExpiry(mode="releases", value=1)
829+
assert is_badge_expired("9.9", versions[1], versions, expiry) is False
830+
831+
# --- changed/deprecated not affected (tested via expand_version_badges) ---

0 commit comments

Comments
 (0)