588 lines
20 KiB
Go
588 lines
20 KiB
Go
package mysql
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
"gorm.io/driver/sqlite"
|
|
"gorm.io/gorm"
|
|
|
|
afterflightinspection "wucher/internal/domain/after_flight_inspection"
|
|
filemanager "wucher/internal/domain/file_manager"
|
|
"wucher/internal/domain/helicopter"
|
|
"wucher/internal/shared/pkg/uuidv7"
|
|
)
|
|
|
|
func intPtr(v int) *int {
|
|
return &v
|
|
}
|
|
|
|
func openHelicopterTestDB(t *testing.T) *gorm.DB {
|
|
t.Helper()
|
|
dsn := fmt.Sprintf("file:helicopter_test_%d?mode=memory&cache=shared", time.Now().UnixNano())
|
|
db, err := gorm.Open(sqlite.Open(dsn), &gorm.Config{
|
|
NowFunc: func() time.Time { return time.Now().UTC() },
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("open sqlite: %v", err)
|
|
}
|
|
if err := db.AutoMigrate(&filemanager.Folder{}, &filemanager.File{}, &filemanager.Attachment{}, &helicopter.Helicopter{}); err != nil {
|
|
t.Fatalf("auto migrate: %v", err)
|
|
}
|
|
return db
|
|
}
|
|
|
|
func TestNewHelicopterRepository(t *testing.T) {
|
|
db := openHelicopterTestDB(t)
|
|
repo := NewHelicopterRepository(db)
|
|
if repo == nil || repo.db == nil {
|
|
t.Fatalf("expected repository initialized")
|
|
}
|
|
if repo.hasUsersTable {
|
|
t.Fatalf("expected users table cache to be false in base helicopter test db")
|
|
}
|
|
}
|
|
|
|
func TestHelicopterRepositoryCachesUsersTablePresence(t *testing.T) {
|
|
db := openHelicopterTestDB(t)
|
|
if err := db.Exec(`CREATE TABLE users (
|
|
id BLOB PRIMARY KEY,
|
|
first_name TEXT,
|
|
last_name TEXT,
|
|
username TEXT,
|
|
email TEXT
|
|
)`).Error; err != nil {
|
|
t.Fatalf("create users table: %v", err)
|
|
}
|
|
|
|
repo := NewHelicopterRepository(db)
|
|
if !repo.hasUsersTable {
|
|
t.Fatalf("expected users table cache to be true")
|
|
}
|
|
|
|
creatorID := uuidv7.MustBytes()
|
|
updaterID := uuidv7.MustBytes()
|
|
if err := db.Table("users").Create([]map[string]any{
|
|
{
|
|
"id": creatorID,
|
|
"first_name": "Ada",
|
|
"last_name": "Lovelace",
|
|
"username": "ada",
|
|
"email": "ada@example.com",
|
|
},
|
|
{
|
|
"id": updaterID,
|
|
"first_name": "Grace",
|
|
"last_name": "Hopper",
|
|
"username": "grace",
|
|
"email": "grace@example.com",
|
|
},
|
|
}).Error; err != nil {
|
|
t.Fatalf("seed users: %v", err)
|
|
}
|
|
|
|
row := &helicopter.Helicopter{
|
|
Designation: "H145",
|
|
Identifier: "PK-AUDIT",
|
|
Type: "Twin",
|
|
CreatedBy: creatorID,
|
|
UpdatedBy: updaterID,
|
|
}
|
|
if err := repo.Create(context.Background(), row); err != nil {
|
|
t.Fatalf("seed helicopter: %v", err)
|
|
}
|
|
|
|
got, err := repo.GetByID(context.Background(), row.ID)
|
|
if err != nil {
|
|
t.Fatalf("get helicopter: %v", err)
|
|
}
|
|
if got == nil {
|
|
t.Fatalf("expected helicopter row")
|
|
}
|
|
if got.CreatedByName != "Ada Lovelace" {
|
|
t.Fatalf("unexpected created_by_name: %q", got.CreatedByName)
|
|
}
|
|
if got.UpdatedByName != "Grace Hopper" {
|
|
t.Fatalf("unexpected updated_by_name: %q", got.UpdatedByName)
|
|
}
|
|
}
|
|
|
|
func TestHelicopterRepositoryCreate(t *testing.T) {
|
|
db := openHelicopterTestDB(t)
|
|
repo := NewHelicopterRepository(db)
|
|
row := &helicopter.Helicopter{Designation: "H145", Identifier: "PK-ABC", Type: "Twin"}
|
|
|
|
if err := repo.Create(context.Background(), row); err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
if len(row.ID) == 0 {
|
|
t.Fatalf("expected id set")
|
|
}
|
|
inactive := &helicopter.Helicopter{Designation: "Inactive", Identifier: "PK-INACTIVE", Type: "Single", IsActive: false}
|
|
if err := repo.Create(context.Background(), inactive); err != nil {
|
|
t.Fatalf("create inactive: %v", err)
|
|
}
|
|
gotInactive, err := repo.GetByID(context.Background(), inactive.ID)
|
|
if err != nil {
|
|
t.Fatalf("get inactive: %v", err)
|
|
}
|
|
if gotInactive == nil || gotInactive.IsActive {
|
|
t.Fatalf("expected inactive helicopter persisted as false")
|
|
}
|
|
|
|
sqlDB, _ := db.DB()
|
|
_ = sqlDB.Close()
|
|
if err := repo.Create(context.Background(), &helicopter.Helicopter{Designation: "AfterClose", Identifier: "PK-CLOSE", Type: "Twin"}); err == nil {
|
|
t.Fatalf("expected error on closed DB")
|
|
}
|
|
}
|
|
|
|
func TestHelicopterRepositoryUpdate(t *testing.T) {
|
|
db := openHelicopterTestDB(t)
|
|
repo := NewHelicopterRepository(db)
|
|
row := &helicopter.Helicopter{Designation: "Old", Identifier: "PK-OLD", Type: "Single"}
|
|
if err := repo.Create(context.Background(), row); err != nil {
|
|
t.Fatalf("seed create: %v", err)
|
|
}
|
|
|
|
row.Designation = "New"
|
|
row.Type = "Twin"
|
|
if err := repo.Update(context.Background(), row); err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
loaded, err := repo.GetByID(context.Background(), row.ID)
|
|
if err != nil || loaded == nil || loaded.Designation != "New" || loaded.Type != "Twin" {
|
|
t.Fatalf("expected updated row")
|
|
}
|
|
|
|
sqlDB, _ := db.DB()
|
|
_ = sqlDB.Close()
|
|
if err := repo.Update(context.Background(), row); err == nil {
|
|
t.Fatalf("expected error on closed DB")
|
|
}
|
|
}
|
|
|
|
func TestHelicopterRepositoryUpdate_ReplacesFotoAttachmentID(t *testing.T) {
|
|
db := openHelicopterTestDB(t)
|
|
repo := NewHelicopterRepository(db)
|
|
now := time.Now().UTC()
|
|
|
|
folder := &filemanager.Folder{
|
|
ID: uuidv7.MustBytes(),
|
|
Name: "photos",
|
|
NameNormalized: "photos",
|
|
Depth: 0,
|
|
PathCache: "/photos",
|
|
NameSlot: "live",
|
|
CreatedAt: now,
|
|
UpdatedAt: now,
|
|
}
|
|
if err := db.Create(folder).Error; err != nil {
|
|
t.Fatalf("create folder: %v", err)
|
|
}
|
|
|
|
makeFile := func(name, key string) *filemanager.File {
|
|
return &filemanager.File{
|
|
ID: uuidv7.MustBytes(),
|
|
FolderID: folder.ID,
|
|
Name: name,
|
|
NameNormalized: strings.ToLower(name),
|
|
Extension: "webp",
|
|
SizeBytes: 1234,
|
|
MimeType: "image/webp",
|
|
Bucket: "bucket",
|
|
ObjectKey: key,
|
|
Status: filemanager.FileStatusReady,
|
|
NameSlot: "live",
|
|
CreatedAt: now,
|
|
UpdatedAt: now,
|
|
}
|
|
}
|
|
oldFile := makeFile("old.webp", "objects/old.webp")
|
|
newFile := makeFile("new.webp", "objects/new.webp")
|
|
if err := db.Create(oldFile).Error; err != nil {
|
|
t.Fatalf("create old file: %v", err)
|
|
}
|
|
if err := db.Create(newFile).Error; err != nil {
|
|
t.Fatalf("create new file: %v", err)
|
|
}
|
|
|
|
oldAttachment := &filemanager.Attachment{
|
|
ID: uuidv7.MustBytes(),
|
|
FileID: oldFile.ID,
|
|
RefType: "helicopter_photo",
|
|
RefID: "helicopter-1",
|
|
IsPrimary: true,
|
|
CreatedAt: now,
|
|
UpdatedAt: now,
|
|
}
|
|
newAttachment := &filemanager.Attachment{
|
|
ID: uuidv7.MustBytes(),
|
|
FileID: newFile.ID,
|
|
RefType: "helicopter_photo",
|
|
RefID: "helicopter-1",
|
|
IsPrimary: true,
|
|
CreatedAt: now,
|
|
UpdatedAt: now,
|
|
}
|
|
if err := db.Create(oldAttachment).Error; err != nil {
|
|
t.Fatalf("create old attachment: %v", err)
|
|
}
|
|
if err := db.Create(newAttachment).Error; err != nil {
|
|
t.Fatalf("create new attachment: %v", err)
|
|
}
|
|
|
|
row := &helicopter.Helicopter{
|
|
ID: uuidv7.MustBytes(),
|
|
Designation: "Old",
|
|
Identifier: "PK-OLD-ATT",
|
|
Type: "Single",
|
|
FotoAttachmentID: oldAttachment.ID,
|
|
FotoAttachment: oldAttachment,
|
|
CreatedAt: now,
|
|
UpdatedAt: now,
|
|
}
|
|
if err := repo.Create(context.Background(), row); err != nil {
|
|
t.Fatalf("seed create helicopter: %v", err)
|
|
}
|
|
|
|
row.FotoAttachmentID = newAttachment.ID
|
|
row.FotoAttachment = oldAttachment
|
|
if err := repo.Update(context.Background(), row); err != nil {
|
|
t.Fatalf("update helicopter: %v", err)
|
|
}
|
|
|
|
loaded, err := repo.GetByID(context.Background(), row.ID)
|
|
if err != nil {
|
|
t.Fatalf("get by id after update: %v", err)
|
|
}
|
|
if loaded == nil {
|
|
t.Fatalf("expected updated row")
|
|
}
|
|
if string(loaded.FotoAttachmentID) != string(newAttachment.ID) {
|
|
t.Fatalf("expected foto_attachment_id replaced")
|
|
}
|
|
}
|
|
|
|
func TestHelicopterRepositoryDelete(t *testing.T) {
|
|
db := openHelicopterTestDB(t)
|
|
repo := NewHelicopterRepository(db)
|
|
row := &helicopter.Helicopter{Designation: "DeleteMe", Identifier: "PK-DEL", Type: "Twin"}
|
|
if err := repo.Create(context.Background(), row); err != nil {
|
|
t.Fatalf("seed create: %v", err)
|
|
}
|
|
|
|
if err := repo.Delete(context.Background(), row.ID); err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
|
|
got, err := repo.GetByID(context.Background(), row.ID)
|
|
if err != nil {
|
|
t.Fatalf("get by id after delete: %v", err)
|
|
}
|
|
if got != nil {
|
|
t.Fatalf("expected row deleted")
|
|
}
|
|
}
|
|
|
|
func TestHelicopterRepositoryGetByID(t *testing.T) {
|
|
t.Run("found", func(t *testing.T) {
|
|
db := openHelicopterTestDB(t)
|
|
repo := NewHelicopterRepository(db)
|
|
row := &helicopter.Helicopter{Designation: "Found", Identifier: "PK-FND", Type: "Twin"}
|
|
if err := repo.Create(context.Background(), row); err != nil {
|
|
t.Fatalf("seed create: %v", err)
|
|
}
|
|
|
|
got, err := repo.GetByID(context.Background(), row.ID)
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
if got == nil || got.Identifier != "PK-FND" {
|
|
t.Fatalf("expected row found")
|
|
}
|
|
})
|
|
|
|
t.Run("not found", func(t *testing.T) {
|
|
db := openHelicopterTestDB(t)
|
|
repo := NewHelicopterRepository(db)
|
|
got, err := repo.GetByID(context.Background(), uuidv7.MustBytes())
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
if got != nil {
|
|
t.Fatalf("expected nil for not found")
|
|
}
|
|
})
|
|
|
|
t.Run("db error", func(t *testing.T) {
|
|
db := openHelicopterTestDB(t)
|
|
repo := NewHelicopterRepository(db)
|
|
sqlDB, _ := db.DB()
|
|
_ = sqlDB.Close()
|
|
|
|
if _, err := repo.GetByID(context.Background(), uuidv7.MustBytes()); err == nil {
|
|
t.Fatalf("expected error on closed DB")
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestHelicopterRepositoryList(t *testing.T) {
|
|
t.Run("success without limit", func(t *testing.T) {
|
|
db := openHelicopterTestDB(t)
|
|
repo := NewHelicopterRepository(db)
|
|
_ = repo.Create(context.Background(), &helicopter.Helicopter{Designation: "H145", Identifier: "PK-A", Type: "Twin"})
|
|
_ = repo.Create(context.Background(), &helicopter.Helicopter{Designation: "H125", Identifier: "PK-B", Type: "Single"})
|
|
|
|
rows, total, err := repo.List(context.Background(), "", nil, "", 0, 0, nil)
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
if total != 2 || len(rows) != 2 {
|
|
t.Fatalf("expected 2 rows, total=%d len=%d", total, len(rows))
|
|
}
|
|
})
|
|
|
|
t.Run("success with filter sort and limit", func(t *testing.T) {
|
|
db := openHelicopterTestDB(t)
|
|
repo := NewHelicopterRepository(db)
|
|
_ = repo.Create(context.Background(), &helicopter.Helicopter{Designation: "Main", Identifier: "PK-MAIN", Type: "Twin"})
|
|
_ = repo.Create(context.Background(), &helicopter.Helicopter{Designation: "Backup", Identifier: "PK-BACK", Type: "Single"})
|
|
|
|
rows, total, err := repo.List(context.Background(), "MAIN", nil, "identifier DESC", 1, 0, nil)
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
if total != 1 || len(rows) != 1 || rows[0].Identifier != "PK-MAIN" {
|
|
t.Fatalf("unexpected list result")
|
|
}
|
|
})
|
|
|
|
t.Run("default order active sortkey first and inactive last", func(t *testing.T) {
|
|
db := openHelicopterTestDB(t)
|
|
repo := NewHelicopterRepository(db)
|
|
_ = repo.Create(context.Background(), &helicopter.Helicopter{Designation: "Gamma", Identifier: "PK-G", Type: "Twin", IsActive: true})
|
|
_ = repo.Create(context.Background(), &helicopter.Helicopter{Designation: "Beta", Identifier: "PK-B0", Type: "Twin", SortKey: intPtr(0), IsActive: true})
|
|
_ = repo.Create(context.Background(), &helicopter.Helicopter{Designation: "Charlie", Identifier: "PK-C", Type: "Twin", SortKey: intPtr(2), IsActive: true})
|
|
_ = repo.Create(context.Background(), &helicopter.Helicopter{Designation: "Alpha", Identifier: "PK-A1", Type: "Twin", IsActive: true})
|
|
_ = repo.Create(context.Background(), &helicopter.Helicopter{Designation: "Alpha", Identifier: "PK-A2", Type: "Twin", SortKey: intPtr(1), IsActive: true})
|
|
_ = repo.Create(context.Background(), &helicopter.Helicopter{Designation: "Zulu", Identifier: "PK-Z", Type: "Twin", IsActive: false})
|
|
_ = repo.Create(context.Background(), &helicopter.Helicopter{Designation: "Bravo", Identifier: "PK-B", Type: "Twin", IsActive: false, SortKey: intPtr(9)})
|
|
|
|
rows, total, err := repo.List(context.Background(), "", nil, "", 0, 0, nil)
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
if total != 7 || len(rows) != 7 {
|
|
t.Fatalf("unexpected total/len total=%d len=%d", total, len(rows))
|
|
}
|
|
|
|
gotOrder := []string{
|
|
rows[0].Designation + "|" + rows[0].Identifier,
|
|
rows[1].Designation + "|" + rows[1].Identifier,
|
|
rows[2].Designation + "|" + rows[2].Identifier,
|
|
rows[3].Designation + "|" + rows[3].Identifier,
|
|
rows[4].Designation + "|" + rows[4].Identifier,
|
|
rows[5].Designation + "|" + rows[5].Identifier,
|
|
rows[6].Designation + "|" + rows[6].Identifier,
|
|
}
|
|
wantOrder := []string{
|
|
"Beta|PK-B0",
|
|
"Alpha|PK-A2",
|
|
"Charlie|PK-C",
|
|
"Alpha|PK-A1",
|
|
"Gamma|PK-G",
|
|
"Bravo|PK-B",
|
|
"Zulu|PK-Z",
|
|
}
|
|
for i := range wantOrder {
|
|
if gotOrder[i] != wantOrder[i] {
|
|
t.Fatalf("unexpected default order: got=%v want=%v", gotOrder, wantOrder)
|
|
}
|
|
}
|
|
})
|
|
|
|
t.Run("status filter", func(t *testing.T) {
|
|
db := openHelicopterTestDB(t)
|
|
repo := NewHelicopterRepository(db)
|
|
|
|
// Minimal schema for the booked/available EXISTS subquery.
|
|
if err := db.Exec(`CREATE TABLE reserve_acs (id BLOB PRIMARY KEY, helicopter_id BLOB, inspection_id BLOB, deleted_at DATETIME)`).Error; err != nil {
|
|
t.Fatalf("create reserve_acs: %v", err)
|
|
}
|
|
if err := db.Exec(`CREATE TABLE takeover_acs (id BLOB PRIMARY KEY, reserve_ac_id BLOB, deleted_at DATETIME)`).Error; err != nil {
|
|
t.Fatalf("create takeover_acs: %v", err)
|
|
}
|
|
if err := db.Exec(`CREATE TABLE flights (id BLOB PRIMARY KEY, reserve_ac_id BLOB, takeover_ac_id BLOB, deleted_at DATETIME)`).Error; err != nil {
|
|
t.Fatalf("create flights: %v", err)
|
|
}
|
|
if err := db.AutoMigrate(&afterflightinspection.AfterFlightInspection{}); err != nil {
|
|
t.Fatalf("auto migrate after flight inspection: %v", err)
|
|
}
|
|
|
|
aog := &helicopter.Helicopter{Designation: "AOG", Identifier: "PK-AOG", Type: "Twin", AirOnGround: true}
|
|
booked := &helicopter.Helicopter{Designation: "Booked", Identifier: "PK-BKD", Type: "Twin"}
|
|
closed := &helicopter.Helicopter{Designation: "Closed", Identifier: "PK-CLS", Type: "Twin"}
|
|
available := &helicopter.Helicopter{Designation: "Avail", Identifier: "PK-AVL", Type: "Twin"}
|
|
for _, h := range []*helicopter.Helicopter{aog, booked, closed, available} {
|
|
if err := repo.Create(context.Background(), h); err != nil {
|
|
t.Fatalf("create helicopter: %v", err)
|
|
}
|
|
}
|
|
|
|
// Give "booked" an active (non-deleted) flight assignment.
|
|
raID := uuidv7.MustBytes()
|
|
takeoverID := uuidv7.MustBytes()
|
|
if err := db.Table("reserve_acs").Create(map[string]any{"id": raID, "helicopter_id": booked.ID}).Error; err != nil {
|
|
t.Fatalf("insert reserve_ac: %v", err)
|
|
}
|
|
if err := db.Table("takeover_acs").Create(map[string]any{"id": takeoverID, "reserve_ac_id": raID}).Error; err != nil {
|
|
t.Fatalf("insert takeover_ac: %v", err)
|
|
}
|
|
if err := db.Table("flights").Create(map[string]any{"id": uuidv7.MustBytes(), "takeover_ac_id": takeoverID}).Error; err != nil {
|
|
t.Fatalf("insert flight: %v", err)
|
|
}
|
|
closedRAID := uuidv7.MustBytes()
|
|
closedTakeoverID := uuidv7.MustBytes()
|
|
closedInspectionID := uuidv7.MustBytes()
|
|
if err := db.Table("reserve_acs").Create(map[string]any{"id": closedRAID, "helicopter_id": closed.ID, "inspection_id": closedInspectionID}).Error; err != nil {
|
|
t.Fatalf("insert closed reserve_ac: %v", err)
|
|
}
|
|
if err := db.Table("takeover_acs").Create(map[string]any{"id": closedTakeoverID, "reserve_ac_id": closedRAID}).Error; err != nil {
|
|
t.Fatalf("insert closed takeover_ac: %v", err)
|
|
}
|
|
if err := db.Table("flights").Create(map[string]any{"id": uuidv7.MustBytes(), "takeover_ac_id": closedTakeoverID}).Error; err != nil {
|
|
t.Fatalf("insert closed flight: %v", err)
|
|
}
|
|
if err := db.Create(&afterflightinspection.AfterFlightInspection{FlightInspectionID: closedInspectionID, CreatedAt: time.Now().UTC(), UpdatedAt: time.Now().UTC()}).Error; err != nil {
|
|
t.Fatalf("insert after flight inspection: %v", err)
|
|
}
|
|
|
|
cases := []struct {
|
|
name string
|
|
statuses []string
|
|
groundedIDs [][]byte
|
|
want []string
|
|
}{
|
|
{name: "aog only", statuses: []string{"aog"}, want: []string{"PK-AOG"}},
|
|
{name: "booked only", statuses: []string{"booked"}, want: []string{"PK-BKD"}},
|
|
{name: "available only", statuses: []string{"available"}, want: []string{"PK-AVL", "PK-CLS"}},
|
|
{name: "available and booked", statuses: []string{"available", "booked"}, want: []string{"PK-AVL", "PK-BKD", "PK-CLS"}},
|
|
{name: "mcf matches nothing", statuses: []string{"mcf"}, want: []string{}},
|
|
{name: "no filter returns all", statuses: nil, want: []string{"PK-AOG", "PK-AVL", "PK-BKD", "PK-CLS"}},
|
|
{name: "complaint-grounded excluded from available", statuses: []string{"available"}, groundedIDs: [][]byte{available.ID}, want: []string{"PK-CLS"}},
|
|
{name: "complaint-grounded appears as aog", statuses: []string{"aog"}, groundedIDs: [][]byte{available.ID}, want: []string{"PK-AOG", "PK-AVL"}},
|
|
}
|
|
|
|
for _, tc := range cases {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
rows, total, err := repo.List(context.Background(), "", tc.statuses, "identifier ASC", 0, 0, tc.groundedIDs)
|
|
if err != nil {
|
|
t.Fatalf("list: %v", err)
|
|
}
|
|
if int(total) != len(tc.want) || len(rows) != len(tc.want) {
|
|
t.Fatalf("count mismatch: total=%d len=%d want=%d", total, len(rows), len(tc.want))
|
|
}
|
|
got := make([]string, len(rows))
|
|
for i := range rows {
|
|
got[i] = rows[i].Identifier
|
|
}
|
|
for i := range tc.want {
|
|
if got[i] != tc.want[i] {
|
|
t.Fatalf("unexpected rows: got=%v want=%v", got, tc.want)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
})
|
|
|
|
t.Run("count error", func(t *testing.T) {
|
|
db := openHelicopterTestDB(t)
|
|
repo := NewHelicopterRepository(db)
|
|
if err := db.Migrator().DropTable(&helicopter.Helicopter{}); err != nil {
|
|
t.Fatalf("drop table: %v", err)
|
|
}
|
|
|
|
if _, _, err := repo.List(context.Background(), "", nil, "", 10, 0, nil); err == nil {
|
|
t.Fatalf("expected count error")
|
|
}
|
|
})
|
|
|
|
t.Run("find error", func(t *testing.T) {
|
|
db := openHelicopterTestDB(t)
|
|
repo := NewHelicopterRepository(db)
|
|
_ = repo.Create(context.Background(), &helicopter.Helicopter{Designation: "Main", Identifier: "PK-ERR", Type: "Twin"})
|
|
|
|
if _, _, err := repo.List(context.Background(), "", nil, "designation ASC, )", 10, 0, nil); err == nil {
|
|
t.Fatalf("expected find error from invalid sort")
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestHelicopterRepositoryNextReportNumber(t *testing.T) {
|
|
t.Run("success", func(t *testing.T) {
|
|
db := openHelicopterTestDB(t)
|
|
repo := NewHelicopterRepository(db)
|
|
row := &helicopter.Helicopter{
|
|
Designation: "H145",
|
|
Identifier: " PK-ABC ",
|
|
Type: "Twin",
|
|
ReportSequence: 7,
|
|
}
|
|
if err := repo.Create(context.Background(), row); err != nil {
|
|
t.Fatalf("seed create: %v", err)
|
|
}
|
|
|
|
reportNumber, sequence, err := repo.NextReportNumber(context.Background(), row.ID)
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
if reportNumber != "PK-ABC-0008" || sequence != 8 {
|
|
t.Fatalf("unexpected report number/sequence: %q %d", reportNumber, sequence)
|
|
}
|
|
loaded, err := repo.GetByID(context.Background(), row.ID)
|
|
if err != nil || loaded == nil || loaded.ReportSequence != 8 {
|
|
t.Fatalf("expected report_sequence updated")
|
|
}
|
|
})
|
|
|
|
t.Run("identifier empty", func(t *testing.T) {
|
|
db := openHelicopterTestDB(t)
|
|
repo := NewHelicopterRepository(db)
|
|
row := &helicopter.Helicopter{
|
|
Designation: "H145",
|
|
Identifier: " ",
|
|
Type: "Twin",
|
|
}
|
|
if err := repo.Create(context.Background(), row); err != nil {
|
|
t.Fatalf("seed create: %v", err)
|
|
}
|
|
|
|
if _, _, err := repo.NextReportNumber(context.Background(), row.ID); err == nil {
|
|
t.Fatalf("expected identifier empty error")
|
|
}
|
|
})
|
|
|
|
t.Run("not found", func(t *testing.T) {
|
|
db := openHelicopterTestDB(t)
|
|
repo := NewHelicopterRepository(db)
|
|
if _, _, err := repo.NextReportNumber(context.Background(), uuidv7.MustBytes()); err == nil {
|
|
t.Fatalf("expected not found error")
|
|
}
|
|
})
|
|
|
|
t.Run("db error", func(t *testing.T) {
|
|
db := openHelicopterTestDB(t)
|
|
repo := NewHelicopterRepository(db)
|
|
sqlDB, _ := db.DB()
|
|
_ = sqlDB.Close()
|
|
|
|
if _, _, err := repo.NextReportNumber(context.Background(), uuidv7.MustBytes()); err == nil {
|
|
t.Fatalf("expected error on closed DB")
|
|
}
|
|
})
|
|
}
|