//go:build test // +build test package user import ( "context" "net/http" "net/http/httptest" "strings" "testing" "crussell/testutils" "crussell/mw" "crussell/testutils/fixtures" "github.com/go-chi/chi/v5" ) // makePatchTestsRequest builds a request for /api/admin/users/{user_id}/patch-tests[/{test_id}]. func makePatchTestsRequest(handler http.HandlerFunc, method, path string, body interface{}, userID, role string, ctx context.Context) *httptest.ResponseRecorder { req := httptest.NewRequest(method, path, nil) req = req.WithContext(ctx) // Extract URL params from path: /api/admin/users/{user_id}/patch-tests[/{test_id}] prefix := "/api/admin/users/" suffix := strings.TrimPrefix(path, prefix) parts := strings.SplitN(suffix, "/", 3) rctx := chi.NewRouteContext() if len(parts) > 0 { rctx.URLParams.Add("user_id", parts[0]) } if len(parts) > 2 { rctx.URLParams.Add("test_id", parts[2]) } chiCtx := context.WithValue(req.Context(), chi.RouteCtxKey, rctx) chiCtx = context.WithValue(chiCtx, mw.UserIDKey, userID) chiCtx = context.WithValue(chiCtx, mw.UserRoleKey, role) req = req.WithContext(chiCtx) w := httptest.NewRecorder() handler(w, req) return w } // ============================================================================= // Tests // ============================================================================= func TestGetUserPatchTests_Empty(t *testing.T) { t.Parallel() ctx, tx := testutils.SetupTestTx(t) userID, err := fixtures.CreateTestUser(tx) if err != nil { t.Fatalf("failed to create test user: %v", err) } w := makePatchTestsRequest(GetUserPatchTestsHandler, "GET", "/api/admin/users/"+userID+"/patch-tests", nil, "admin001", "admin", ctx) if w.Code != http.StatusOK { t.Errorf("expected 200, got %d. body: %s", w.Code, w.Body.String()) } } func TestGetUserPatchTests_WithRecords(t *testing.T) { t.Parallel() ctx, tx := testutils.SetupTestTx(t) userID, err := fixtures.CreateTestUser(tx) if err != nil { t.Fatalf("failed to create test user: %v", err) } serviceID, err := fixtures.CreateTestService(tx) if err != nil { t.Fatalf("failed to create service: %v", err) } // Create patch tests and link to user ptID1, err := fixtures.CreateTestPatchTest(tx, []string{serviceID}) if err != nil { t.Fatalf("failed to create patch test: %v", err) } ptID2, err := fixtures.CreateTestPatchTest(tx, []string{serviceID}) if err != nil { t.Fatalf("failed to create patch test: %v", err) } // Link user to patch tests err = fixtures.CreateUserPatchTest(tx, userID, ptID1, "2024-06-01 10:00:00") if err != nil { t.Fatalf("failed to link user to patch test: %v", err) } err = fixtures.CreateUserPatchTest(tx, userID, ptID2, "2024-06-15 14:00:00") if err != nil { t.Fatalf("failed to link user to patch test: %v", err) } w := makePatchTestsRequest(GetUserPatchTestsHandler, "GET", "/api/admin/users/"+userID+"/patch-tests", nil, "admin001", "admin", ctx) if w.Code != http.StatusOK { t.Fatalf("expected 200, got %d. body: %s", w.Code, w.Body.String()) } } func TestGetUserPatchTests_InvalidUserID(t *testing.T) { t.Parallel() w := makePatchTestsRequest(GetUserPatchTestsHandler, "GET", "/api/admin/users/invalid/patch-tests", nil, "admin001", "admin", context.Background()) if w.Code != http.StatusNotFound { t.Errorf("expected 404 for invalid user ID, got %d", w.Code) } } func TestDeletePatchTest_HappyPath(t *testing.T) { t.Parallel() ctx, tx := testutils.SetupTestTx(t) userID, err := fixtures.CreateTestUser(tx) if err != nil { t.Fatalf("failed to create test user: %v", err) } serviceID, err := fixtures.CreateTestService(tx) if err != nil { t.Fatalf("failed to create service: %v", err) } ptID, err := fixtures.CreateTestPatchTest(tx, []string{serviceID}) if err != nil { t.Fatalf("failed to create patch test: %v", err) } err = fixtures.CreateUserPatchTest(tx, userID, ptID, "2024-06-10 10:00:00") if err != nil { t.Fatalf("failed to link user to patch test: %v", err) } // Get the user_patch_tests.id (what the handler expects as test_id) var uptID string tx.QueryRow(ctx, "SELECT id FROM user_patch_tests WHERE user_id = $1 AND patch_test_id = $2", userID, ptID).Scan(&uptID) w := makePatchTestsRequest(DeletePatchTestHandler, "DELETE", "/api/admin/users/"+userID+"/patch-tests/"+uptID, nil, "admin001", "admin", ctx) if w.Code != http.StatusNoContent { t.Errorf("expected 204, got %d. body: %s", w.Code, w.Body.String()) } } func TestDeletePatchTest_NotFound(t *testing.T) { t.Parallel() ctx, tx := testutils.SetupTestTx(t) userID, err := fixtures.CreateTestUser(tx) if err != nil { t.Fatalf("failed to create test user: %v", err) } w := makePatchTestsRequest(DeletePatchTestHandler, "DELETE", "/api/admin/users/"+userID+"/patch-tests/nonexistent", nil, "admin001", "admin", ctx) if w.Code != http.StatusNotFound { t.Errorf("expected 404 for non-existent test, got %d", w.Code) } } func TestDeletePatchTest_InvalidUserID(t *testing.T) { t.Parallel() w := makePatchTestsRequest(DeletePatchTestHandler, "DELETE", "/api/admin/users/invalid/patch-tests/1", nil, "admin001", "admin", context.Background()) if w.Code != http.StatusNotFound { t.Errorf("expected 404 for invalid user ID, got %d", w.Code) } } func TestDeletePatchTest_InvalidTestID(t *testing.T) { t.Parallel() w := makePatchTestsRequest(DeletePatchTestHandler, "DELETE", "/api/admin/users/validuserid/patch-tests/invalid", nil, "admin001", "admin", context.Background()) if w.Code != http.StatusNotFound { t.Errorf("expected 404 for invalid test ID, got %d", w.Code) } }