ZDDC/zddc/internal/handler/appsvirtual_test.go
ZDDC 237c353845 feat(server): /_apps/ — virtual public directory of standalone tool HTMLs
A no-auth virtual folder so anyone can grab a tool and run it against their own
local filesystem: GET /_apps/ is an index (Download / Open links); GET
/_apps/<tool>.html serves that tool's HTML (?download forces a save). Prefers
the site .zddc.zip bundle member (freshest), falls back to the binary's
embedded copy; tables/form come from the embedded tables bundle. Carries no
data, so it's served before the ACL/cascade and the reserved-prefix guard;
`_`-prefixed + virtual means no collision with content.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-09 10:28:01 -05:00

42 lines
1.3 KiB
Go

package handler
import (
"net/http"
"net/http/httptest"
"strings"
"testing"
)
func TestServeApps(t *testing.T) {
// Index lists the tools.
rec := httptest.NewRecorder()
ServeApps(nil, rec, httptest.NewRequest(http.MethodGet, AppsVirtualPrefix, nil))
if rec.Code != http.StatusOK {
t.Fatalf("index: want 200, got %d", rec.Code)
}
if !strings.Contains(rec.Body.String(), "Classifier") {
t.Errorf("index should list Classifier")
}
// A known tool resolves to HTML (embedded bytes may be empty in a fresh
// checkout, so accept 200 with a body OR 404 only when the slot is empty).
rec = httptest.NewRecorder()
ServeApps(nil, rec, httptest.NewRequest(http.MethodGet, AppsVirtualPrefix+"classifier.html", nil))
if rec.Code != http.StatusOK && rec.Code != http.StatusNotFound {
t.Errorf("classifier.html: unexpected %d", rec.Code)
}
// Unknown name → 404.
rec = httptest.NewRecorder()
ServeApps(nil, rec, httptest.NewRequest(http.MethodGet, AppsVirtualPrefix+"nope.html", nil))
if rec.Code != http.StatusNotFound {
t.Errorf("unknown: want 404, got %d", rec.Code)
}
// Path traversal / subpath → 404.
rec = httptest.NewRecorder()
ServeApps(nil, rec, httptest.NewRequest(http.MethodGet, AppsVirtualPrefix+"a/b.html", nil))
if rec.Code != http.StatusNotFound {
t.Errorf("subpath: want 404, got %d", rec.Code)
}
}