180 lines
4.1 KiB
Go
180 lines
4.1 KiB
Go
package test
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/json"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"testing"
|
|
|
|
"gitea.avt.data-center.id/othman.suseno/atlas/internal/httpapp"
|
|
)
|
|
|
|
// TestServer provides an integration test server
|
|
type TestServer struct {
|
|
App *httpapp.App
|
|
Server *httptest.Server
|
|
Client *http.Client
|
|
AuthToken string
|
|
}
|
|
|
|
// NewTestServer creates a new test server
|
|
func NewTestServer(t *testing.T) *TestServer {
|
|
// Use absolute paths or create templates directory for tests
|
|
templatesDir := "web/templates"
|
|
staticDir := "web/static"
|
|
|
|
app, err := httpapp.New(httpapp.Config{
|
|
Addr: ":0", // Use random port
|
|
TemplatesDir: templatesDir,
|
|
StaticDir: staticDir,
|
|
DatabaseConn: "", // Empty = in-memory mode (no database)
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("create test app: %v", err)
|
|
}
|
|
|
|
server := httptest.NewServer(app.Router())
|
|
|
|
return &TestServer{
|
|
App: app,
|
|
Server: server,
|
|
Client: &http.Client{},
|
|
}
|
|
}
|
|
|
|
// Close shuts down the test server
|
|
func (ts *TestServer) Close() {
|
|
ts.Server.Close()
|
|
ts.App.StopScheduler()
|
|
}
|
|
|
|
// Login performs a login and stores the auth token
|
|
func (ts *TestServer) Login(t *testing.T, username, password string) {
|
|
reqBody := map[string]string{
|
|
"username": username,
|
|
"password": password,
|
|
}
|
|
|
|
body, _ := json.Marshal(reqBody)
|
|
req, err := http.NewRequest("POST", ts.Server.URL+"/api/v1/auth/login",
|
|
bytes.NewReader(body))
|
|
if err != nil {
|
|
t.Fatalf("create login request: %v", err)
|
|
}
|
|
req.Header.Set("Content-Type", "application/json")
|
|
|
|
resp, err := ts.Client.Do(req)
|
|
if err != nil {
|
|
t.Fatalf("login request: %v", err)
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
if resp.StatusCode != http.StatusOK {
|
|
t.Fatalf("login failed with status %d", resp.StatusCode)
|
|
}
|
|
|
|
var result map[string]interface{}
|
|
if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
|
|
t.Fatalf("decode login response: %v", err)
|
|
}
|
|
|
|
if token, ok := result["token"].(string); ok {
|
|
ts.AuthToken = token
|
|
} else {
|
|
t.Fatal("no token in login response")
|
|
}
|
|
}
|
|
|
|
// Get performs an authenticated GET request
|
|
func (ts *TestServer) Get(t *testing.T, path string) *http.Response {
|
|
req, err := http.NewRequest("GET", ts.Server.URL+path, nil)
|
|
if err != nil {
|
|
t.Fatalf("create GET request: %v", err)
|
|
}
|
|
|
|
if ts.AuthToken != "" {
|
|
req.Header.Set("Authorization", "Bearer "+ts.AuthToken)
|
|
}
|
|
|
|
resp, err := ts.Client.Do(req)
|
|
if err != nil {
|
|
t.Fatalf("GET request: %v", err)
|
|
}
|
|
|
|
return resp
|
|
}
|
|
|
|
// Post performs an authenticated POST request
|
|
func (ts *TestServer) Post(t *testing.T, path string, body interface{}) *http.Response {
|
|
bodyBytes, err := json.Marshal(body)
|
|
if err != nil {
|
|
t.Fatalf("marshal request body: %v", err)
|
|
}
|
|
|
|
req, err := http.NewRequest("POST", ts.Server.URL+path, bytes.NewReader(bodyBytes))
|
|
if err != nil {
|
|
t.Fatalf("create POST request: %v", err)
|
|
}
|
|
|
|
req.Header.Set("Content-Type", "application/json")
|
|
if ts.AuthToken != "" {
|
|
req.Header.Set("Authorization", "Bearer "+ts.AuthToken)
|
|
}
|
|
|
|
resp, err := ts.Client.Do(req)
|
|
if err != nil {
|
|
t.Fatalf("POST request: %v", err)
|
|
}
|
|
|
|
return resp
|
|
}
|
|
|
|
// TestHealthCheck tests the health check endpoint
|
|
func TestHealthCheck(t *testing.T) {
|
|
ts := NewTestServer(t)
|
|
defer ts.Close()
|
|
|
|
resp := ts.Get(t, "/healthz")
|
|
if resp.StatusCode != http.StatusOK {
|
|
t.Errorf("expected status 200, got %d", resp.StatusCode)
|
|
}
|
|
}
|
|
|
|
// TestLogin tests the login endpoint
|
|
func TestLogin(t *testing.T) {
|
|
ts := NewTestServer(t)
|
|
defer ts.Close()
|
|
|
|
// Test with default admin credentials
|
|
ts.Login(t, "admin", "admin")
|
|
|
|
if ts.AuthToken == "" {
|
|
t.Error("expected auth token after login")
|
|
}
|
|
}
|
|
|
|
// TestUnauthorizedAccess tests that protected endpoints require authentication
|
|
func TestUnauthorizedAccess(t *testing.T) {
|
|
ts := NewTestServer(t)
|
|
defer ts.Close()
|
|
|
|
resp := ts.Get(t, "/api/v1/pools")
|
|
if resp.StatusCode != http.StatusUnauthorized {
|
|
t.Errorf("expected status 401, got %d", resp.StatusCode)
|
|
}
|
|
}
|
|
|
|
// TestAuthenticatedAccess tests that authenticated requests work
|
|
func TestAuthenticatedAccess(t *testing.T) {
|
|
ts := NewTestServer(t)
|
|
defer ts.Close()
|
|
|
|
ts.Login(t, "admin", "admin")
|
|
|
|
resp := ts.Get(t, "/api/v1/pools")
|
|
if resp.StatusCode != http.StatusOK {
|
|
t.Errorf("expected status 200, got %d", resp.StatusCode)
|
|
}
|
|
}
|