Files
fm_be/internal/service/icao_service_test.go
2026-07-16 22:16:45 +07:00

232 lines
6.6 KiB
Go

package service
import (
"context"
"errors"
"testing"
"wucher/internal/domain/icao"
)
type icaoRepoMock struct {
createCalled bool
updateCalled bool
deleteCalled bool
getByIDCalled bool
listCalled bool
lastCreate *icao.ICAO
lastUpdate *icao.ICAO
lastDeleteID []byte
lastDeleteBy []byte
lastGetByID []byte
lastListFilter string
lastListSort string
lastListLimit int
lastListOffset int
getByIDResult *icao.ICAO
listResult []icao.ICAO
listTotal int64
createErr error
updateErr error
deleteErr error
getByIDErr error
listErr error
}
func (m *icaoRepoMock) Create(_ context.Context, o *icao.ICAO) error {
m.createCalled = true
m.lastCreate = o
return m.createErr
}
func (m *icaoRepoMock) Update(_ context.Context, o *icao.ICAO) error {
m.updateCalled = true
m.lastUpdate = o
return m.updateErr
}
func (m *icaoRepoMock) Delete(_ context.Context, id []byte, deletedBy []byte) error {
m.deleteCalled = true
m.lastDeleteID = id
m.lastDeleteBy = deletedBy
return m.deleteErr
}
func (m *icaoRepoMock) GetByID(_ context.Context, id []byte) (*icao.ICAO, error) {
m.getByIDCalled = true
m.lastGetByID = id
return m.getByIDResult, m.getByIDErr
}
func (m *icaoRepoMock) List(_ context.Context, filter, sort string, limit, offset int) ([]icao.ICAO, int64, error) {
m.listCalled = true
m.lastListFilter = filter
m.lastListSort = sort
m.lastListLimit = limit
m.lastListOffset = offset
return m.listResult, m.listTotal, m.listErr
}
func TestNewICAOService(t *testing.T) {
repo := &icaoRepoMock{}
svc := NewICAOService(repo)
if svc == nil || svc.repo == nil {
t.Fatalf("expected service and repo initialized")
}
}
func TestICAOServiceCreate(t *testing.T) {
repo := &icaoRepoMock{}
svc := NewICAOService(repo)
row := &icao.ICAO{ICAOCode: "EDDB"}
if err := svc.Create(context.Background(), row); err != nil {
t.Fatalf("unexpected error: %v", err)
}
if !repo.createCalled || repo.lastCreate != row {
t.Fatalf("expected Create forwarded to repo")
}
repo.createErr = errors.New("create failed")
if err := svc.Create(context.Background(), row); err == nil {
t.Fatalf("expected error from repo")
}
}
func TestICAOServiceUpdate(t *testing.T) {
repo := &icaoRepoMock{}
svc := NewICAOService(repo)
row := &icao.ICAO{ICAOCode: "EDDF"}
if err := svc.Update(context.Background(), row); err != nil {
t.Fatalf("unexpected error: %v", err)
}
if !repo.updateCalled || repo.lastUpdate != row {
t.Fatalf("expected Update forwarded to repo")
}
repo.updateErr = errors.New("update failed")
if err := svc.Update(context.Background(), row); err == nil {
t.Fatalf("expected error from repo")
}
}
func TestICAOServiceDelete(t *testing.T) {
repo := &icaoRepoMock{}
svc := NewICAOService(repo)
id := []byte("id")
deletedBy := []byte("by")
if err := svc.Delete(context.Background(), id, deletedBy); err != nil {
t.Fatalf("unexpected error: %v", err)
}
if !repo.deleteCalled {
t.Fatalf("expected Delete forwarded to repo")
}
if string(repo.lastDeleteID) != string(id) || string(repo.lastDeleteBy) != string(deletedBy) {
t.Fatalf("expected delete params forwarded")
}
repo.deleteErr = errors.New("delete failed")
if err := svc.Delete(context.Background(), id, deletedBy); err == nil {
t.Fatalf("expected error from repo")
}
}
func TestICAOServiceGetByID(t *testing.T) {
expected := &icao.ICAO{ICAOCode: "A"}
repo := &icaoRepoMock{getByIDResult: expected}
svc := NewICAOService(repo)
id := []byte("id")
got, err := svc.GetByID(context.Background(), id)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if got != expected {
t.Fatalf("unexpected result")
}
if !repo.getByIDCalled || string(repo.lastGetByID) != string(id) {
t.Fatalf("expected GetByID forwarded")
}
repo.getByIDErr = errors.New("get failed")
if _, err := svc.GetByID(context.Background(), id); err == nil {
t.Fatalf("expected error from repo")
}
}
func TestICAOServiceList(t *testing.T) {
repo := &icaoRepoMock{
listResult: []icao.ICAO{{ICAOCode: "A"}},
listTotal: 1,
}
svc := NewICAOService(repo)
rows, total, err := svc.List(context.Background(), "find", "icao_code", 10, 20)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if len(rows) != 1 || total != 1 {
t.Fatalf("unexpected list result")
}
if !repo.listCalled {
t.Fatalf("expected List forwarded to repo")
}
if repo.lastListFilter != "find" || repo.lastListSort != "icao_code ASC" || repo.lastListLimit != 10 || repo.lastListOffset != 20 {
t.Fatalf("unexpected list args forwarded")
}
rows, total, err = svc.List(context.Background(), "find", "sortkey", 10, 20)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if len(rows) != 1 || total != 1 {
t.Fatalf("unexpected list result")
}
if repo.lastListSort != "is_active DESC, CASE WHEN is_active = 1 AND sortkey IS NOT NULL AND sortkey >= 0 THEN 0 ELSE 1 END ASC, CASE WHEN is_active = 1 AND sortkey IS NOT NULL AND sortkey >= 0 THEN sortkey END ASC, icao_code ASC" {
t.Fatalf("unexpected sortkey args forwarded: %q", repo.lastListSort)
}
repo.listErr = errors.New("list failed")
if _, _, err := svc.List(context.Background(), "", "unknown", 1, 0); err == nil {
t.Fatalf("expected error from repo")
}
}
func TestNormalizeICAOSort(t *testing.T) {
cases := map[string]string{
"icao_code": "icao_code ASC",
"-icao_code": "icao_code DESC",
"sortkey": "is_active DESC, CASE WHEN is_active = 1 AND sortkey IS NOT NULL AND sortkey >= 0 THEN 0 ELSE 1 END ASC, CASE WHEN is_active = 1 AND sortkey IS NOT NULL AND sortkey >= 0 THEN sortkey END ASC, icao_code ASC",
"-sortkey": "is_active DESC, CASE WHEN is_active = 1 AND sortkey IS NOT NULL AND sortkey >= 0 THEN 0 ELSE 1 END ASC, CASE WHEN is_active = 1 AND sortkey IS NOT NULL AND sortkey >= 0 THEN sortkey END DESC, icao_code ASC",
"address": "address ASC",
"-address": "address DESC",
"landline_number": "landline_number ASC",
"-landline_number": "landline_number DESC",
"mobile_number": "mobile_number ASC",
"-mobile_number": "mobile_number DESC",
"email": "email ASC",
"-email": "email DESC",
"note": "note ASC",
"-note": "note DESC",
"is_active": "is_active ASC",
"-is_active": "is_active DESC",
"created_at": "created_at ASC",
"-created_at": "created_at DESC",
"updated_at": "updated_at ASC",
"-updated_at": "updated_at DESC",
"unknown": "",
"": "",
}
for in, want := range cases {
if got := normalizeICAOSort(in); got != want {
t.Fatalf("normalizeICAOSort(%q) = %q, want %q", in, got, want)
}
}
}