mirror of
https://github.com/kuhyx/utils.git
synced 2026-11-10 22:27:13 +01:00
The three Python packages pinned ruff twice at different versions: requirements.txt at 0.16.7, .pre-commit-config.yaml at v0.15.2. Only the older one ever ran, so `select = ["ALL"]` was enforced two minor versions behind. Measured before aligning: v0.15.2 reports 0 findings, every 0.16.x reports CPY001 on each file -- 70 crdt-sync, 23 freedays, 71 gatelock, and no other rule. Resolved by adding the notice rather than ignoring the rule, so the gate keeps its teeth. Two gatelock modules sat at exactly the 250-line cap, so a one-line header tipped them to 251. Both are split along a real seam rather than shaved: _widget_fills.py colour arithmetic over LockConfig, no tkinter import _surfaces_focus.py selects among existing surfaces, never mutates them The focus split keeps _surfaces.py's documented containment (it stays the only module that creates, moves or destroys windows), and the static guard in test_recovery_invariants.py globs _surfaces*.py, so the new sibling is covered with no list to extend. widgets.py re-exports the fills helpers, which keeps gatelock.widgets the single public surface its tests import. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019kMvSMtsVMB3d2uoZ56pbp
85 lines
3.2 KiB
Python
85 lines
3.2 KiB
Python
# Copyright (c) 2026 Krzysztof Rudnicki
|
|
"""Tests for ``describe_google_token`` in ``tool/link_google``.
|
|
|
|
Split from :mod:`test_tool_link_google` (which covers linking) and
|
|
:mod:`test_tool_link_google_main` (the CLI) to stay under the 250-line cap.
|
|
|
|
These are the local, pre-network checks. They exist so a misconfiguration
|
|
reports itself here rather than as an opaque Firebase rejection, so what is
|
|
asserted is the *message* -- naming what was pasted by mistake is the entire
|
|
value of the check.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import base64
|
|
|
|
import pytest
|
|
|
|
from crdt_sync.tests.test_tool_link_google import _google_token, _jwt
|
|
from tool import link_google as lg
|
|
|
|
|
|
def test_a_token_that_is_not_three_parts_is_rejected() -> None:
|
|
"""An access token or an auth code pasted by mistake.
|
|
|
|
The message names both, because that is the actual confusion -- the
|
|
module docstring exists because the Firebase-side error does not.
|
|
"""
|
|
with pytest.raises(lg.LinkError, match="not an access token"):
|
|
lg.describe_google_token("not-a-jwt")
|
|
|
|
|
|
def test_a_token_with_an_unparseable_payload_is_rejected() -> None:
|
|
"""Three parts, but the middle one is not base64url JSON."""
|
|
with pytest.raises(lg.LinkError, match="not valid base64url JSON"):
|
|
lg.describe_google_token("header.!!!not-base64!!!.signature")
|
|
|
|
|
|
def test_a_payload_that_is_not_an_object_is_rejected() -> None:
|
|
"""Valid base64url JSON, wrong shape."""
|
|
payload = base64.urlsafe_b64encode(b'"just a string"').decode().rstrip("=")
|
|
|
|
with pytest.raises(lg.LinkError, match="not a JSON object"):
|
|
lg.describe_google_token(f"header.{payload}.signature")
|
|
|
|
|
|
def test_a_token_from_another_issuer_is_rejected() -> None:
|
|
"""The check that makes a misconfiguration report itself locally."""
|
|
with pytest.raises(lg.LinkError, match="not Google"):
|
|
lg.describe_google_token(_google_token(iss="https://login.example.com"))
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"issuer", ["https://accounts.google.com", "accounts.google.com"]
|
|
)
|
|
def test_both_google_issuer_spellings_are_accepted(issuer: str) -> None:
|
|
"""Google uses both forms; rejecting either would be a false alarm."""
|
|
assert "person@gmail.com" in lg.describe_google_token(_google_token(iss=issuer))
|
|
|
|
|
|
def test_the_description_names_the_account_and_the_audience() -> None:
|
|
"""The operator's only chance to notice they are linking the wrong one."""
|
|
description = lg.describe_google_token(_google_token())
|
|
|
|
assert "person@gmail.com" in description
|
|
assert "the-web-client-id.apps.googleusercontent.com" in description
|
|
|
|
|
|
def test_missing_optional_claims_are_described_rather_than_crashing() -> None:
|
|
"""A token without email/aud is odd but still describable."""
|
|
token = _jwt({"iss": "accounts.google.com"})
|
|
|
|
description = lg.describe_google_token(token)
|
|
|
|
assert "<no email claim>" in description
|
|
assert "<no aud claim>" in description
|
|
|
|
|
|
def test_padding_is_restored_before_decoding() -> None:
|
|
"""base64url in a JWT is unpadded; decoding without padding fails."""
|
|
# A payload whose length is not a multiple of 4 once stripped.
|
|
claims = {"iss": "accounts.google.com", "email": "a@b.co"}
|
|
|
|
assert "a@b.co" in lg.describe_google_token(_jwt(claims))
|