ultisuite-backend/internal/integrationtest/client.go
R3D347HR4Y fa5394e10d feat(tests): add integration testing framework and configuration
- Introduced a new `.env.test.example` file for integration test configuration.
- Added a `Makefile` to streamline test commands for unit and integration tests.
- Implemented an integration testing harness with support for PostgreSQL, MinIO, and Redis using testcontainers.
- Created a suite of integration tests covering health checks and user management functionalities.
- Enhanced CI workflow to include integration tests with necessary environment variables.
2026-06-07 19:44:29 +02:00

94 lines
2.2 KiB
Go

//go:build integration
package integrationtest
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
"strings"
)
// Client performs authenticated HTTP requests against the test server.
type Client struct {
baseURL string
token string
http *http.Client
}
func NewClient(baseURL, token string) *Client {
return &Client{
baseURL: strings.TrimSuffix(baseURL, "/"),
token: token,
http: &http.Client{},
}
}
type Response struct {
Status int
Body []byte
Header http.Header
}
func (c *Client) Do(method, path string, body any) (*Response, error) {
var reader io.Reader
if body != nil {
data, err := json.Marshal(body)
if err != nil {
return nil, err
}
reader = bytes.NewReader(data)
}
req, err := http.NewRequest(method, c.baseURL+path, reader)
if err != nil {
return nil, err
}
if body != nil {
req.Header.Set("Content-Type", "application/json")
}
if c.token != "" {
req.Header.Set("Authorization", "Bearer "+c.token)
}
resp, err := c.http.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
data, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}
return &Response{Status: resp.StatusCode, Body: data, Header: resp.Header}, nil
}
func (c *Client) Get(path string) (*Response, error) { return c.Do(http.MethodGet, path, nil) }
func (c *Client) Post(path string, body any) (*Response, error) {
return c.Do(http.MethodPost, path, body)
}
func (c *Client) Put(path string, body any) (*Response, error) { return c.Do(http.MethodPut, path, body) }
func (c *Client) Patch(path string, body any) (*Response, error) {
return c.Do(http.MethodPatch, path, body)
}
func (c *Client) Delete(path string) (*Response, error) { return c.Do(http.MethodDelete, path, nil) }
func (r *Response) JSON(v any) error {
return json.Unmarshal(r.Body, v)
}
func (r *Response) MustStatus(want int) error {
if r.Status != want {
return fmt.Errorf("status = %d, want %d; body = %s", r.Status, want, string(r.Body))
}
return nil
}
// WithToken returns a copy using a different bearer token (e.g. API token).
func (c *Client) WithToken(token string) *Client {
return &Client{baseURL: c.baseURL, token: token, http: c.http}
}