Phase A of #161: ships the smoke script and README before the maximus-api prices-proxy endpoint is live in prod. The script will fail on case 1 (HTTP 404) until /v1/prices is implemented and deployed — that is expected; running it is gated to Phase B (after prices-proxy ships, before cutting v0.9.0). Script covers 4 cases: 1. Stock happy path (AAPL) — HTTP 200, .price > 0 2. Crypto happy path (BTC) — HTTP 200, .price > 0 3. Invalid symbol — HTTP 404, error.code=symbol_not_found 4. Missing auth — HTTP 401, error.code=missing_token `set -euo pipefail`, exits non-zero on first failure. Reads token from MAXIMUS_API_TEST_TOKEN env var (never committed). README documents env vars and the two paths for obtaining a premium test token (admin endpoint TODO in maximus-api, manual JWT signing as current workaround). CSP whitelist for https://api.lacompagniemaximus.com is already in place in src-tauri/tauri.conf.json — verified, no change needed. No application code touched; npm test (492) and cargo test --lib (69) remain green. Phase A only (#161)
104 lines
3.8 KiB
Bash
Executable file
104 lines
3.8 KiB
Bash
Executable file
#!/usr/bin/env bash
|
|
# Smoke test — /v1/prices end-to-end against the deployed maximus-api.
|
|
#
|
|
# Issue #161 (Phase A): committed for reproducibility before each release.
|
|
# Issue #161 (Phase B): runnable once maximus-api/prices-proxy ships.
|
|
# Until then, /v1/prices returns 404 in prod and this script will exit 1
|
|
# on the first happy-path call. That is expected during Phase A.
|
|
#
|
|
# Usage:
|
|
# MAXIMUS_API_TEST_TOKEN=<premium-license-token> ./tests/smoke/prices.sh
|
|
#
|
|
# Optional overrides:
|
|
# MAXIMUS_API_URL (default: https://api.lacompagniemaximus.com)
|
|
# SMOKE_DATE (default: yesterday — pick a weekday for stocks)
|
|
#
|
|
# Dependencies: bash 4+, curl, jq, GNU `date -d` (Linux). On macOS, set
|
|
# SMOKE_DATE manually instead of relying on the default.
|
|
#
|
|
# Exit codes:
|
|
# 0 all 4 cases pass
|
|
# 1 any single case fails (the script is set -e; first failure aborts)
|
|
# 2 required env var missing
|
|
|
|
set -euo pipefail
|
|
|
|
API_URL="${MAXIMUS_API_URL:-https://api.lacompagniemaximus.com}"
|
|
TOKEN="${MAXIMUS_API_TEST_TOKEN:-}"
|
|
DATE="${SMOKE_DATE:-$(date -d 'yesterday' +%Y-%m-%d)}"
|
|
|
|
if [ -z "$TOKEN" ]; then
|
|
echo "error: MAXIMUS_API_TEST_TOKEN must be set to a premium test license token." >&2
|
|
echo " See tests/smoke/README.md for how to obtain one." >&2
|
|
exit 2
|
|
fi
|
|
|
|
TMP=$(mktemp)
|
|
trap 'rm -f "$TMP"' EXIT
|
|
|
|
pass() { echo " pass: $1"; }
|
|
fail() { echo " FAIL: $1" >&2; exit 1; }
|
|
|
|
echo "smoke: $API_URL/v1/prices (date=$DATE)"
|
|
|
|
# -----------------------------------------------------------------------------
|
|
# Case 1 — stock happy path
|
|
# -----------------------------------------------------------------------------
|
|
echo "[1/4] stock happy path (AAPL)"
|
|
if ! curl -fsS \
|
|
-H "Authorization: Bearer $TOKEN" \
|
|
-o "$TMP" \
|
|
"$API_URL/v1/prices?symbol=AAPL&date=$DATE"; then
|
|
fail "stock fetch did not return 200 for AAPL"
|
|
fi
|
|
if ! jq -e '.price > 0' "$TMP" >/dev/null; then
|
|
fail "stock response did not contain a positive .price field"
|
|
fi
|
|
pass "AAPL .price = $(jq -r '.price' "$TMP")"
|
|
|
|
# -----------------------------------------------------------------------------
|
|
# Case 2 — crypto happy path
|
|
# -----------------------------------------------------------------------------
|
|
echo "[2/4] crypto happy path (BTC)"
|
|
if ! curl -fsS \
|
|
-H "Authorization: Bearer $TOKEN" \
|
|
-o "$TMP" \
|
|
"$API_URL/v1/prices?symbol=BTC&date=$DATE"; then
|
|
fail "crypto fetch did not return 200 for BTC"
|
|
fi
|
|
if ! jq -e '.price > 0' "$TMP" >/dev/null; then
|
|
fail "crypto response did not contain a positive .price field"
|
|
fi
|
|
pass "BTC .price = $(jq -r '.price' "$TMP")"
|
|
|
|
# -----------------------------------------------------------------------------
|
|
# Case 3 — invalid symbol -> 404 / symbol_not_found
|
|
# -----------------------------------------------------------------------------
|
|
echo "[3/4] invalid symbol (NOTREAL_XYZ)"
|
|
http=$(curl -s -o "$TMP" -w '%{http_code}' \
|
|
-H "Authorization: Bearer $TOKEN" \
|
|
"$API_URL/v1/prices?symbol=NOTREAL_XYZ&date=$DATE")
|
|
if [ "$http" != "404" ]; then
|
|
fail "invalid symbol expected HTTP 404, got $http"
|
|
fi
|
|
if ! jq -e '.error.code == "symbol_not_found"' "$TMP" >/dev/null; then
|
|
fail "invalid symbol expected error.code = 'symbol_not_found', got: $(cat "$TMP")"
|
|
fi
|
|
pass "404 + symbol_not_found"
|
|
|
|
# -----------------------------------------------------------------------------
|
|
# Case 4 — no auth -> 401 / missing_token
|
|
# -----------------------------------------------------------------------------
|
|
echo "[4/4] missing auth"
|
|
http=$(curl -s -o "$TMP" -w '%{http_code}' \
|
|
"$API_URL/v1/prices?symbol=AAPL&date=$DATE")
|
|
if [ "$http" != "401" ]; then
|
|
fail "missing-auth expected HTTP 401, got $http"
|
|
fi
|
|
if ! jq -e '.error.code == "missing_token"' "$TMP" >/dev/null; then
|
|
fail "missing-auth expected error.code = 'missing_token', got: $(cat "$TMP")"
|
|
fi
|
|
pass "401 + missing_token"
|
|
|
|
echo ""
|
|
echo "smoke: all 4 cases pass"
|