chore(服务端): 初始化工程仓库
This commit is contained in:
@@ -0,0 +1,96 @@
|
||||
package server
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"github.com/jackc/pgx/v5/pgxpool"
|
||||
"net/http/httptest"
|
||||
"os"
|
||||
"perler-beads-server/internal/domain"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestAnonymousPermissions(t *testing.T) {
|
||||
r := (&Server{}).Router()
|
||||
for _, path := range []string{"/api/me", "/api/my/patterns", "/api/favorites", "/api/tables", "/api/service-requests", "/api/admin/patterns"} {
|
||||
w := httptest.NewRecorder()
|
||||
r.ServeHTTP(w, httptest.NewRequest("GET", path, nil))
|
||||
var v struct{ Code int }
|
||||
if json.Unmarshal(w.Body.Bytes(), &v) != nil || w.Code != 200 || v.Code != 403 {
|
||||
t.Fatalf("%s: %s", path, w.Body)
|
||||
}
|
||||
}
|
||||
}
|
||||
func TestPrintMillimetersEscapes(t *testing.T) {
|
||||
code := "R"
|
||||
p := domain.Pattern{Title: "<script>", Width: 1, Height: 1, Cells: []*string{&code}, Colors: []domain.Color{{Code: code, Hex: "#ff0000"}}, BeadCount: 1}
|
||||
var b bytes.Buffer
|
||||
if e := renderSVG(&b, p, 5); e != nil {
|
||||
t.Fatal(e)
|
||||
}
|
||||
svg := b.String()
|
||||
for _, want := range []string{`width="100.00mm"`, `height="100.00mm"`, "<script>", "50 mm calibration", "R: 1"} {
|
||||
if !strings.Contains(svg, want) {
|
||||
t.Fatalf("missing %s", want)
|
||||
}
|
||||
}
|
||||
if strings.Contains(svg, "<script>") {
|
||||
t.Fatal("unescaped title")
|
||||
}
|
||||
}
|
||||
func TestPostgresPersistentIdempotency(t *testing.T) {
|
||||
dsn := os.Getenv("TEST_DATABASE_URL")
|
||||
if dsn == "" {
|
||||
t.Skip("TEST_DATABASE_URL absent; dedicated PostgreSQL integration database required")
|
||||
}
|
||||
cfg, e := pgxpool.ParseConfig(dsn)
|
||||
if e != nil {
|
||||
t.Fatal(e)
|
||||
}
|
||||
if !strings.Contains(cfg.ConnConfig.Database, "test") {
|
||||
t.Fatal("test database name must contain test")
|
||||
}
|
||||
ctx := context.Background()
|
||||
db, e := pgxpool.NewWithConfig(ctx, cfg)
|
||||
if e != nil {
|
||||
t.Fatal(e)
|
||||
}
|
||||
defer db.Close()
|
||||
if e = Migrate(ctx, db); e != nil {
|
||||
t.Fatal(e)
|
||||
}
|
||||
tx, e := db.Begin(ctx)
|
||||
if e != nil {
|
||||
t.Fatal(e)
|
||||
}
|
||||
defer tx.Rollback(ctx)
|
||||
id := "integration-" + t.Name()
|
||||
_, e = tx.Exec(ctx, `INSERT INTO request_keys VALUES($1,'9e7aec78-f5a0-4f00-81fa-7606a8d9f7c0',$2,'{}')`, id, domain.Fingerprint("help", "a", ""))
|
||||
if e != nil {
|
||||
t.Fatal(e)
|
||||
}
|
||||
_, e = tx.Exec(ctx, `INSERT INTO request_keys VALUES($1,'9e7aec78-f5a0-4f00-81fa-7606a8d9f7c0',$2,'{}')`, id, domain.Fingerprint("help", "b", ""))
|
||||
if e == nil {
|
||||
t.Fatal("persistent unique key allowed duplicate")
|
||||
}
|
||||
}
|
||||
func TestDemoFixtures(t *testing.T) {
|
||||
cs := demoColors()
|
||||
if len(cs) < 8 {
|
||||
t.Fatal("too few demo colors")
|
||||
}
|
||||
ps := demoPatterns("store-001", cs)
|
||||
if len(ps) != 4 {
|
||||
t.Fatal("need four motifs")
|
||||
}
|
||||
for _, p := range ps {
|
||||
if e := p.Validate(); e != nil {
|
||||
t.Fatal(e)
|
||||
}
|
||||
if !p.Demo || p.BeadCount == 0 {
|
||||
t.Fatal("demo must be marked and nonempty")
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user