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 = "test.db" // 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() { // Clean up previous run os.Remove(TestDBFile) // Configure for testing cfg.Config.DB = config.Database{ Type: "sqlite", DSN: TestDBFile, } cfg.Config.Redis = config.Redis{ Addr: "memory", } // Initialize DB connection // Force re-initialization if necessary, but cfg.Config.DB.Client calls might need a reset? // Assuming vigo/contrib/config handles this or we need to manually trigger it. // Looking at cfg.go: var DB = Config.DB.Client // Since DB is a variable, it might have been initialized with default values. // We might need to rely on the fact that Config.DB.Client() creates a new connection based on current Config.DB values. // But wait, cfg.DB is a variable initialized at package level. // If the app uses cfg.DB directly, it might be stale. // However, looking at main.go, it uses `models.Migrate()`. // models/init.go probably uses cfg.DB. // Important: Initialize the application components models.Migrate() event.Start() // Set router // vbase.Router is already initialized in init.go } func teardown() { os.Remove(TestDBFile) } // 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"` }