feat(e2e): use direct HTTP for chapter scraping, cap TTS at 200 chars

- e2e fixture: replace single contentClient with directClient (plain HTTP)
  for chapter/metadata/ranking + contentClient (Browserless) for urlClient
  only — matches production wiring and is significantly faster
- server: add max_chars field to audio request body; truncates stripped text
  to N runes before sending to Kokoro (used by e2e for quick TTS tests)
- fix: move RankingItem to scraper package to break novelfire→storage import
  cycle; storage.RankingItem is now a type alias for backward compat
- fix: update stale New() call in novelfire integration test (missing args)
- fix: replace removed blob-ranking methods in storage integration test with
  current per-item API (UpsertRankingItem/ListRankingItems/RankingLastUpdated)
- justfile: add test-e2e and e2e tasks
This commit is contained in:
Admin
2026-03-03 20:02:15 +05:00
parent b8d4d94b18
commit af3c487afb
8 changed files with 105 additions and 83 deletions

View File

@@ -106,14 +106,22 @@ func newE2EFixture(t *testing.T) *e2eFixture {
t.Fatalf("NewHybridStore: %v", err)
}
client := browser.NewContentClient(browser.Config{
// directClient: plain HTTP GET — used for chapter text, metadata, and ranking
// (novelfire.net serves these pages server-side; no JS rendering needed).
directClient := browser.NewDirectHTTPClient(browser.Config{
Timeout: 60 * time.Second,
MaxConcurrent: 2,
})
// urlClient: Browserless content strategy — used only for chapter-list
// pagination pages which require JS rendering to populate the list.
urlClient := browser.NewContentClient(browser.Config{
BaseURL: browserlessURL,
Token: os.Getenv("BROWSERLESS_TOKEN"),
Timeout: 120 * time.Second,
MaxConcurrent: 2,
})
log := slog.New(slog.NewTextHandler(os.Stderr, &slog.HandlerOptions{Level: slog.LevelWarn}))
sc := novelfire.New(client, log, client, nil)
sc := novelfire.New(directClient, log, urlClient, nil)
return &e2eFixture{
sc: sc,
@@ -389,8 +397,9 @@ func TestE2E_FullScenario(t *testing.T) {
audioURL := fmt.Sprintf("%s/api/audio/%s/%d", f.scraperURL, testSlug, ref.Number)
body, _ := json.Marshal(map[string]interface{}{
"voice": voice,
"speed": 1.0,
"voice": voice,
"speed": 1.0,
"max_chars": 200,
})
audioReq, _ := http.NewRequestWithContext(ctx, http.MethodPost, audioURL, bytes.NewReader(body))