Files
creator-hub/internal/controlplane/api/owned_cover_cache_test.go
T

98 lines
3.8 KiB
Go

package api
import (
"bytes"
"encoding/base64"
"encoding/json"
"fmt"
"io"
"net/http"
"net/http/httptest"
"os"
"path/filepath"
"strings"
"testing"
"time"
"git.ipao.vip/rogee/creator-hub/internal/account"
"git.ipao.vip/rogee/creator-hub/internal/creator"
hub "git.ipao.vip/rogee/creator-hub/internal/environment"
"github.com/gofiber/fiber/v3"
)
func TestOwnedCoversCacheFilesAndReportIndividualFailures(t *testing.T) {
databaseURL := os.Getenv("CREATORHUB_POSTGRES_TEST_URL")
if databaseURL == "" {
t.Skip("set CREATORHUB_POSTGRES_TEST_URL for isolated PostgreSQL coverage")
}
store, accounts, ctx := openCreatorIntegrationStoreForAPITest(t, databaseURL)
owner := account.Account{
ID: "owned-cover-account", Name: "封面账号", Platform: creator.PlatformDouyin, PlatformAccountKey: "12345678901",
CredentialReference: account.CredentialReference{ID: "cover-test-credential", Provider: "os_keyring"},
CredentialKey: "creatorhub/owned-cover-account/cookies",
}
if err := accounts.CreateAccount(ctx, owner, &testCredentialBridge{values: make(map[string]string)}); err != nil {
t.Fatal(err)
}
works := make(map[string]creator.Work)
for _, key := range []string{"good", "broken"} {
work, _, err := store.UpsertWork(ctx, creator.WorkInput{SourceType: creator.SourceOwned, SourceID: owner.ID, Platform: creator.PlatformDouyin, WorkKey: "owned-cover-" + key, CoverURL: "https://p3-pc-sign.douyinpic.com/" + key + ".png"}, time.Now().UTC())
if err != nil {
t.Fatal(err)
}
works[key] = work
}
requests := 0
gateway := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.URL.Path != "/v1/browsers/owned-cover-alias/douyin/image" {
http.NotFound(w, r)
return
}
requests++
var payload struct {
URL string `json:"url"`
}
if err := json.NewDecoder(r.Body).Decode(&payload); err != nil {
t.Error(err)
w.WriteHeader(400)
return
}
if strings.Contains(payload.URL, "broken") {
w.WriteHeader(502)
_, _ = io.WriteString(w, "image upstream unavailable")
return
}
_ = json.NewEncoder(w).Encode(map[string]any{"status": 200, "content_type": "image/png", "body_base64": base64.StdEncoding.EncodeToString([]byte("owned-cover-bytes"))})
}))
t.Cleanup(gateway.Close)
browser := creatorGatewayBrowser{gateway: hub.Gateway{Endpoint: gateway.URL, Token: "test-token"}, environment: hub.EnvironmentContext{Env: hub.Env{Alias: "owned-cover-alias"}, RuntimeID: "runtime-cover", RuntimeNetworkID: "network-cover", BindingVersion: 1}}
if err := cacheWorkCovers(ctx, store, browser, creator.SourceOwned, owner.ID); err == nil || !strings.Contains(err.Error(), works["broken"].ID) {
t.Fatalf("individual failure was hidden: %v", err)
}
if requests != 2 {
t.Fatalf("failure stopped other covers from downloading: %d", requests)
}
path, err := store.GetWorkCover(ctx, works["good"].ID)
if err != nil {
t.Fatal(err)
}
if filepath.Base(filepath.Dir(path)) != owner.PlatformAccountKey || filepath.Base(path) != "owned-cover-good.png" {
t.Fatalf("wrong UID/work-ID layout: %s", path)
}
missing, err := store.ListWorksMissingCover(ctx, creator.SourceOwned, owner.ID)
if err != nil || len(missing) != 1 || missing[0].ID != works["broken"].ID {
t.Fatalf("cache retry targets: %v %v", missing, err)
}
app := fiber.New()
RegisterCreator(app, store, accounts, nil)
response, err := app.Test(httptest.NewRequest(http.MethodGet, fmt.Sprintf("/api/creator/works/%s/cover", works["good"].ID), nil))
if err != nil {
t.Fatal(err)
}
defer response.Body.Close()
body, err := io.ReadAll(response.Body)
if err != nil || response.StatusCode != 200 || !strings.HasPrefix(response.Header.Get("Content-Type"), "image/png") || !bytes.Equal(body, []byte("owned-cover-bytes")) {
t.Fatalf("static cover response: %d %s %q %v", response.StatusCode, response.Header.Get("Content-Type"), body, err)
}
}