generated from mathias/template-go-web
TestAtlasJSON_ServesAtlasWithGeneratedCIStage demanded STAGE 06 contain the
job names parsed from the embedded cd.yml (guard/check/build/deploy). But when
the forge is reachable, the handler deliberately REPLACES those nodes with the
latest real run — live per-job status, which is the whole point of that overlay.
So the test passed on a laptop with no route to Gitea and failed inside CI,
where the overlay works as designed:
CI stage missing generated job "guard"
(got map[Detect unsubstituted template:true Lint / Test / Vet:true
▶ run #62 · running:true])
It went red on a commit that touched only atlas.json — a test that depends on
whether the network is reachable will eventually fail on someone innocent, and
did.
The endpoint test now asserts the shape it serves — STAGE 06 exists, is
populated by whichever source won, and every node has a title. The
deterministic assertion already exists where it belongs, in
TestBuild_OverlaysCIStageNodesFromWorkflow, which feeds Build a fixed workflow
and never touches the network.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011PL5XcG68SvQqz3vGVbWbf
100 lines
2.7 KiB
Go
100 lines
2.7 KiB
Go
package web
|
|
|
|
import (
|
|
"encoding/json"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"strings"
|
|
"testing"
|
|
|
|
"git.d-ma.be/mathias/cad-atlas/internal/atlas"
|
|
)
|
|
|
|
func TestRootServesAtlas(t *testing.T) {
|
|
srv := httptest.NewServer(NewHandler())
|
|
defer srv.Close()
|
|
|
|
resp, err := http.Get(srv.URL + "/")
|
|
if err != nil {
|
|
t.Fatalf("GET /: %v", err)
|
|
}
|
|
defer func() { _ = resp.Body.Close() }()
|
|
|
|
if resp.StatusCode != http.StatusOK {
|
|
t.Fatalf("GET / status = %d, want 200", resp.StatusCode)
|
|
}
|
|
buf := make([]byte, 4096)
|
|
n, _ := resp.Body.Read(buf)
|
|
if !strings.Contains(string(buf[:n]), "CAD") {
|
|
t.Fatalf("GET / body missing atlas marker %q", "CAD")
|
|
}
|
|
}
|
|
|
|
// This asserts the SHAPE the endpoint serves, not the exact CI job names.
|
|
//
|
|
// STAGE 06 has two sources: the embedded workflow (deterministic) and, when the
|
|
// forge is reachable, the live latest run — which overwrites it with real job
|
|
// names and a "▶ run #N" node. The old assertion demanded the workflow-derived
|
|
// names, so it passed on a laptop with no route to Gitea and failed inside CI,
|
|
// where the overlay works exactly as designed. It went red on 2026-08-19 for a
|
|
// commit that only touched atlas.json.
|
|
//
|
|
// The deterministic assertion lives in the atlas package
|
|
// (TestBuild_OverlaysCIStageNodesFromWorkflow), which feeds Build a fixed
|
|
// workflow and no network. Here we check the endpoint serves a usable atlas
|
|
// whichever source won.
|
|
func TestAtlasJSON_ServesAtlasWithPopulatedCIStage(t *testing.T) {
|
|
srv := httptest.NewServer(NewHandler())
|
|
defer srv.Close()
|
|
|
|
resp, err := http.Get(srv.URL + "/api/atlas.json")
|
|
if err != nil {
|
|
t.Fatalf("GET /api/atlas.json: %v", err)
|
|
}
|
|
defer func() { _ = resp.Body.Close() }()
|
|
|
|
if resp.StatusCode != http.StatusOK {
|
|
t.Fatalf("status = %d, want 200", resp.StatusCode)
|
|
}
|
|
var a atlas.Atlas
|
|
if err := json.NewDecoder(resp.Body).Decode(&a); err != nil {
|
|
t.Fatalf("decode atlas: %v", err)
|
|
}
|
|
if len(a.Stages) == 0 {
|
|
t.Fatal("atlas has no stages")
|
|
}
|
|
|
|
var ci *atlas.Stage
|
|
for i := range a.Stages {
|
|
if a.Stages[i].No == "STAGE 06" {
|
|
ci = &a.Stages[i]
|
|
}
|
|
}
|
|
if ci == nil {
|
|
t.Fatal("STAGE 06 missing from the served atlas")
|
|
}
|
|
if len(ci.Nodes) == 0 {
|
|
t.Fatal("STAGE 06 has no nodes — neither the embedded workflow nor the live run populated it")
|
|
}
|
|
for _, n := range ci.Nodes {
|
|
if n.Title == "" {
|
|
t.Fatalf("STAGE 06 node with no title: %+v", n)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestUnknownPath404(t *testing.T) {
|
|
srv := httptest.NewServer(NewHandler())
|
|
defer srv.Close()
|
|
|
|
resp, err := http.Get(srv.URL + "/nope")
|
|
if err != nil {
|
|
t.Fatalf("GET /nope: %v", err)
|
|
}
|
|
defer func() { _ = resp.Body.Close() }()
|
|
|
|
if resp.StatusCode != http.StatusNotFound {
|
|
t.Fatalf("GET /nope status = %d, want 404", resp.StatusCode)
|
|
}
|
|
}
|