package tests import ( "bytes" "encoding/json" "io" "net/http" "net/http/httptest" "os" "testing" "github.com/veypi/vbase" "github.com/veypi/vbase/cfg" "github.com/veypi/vbase/models" "github.com/veypi/vigo/contrib/config" "github.com/veypi/vigo/contrib/event" ) const TestDBFile = "file::memory:?cache=shared" // Global variables to hold test data var ( AdminToken string User1Token string User2Token string AdminID string User1ID string User2ID string ) func TestMain(m *testing.M) { // Setup setup() // Run tests code := m.Run() // Teardown teardown() os.Exit(code) } func setup() { // Configure for testing // Use in-memory SQLite database cfg.Config.DB = config.Database{ Type: "sqlite", DSN: TestDBFile, } // Use mock/memory Redis cfg.Config.Redis = config.Redis{ Addr: "memory", } // Initialize DB connection and run migrations if err := models.Migrate(); err != nil { panic("failed to migrate database: " + err.Error()) } // Initialize other components event.Start() } func teardown() { // No cleanup needed for in-memory database } // Helpers func doRequest(t *testing.T, method, path string, body interface{}, token string) *httptest.ResponseRecorder { var bodyReader io.Reader if body != nil { jsonBody, err := json.Marshal(body) if err != nil { t.Fatalf("Failed to marshal body: %v", err) } bodyReader = bytes.NewReader(jsonBody) } req, err := http.NewRequest(method, path, bodyReader) if err != nil { t.Fatalf("Failed to create request: %v", err) } if token != "" { req.Header.Set("Authorization", "Bearer "+token) } req.Header.Set("Content-Type", "application/json") w := httptest.NewRecorder() // Create a vigo context to wrap the request // However, since we are testing the router, we should just serve HTTP vbase.Router.ServeHTTP(w, req) return w } func assertStatus(t *testing.T, w *httptest.ResponseRecorder, expectedCode int) { if w.Code != expectedCode { // Vigo might return 200 OK but with a JSON error code in body // Check body for error details t.Errorf("Expected HTTP status %d, got %d. Body: %s", expectedCode, w.Code, w.Body.String()) } } // assertVigoCode checks the 'code' field in JSON response func assertVigoCode(t *testing.T, w *httptest.ResponseRecorder, expectedCode int) { var resp struct { Code int `json:"code"` } if err := json.Unmarshal(w.Body.Bytes(), &resp); err != nil { t.Fatalf("Failed to unmarshal response: %v. Body: %s", err, w.Body.String()) } if resp.Code != expectedCode { t.Errorf("Expected Vigo code %d, got %d. Body: %s", expectedCode, resp.Code, w.Body.String()) } } // decodeResponse decodes the JSON response into v func decodeResponse(t *testing.T, w *httptest.ResponseRecorder, v interface{}) { if err := json.Unmarshal(w.Body.Bytes(), v); err != nil { t.Fatalf("Failed to unmarshal response: %v. Body: %s", err, w.Body.String()) } } // Common structs for responses type BaseResp struct { Code int `json:"code"` Msg string `json:"msg"` } type LoginResp struct { AccessToken string `json:"access_token"` RefreshToken string `json:"refresh_token"` TokenType string `json:"token_type"` ExpiresIn int `json:"expires_in"` User struct { ID string `json:"id"` Username string `json:"username"` Email string `json:"email"` } `json:"user"` } type UserResp struct { ID string `json:"id"` Username string `json:"username"` Nickname string `json:"nickname"` Email string `json:"email"` RoleCode string `json:"role_code"` } type OrgResp struct { ID string `json:"id"` Name string `json:"name"` Code string `json:"code"` }