dana-medical-site/internal/api/ssr_test.go
2026-10-14 13:33:13 +00:00

84 lines
2.3 KiB
Go

package api
import (
"bytes"
"context"
"fmt"
"os/exec"
"path/filepath"
"testing"
"time"
)
func fixtureRenderer(t *testing.T) *pageRenderer {
t.Helper()
node, err := exec.LookPath("node")
if err != nil {
t.Skip("Node.js unavailable")
}
script, err := filepath.Abs("testdata/render-fixture.mjs")
if err != nil {
t.Fatal(err)
}
return &pageRenderer{node: node, script: script, slots: make(chan struct{}, 2), cache: map[string]renderCacheEntry{}}
}
func TestRendererRefreshesContent(t *testing.T) {
p := fixtureRenderer(t)
for _, step := range []struct {
text string
hit bool
}{{"old", false}, {"old", true}, {"new", false}, {"new", true}} {
out, hit, err := p.render(context.Background(), "/page/", []byte(fmt.Sprintf(`{"text":%q}`, step.text)))
if err != nil || hit != step.hit || !bytes.Contains(out, []byte(step.text)) {
t.Fatalf("step %+v: hit=%v err=%v", step, hit, err)
}
}
if p.cacheBytes != len(p.cache["/page/"].html) {
t.Fatal("replacement cache accounting is wrong")
}
}
func TestRendererRejectsBrokenOutput(t *testing.T) {
p := fixtureRenderer(t)
for _, input := range []string{`{"fail":true}`, `{"invalid":true}`} {
if _, _, err := p.render(context.Background(), "/page/", []byte(input)); err == nil {
t.Fatal("broken output accepted")
}
}
if len(p.cache) != 0 || len(p.slots) != 0 {
t.Fatal("failure cached or renderer slot leaked")
}
ctx, cancel := context.WithTimeout(context.Background(), 100*time.Millisecond)
defer cancel()
if _, _, err := p.render(ctx, "/page/", []byte(`{"wait":5000}`)); err == nil {
t.Fatal("cancelled render succeeded")
}
if len(p.slots) != 0 {
t.Fatal("cancelled render leaked slot")
}
}
func TestRendererDoesNotCacheQueryVariants(t *testing.T) {
p := fixtureRenderer(t)
for i := 0; i < 2; i++ {
_, hit, err := p.render(context.Background(), "/page/?q=test", []byte(`{"text":"query"}`))
if err != nil || hit {
t.Fatalf("query variant: hit=%v err=%v", hit, err)
}
}
if len(p.cache) != 0 {
t.Fatal("query displaced canonical cache")
}
}
func TestCappedBuffer(t *testing.T) {
b := &cappedBuffer{limit: 4}
if n, err := b.Write([]byte("abcdef")); n != 6 || err != nil || b.String() != "abcd" || !b.overflow {
t.Fatal("output bound failed")
}
if _, err := b.Write([]byte("more")); err != nil || b.Len() != 4 {
t.Fatal("repeated overflow failed")
}
}