socle

pages_test.go

package main

import (
	"fmt"
	"sort"
	"strings"
	"testing"

	"github.com/warpfork/go-testmark"
)

// TestPageSnapshots drives the browse pages through the fixture cases in testdata/pages.md.
// Each case is a pair of hunks: <case>/url (the GET target) and <case>/response
// (status line, the interesting headers, a blank line, then the body).
// Run with -testmark.regen to regenerate the response hunks and review via git diff.
//
// Determinism rests on the hermetic fixture repo (pinned shas), the pinned theme seed,
// and httptest's fixed request host.  The fixture shas appear verbatim in the snapshots;
// if they drift, gitfixture_test.go is the place to look.
func TestPageSnapshots(t *testing.T) {
	doc, err := testmark.ReadFile("testdata/pages.md")
	if err != nil {
		t.Fatalf("reading fixtures: %v", err)
	}
	doc.BuildDirIndex()
	s := fixtureServer(t)
	var pa testmark.PatchAccumulator
	for _, dirent := range doc.DirEnt.ChildrenList {
		t.Run(dirent.Name, func(t *testing.T) {
			urlEnt := dirent.Children["url"]
			resEnt := dirent.Children["response"]
			if urlEnt == nil || urlEnt.Hunk == nil || resEnt == nil || resEnt.Hunk == nil {
				t.Fatalf("fixture %q needs both a url and a response hunk", dirent.Name)
			}
			target := strings.TrimSpace(string(urlEnt.Hunk.Body))
			got := describeResponse(s, target)
			if *testmark.Regen {
				pa.AppendPatchIfBodyDiffers(*resEnt.Hunk, []byte(got))
			} else if got != string(resEnt.Hunk.Body) {
				t.Errorf("response mismatch for %s:\n--- got:\n%s--- want:\n%s", target, got, resEnt.Hunk.Body)
			}
		})
	}
	if *testmark.Regen {
		if err := pa.WriteFileWithPatches(doc, "testdata/pages.md"); err != nil {
			t.Fatal(err)
		}
	}
}

// describeResponse renders one GET as the stable text the fixtures assert on:
// the status, every header except the content-length (dull) and date-ish ones, then the body.
func describeResponse(s *server, target string) string {
	rec := do(s, target, nil, nil)
	var sb strings.Builder
	fmt.Fprintf(&sb, "status: %d\n", rec.Code)
	names := make([]string, 0, len(rec.Header()))
	for name := range rec.Header() {
		if name != "Content-Length" {
			names = append(names, name)
		}
	}
	sort.Strings(names)
	for _, name := range names {
		fmt.Fprintf(&sb, "%s: %s\n", name, strings.Join(rec.Header()[name], ", "))
	}
	sb.WriteString("\n")
	sb.Write(rec.Body.Bytes())
	return sb.String()
}

pages_test.go · 2.3 KiB · 619b45eb15