chore: add routes test
This commit is contained in:
parent
7c375e1002
commit
4181264a68
1 changed files with 233 additions and 0 deletions
233
internal/routes/routes_test.go
Normal file
233
internal/routes/routes_test.go
Normal file
|
|
@ -0,0 +1,233 @@
|
|||
package routes
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"git.juancwu.dev/juancwu/budgit/internal/app"
|
||||
"git.juancwu.dev/juancwu/budgit/internal/model"
|
||||
"git.juancwu.dev/juancwu/budgit/internal/repository"
|
||||
"git.juancwu.dev/juancwu/budgit/internal/service"
|
||||
"git.juancwu.dev/juancwu/budgit/internal/testutil"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func newTestApp(dbi testutil.DBInfo) *app.App {
|
||||
cfg := testutil.TestConfig()
|
||||
cfg.DBDriver = dbi.Driver
|
||||
|
||||
userRepo := repository.NewUserRepository(dbi.DB)
|
||||
tokenRepo := repository.NewTokenRepository(dbi.DB)
|
||||
spaceRepo := repository.NewSpaceRepository(dbi.DB)
|
||||
inviteRepo := repository.NewInvitationRepository(dbi.DB)
|
||||
|
||||
spaceSvc := service.NewSpaceService(spaceRepo)
|
||||
emailSvc := service.NewEmailService(nil, "test@example.com", "http://localhost:9999", "Budgit Test", false)
|
||||
authSvc := service.NewAuthService(emailSvc, userRepo, tokenRepo, spaceSvc, cfg.JWTSecret, cfg.JWTExpiry, cfg.TokenMagicLinkExpiry, false)
|
||||
userSvc := service.NewUserService(userRepo)
|
||||
inviteSvc := service.NewInviteService(inviteRepo, spaceRepo, userRepo, emailSvc)
|
||||
|
||||
return &app.App{
|
||||
Cfg: cfg,
|
||||
DB: dbi.DB,
|
||||
UserService: userSvc,
|
||||
AuthService: authSvc,
|
||||
EmailService: emailSvc,
|
||||
SpaceService: spaceSvc,
|
||||
InviteService: inviteSvc,
|
||||
}
|
||||
}
|
||||
|
||||
// authCookie generates a valid JWT cookie for the given user.
|
||||
func authCookie(a *app.App, user *model.User) *http.Cookie {
|
||||
token, err := a.AuthService.GenerateJWT(user)
|
||||
if err != nil {
|
||||
panic("failed to generate test JWT: " + err.Error())
|
||||
}
|
||||
return &http.Cookie{
|
||||
Name: "auth_token",
|
||||
Value: token,
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetupRoutes_PublicRoutes(t *testing.T) {
|
||||
testutil.ForEachDB(t, func(t *testing.T, dbi testutil.DBInfo) {
|
||||
a := newTestApp(dbi)
|
||||
handler := SetupRoutes(a)
|
||||
|
||||
routes := []string{"/forbidden", "/privacy", "/terms"}
|
||||
|
||||
for _, path := range routes {
|
||||
t.Run(path, func(t *testing.T) {
|
||||
req := httptest.NewRequest(http.MethodGet, path, nil)
|
||||
w := httptest.NewRecorder()
|
||||
handler.ServeHTTP(w, req)
|
||||
assert.Equal(t, http.StatusOK, w.Code)
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestSetupRoutes_HomeRedirects(t *testing.T) {
|
||||
testutil.ForEachDB(t, func(t *testing.T, dbi testutil.DBInfo) {
|
||||
a := newTestApp(dbi)
|
||||
handler := SetupRoutes(a)
|
||||
|
||||
// Unauthenticated → redirect to /auth
|
||||
req := httptest.NewRequest(http.MethodGet, "/", nil)
|
||||
w := httptest.NewRecorder()
|
||||
handler.ServeHTTP(w, req)
|
||||
assert.Equal(t, http.StatusSeeOther, w.Code)
|
||||
assert.Equal(t, "/auth", w.Header().Get("Location"))
|
||||
|
||||
// Authenticated → redirect to /app/spaces
|
||||
name := "Test User"
|
||||
user := testutil.CreateTestUserWithName(t, dbi.DB, "home@example.com", &name)
|
||||
req = httptest.NewRequest(http.MethodGet, "/", nil)
|
||||
req.AddCookie(authCookie(a, user))
|
||||
w = httptest.NewRecorder()
|
||||
handler.ServeHTTP(w, req)
|
||||
assert.Equal(t, http.StatusSeeOther, w.Code)
|
||||
assert.Equal(t, "/app/spaces", w.Header().Get("Location"))
|
||||
})
|
||||
}
|
||||
|
||||
func TestSetupRoutes_GuestRoutes(t *testing.T) {
|
||||
testutil.ForEachDB(t, func(t *testing.T, dbi testutil.DBInfo) {
|
||||
a := newTestApp(dbi)
|
||||
handler := SetupRoutes(a)
|
||||
|
||||
routes := []string{"/auth", "/auth/password"}
|
||||
|
||||
for _, path := range routes {
|
||||
t.Run(path, func(t *testing.T) {
|
||||
req := httptest.NewRequest(http.MethodGet, path, nil)
|
||||
w := httptest.NewRecorder()
|
||||
handler.ServeHTTP(w, req)
|
||||
assert.Equal(t, http.StatusOK, w.Code)
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestSetupRoutes_GuestRoutes_RedirectAuthenticated(t *testing.T) {
|
||||
testutil.ForEachDB(t, func(t *testing.T, dbi testutil.DBInfo) {
|
||||
a := newTestApp(dbi)
|
||||
handler := SetupRoutes(a)
|
||||
|
||||
name := "Test User"
|
||||
user := testutil.CreateTestUserWithName(t, dbi.DB, "auth@example.com", &name)
|
||||
|
||||
req := httptest.NewRequest(http.MethodGet, "/auth", nil)
|
||||
req.AddCookie(authCookie(a, user))
|
||||
w := httptest.NewRecorder()
|
||||
handler.ServeHTTP(w, req)
|
||||
|
||||
assert.Equal(t, http.StatusSeeOther, w.Code)
|
||||
assert.Equal(t, "/app/dashboard", w.Header().Get("Location"))
|
||||
})
|
||||
}
|
||||
|
||||
func TestSetupRoutes_AuthRequired_RedirectUnauthenticated(t *testing.T) {
|
||||
testutil.ForEachDB(t, func(t *testing.T, dbi testutil.DBInfo) {
|
||||
a := newTestApp(dbi)
|
||||
handler := SetupRoutes(a)
|
||||
|
||||
routes := []string{"/app/spaces", "/app/settings"}
|
||||
|
||||
for _, path := range routes {
|
||||
t.Run(path, func(t *testing.T) {
|
||||
req := httptest.NewRequest(http.MethodGet, path, nil)
|
||||
w := httptest.NewRecorder()
|
||||
handler.ServeHTTP(w, req)
|
||||
assert.Equal(t, http.StatusSeeOther, w.Code)
|
||||
assert.Equal(t, "/auth", w.Header().Get("Location"))
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestSetupRoutes_AuthRequired_Authenticated(t *testing.T) {
|
||||
testutil.ForEachDB(t, func(t *testing.T, dbi testutil.DBInfo) {
|
||||
a := newTestApp(dbi)
|
||||
handler := SetupRoutes(a)
|
||||
|
||||
name := "Test User"
|
||||
user := testutil.CreateTestUserWithName(t, dbi.DB, "appuser@example.com", &name)
|
||||
|
||||
routes := []string{"/app/spaces", "/app/settings"}
|
||||
|
||||
for _, path := range routes {
|
||||
t.Run(path, func(t *testing.T) {
|
||||
req := httptest.NewRequest(http.MethodGet, path, nil)
|
||||
req.AddCookie(authCookie(a, user))
|
||||
w := httptest.NewRecorder()
|
||||
handler.ServeHTTP(w, req)
|
||||
assert.Equal(t, http.StatusOK, w.Code)
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestSetupRoutes_OnboardingRedirect(t *testing.T) {
|
||||
testutil.ForEachDB(t, func(t *testing.T, dbi testutil.DBInfo) {
|
||||
a := newTestApp(dbi)
|
||||
handler := SetupRoutes(a)
|
||||
|
||||
// User without name → needs onboarding
|
||||
user := testutil.CreateTestUser(t, dbi.DB, "noname@example.com", nil)
|
||||
|
||||
req := httptest.NewRequest(http.MethodGet, "/app/spaces", nil)
|
||||
req.AddCookie(authCookie(a, user))
|
||||
w := httptest.NewRecorder()
|
||||
handler.ServeHTTP(w, req)
|
||||
|
||||
assert.Equal(t, http.StatusSeeOther, w.Code)
|
||||
assert.Equal(t, "/auth/onboarding", w.Header().Get("Location"))
|
||||
})
|
||||
}
|
||||
|
||||
func TestSetupRoutes_PermanentRedirect(t *testing.T) {
|
||||
testutil.ForEachDB(t, func(t *testing.T, dbi testutil.DBInfo) {
|
||||
a := newTestApp(dbi)
|
||||
handler := SetupRoutes(a)
|
||||
|
||||
req := httptest.NewRequest(http.MethodGet, "/app/dashboard", nil)
|
||||
w := httptest.NewRecorder()
|
||||
handler.ServeHTTP(w, req)
|
||||
|
||||
assert.Equal(t, http.StatusMovedPermanently, w.Code)
|
||||
assert.Equal(t, "/app/spaces", w.Header().Get("Location"))
|
||||
})
|
||||
}
|
||||
|
||||
func TestSetupRoutes_NotFound(t *testing.T) {
|
||||
testutil.ForEachDB(t, func(t *testing.T, dbi testutil.DBInfo) {
|
||||
a := newTestApp(dbi)
|
||||
handler := SetupRoutes(a)
|
||||
|
||||
req := httptest.NewRequest(http.MethodGet, "/nonexistent/page", nil)
|
||||
w := httptest.NewRecorder()
|
||||
handler.ServeHTTP(w, req)
|
||||
|
||||
// The catch-all route renders the NotFound page (handler returns 200).
|
||||
// This test verifies the catch-all route is registered and handles unknown paths.
|
||||
assert.Equal(t, http.StatusOK, w.Code)
|
||||
})
|
||||
}
|
||||
|
||||
func TestSetupRoutes_StaticAssets(t *testing.T) {
|
||||
testutil.ForEachDB(t, func(t *testing.T, dbi testutil.DBInfo) {
|
||||
a := newTestApp(dbi)
|
||||
handler := SetupRoutes(a)
|
||||
|
||||
req := httptest.NewRequest(http.MethodGet, "/assets/css/output.css", nil)
|
||||
w := httptest.NewRecorder()
|
||||
handler.ServeHTTP(w, req)
|
||||
|
||||
// Static asset should be served (200) or at minimum not 404 via the catch-all
|
||||
assert.Equal(t, http.StatusOK, w.Code)
|
||||
assert.Contains(t, w.Header().Get("Cache-Control"), "public")
|
||||
})
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue