mirror of
https://github.com/jhd3197/ServerKit.git
synced 2026-11-02 10:07:29 +09:00
Backend: hand-shaped {'error': ...} bodies in app/api get an AST census
and ceiling (1159) — milestone B's migrate-when-touched policy made
enforceable. Frontend: check-frontend-boundaries.mjs gains adoption
ceilings for raw api.* calls in pages (460, E1), per-page toast.error
extraction (264, E1), form-group blocks (343, F2), and unencoded query
interpolations in services/api (97, C4-interim) — totals that may only go
down, with a slack guard so a ceiling cannot drift above reality.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
72 lines
2.6 KiB
Python
72 lines
2.6 KiB
Python
"""The hand-shaped-error-body ratchet (plan 76, milestone B closure).
|
|
|
|
The conversion itself is migrate-when-touched (invariant 9); this ceiling is
|
|
what makes that policy real — see ``error_shape_census.py`` for the contract.
|
|
"""
|
|
|
|
from error_shape_census import census, count_file, read_ceiling, total
|
|
|
|
|
|
def test_the_count_is_at_or_below_the_ceiling():
|
|
found = census()
|
|
count = total(found)
|
|
ceiling = read_ceiling()
|
|
worst = sorted(found, key=lambda p: -len(found[p]))[:5]
|
|
assert count <= ceiling, (
|
|
f'{count} hand-shaped error bodies in app/api, ceiling is {ceiling}.\n'
|
|
f'Raise a typed error from app.exceptions instead — the global handler '
|
|
f'owns the body, the status, and the request id.\n'
|
|
f'Heaviest files: ' + ', '.join(f'{p} ({len(found[p])})' for p in worst)
|
|
)
|
|
|
|
|
|
def test_the_ceiling_is_not_stale():
|
|
count, ceiling = total(), read_ceiling()
|
|
assert ceiling - count <= 25, (
|
|
f'ceiling {ceiling} is {ceiling - count} above the actual {count}; '
|
|
f'run `python tests/error_shape_census.py --update`'
|
|
)
|
|
|
|
|
|
class TestTheCensusCountsTheRightThings:
|
|
"""A miscounting ratchet is worse than none: it reads green either way."""
|
|
|
|
def _count(self, tmp_path, source):
|
|
path = tmp_path / 'sample.py'
|
|
path.write_text(source, encoding='utf-8')
|
|
return len(count_file(str(path)))
|
|
|
|
def test_counts_a_jsonified_error_body(self, tmp_path):
|
|
assert self._count(tmp_path, (
|
|
"def handler():\n"
|
|
" return jsonify({'error': 'nope'}), 404\n"
|
|
)) == 1
|
|
|
|
def test_counts_a_bare_dict_error_body(self, tmp_path):
|
|
assert self._count(tmp_path, (
|
|
"def handler():\n"
|
|
" return {'error': 'nope'}, 400\n"
|
|
)) == 1
|
|
|
|
def test_does_not_count_a_success_body(self, tmp_path):
|
|
assert self._count(tmp_path, (
|
|
"def handler():\n"
|
|
" return jsonify({'success': True, 'data': []}), 200\n"
|
|
)) == 0
|
|
|
|
def test_does_not_count_a_typed_raise(self, tmp_path):
|
|
"""What the migration produces must not read as debt."""
|
|
assert self._count(tmp_path, (
|
|
"def handler():\n"
|
|
" raise NotFoundError('nope')\n"
|
|
)) == 0
|
|
|
|
def test_does_not_count_a_variable_body(self, tmp_path):
|
|
"""`return body, status` where body was built elsewhere is out of
|
|
scope for a syntactic census — the recorder helpers return those."""
|
|
assert self._count(tmp_path, (
|
|
"def handler():\n"
|
|
" body, status = unexpected_response(exc)\n"
|
|
" return body, status\n"
|
|
)) == 0
|