package web_test
import (
"io"
"io/fs"
"net/http"
"net/http/httptest"
"strings"
"testing"
"sourcecraft.dev/bigbes/lethe/internal/server/web"
)
// TestHandler_InjectsConfigIntoIndex asserts that GET / returns 200 HTML
// containing window.__LETHE_CONFIG__ with the supplied values, exactly once.
func TestHandler_InjectsConfigIntoIndex(t *testing.T) {
h := web.Handler(web.Config{
Issuer: "http://stub",
ClientID: "lethe",
})
req := httptest.NewRequest(http.MethodGet, "/", nil)
rr := httptest.NewRecorder()
h.ServeHTTP(rr, req)
resp := rr.Result()
if resp.StatusCode != http.StatusOK {
t.Fatalf("status = %d; want 200", resp.StatusCode)
}
body, _ := io.ReadAll(resp.Body)
bodyStr := string(body)
want := `window.__LETHE_CONFIG__={"issuer":"http://stub","client_id":"lethe"}`
if !strings.Contains(bodyStr, want) {
t.Errorf("body does not contain %q\nbody (first 500 chars):\n%s", want, truncate(bodyStr, 500))
}
// Exactly once.
count := strings.Count(bodyStr, "__LETHE_CONFIG__")
if count != 1 {
t.Errorf("__LETHE_CONFIG__ appears %d times; want 1", count)
}
}
// TestHandler_AssetsBypassInjection asserts that static asset paths do not
// receive the script injection. We test by checking the response body does
// not contain __LETHE_CONFIG__ — robust against asset filename changes.
func TestHandler_AssetsBypassInjection(t *testing.T) {
// Discover an asset file from the embedded FS via the handler's fallback
// behavior, or just verify that a known asset path bypasses injection.
// We check absence of __LETHE_CONFIG__ in any /assets/ response.
h := web.Handler(web.Config{
Issuer: "http://stub",
ClientID: "lethe",
})
// Find an actual asset file name to request.
sub, err := web.DistFS()
if err != nil {
t.Fatalf("DistFS: %v", err)
}
var assetFile string
_ = fs.WalkDir(sub, "assets", func(path string, d fs.DirEntry, err error) error {
if err != nil {
return err
}
if !d.IsDir() && assetFile == "" {
assetFile = path
}
return nil
})
if assetFile == "" {
t.Skip("no asset files found in embedded FS — skip")
}
req := httptest.NewRequest(http.MethodGet, "/"+assetFile, nil)
rr := httptest.NewRecorder()
h.ServeHTTP(rr, req)
resp := rr.Result()
body, _ := io.ReadAll(resp.Body)
if strings.Contains(string(body), "__LETHE_CONFIG__") {
t.Errorf("asset %q response contains __LETHE_CONFIG__ — should be bypass", assetFile)
}
}
// TestHandler_SPAFallbackInjects asserts that an unknown SPA route returns
// 200 HTML with the config injection (SPA fallback returns index.html).
func TestHandler_SPAFallbackInjects(t *testing.T) {
h := web.Handler(web.Config{
Issuer: "http://stub",
ClientID: "lethe",
})
req := httptest.NewRequest(http.MethodGet, "/some/spa/route", nil)
rr := httptest.NewRecorder()
h.ServeHTTP(rr, req)
resp := rr.Result()
if resp.StatusCode != http.StatusOK {
t.Fatalf("status = %d; want 200", resp.StatusCode)
}
body, _ := io.ReadAll(resp.Body)
bodyStr := string(body)
if !strings.Contains(bodyStr, "__LETHE_CONFIG__") {
t.Errorf("SPA fallback response does not contain __LETHE_CONFIG__\nbody:\n%s", truncate(bodyStr, 500))
}
}
func truncate(s string, n int) string {
if len(s) <= n {
return s
}
return s[:n] + "..."
}