206 lines
5.3 KiB
Go
206 lines
5.3 KiB
Go
|
|
// SPDX-License-Identifier: EUPL-1.2
|
||
|
|
|
||
|
|
package api_test
|
||
|
|
|
||
|
|
import (
|
||
|
|
"encoding/json"
|
||
|
|
"testing"
|
||
|
|
|
||
|
|
api "forge.lthn.ai/core/go-api"
|
||
|
|
)
|
||
|
|
|
||
|
|
// ── OK ──────────────────────────────────────────────────────────────────
|
||
|
|
|
||
|
|
func TestOK_Good(t *testing.T) {
|
||
|
|
r := api.OK("hello")
|
||
|
|
|
||
|
|
if !r.Success {
|
||
|
|
t.Fatal("expected Success=true")
|
||
|
|
}
|
||
|
|
if r.Data != "hello" {
|
||
|
|
t.Fatalf("expected Data=%q, got %q", "hello", r.Data)
|
||
|
|
}
|
||
|
|
if r.Error != nil {
|
||
|
|
t.Fatal("expected Error to be nil")
|
||
|
|
}
|
||
|
|
if r.Meta != nil {
|
||
|
|
t.Fatal("expected Meta to be nil")
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestOK_Good_StructData(t *testing.T) {
|
||
|
|
type user struct {
|
||
|
|
Name string `json:"name"`
|
||
|
|
}
|
||
|
|
r := api.OK(user{Name: "Ada"})
|
||
|
|
|
||
|
|
if !r.Success {
|
||
|
|
t.Fatal("expected Success=true")
|
||
|
|
}
|
||
|
|
if r.Data.Name != "Ada" {
|
||
|
|
t.Fatalf("expected Data.Name=%q, got %q", "Ada", r.Data.Name)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestOK_Good_JSONOmitsErrorAndMeta(t *testing.T) {
|
||
|
|
r := api.OK("data")
|
||
|
|
b, err := json.Marshal(r)
|
||
|
|
if err != nil {
|
||
|
|
t.Fatalf("marshal error: %v", err)
|
||
|
|
}
|
||
|
|
|
||
|
|
var raw map[string]any
|
||
|
|
if err := json.Unmarshal(b, &raw); err != nil {
|
||
|
|
t.Fatalf("unmarshal error: %v", err)
|
||
|
|
}
|
||
|
|
|
||
|
|
if _, ok := raw["error"]; ok {
|
||
|
|
t.Fatal("expected 'error' field to be omitted from JSON")
|
||
|
|
}
|
||
|
|
if _, ok := raw["meta"]; ok {
|
||
|
|
t.Fatal("expected 'meta' field to be omitted from JSON")
|
||
|
|
}
|
||
|
|
if _, ok := raw["success"]; !ok {
|
||
|
|
t.Fatal("expected 'success' field to be present")
|
||
|
|
}
|
||
|
|
if _, ok := raw["data"]; !ok {
|
||
|
|
t.Fatal("expected 'data' field to be present")
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// ── Fail ────────────────────────────────────────────────────────────────
|
||
|
|
|
||
|
|
func TestFail_Good(t *testing.T) {
|
||
|
|
r := api.Fail("NOT_FOUND", "resource not found")
|
||
|
|
|
||
|
|
if r.Success {
|
||
|
|
t.Fatal("expected Success=false")
|
||
|
|
}
|
||
|
|
if r.Error == nil {
|
||
|
|
t.Fatal("expected Error to be non-nil")
|
||
|
|
}
|
||
|
|
if r.Error.Code != "NOT_FOUND" {
|
||
|
|
t.Fatalf("expected Code=%q, got %q", "NOT_FOUND", r.Error.Code)
|
||
|
|
}
|
||
|
|
if r.Error.Message != "resource not found" {
|
||
|
|
t.Fatalf("expected Message=%q, got %q", "resource not found", r.Error.Message)
|
||
|
|
}
|
||
|
|
if r.Error.Details != nil {
|
||
|
|
t.Fatal("expected Details to be nil")
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestFail_Good_JSONOmitsData(t *testing.T) {
|
||
|
|
r := api.Fail("ERR", "something went wrong")
|
||
|
|
b, err := json.Marshal(r)
|
||
|
|
if err != nil {
|
||
|
|
t.Fatalf("marshal error: %v", err)
|
||
|
|
}
|
||
|
|
|
||
|
|
var raw map[string]any
|
||
|
|
if err := json.Unmarshal(b, &raw); err != nil {
|
||
|
|
t.Fatalf("unmarshal error: %v", err)
|
||
|
|
}
|
||
|
|
|
||
|
|
if _, ok := raw["data"]; ok {
|
||
|
|
t.Fatal("expected 'data' field to be omitted from JSON")
|
||
|
|
}
|
||
|
|
if _, ok := raw["error"]; !ok {
|
||
|
|
t.Fatal("expected 'error' field to be present")
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// ── FailWithDetails ─────────────────────────────────────────────────────
|
||
|
|
|
||
|
|
func TestFailWithDetails_Good(t *testing.T) {
|
||
|
|
details := map[string]string{"field": "email", "reason": "invalid format"}
|
||
|
|
r := api.FailWithDetails("VALIDATION", "validation failed", details)
|
||
|
|
|
||
|
|
if r.Success {
|
||
|
|
t.Fatal("expected Success=false")
|
||
|
|
}
|
||
|
|
if r.Error == nil {
|
||
|
|
t.Fatal("expected Error to be non-nil")
|
||
|
|
}
|
||
|
|
if r.Error.Code != "VALIDATION" {
|
||
|
|
t.Fatalf("expected Code=%q, got %q", "VALIDATION", r.Error.Code)
|
||
|
|
}
|
||
|
|
if r.Error.Details == nil {
|
||
|
|
t.Fatal("expected Details to be non-nil")
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestFailWithDetails_Good_JSONIncludesDetails(t *testing.T) {
|
||
|
|
r := api.FailWithDetails("ERR", "bad", "extra info")
|
||
|
|
b, err := json.Marshal(r)
|
||
|
|
if err != nil {
|
||
|
|
t.Fatalf("marshal error: %v", err)
|
||
|
|
}
|
||
|
|
|
||
|
|
var raw map[string]any
|
||
|
|
if err := json.Unmarshal(b, &raw); err != nil {
|
||
|
|
t.Fatalf("unmarshal error: %v", err)
|
||
|
|
}
|
||
|
|
|
||
|
|
errObj, ok := raw["error"].(map[string]any)
|
||
|
|
if !ok {
|
||
|
|
t.Fatal("expected 'error' to be an object")
|
||
|
|
}
|
||
|
|
if _, ok := errObj["details"]; !ok {
|
||
|
|
t.Fatal("expected 'details' field to be present in error")
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// ── Paginated ───────────────────────────────────────────────────────────
|
||
|
|
|
||
|
|
func TestPaginated_Good(t *testing.T) {
|
||
|
|
items := []string{"a", "b", "c"}
|
||
|
|
r := api.Paginated(items, 2, 25, 100)
|
||
|
|
|
||
|
|
if !r.Success {
|
||
|
|
t.Fatal("expected Success=true")
|
||
|
|
}
|
||
|
|
if len(r.Data) != 3 {
|
||
|
|
t.Fatalf("expected 3 items, got %d", len(r.Data))
|
||
|
|
}
|
||
|
|
if r.Meta == nil {
|
||
|
|
t.Fatal("expected Meta to be non-nil")
|
||
|
|
}
|
||
|
|
if r.Meta.Page != 2 {
|
||
|
|
t.Fatalf("expected Page=2, got %d", r.Meta.Page)
|
||
|
|
}
|
||
|
|
if r.Meta.PerPage != 25 {
|
||
|
|
t.Fatalf("expected PerPage=25, got %d", r.Meta.PerPage)
|
||
|
|
}
|
||
|
|
if r.Meta.Total != 100 {
|
||
|
|
t.Fatalf("expected Total=100, got %d", r.Meta.Total)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestPaginated_Good_JSONIncludesMeta(t *testing.T) {
|
||
|
|
r := api.Paginated([]int{1}, 1, 10, 50)
|
||
|
|
b, err := json.Marshal(r)
|
||
|
|
if err != nil {
|
||
|
|
t.Fatalf("marshal error: %v", err)
|
||
|
|
}
|
||
|
|
|
||
|
|
var raw map[string]any
|
||
|
|
if err := json.Unmarshal(b, &raw); err != nil {
|
||
|
|
t.Fatalf("unmarshal error: %v", err)
|
||
|
|
}
|
||
|
|
|
||
|
|
if _, ok := raw["meta"]; !ok {
|
||
|
|
t.Fatal("expected 'meta' field to be present")
|
||
|
|
}
|
||
|
|
meta := raw["meta"].(map[string]any)
|
||
|
|
if meta["page"].(float64) != 1 {
|
||
|
|
t.Fatalf("expected page=1, got %v", meta["page"])
|
||
|
|
}
|
||
|
|
if meta["per_page"].(float64) != 10 {
|
||
|
|
t.Fatalf("expected per_page=10, got %v", meta["per_page"])
|
||
|
|
}
|
||
|
|
if meta["total"].(float64) != 50 {
|
||
|
|
t.Fatalf("expected total=50, got %v", meta["total"])
|
||
|
|
}
|
||
|
|
}
|