package runner import ( "context" "encoding/base64" "errors" "os" "path/filepath" "testing" "time" "github.com/easyai/easyai-ai-gateway/apps/api/internal/clients" "github.com/easyai/easyai-ai-gateway/apps/api/internal/config" "github.com/easyai/easyai-ai-gateway/apps/api/internal/store" ) func TestHydrateProviderRequestAssetsConvertsStrictBase64Field(t *testing.T) { storageDir := t.TempDir() fileName := "gateway-request-asset-test.png" if err := os.WriteFile(filepath.Join(storageDir, fileName), []byte("image bytes"), 0o644); err != nil { t.Fatalf("write request asset: %v", err) } service := &Service{cfg: config.Config{LocalUploadedStorageDir: storageDir}} body := map[string]any{ "model": "demo", "b64_json": map[string]any{ "assetRef": map[string]any{ "sha256": "sha-test", "contentType": "image/png", "url": "/static/uploaded/" + fileName, "storageProvider": "local_static", }, "url": "/static/uploaded/" + fileName, }, } hydrated, err := service.hydrateProviderRequestAssets(context.Background(), body) if err != nil { t.Fatalf("hydrate request assets: %v", err) } if got, want := stringFromAny(hydrated["b64_json"]), base64.StdEncoding.EncodeToString([]byte("image bytes")); got != want { t.Fatalf("unexpected hydrated base64: got %q want %q", got, want) } } func TestHydrateProviderRequestAssetsReturnsExpiredError(t *testing.T) { expiredAt := time.Now().Add(-time.Minute).UTC().Format(time.RFC3339) service := &Service{} body := map[string]any{ "image_url": map[string]any{ "assetRef": map[string]any{ "sha256": "sha-expired", "contentType": "image/png", "url": "/static/uploaded/gateway-request-asset-expired.png", "storageProvider": "local_static", "expiresAt": expiredAt, }, "url": "/static/uploaded/gateway-request-asset-expired.png", }, } _, err := service.hydrateProviderRequestAssets(context.Background(), body) if err == nil { t.Fatal("expected expired request asset error") } var clientErr *clients.ClientError if !errors.As(err, &clientErr) || clientErr.Code != "request_asset_expired" { t.Fatalf("expected request_asset_expired, got %T %v", err, err) } } func TestStringFromAnyReadsRequestAssetWrapperURL(t *testing.T) { wrapper := map[string]any{ "assetRef": map[string]any{"url": "https://cdn.example/request.png"}, } if got := stringFromAny(wrapper); got != "https://cdn.example/request.png" { t.Fatalf("expected wrapper URL, got %q", got) } } func TestSlimTaskRequestSnapshotKeepsMessageRefs(t *testing.T) { service := &Service{} task := store.GatewayTask{Request: map[string]any{ "conversationId": "conv-1", "messageRefs": []any{map[string]any{"messageId": "msg-1", "position": 0}}, "newMessageCount": 1, }} body := map[string]any{ "model": "demo", "messages": []any{map[string]any{"role": "user", "content": "hello"}}, } snapshot := service.slimTaskRequestSnapshot(task, body) if snapshot["messages"] != nil { t.Fatalf("snapshot should not persist restored messages: %+v", snapshot) } if snapshot["messageRefs"] == nil || snapshot["newMessageCount"] != 1 { t.Fatalf("snapshot should keep message refs and new count: %+v", snapshot) } }