Some checks failed
api-ci-deploy / test-build-deploy (push) Has been cancelled
- client.py: set apikey explicitly in _create_base_client headers (Kong needs it on every request; for per-user clients apikey stays anon while Authorization carries the user JWT). Fixes the 2 stale header unit tests that asserted apikey in options.headers, and is robust against supabase-py default-header changes. - test_dev_stack: exact == seed counts → >= baselines. The greenfield seed sets a floor; additive exam-marker fixtures (S4-4 cohort) legitimately push live .94 counts above the old snapshot. >= still catches a broken/missing seed. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
87 lines
3.3 KiB
Python
87 lines
3.3 KiB
Python
import os
|
|
|
|
import requests
|
|
|
|
|
|
def _supabase_headers():
|
|
key = os.getenv('SERVICE_ROLE_KEY') or os.getenv('ANON_KEY')
|
|
assert key, 'SERVICE_ROLE_KEY or ANON_KEY must be set for Supabase integration tests'
|
|
return {
|
|
'apikey': key,
|
|
'Authorization': f'Bearer {key}',
|
|
'Prefer': 'count=exact',
|
|
}
|
|
|
|
|
|
def _rest_count(table: str) -> int:
|
|
supabase_url = os.getenv('SUPABASE_URL')
|
|
assert supabase_url, 'SUPABASE_URL must be set'
|
|
response = requests.get(
|
|
f'{supabase_url.rstrip("/")}/rest/v1/{table}',
|
|
headers=_supabase_headers(),
|
|
params={'select': 'id'},
|
|
timeout=15,
|
|
)
|
|
assert response.status_code in (200, 206), response.text[:500]
|
|
content_range = response.headers.get('content-range', '')
|
|
assert '/' in content_range, f'missing exact content-range count for {table}: {content_range!r}'
|
|
return int(content_range.rsplit('/', 1)[1])
|
|
|
|
|
|
def test_dev_environment_points_at_dev_supabase():
|
|
assert os.getenv('SUPABASE_URL') == 'http://192.168.0.94:8000'
|
|
|
|
|
|
def test_dev_api_health_endpoint_is_healthy():
|
|
health_url = os.getenv('API_HEALTH_URL', 'http://192.168.0.64:18000/health')
|
|
response = requests.get(health_url, timeout=15)
|
|
assert response.status_code == 200
|
|
payload = response.json()
|
|
assert payload['status'] == 'healthy'
|
|
|
|
runtime = payload['runtime']
|
|
assert runtime['api_runtime_role'] == 'dev'
|
|
assert runtime['start_mode'] == 'dev'
|
|
assert runtime['app_environment'] == 'development'
|
|
assert runtime['environment'] == 'development'
|
|
assert runtime['backend_dev_mode'] is True
|
|
assert runtime['compose_project'] == 'api-dev'
|
|
assert runtime['supabase_url_host'] == '192.168.0.94'
|
|
|
|
assert payload['services']['supabase']['status'] == 'healthy'
|
|
assert payload['services']['supabase']['url_host'] == '192.168.0.94'
|
|
assert payload['services']['redis']['status'] == 'healthy'
|
|
assert payload['services']['redis']['environment'] == 'dev'
|
|
assert payload['services']['redis']['database'] == 0
|
|
|
|
|
|
# NOTE: these are >= baselines, not exact counts. The greenfield seed produces this floor;
|
|
# additive exam-marker fixtures (S4-4 cohort adds ~10 students/memberships; ad-hoc classes) push
|
|
# the live .94 counts above it. Exact == froze a snapshot that any new fixture breaks, while >=
|
|
# still catches a broken or missing seed.
|
|
def test_supabase_dev_seed_core_counts():
|
|
assert _rest_count('profiles') >= 21
|
|
assert _rest_count('institute_memberships') >= 21
|
|
assert _rest_count('institutes') >= 2
|
|
|
|
|
|
def test_supabase_dev_seed_timetable_counts():
|
|
assert _rest_count('classes') >= 17
|
|
assert _rest_count('taught_lessons') >= 1462
|
|
|
|
|
|
def test_runtime_identity_does_not_expose_secret_values():
|
|
health_url = os.getenv('API_HEALTH_URL', 'http://192.168.0.64:18000/health')
|
|
response = requests.get(health_url, timeout=15)
|
|
assert response.status_code == 200
|
|
payload_text = response.text
|
|
for secret_name in ('SERVICE_ROLE_KEY', 'ANON_KEY', 'SUPABASE_JWT_SECRET', 'REDIS_PASSWORD'):
|
|
secret_value = os.getenv(secret_name)
|
|
if secret_value:
|
|
assert secret_value not in payload_text
|
|
|
|
runtime = response.json()['runtime']
|
|
assert 'supabase_url' not in runtime
|
|
assert 'service_role_key' not in runtime
|
|
assert 'anon_key' not in runtime
|