Files
tapir/internal/web/welcome_test.go
T
mathiasandClaude Sonnet 4.6 38f222c931
CI / Lint / Test / Vet (push) Successful in 11s
CI / Build & Import (push) Successful in 12s
chore: rename Go module path gitea.d-ma.be → git.d-ma.be
Infra ADR-0004 renamed the Gitea host. Bulk replace across go.mod and
all .go import paths. Build and tests pass unchanged.

Closes #20

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Dt6aHEDWRjkK14Voi6HnGh
2026-07-02 14:37:33 +02:00

98 lines
3.5 KiB
Go

package web_test
import (
"net/http"
"net/http/httptest"
"testing"
"github.com/stretchr/testify/require"
"git.d-ma.be/mathias/tapir/internal/web"
)
// fakeAuth is a configurable web.Auth for the landing-page tests: it reports a
// fixed (user, ok) from CurrentUser and, when logged out, replicates DexAuth's
// redirect split in Middleware — bare root → /welcome, deeper paths → login.
// StubAuth can't express the logged-out case (it allows everything), so the
// welcome routing needs this.
type fakeAuth struct {
user web.User
ok bool
}
func (f fakeAuth) CurrentUser(*http.Request) (web.User, bool) { return f.user, f.ok }
func (f fakeAuth) Routes() http.Handler { return http.NewServeMux() }
func (f fakeAuth) Middleware(h http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if f.ok {
h.ServeHTTP(w, r)
return
}
if r.URL.Path == "/" {
http.Redirect(w, r, "/welcome", http.StatusFound)
return
}
http.Redirect(w, r, "/auth/login", http.StatusFound)
})
}
// appWithAuth builds an App with a given Auth but no store wiring — enough for
// the /welcome page (which never touches the store) and the unauthenticated
// redirect paths (which never reach a handler).
func appWithAuth(auth web.Auth) *web.App {
return &web.App{Auth: auth}
}
func TestWelcomeLoggedOut(t *testing.T) {
app := appWithAuth(fakeAuth{ok: false})
rec := do(t, app, httptest.NewRequest(http.MethodGet, "/welcome", nil))
require.Equal(t, http.StatusOK, rec.Code)
html := body(t, rec)
require.Contains(t, html, "Get Started", "logged-out CTA present")
require.Contains(t, html, `href="/auth/login"`, "CTA links into the Dex flow")
require.NotContains(t, html, "Go to my Tapir", "no logged-in controls")
// Invites are owned by Authentik now (ADR-019); Tapir no longer handles
// invite links. The old "invite link will set up your account automatically"
// promise is stale and misleading — it must be gone.
require.NotContains(t, html, "invite link", "stale Authentik-superseded invite copy must be removed")
require.Contains(t, html, "invite-only", "honest invite-only framing present")
}
func TestWelcomeLoggedIn(t *testing.T) {
app := appWithAuth(fakeAuth{user: web.User{Subject: "s", Email: "me@d-ma.be"}, ok: true})
rec := do(t, app, httptest.NewRequest(http.MethodGet, "/welcome", nil))
require.Equal(t, http.StatusOK, rec.Code)
html := body(t, rec)
require.Contains(t, html, "Go to my Tapir", "logged-in CTA present")
require.Contains(t, html, `href="/"`, "links back into the app")
require.Contains(t, html, "me@d-ma.be", "greets by email")
require.NotContains(t, html, "Get Started", "no logged-out CTA")
}
func TestUnauthenticatedRootRedirectsToWelcome(t *testing.T) {
app := appWithAuth(fakeAuth{ok: false})
rec := do(t, app, httptest.NewRequest(http.MethodGet, "/", nil))
require.Equal(t, http.StatusFound, rec.Code)
require.Equal(t, "/welcome", rec.Header().Get("Location"))
}
func TestUnauthenticatedDeepLinkRedirectsToLogin(t *testing.T) {
app := appWithAuth(fakeAuth{ok: false})
rec := do(t, app, httptest.NewRequest(http.MethodGet, "/v/some-id", nil))
require.Equal(t, http.StatusFound, rec.Code)
require.Equal(t, "/auth/login", rec.Header().Get("Location"))
}
func TestAuthenticatedRootRendersList(t *testing.T) {
app := newApp(t)
resetDB(t, rawPool(t))
rec := do(t, app, httptest.NewRequest(http.MethodGet, "/", nil))
require.Equal(t, http.StatusOK, rec.Code)
require.Contains(t, body(t, rec), "<html", "authenticated root still renders the list page")
}