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

160 lines
4.2 KiB
Go

//go:build integration
// +build integration
package integration
import (
"bytes"
"encoding/json"
"io"
"net/http"
"net/http/httptest"
"os"
"testing"
"time"
"github.com/golang-jwt/jwt/v5"
"github.com/rede5/gohorsejobs/backend/internal/database"
"github.com/rede5/gohorsejobs/backend/internal/router"
)
var testServer *httptest.Server
func TestMain(m *testing.M) {
setTestEnv()
database.InitDB()
testServer = httptest.NewServer(router.NewRouter())
defer testServer.Close()
code := m.Run()
cleanupTestData()
os.Exit(code)
}
func setTestEnv() {
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")
}
}
func cleanupTestData() {
if database.DB != nil {
database.DB.Exec("DELETE FROM applications WHERE id > 0")
database.DB.Exec("DELETE FROM jobs WHERE title LIKE 'Int Test%'")
database.DB.Exec("DELETE FROM companies WHERE name LIKE 'Int Test%'")
database.DB.Exec("DELETE FROM users WHERE full_name LIKE 'Int Test%'")
}
}
// Helpers
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) delete(path string) (*http.Response, error) {
return c.doRequest("DELETE", path, nil)
}
func createAuthToken(t *testing.T, userID, tenantID string, roles []string) string {
t.Helper()
secret := os.Getenv("JWT_SECRET")
claims := jwt.MapClaims{
"sub": userID,
"tenant": tenantID,
"roles": roles,
"iss": "gohorse-jobs",
"exp": time.Now().Add(time.Hour).Unix(),
"iat": time.Now().Unix(),
}
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
str, err := token.SignedString([]byte(secret))
if err != nil {
t.Fatalf("Failed to sign token: %v", err)
}
return str
}
func setupTestCompanyAndUser(t *testing.T) (companyID, userID string) {
t.Helper()
// User
err := database.DB.QueryRow(`
INSERT INTO users (identifier, password_hash, role, full_name, email, created_at, updated_at)
VALUES ($1, $2, $3, $4, $5, NOW(), NOW())
ON CONFLICT (identifier) DO UPDATE SET full_name = $4
RETURNING id`,
"int-test-user", "hash", "superadmin", "Int Test User", "int@test.com",
).Scan(&userID)
if err != nil {
t.Fatalf("Failed setup user: %v", err)
}
database.DB.Exec("INSERT INTO user_roles (user_id, role) VALUES ($1, 'superadmin') ON CONFLICT DO NOTHING", userID)
// Company
err = database.DB.QueryRow(`
INSERT INTO companies (name, slug, type, active, verified, created_at, updated_at)
VALUES ($1, $2, $3, $4, $5, NOW(), NOW())
ON CONFLICT (slug) DO UPDATE SET name = $1
RETURNING id`,
"Int Test Company", "int-test-company", "employer", true, true,
).Scan(&companyID)
if err != nil {
t.Fatalf("Failed setup company: %v", err)
}
return companyID, userID
}
func createTestCandidate(t *testing.T) string {
var id string
err := database.DB.QueryRow(`
INSERT INTO users (identifier, password_hash, role, full_name, email, status, created_at, updated_at)
VALUES ('int_cand_' || gen_random_uuid(), 'hash', 'candidate', 'Int Test Cand', 'cand@int.com', 'active', NOW(), NOW())
RETURNING id
`).Scan(&id)
if err != nil {
t.Fatalf("Failed create candidate: %v", err)
}
database.DB.Exec("INSERT INTO user_roles (user_id, role) VALUES ($1, 'candidate')", id)
return id
}