gohorsejobs/backend/tests/e2e/e2e_test.go
2026-02-12 20:13:46 -03:00

163 lines
3.9 KiB
Go

//go:build e2e
// +build e2e
package e2e
import (
"bytes"
"encoding/json"
"io"
"net/http"
"net/http/httptest"
"os"
"testing"
"github.com/rede5/gohorsejobs/backend/internal/database"
"github.com/rede5/gohorsejobs/backend/internal/router"
)
var testServer *httptest.Server
// TestMain sets up the test environment for all E2E tests
func TestMain(m *testing.M) {
// Set environment variables for testing
setTestEnv()
// Initialize database connection
database.InitDB()
// Create test server
testServer = httptest.NewServer(router.NewRouter())
defer testServer.Close()
// Run tests
code := m.Run()
// Cleanup
cleanupTestData()
os.Exit(code)
}
// setTestEnv sets up environment variables for testing
// Uses the same database as development (loaded from .env in CI/CD or manually set)
func setTestEnv() {
// Only set if not already set (allows override via .env file)
// These are defaults for when running tests without sourcing .env
if os.Getenv("DATABASE_URL") == "" {
os.Setenv("DATABASE_URL", "postgres://yuki:xl1zfmr6e9bb@db-60059.dc-sp-1.absamcloud.com:26868/gohorsejobs_dev?sslmode=require")
}
if os.Getenv("JWT_SECRET") == "" {
os.Setenv("JWT_SECRET", "gohorse-super-secret-key-2024-production")
}
}
// cleanupTestData removes test data from the database
func cleanupTestData() {
if database.DB != nil {
// Clean up in reverse order of dependencies
database.DB.Exec("DELETE FROM applications WHERE id > 0")
database.DB.Exec("DELETE FROM jobs WHERE title LIKE 'E2E Test%'")
database.DB.Exec("DELETE FROM companies WHERE name LIKE 'E2E Test%'")
}
}
// httpClient helper for making requests to test server
type testClient struct {
baseURL string
token string
}
func newTestClient() *testClient {
return &testClient{
baseURL: testServer.URL,
}
}
func (c *testClient) setAuthToken(token string) {
c.token = token
}
func (c *testClient) doRequest(method, path string, body interface{}) (*http.Response, error) {
var reqBody io.Reader
if body != nil {
jsonData, err := json.Marshal(body)
if err != nil {
return nil, err
}
reqBody = bytes.NewReader(jsonData)
}
req, err := http.NewRequest(method, c.baseURL+path, reqBody)
if err != nil {
return nil, err
}
req.Header.Set("Content-Type", "application/json")
if c.token != "" {
req.Header.Set("Authorization", "Bearer "+c.token)
}
return http.DefaultClient.Do(req)
}
func (c *testClient) get(path string) (*http.Response, error) {
return c.doRequest("GET", path, nil)
}
func (c *testClient) post(path string, body interface{}) (*http.Response, error) {
return c.doRequest("POST", path, body)
}
func (c *testClient) put(path string, body interface{}) (*http.Response, error) {
return c.doRequest("PUT", path, body)
}
func (c *testClient) delete(path string) (*http.Response, error) {
return c.doRequest("DELETE", path, nil)
}
// parseJSON helper to decode JSON response
func parseJSON(resp *http.Response, target interface{}) error {
defer resp.Body.Close()
return json.NewDecoder(resp.Body).Decode(target)
}
// TestHealthCheck verifies the server is running
func TestHealthCheck(t *testing.T) {
client := newTestClient()
resp, err := client.get("/health")
if err != nil {
t.Fatalf("Failed to make request: %v", err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
t.Errorf("Expected status 200, got %d", resp.StatusCode)
}
}
// TestRootEndpoint verifies the API info endpoint
func TestRootEndpoint(t *testing.T) {
client := newTestClient()
resp, err := client.get("/")
if err != nil {
t.Fatalf("Failed to make request: %v", err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
t.Errorf("Expected status 200, got %d", resp.StatusCode)
}
var result map[string]interface{}
if err := parseJSON(resp, &result); err != nil {
t.Fatalf("Failed to parse JSON: %v", err)
}
if result["message"] != "🐴 GoHorseJobs API is running!" {
t.Errorf("Unexpected message: %v", result["message"])
}
}