feat(store): sqlc-запросы, dto TemplateDoc, Repository, интеграционные тесты CRUD
This commit is contained in:
@@ -0,0 +1,98 @@
|
||||
package store
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/jackc/pgx/v5/pgtype"
|
||||
"github.com/jackc/pgx/v5/pgxpool"
|
||||
|
||||
"github.com/vasyakrg/dns-autoresolver/internal/store/db"
|
||||
"github.com/vasyakrg/dns-autoresolver/internal/store/dto"
|
||||
)
|
||||
|
||||
// defaultProject is the seed default tenant project (see migrations/0001_init.sql).
|
||||
//
|
||||
// NOTE: sqlc generated UUID columns as pgtype.UUID (not google/uuid.UUID) —
|
||||
// pgUUID bridges the two so tests can still use uuid.New()/uuid.MustParse.
|
||||
var defaultProject = pgUUID(uuid.MustParse("00000000-0000-0000-0000-000000000002"))
|
||||
|
||||
func pgUUID(id uuid.UUID) pgtype.UUID {
|
||||
return pgtype.UUID{Bytes: id, Valid: true}
|
||||
}
|
||||
|
||||
func newStore(t *testing.T) (*Store, context.Context) {
|
||||
dsn := startPostgres(t)
|
||||
pool, err := pgxpool.New(context.Background(), dsn)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Cleanup(pool.Close)
|
||||
return New(pool), context.Background()
|
||||
}
|
||||
|
||||
func TestAccountCRUD(t *testing.T) {
|
||||
s, ctx := newStore(t)
|
||||
acc, err := s.Queries().CreateAccount(ctx, db.CreateAccountParams{
|
||||
ID: pgUUID(uuid.New()), ProjectID: defaultProject,
|
||||
Provider: "selectel", SecretEnc: "enc-blob", Comment: "prod",
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
got, err := s.Queries().GetAccount(ctx, db.GetAccountParams{ID: acc.ID, ProjectID: defaultProject})
|
||||
if err != nil || got.Provider != "selectel" || got.SecretEnc != "enc-blob" {
|
||||
t.Fatalf("get mismatch: %+v err=%v", got, err)
|
||||
}
|
||||
|
||||
list, err := s.Queries().ListAccounts(ctx, defaultProject)
|
||||
if err != nil || len(list) != 1 {
|
||||
t.Fatalf("list mismatch: %+v err=%v", list, err)
|
||||
}
|
||||
|
||||
if err := s.Queries().DeleteAccount(ctx, db.DeleteAccountParams{ID: acc.ID, ProjectID: defaultProject}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if _, err := s.Queries().GetAccount(ctx, db.GetAccountParams{ID: acc.ID, ProjectID: defaultProject}); err == nil {
|
||||
t.Fatal("expected error after delete, got nil")
|
||||
}
|
||||
}
|
||||
|
||||
func TestTemplateJSONBRoundTrip(t *testing.T) {
|
||||
s, ctx := newStore(t)
|
||||
doc := dto.TemplateDoc{Records: []dto.RecordDTO{
|
||||
{Type: "A", Name: "www.example.com.", TTL: 300, Values: []string{"1.2.3.4"}},
|
||||
{Type: "SRV", Name: "_autodiscover._tcp.example.com.", TTL: 3600, Values: []string{"0 0 443 mail.example.com."}},
|
||||
}}
|
||||
tpl, err := s.Queries().CreateTemplate(ctx, db.CreateTemplateParams{
|
||||
ID: pgUUID(uuid.New()), ProjectID: defaultProject, Name: "base", Doc: &doc,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
got, err := s.Queries().GetTemplate(ctx, db.GetTemplateParams{ID: tpl.ID, ProjectID: defaultProject})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if got.Doc == nil || len(got.Doc.Records) != 2 || got.Doc.Records[1].Type != "SRV" {
|
||||
t.Fatalf("jsonb round-trip failed: %+v", got.Doc)
|
||||
}
|
||||
|
||||
doc2 := dto.TemplateDoc{Records: []dto.RecordDTO{
|
||||
{Type: "A", Name: "www.example.com.", TTL: 60, Values: []string{"5.6.7.8"}},
|
||||
}}
|
||||
updated, err := s.Queries().UpdateTemplate(ctx, db.UpdateTemplateParams{
|
||||
ID: tpl.ID, ProjectID: defaultProject, Name: "base-v2", Doc: &doc2,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if updated.Version != tpl.Version+1 || updated.Doc == nil || len(updated.Doc.Records) != 1 {
|
||||
t.Fatalf("update mismatch: %+v", updated)
|
||||
}
|
||||
|
||||
if err := s.Queries().DeleteTemplate(ctx, db.DeleteTemplateParams{ID: tpl.ID, ProjectID: defaultProject}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user