- 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.
94 lines
2.2 KiB
Go
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}
|
|
}
|