"""Tests for raycast_api.signing.transforms.""" from __future__ import annotations import pytest from raycast_api.signing.transforms import apply_rot from raycast_api.signing_spec import RotRange RAYCAST_RANGES = [ RotRange(0x41, 0x5A, 13), RotRange(0x61, 0x7A, 13), RotRange(0x30, 0x39, 5), ] class TestRaycastDefaults: def test_letter_rotation_matches_handoff(self) -> None: assert apply_rot("abcXYZ", RAYCAST_RANGES) == "nopKLM" def test_digit_rotation(self) -> None: assert apply_rot("01234", RAYCAST_RANGES) == "56789" assert apply_rot("56789", RAYCAST_RANGES) == "01234" def test_punctuation_unchanged(self) -> None: assert apply_rot("a.b", RAYCAST_RANGES) == "n.o" assert apply_rot(":/?-_=", RAYCAST_RANGES) == ":/?-_=" def test_double_apply_is_identity_for_letters_and_hex_digits(self) -> None: sample = "deadbeef0123456789" assert apply_rot(apply_rot(sample, RAYCAST_RANGES), RAYCAST_RANGES) == sample def test_empty_string(self) -> None: assert apply_rot("", RAYCAST_RANGES) == "" def test_unicode_outside_ranges_passes_through(self) -> None: assert apply_rot("café→", RAYCAST_RANGES) == "pnsé→" class TestArbitraryRanges: def test_single_range_no_overflow(self) -> None: assert apply_rot("ABCXYZ", [RotRange(0x41, 0x5A, 0)]) == "ABCXYZ" def test_shift_wraps(self) -> None: assert apply_rot("hello", [RotRange(0x61, 0x7A, 26)]) == "hello" assert apply_rot("abz", [RotRange(0x61, 0x7A, 1)]) == "bca" def test_first_matching_range_wins(self) -> None: ranges = [RotRange(0x61, 0x7A, 1), RotRange(0x61, 0x7A, 5)] assert apply_rot("a", ranges) == "b" def test_range_outside_input_does_nothing(self) -> None: assert apply_rot("hello", [RotRange(0x30, 0x39, 5)]) == "hello" def test_negative_shift_rejected_at_construction(self) -> None: with pytest.raises(ValueError): RotRange(0x41, 0x5A, -1)