Files
ServerKit/backend/tests/test_services_alias.py
Juan DenisandClaude Opus 4.8 3f18a0ebd3 refactor(unify): §1 — single Services detail surface; /apps→/services
Feature-unification plan §1 (Services UI = Applications backend). Ends the
"Applications vs Services" terminology split by collapsing the two detail
pages into one canonical surface and aliasing the backend.

Frontend:
- Merge ApplicationDetail's exclusive tabs (Container Ops, WAF, Build, Deploy,
  Previews) into the canonical ServiceDetail (PageTopbar chrome). Type-gating
  preserved exactly: ops=Docker, waf=Docker+Python, build/deploy/previews=all.
- serviceTypes.js tab lists extended for the merged tabs.
- /apps/:id and /apps/:id/:tab now redirect to /services/:id[/:tab] via
  LegacyAppRedirect (deep links preserved); ApplicationDetail.jsx deleted.
- Drop the /apps page-title entry and "Application Details" dynamic title.
- api.getServices()/getService() aliases over getApps()/getApp().

Backend:
- Mount apps_bp a second time under /api/v1/services as a true alias of
  /api/v1/apps (Flask blueprint re-registration with name='services').
- Test: /api/v1/services resolves identically to /api/v1/apps.

Verified: frontend build clean, eslint 0 errors, 3 alias tests pass.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-24 14:06:05 -04:00

40 lines
1.5 KiB
Python

"""§1 unification: /api/v1/services is a true alias of /api/v1/apps.
"Services" is the user-facing term for the backend's Applications. The same
`apps_bp` blueprint is mounted under both prefixes, so every route must resolve
identically regardless of which prefix a caller uses.
"""
def test_services_alias_matches_apps_list(client, auth_headers):
apps_res = client.get('/api/v1/apps', headers=auth_headers)
services_res = client.get('/api/v1/services', headers=auth_headers)
assert apps_res.status_code == 200
assert services_res.status_code == 200
# Same handler, same (empty) data shape.
assert services_res.get_json() == apps_res.get_json()
def test_services_alias_requires_auth_like_apps():
# Both prefixes are JWT-protected; an unauthenticated call is rejected the
# same way on either mount.
import app as _app_pkg # noqa: F401
from app import create_app
application = create_app('testing')
with application.test_client() as c:
apps_res = c.get('/api/v1/apps')
services_res = c.get('/api/v1/services')
assert apps_res.status_code == services_res.status_code
assert apps_res.status_code in (401, 422)
def test_both_prefixes_registered_in_url_map():
from app import create_app
application = create_app('testing')
rules = {r.rule for r in application.url_map.iter_rules()}
assert '/api/v1/apps/' in rules or '/api/v1/apps' in rules
assert '/api/v1/services/' in rules or '/api/v1/services' in rules