83 lines
3.5 KiB
Go
83 lines
3.5 KiB
Go
package taskdetail
|
|
|
|
import (
|
|
"context"
|
|
"database/sql"
|
|
"errors"
|
|
"path/filepath"
|
|
"runtime"
|
|
"strings"
|
|
"testing"
|
|
|
|
"cmbuyer/admin/internal/migrations"
|
|
"cmbuyer/admin/internal/storage/sqlite"
|
|
)
|
|
|
|
const (
|
|
detailTask = "a3c9f507-7473-4fa6-8d71-8786c34c6301"
|
|
detailAuth = "b3c9f507-7473-4fa6-8d71-8786c34c6301"
|
|
detailTry = "c3c9f507-7473-4fa6-8d71-8786c34c6301"
|
|
)
|
|
|
|
func TestSQLiteStoreReturnsOnlyPersistedAuditFacts(t *testing.T) {
|
|
database := openDetailDatabase(t)
|
|
timestamp := "2026-08-04T00:00:00Z"
|
|
if _, err := database.Exec(`INSERT INTO tasks (id, source, title, goods_id, sku_color, sku_size, quantity, max_total_price, status, version, created_at, updated_at) VALUES (?, 'MANUAL', 'shirt', '123', 'black', 'M', 2, '30.00', 'CLAIMED', 3, ?, ?)`, detailTask, timestamp, timestamp); err != nil {
|
|
t.Fatalf("insert task: %v", err)
|
|
}
|
|
if _, err := database.Exec(`INSERT INTO order_authorizations (id, task_id, task_version, start_key, goods_id, sku_color, sku_size, quantity, total_price_cap, status, created_by, created_at, expires_at) VALUES (?, ?, 2, 'start', '123', 'black', 'M', 2, '30.00', 'CLAIMED', 'admin', ?, ?)`, detailAuth, detailTask, timestamp, timestamp); err != nil {
|
|
t.Fatalf("insert authorization: %v", err)
|
|
}
|
|
if _, err := database.Exec(`INSERT INTO purchase_attempts (id, task_id, authorization_id, claim_generation, status, started_at) VALUES (?, ?, ?, 1, 'CLAIMED', ?)`, detailTry, detailTask, detailAuth, timestamp); err != nil {
|
|
t.Fatalf("insert attempt: %v", err)
|
|
}
|
|
hash := strings.Repeat("a", 64)
|
|
if _, err := database.Exec(`INSERT INTO evidence_assets (id, upload_key, task_id, attempt_id, kind, privacy_tier, sha256, byte_size, content_type, width_px, height_px, storage_key, uploaded_by_device_id, captured_at, created_at) VALUES ('d3c9f507-7473-4fa6-8d71-8786c34c6301', 'upload', ?, ?, 'SKU_PANEL_GATE_1', 'INTERNAL_RAW', ?, 100, 'image/png', 10, 20, ?, 'device', ?, ?)`, detailTask, detailTry, hash, "aa/"+hash+".png", timestamp, timestamp); err != nil {
|
|
t.Fatalf("insert evidence: %v", err)
|
|
}
|
|
store, err := NewSQLiteStore(database)
|
|
if err != nil {
|
|
t.Fatalf("NewSQLiteStore: %v", err)
|
|
}
|
|
detail, err := store.Get(context.Background(), detailTask)
|
|
if err != nil {
|
|
t.Fatalf("Get: %v", err)
|
|
}
|
|
if detail.Task.ID != detailTask || detail.Task.Status != "CLAIMED" || len(detail.Authorizations) != 1 || len(detail.Attempts) != 1 || len(detail.Evidence) != 1 || len(detail.Submissions) != 0 {
|
|
t.Fatalf("detail = %#v", detail)
|
|
}
|
|
if detail.Attempts[0].Gate1UnitPrice != nil || detail.Attempts[0].FailureCode != nil {
|
|
t.Fatalf("missing attempt facts were fabricated: %#v", detail.Attempts[0])
|
|
}
|
|
}
|
|
|
|
func TestSQLiteStoreFailsClosedForMalformedAndMissingIDs(t *testing.T) {
|
|
database := openDetailDatabase(t)
|
|
store, err := NewSQLiteStore(database)
|
|
if err != nil {
|
|
t.Fatalf("NewSQLiteStore: %v", err)
|
|
}
|
|
for _, id := range []string{"../database", "not-a-uuid", "a3c9f507-7473-1fa6-8d71-8786c34c6301"} {
|
|
if _, err := store.Get(context.Background(), id); !errors.Is(err, ErrNotFound) {
|
|
t.Fatalf("Get(%q) error = %v", id, err)
|
|
}
|
|
}
|
|
}
|
|
|
|
func openDetailDatabase(t *testing.T) *sql.DB {
|
|
t.Helper()
|
|
database, err := sqlite.Open(filepath.Join(t.TempDir(), "details.db"))
|
|
if err != nil {
|
|
t.Fatalf("open database: %v", err)
|
|
}
|
|
t.Cleanup(func() { _ = database.Close() })
|
|
_, file, _, ok := runtime.Caller(0)
|
|
if !ok {
|
|
t.Fatal("locate migration directory")
|
|
}
|
|
if err := migrations.Up(context.Background(), database, filepath.Join(filepath.Dir(file), "..", "..", "migrations")); err != nil {
|
|
t.Fatalf("migrate database: %v", err)
|
|
}
|
|
return database
|
|
}
|