refactor(backend): migrate db.DB to db.Conn PoolProxy across all handlers
Replace direct *pgxpool.Pool usage with PoolProxy wrapper across the entire backend: - db.DB renamed to db.Conn (*pgxpool.Pool -> *PoolProxy) - JWT functions now accept context.Context instead of using context.Background() - Handler DB calls route through PoolProxy for per-test transaction support - Fixture/helper/testdb functions accept Querier interface for decoupling - Query ordering fixed in bookings handlers: COUNT after data query to avoid pgx conn busy - Time truncation fixed: time.Date instead of Truncate(24*time.Hour) for week start calc - testmain_test.go files updated with SeedBaseline and NewPoolProxy Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
@@ -11,27 +11,20 @@ import (
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"crussell/db"
|
||||
"crussell/mw"
|
||||
"crussell/testutils/jwt"
|
||||
"crussell/testutils/testdb"
|
||||
|
||||
"github.com/jackc/pgx/v5/pgxpool"
|
||||
)
|
||||
|
||||
// SetupTestDB resets test data by truncating tables
|
||||
// Assumes db.DB is already set by TestMain
|
||||
func SetupTestDB(t *testing.T) func() {
|
||||
t.Helper()
|
||||
// contextKey matches mw.UserIDKey to avoid import cycle with auth package.
|
||||
type contextKey string
|
||||
|
||||
testdb.TruncateTables(t, db.DB)
|
||||
const userIDKey contextKey = "user_id"
|
||||
|
||||
return func() {}
|
||||
}
|
||||
|
||||
// MakeRequest makes an HTTP request to a handler with optional JWT token
|
||||
// token can be user token or admin token. Pass empty string for no auth.
|
||||
func MakeRequest(handler http.Handler, method, path string, body interface{}, token string) *httptest.ResponseRecorder {
|
||||
// MakeRequest makes an HTTP request to a handler with optional JWT token.
|
||||
// ctx should carry a per-test transaction (from SetupTestTx) for PoolProxy routing.
|
||||
func MakeRequest(handler http.Handler, method, path string, body interface{}, token string, ctx context.Context) *httptest.ResponseRecorder {
|
||||
var req *http.Request
|
||||
if body != nil {
|
||||
bodyBytes, _ := json.Marshal(body)
|
||||
@@ -41,6 +34,8 @@ func MakeRequest(handler http.Handler, method, path string, body interface{}, to
|
||||
req = httptest.NewRequest(method, path, nil)
|
||||
}
|
||||
|
||||
req = req.WithContext(ctx)
|
||||
|
||||
if token != "" {
|
||||
req.Header.Set("Authorization", "Bearer "+token)
|
||||
}
|
||||
@@ -68,25 +63,26 @@ func MakeRequestWithContext(handler http.Handler, method, path string, body inte
|
||||
return w
|
||||
}
|
||||
|
||||
// MakeUserRequest makes a request as an authenticated user
|
||||
// Generates a valid user token and includes it in the Authorization header
|
||||
func MakeUserRequest(handler http.Handler, method, path string, body interface{}, userID string) *httptest.ResponseRecorder {
|
||||
// MakeUserRequest makes a request as an authenticated user.
|
||||
// ctx should carry a per-test transaction (from SetupTestTx) for PoolProxy routing.
|
||||
func MakeUserRequest(handler http.Handler, method, path string, body interface{}, userID string, ctx context.Context) *httptest.ResponseRecorder {
|
||||
token := jwt.GenerateUserToken(userID)
|
||||
return MakeRequest(handler, method, path, body, token)
|
||||
return MakeRequest(handler, method, path, body, token, ctx)
|
||||
}
|
||||
|
||||
// MakeAdminRequest makes a request as an authenticated admin
|
||||
// Generates a valid admin token and includes it in the Authorization header
|
||||
func MakeAdminRequest(handler http.Handler, method, path string, body interface{}, adminID string) *httptest.ResponseRecorder {
|
||||
// MakeAdminRequest makes a request as an authenticated admin.
|
||||
// ctx should carry a per-test transaction (from SetupTestTx) for PoolProxy routing.
|
||||
func MakeAdminRequest(handler http.Handler, method, path string, body interface{}, adminID string, ctx context.Context) *httptest.ResponseRecorder {
|
||||
token := jwt.GenerateTestToken(adminID, "admin")
|
||||
return MakeRequest(handler, method, path, body, token)
|
||||
return MakeRequest(handler, method, path, body, token, ctx)
|
||||
}
|
||||
|
||||
// MakeContextRequest makes a request with user context set
|
||||
// Useful for testing handlers that check context before validating token
|
||||
func MakeContextRequest(handler http.Handler, method, path string, body interface{}, userID string) *httptest.ResponseRecorder {
|
||||
ctx := context.WithValue(context.Background(), mw.UserIDKey, userID)
|
||||
return MakeRequestWithContext(handler, method, path, body, ctx)
|
||||
// MakeContextRequest makes a request with user context set.
|
||||
// ctx should carry a per-test transaction (from SetupTestTx) for PoolProxy routing.
|
||||
// The user ID is layered on top of the transaction context.
|
||||
func MakeContextRequest(handler http.Handler, method, path string, body interface{}, userID string, ctx context.Context) *httptest.ResponseRecorder {
|
||||
reqCtx := context.WithValue(ctx, userIDKey, userID)
|
||||
return MakeRequestWithContext(handler, method, path, body, reqCtx)
|
||||
}
|
||||
|
||||
// ParseResponseBody unmarshals the response body into dest
|
||||
@@ -156,9 +152,10 @@ func GetBodyAsJSON(w *httptest.ResponseRecorder) (map[string]interface{}, error)
|
||||
return result, err
|
||||
}
|
||||
|
||||
// MakeRequestNoAuth makes an HTTP request without authentication (for testing unauthenticated endpoints)
|
||||
func MakeRequestNoAuth(handler http.Handler, method, path string, body interface{}) *httptest.ResponseRecorder {
|
||||
return MakeRequest(handler, method, path, body, "")
|
||||
// MakeRequestNoAuth makes an HTTP request without authentication.
|
||||
// ctx should carry a per-test transaction (from SetupTestTx) for PoolProxy routing.
|
||||
func MakeRequestNoAuth(handler http.Handler, method, path string, body interface{}, ctx context.Context) *httptest.ResponseRecorder {
|
||||
return MakeRequest(handler, method, path, body, "", ctx)
|
||||
}
|
||||
|
||||
// AssertErrorStatusCode checks status code and validates error is in response body
|
||||
|
||||
Reference in New Issue
Block a user