#!/usr/bin/env python3 """ test_endpoints.py — Grubflip API test suite Tests Grubflip API endpoints as they come online. Structured as stubs that will be filled in as Mike deploys endpoints. Current endpoint coverage (from Mike's task list): - Menu endpoints (CRUD) - Order endpoints - Restaurant endpoints - User endpoints - Auth endpoints Usage: python3 grubflip/api/test_endpoints.py [dev|prod] [--json] Author: Luna (@luna) — QA """ import sys import os sys.path.insert(0, os.path.join(os.path.dirname(__file__), "../..")) from shared.lib.test_helpers import TestRunner, get_base_url def main(): env = "dev" json_mode = False for arg in sys.argv[1:]: if arg == "--json": json_mode = True elif arg in ("dev", "prod"): env = arg base = get_base_url("grubflip", env) if not base: print(f"Unknown environment: {env}") sys.exit(1) t = TestRunner(f"grubflip-api-{env}", json_mode=json_mode) # ─── Connectivity check ────────────────────────────────── t.section("API CONNECTIVITY") resp = t.http_get(base) if resp["status"] == 0: t.fail("API base reachable", resp["error"]) # If we can't even reach it, skip everything else exit_code = t.summary() sys.exit(exit_code) else: t.pass_(f"API base responds (HTTP {resp['status']}, {resp['time_ms']:.0f}ms)") # ─── Menu endpoints ────────────────────────────────────── t.section("MENU ENDPOINTS") menu_endpoints = [ ("GET", "/menus", "List menus"), ("GET", "/menus/1", "Get menu by ID"), ("GET", "/menu-items", "List menu items"), ("GET", "/menu-items/1", "Get menu item by ID"), ] for method, path, label in menu_endpoints: url = f"{base}{path}" if method == "GET": resp = t.http_get(url) else: resp = t.http_post(url) if resp["status"] == 0: t.skip(label, f"unreachable: {resp['error']}") elif resp["status"] == 404: t.skip(label, "404 — endpoint not deployed yet") elif resp["status"] in (200, 201, 400, 401, 422): t.pass_(f"{label} — HTTP {resp['status']} ({resp['time_ms']:.0f}ms)") else: t.fail(label, f"HTTP {resp['status']}") # ─── Restaurant endpoints ──────────────────────────────── t.section("RESTAURANT ENDPOINTS") restaurant_endpoints = [ ("GET", "/restaurants", "List restaurants"), ("GET", "/restaurants/1", "Get restaurant by ID"), ] for method, path, label in restaurant_endpoints: url = f"{base}{path}" resp = t.http_get(url) if resp["status"] == 0: t.skip(label, f"unreachable: {resp['error']}") elif resp["status"] == 404: t.skip(label, "404 — endpoint not deployed yet") elif resp["status"] in (200, 400, 401, 403, 422): t.pass_(f"{label} — HTTP {resp['status']} ({resp['time_ms']:.0f}ms)") else: t.fail(label, f"HTTP {resp['status']}") # ─── Order endpoints ───────────────────────────────────── t.section("ORDER ENDPOINTS") order_endpoints = [ ("GET", "/orders", "List orders"), ("GET", "/orders/1", "Get order by ID"), ("POST", "/orders", "Create order"), ] for method, path, label in order_endpoints: url = f"{base}{path}" if method == "POST": resp = t.http_post(url, {"test": True}) else: resp = t.http_get(url) if resp["status"] == 0: t.skip(label, f"unreachable: {resp['error']}") elif resp["status"] == 404: t.skip(label, "404 — endpoint not deployed yet") elif resp["status"] in (200, 201, 400, 401, 422): t.pass_(f"{label} — HTTP {resp['status']} ({resp['time_ms']:.0f}ms)") else: t.fail(label, f"HTTP {resp['status']}") # ─── Auth endpoints ────────────────────────────────────── t.section("AUTH ENDPOINTS") auth_endpoints = [ ("POST", "/auth/login", "Login"), ("POST", "/auth/register", "Register"), ] for method, path, label in auth_endpoints: url = f"{base}{path}" resp = t.http_post(url, {}) if resp["status"] == 0: t.skip(label, f"unreachable: {resp['error']}") elif resp["status"] == 404: t.skip(label, "404 — endpoint not deployed yet") elif resp["status"] in (200, 400, 401, 422): t.pass_(f"{label} — HTTP {resp['status']} ({resp['time_ms']:.0f}ms)") else: t.fail(label, f"HTTP {resp['status']}") exit_code = t.summary() sys.exit(exit_code) if __name__ == "__main__": main()