add tui features
Some checks failed
CI / test-build (push) Failing after 2m26s

This commit is contained in:
2025-12-15 01:08:17 +07:00
parent 96a6b5a4cf
commit 507961716e
12 changed files with 2793 additions and 8 deletions

157
internal/testing/helpers.go Normal file
View File

@@ -0,0 +1,157 @@
package testing
import (
"bytes"
"encoding/json"
"net/http"
"net/http/httptest"
"testing"
)
// TestRequest represents a test HTTP request
type TestRequest struct {
Method string
Path string
Body interface{}
Headers map[string]string
}
// TestResponse represents a test HTTP response
type TestResponse struct {
StatusCode int
Body map[string]interface{}
Headers http.Header
}
// MakeRequest creates and executes an HTTP request for testing
func MakeRequest(t *testing.T, handler http.Handler, req TestRequest) *httptest.ResponseRecorder {
var bodyBytes []byte
if req.Body != nil {
var err error
bodyBytes, err = json.Marshal(req.Body)
if err != nil {
t.Fatalf("marshal request body: %v", err)
}
}
httpReq, err := http.NewRequest(req.Method, req.Path, bytes.NewReader(bodyBytes))
if err != nil {
t.Fatalf("create request: %v", err)
}
// Set headers
if req.Headers != nil {
for k, v := range req.Headers {
httpReq.Header.Set(k, v)
}
}
// Set Content-Type if body is present
if bodyBytes != nil && httpReq.Header.Get("Content-Type") == "" {
httpReq.Header.Set("Content-Type", "application/json")
}
recorder := httptest.NewRecorder()
handler.ServeHTTP(recorder, httpReq)
return recorder
}
// AssertStatusCode asserts the response status code
func AssertStatusCode(t *testing.T, recorder *httptest.ResponseRecorder, expected int) {
if recorder.Code != expected {
t.Errorf("expected status %d, got %d", expected, recorder.Code)
}
}
// AssertJSONResponse asserts the response is valid JSON and matches expected structure
func AssertJSONResponse(t *testing.T, recorder *httptest.ResponseRecorder) map[string]interface{} {
var response map[string]interface{}
if err := json.Unmarshal(recorder.Body.Bytes(), &response); err != nil {
t.Fatalf("unmarshal JSON response: %v\nBody: %s", err, recorder.Body.String())
}
return response
}
// AssertHeader asserts a header value
func AssertHeader(t *testing.T, recorder *httptest.ResponseRecorder, key, expected string) {
actual := recorder.Header().Get(key)
if actual != expected {
t.Errorf("expected header %s=%s, got %s", key, expected, actual)
}
}
// AssertErrorResponse asserts the response is an error response
func AssertErrorResponse(t *testing.T, recorder *httptest.ResponseRecorder, expectedCode string) {
response := AssertJSONResponse(t, recorder)
if code, ok := response["code"].(string); !ok || code != expectedCode {
t.Errorf("expected error code %s, got %v", expectedCode, response["code"])
}
}
// AssertSuccessResponse asserts the response is a success response
func AssertSuccessResponse(t *testing.T, recorder *httptest.ResponseRecorder) map[string]interface{} {
AssertStatusCode(t, recorder, http.StatusOK)
return AssertJSONResponse(t, recorder)
}
// CreateTestUser creates a test user for authentication tests
func CreateTestUser() map[string]interface{} {
return map[string]interface{}{
"username": "testuser",
"password": "TestPass123",
"email": "test@example.com",
"role": "viewer",
}
}
// CreateTestToken creates a mock JWT token for testing
func CreateTestToken(userID, role string) string {
// In a real test, you'd use the actual auth service
// This is a placeholder for test token generation
return "test-token-" + userID
}
// MockZFSClient provides a mock ZFS client for testing
type MockZFSClient struct {
Pools []map[string]interface{}
Datasets []map[string]interface{}
ZVOLs []map[string]interface{}
Snapshots []map[string]interface{}
Error error
}
// NewMockZFSClient creates a new mock ZFS client
func NewMockZFSClient() *MockZFSClient {
return &MockZFSClient{
Pools: []map[string]interface{}{},
Datasets: []map[string]interface{}{},
ZVOLs: []map[string]interface{}{},
Snapshots: []map[string]interface{}{},
}
}
// SetError sets an error to return
func (m *MockZFSClient) SetError(err error) {
m.Error = err
}
// AddPool adds a mock pool
func (m *MockZFSClient) AddPool(pool map[string]interface{}) {
m.Pools = append(m.Pools, pool)
}
// AddDataset adds a mock dataset
func (m *MockZFSClient) AddDataset(dataset map[string]interface{}) {
m.Datasets = append(m.Datasets, dataset)
}
// Reset clears all mock data
func (m *MockZFSClient) Reset() {
m.Pools = []map[string]interface{}{}
m.Datasets = []map[string]interface{}{}
m.ZVOLs = []map[string]interface{}{}
m.Snapshots = []map[string]interface{}{}
m.Error = nil
}