mirror of
https://github.com/SamyRai/tercul-backend.git
synced 2025-12-27 05:11:34 +00:00
139 lines
3.7 KiB
Go
139 lines
3.7 KiB
Go
package e2e
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"encoding/json"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"testing"
|
|
"time"
|
|
|
|
graph "tercul/internal/adapters/graphql"
|
|
"tercul/internal/domain"
|
|
"tercul/internal/observability"
|
|
platform_auth "tercul/internal/platform/auth"
|
|
platform_config "tercul/internal/platform/config"
|
|
"tercul/internal/testutil"
|
|
"tercul/test/fixtures"
|
|
|
|
"github.com/99designs/gqlgen/graphql/handler"
|
|
"github.com/prometheus/client_golang/prometheus"
|
|
"github.com/stretchr/testify/suite"
|
|
"gorm.io/gorm/logger"
|
|
)
|
|
|
|
// E2ETestSuite provides end-to-end testing infrastructure.
|
|
type E2ETestSuite struct {
|
|
testutil.IntegrationTestSuite
|
|
Server *httptest.Server
|
|
Client *http.Client
|
|
JWTManager *platform_auth.JWTManager
|
|
Fixtures *fixtures.Loader
|
|
}
|
|
|
|
func (s *E2ETestSuite) SetupSuite() {
|
|
// Use a file-based SQLite DB for stability across multiple connections.
|
|
// In-memory SQLite (":memory:") can create isolated DBs per connection, which breaks HTTP handler requests.
|
|
s.IntegrationTestSuite.SetupSuite(&testutil.TestConfig{UseInMemoryDB: false, DBPath: "e2e_test.db", LogLevel: logger.Silent})
|
|
|
|
cfg, err := platform_config.LoadConfig()
|
|
s.Require().NoError(err)
|
|
s.JWTManager = platform_auth.NewJWTManager(cfg)
|
|
s.Fixtures = fixtures.NewLoader(s.DB)
|
|
|
|
resolver := &graph.Resolver{App: s.App}
|
|
c := graph.Config{Resolvers: resolver}
|
|
c.Directives.Binding = graph.Binding
|
|
|
|
//nolint:staticcheck // Required here for custom error presenter
|
|
srv := handler.NewDefaultServer(graph.NewExecutableSchema(c))
|
|
srv.SetErrorPresenter(graph.NewErrorPresenter())
|
|
|
|
reg := prometheus.NewRegistry()
|
|
metrics := observability.NewMetrics(reg)
|
|
|
|
var chain http.Handler
|
|
chain = srv
|
|
chain = platform_auth.GraphQLAuthMiddleware(s.JWTManager)(chain)
|
|
chain = metrics.PrometheusMiddleware(chain)
|
|
chain = observability.TracingMiddleware(chain)
|
|
chain = observability.RequestIDMiddleware(chain)
|
|
|
|
s.Server = httptest.NewServer(chain)
|
|
s.Client = s.Server.Client()
|
|
}
|
|
|
|
func (s *E2ETestSuite) TearDownSuite() {
|
|
if s.Server != nil {
|
|
s.Server.Close()
|
|
}
|
|
s.IntegrationTestSuite.TearDownSuite()
|
|
}
|
|
|
|
func (s *E2ETestSuite) SetupTest() {
|
|
ctx := context.Background()
|
|
s.Require().NoError(s.Fixtures.Clear(ctx))
|
|
s.Require().NoError(s.Fixtures.LoadAll(ctx))
|
|
}
|
|
|
|
func (s *E2ETestSuite) TearDownTest() {
|
|
ctx := context.Background()
|
|
_ = s.Fixtures.Clear(ctx)
|
|
}
|
|
|
|
func (s *E2ETestSuite) GenerateToken(username string) string {
|
|
var user domain.User
|
|
err := s.DB.Where("username = ?", username).First(&user).Error
|
|
s.Require().NoError(err)
|
|
|
|
token, err := s.JWTManager.GenerateToken(&user)
|
|
s.Require().NoError(err)
|
|
return token
|
|
}
|
|
|
|
func (s *E2ETestSuite) executeGraphQL(query string, variables map[string]interface{}, token string) map[string]interface{} {
|
|
payload := map[string]interface{}{"query": query}
|
|
if variables != nil {
|
|
payload["variables"] = variables
|
|
}
|
|
body, err := json.Marshal(payload)
|
|
s.Require().NoError(err)
|
|
|
|
req, err := http.NewRequest("POST", s.Server.URL, bytes.NewBuffer(body))
|
|
s.Require().NoError(err)
|
|
req.Header.Set("Content-Type", "application/json")
|
|
if token != "" {
|
|
req.Header.Set("Authorization", "Bearer "+token)
|
|
}
|
|
|
|
resp, err := s.Client.Do(req)
|
|
s.Require().NoError(err)
|
|
defer resp.Body.Close()
|
|
|
|
var out map[string]interface{}
|
|
s.Require().NoError(json.NewDecoder(resp.Body).Decode(&out))
|
|
return out
|
|
}
|
|
|
|
func (s *E2ETestSuite) Eventually(condition func() bool, timeout time.Duration, message string) {
|
|
start := time.Now()
|
|
for {
|
|
if condition() {
|
|
return
|
|
}
|
|
if time.Since(start) > timeout {
|
|
s.Fail(message)
|
|
return
|
|
}
|
|
time.Sleep(25 * time.Millisecond)
|
|
}
|
|
}
|
|
|
|
func TestE2ETestSuite(t *testing.T) {
|
|
if testing.Short() {
|
|
t.Skip("Skipping E2E tests in short mode")
|
|
}
|
|
suite.Run(t, new(E2ETestSuite))
|
|
}
|