- New Go backend binary (backend + runner) replacing old scraper/ - Rename SCRAPER_API_URL → BACKEND_API_URL in UI env and docker-compose - Rename scraperFetch → backendFetch across all 19 UI server files - Remove SCRAPER_PROXY env var and proxy transport from browser.Config - Add Meilisearch, Valkey, Caddy to docker-compose - Add docs/: api-endpoints.md, request-flow.mermaid.md, data-flow.mermaid.md
105 lines
2.7 KiB
Go
105 lines
2.7 KiB
Go
package domain_test
|
|
|
|
import (
|
|
"encoding/json"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/libnovel/backend/internal/domain"
|
|
)
|
|
|
|
func TestBookMeta_JSONRoundtrip(t *testing.T) {
|
|
orig := domain.BookMeta{
|
|
Slug: "a-great-novel",
|
|
Title: "A Great Novel",
|
|
Author: "Jane Doe",
|
|
Cover: "https://example.com/cover.jpg",
|
|
Status: "Ongoing",
|
|
Genres: []string{"Fantasy", "Action"},
|
|
Summary: "A thrilling tale.",
|
|
TotalChapters: 120,
|
|
SourceURL: "https://novelfire.net/book/a-great-novel",
|
|
Ranking: 3,
|
|
}
|
|
|
|
b, err := json.Marshal(orig)
|
|
if err != nil {
|
|
t.Fatalf("marshal: %v", err)
|
|
}
|
|
var got domain.BookMeta
|
|
if err := json.Unmarshal(b, &got); err != nil {
|
|
t.Fatalf("unmarshal: %v", err)
|
|
}
|
|
if got.Slug != orig.Slug {
|
|
t.Errorf("Slug: want %q, got %q", orig.Slug, got.Slug)
|
|
}
|
|
if got.TotalChapters != orig.TotalChapters {
|
|
t.Errorf("TotalChapters: want %d, got %d", orig.TotalChapters, got.TotalChapters)
|
|
}
|
|
if len(got.Genres) != len(orig.Genres) {
|
|
t.Errorf("Genres len: want %d, got %d", len(orig.Genres), len(got.Genres))
|
|
}
|
|
}
|
|
|
|
func TestChapterRef_JSONRoundtrip(t *testing.T) {
|
|
orig := domain.ChapterRef{Number: 42, Title: "The Battle", URL: "https://example.com/ch-42", Volume: 2}
|
|
b, _ := json.Marshal(orig)
|
|
var got domain.ChapterRef
|
|
json.Unmarshal(b, &got)
|
|
if got != orig {
|
|
t.Errorf("want %+v, got %+v", orig, got)
|
|
}
|
|
}
|
|
|
|
func TestRankingItem_JSONRoundtrip(t *testing.T) {
|
|
now := time.Now().Truncate(time.Second)
|
|
orig := domain.RankingItem{
|
|
Rank: 1,
|
|
Slug: "top-novel",
|
|
Title: "Top Novel",
|
|
SourceURL: "https://novelfire.net/book/top-novel",
|
|
Updated: now,
|
|
}
|
|
b, _ := json.Marshal(orig)
|
|
var got domain.RankingItem
|
|
json.Unmarshal(b, &got)
|
|
if got.Rank != orig.Rank || got.Slug != orig.Slug {
|
|
t.Errorf("want %+v, got %+v", orig, got)
|
|
}
|
|
}
|
|
|
|
func TestScrapeResult_JSONRoundtrip(t *testing.T) {
|
|
orig := domain.ScrapeResult{BooksFound: 10, ChaptersScraped: 200, ChaptersSkipped: 5, Errors: 1, ErrorMessage: "one error"}
|
|
b, _ := json.Marshal(orig)
|
|
var got domain.ScrapeResult
|
|
json.Unmarshal(b, &got)
|
|
if got != orig {
|
|
t.Errorf("want %+v, got %+v", orig, got)
|
|
}
|
|
}
|
|
|
|
func TestAudioResult_JSONRoundtrip(t *testing.T) {
|
|
orig := domain.AudioResult{ObjectKey: "audio/slug/1/af_bella.mp3"}
|
|
b, _ := json.Marshal(orig)
|
|
var got domain.AudioResult
|
|
json.Unmarshal(b, &got)
|
|
if got != orig {
|
|
t.Errorf("want %+v, got %+v", orig, got)
|
|
}
|
|
}
|
|
|
|
func TestTaskStatus_Values(t *testing.T) {
|
|
cases := []domain.TaskStatus{
|
|
domain.TaskStatusPending,
|
|
domain.TaskStatusRunning,
|
|
domain.TaskStatusDone,
|
|
domain.TaskStatusFailed,
|
|
domain.TaskStatusCancelled,
|
|
}
|
|
for _, s := range cases {
|
|
if s == "" {
|
|
t.Errorf("TaskStatus constant must not be empty")
|
|
}
|
|
}
|
|
}
|