Files
sm-feedback-plugin/internal/pgtest/pgtest.go
Jakub Zych b4b4135ad3 feat: golem15.feedback plugin with the widget config route
- plugin golem15.feedback (requires golem15.user), its config, lang (en, pl), models and migrations
- typed settings singleton golem15_feedback_settings with the WinterCMS defaults and a widget key generated on first creation
- GET /_feedback/api/v1/{key}/config behind the constant-time key check and the fail-closed Origin allow-list, with the feedback-config and feedback-submit buckets
2026-10-04 00:01:22 +02:00

100 lines
2.7 KiB
Go

// Package pgtest starts one Postgres container per test binary for the
// plugin's database tests and migrates golem15.user, golem15.feedback and
// the framework tables (system_files, the job queue) into it. The test
// binary must link the golem15.feedback plugin (its package or an
// importer of it), which registers itself in init.
package pgtest
import (
"bytes"
"context"
"database/sql"
"os"
"path/filepath"
"sync"
"testing"
"time"
_ "git.golem15.com/golem15/sm-user-plugin"
"git.golem15.com/golem15/summercms/modules/backpack"
"git.golem15.com/golem15/summercms/modules/compass"
"git.golem15.com/golem15/summercms/modules/lagoon"
"git.golem15.com/golem15/summercms/modules/party"
"github.com/testcontainers/testcontainers-go/modules/postgres"
"gorm.io/gorm"
)
// PluginIDs are the plugins the database is migrated for.
var PluginIDs = []string{"golem15.user", "golem15.feedback"}
var (
once sync.Once
gdb *gorm.DB
sqlDB *sql.DB
err error
)
// DB returns the shared, migrated database. Tests that need an empty
// table delete its rows first.
func DB(t testing.TB) *gorm.DB {
t.Helper()
once.Do(func() {
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Minute)
defer cancel()
if err = lagoon.PublishEncryptionKeys(nil, bytes.Repeat([]byte("F"), 32), nil); err != nil {
return
}
var ctr *postgres.PostgresContainer
ctr, err = postgres.Run(ctx, "postgres:16-alpine",
postgres.WithDatabase("feedback"),
postgres.WithUsername("feedback"),
postgres.WithPassword("feedback"),
postgres.BasicWaitStrategies(),
)
if err != nil {
return
}
var dsn string
if dsn, err = ctr.ConnectionString(ctx, "sslmode=disable"); err != nil {
return
}
if sqlDB, err = sql.Open("pgx", dsn); err != nil {
return
}
if gdb, err = lagoon.Use(ctx, sqlDB); err != nil {
return
}
var dir string
if dir, err = os.MkdirTemp("", "feedback-pgtest-"); err != nil {
return
}
defer os.RemoveAll(dir)
if err = os.WriteFile(filepath.Join(dir, "app.yaml"), []byte("name: feedback-pgtest\n"), 0o644); err != nil {
return
}
var cfg *compass.Config
if cfg, err = compass.Open(compass.Options{Dir: dir, Environ: []string{
"SUMMER_ENV=development",
// A throwaway secret: golem15.user refuses to boot without one.
"SUMMER_GOLEM15__USER__JWT__SECRET=pgtest-only-jwt-secret-0123456789abcdef",
}}); err != nil {
return
}
var plugins []party.Plugin
if plugins, err = party.Activate(backpack.New(cfg), PluginIDs); err != nil {
return
}
err = lagoon.Migrate(gdb, plugins)
})
if err != nil {
t.Fatalf("pgtest: %v", err)
}
return gdb
}
// SQL is the database's *sql.DB.
func SQL(t testing.TB) *sql.DB {
DB(t)
return sqlDB
}