cmd/server/tests/podcast_test.go — six suites, the shared-dev-DB doctrine (test*-named libraries, cascading cleanup, no binary fixtures): - TestPodcastRLSSurfaces: THE AUDITOR (invariant 13) — non-subscriber 404 on feed detail + SSR page (existence leak), episodes absent from generic media reads, admin escape, subscriber visibility, then the hidden-library flip hiding an already-subscribed feed (the feed policy's library-visibility join). Seeding runs as the FIRST ADMIN — the seed identity has neither subscription nor users row, so podcast INSERT..RETURNING (SELECT policy under FORCE) 42501s for it; production pods run as exactly that admin (invariant 12). All direct row probes read through the admin scope for the same reason. - TestPodcastAddFeedFlow: member add + subscribe + metadata-only upsert; duplicate-URL dedupe (no second row); allow_member_feeds gate (member 403 / admin 201 / subscribe-still-allowed). - TestPodcastShrunkenFeedRetention: feed purges an episode from the XML, both rows persist (upsert-without-delete pin, D14). - TestPodcastEditSegregation: generic edit 400 + write-to-file refusal for episodes; control book edit unaffected. - TestPodcastDownloadWorker (ffmpeg-generated tone at runtime): file lands at <download-root>/<feed-slug>/NNNN-…, audio_metadata probed; re-download of a downloaded episode never re-fetches (idempotency pin, enclosure-hit counted); dead enclosure → failed + persisted reason + metadata intact. Fetch/SSRF tests swap the client via SetPodcastHTTPClientForTests (the production client refuses loopback httptest servers by design — the real client gets its own negative test in services). - TestPodcastScannerExclusion: SetFolders on a podcasts library root yields zero scanner folders (invariant 4 pin) — MediaScanner .FolderCount() accessor added. Unit: internal/services/podcast_rss_test.go — namespace-aware parsing fixture (three XML namespaces, fallback chains, hosts/guests), duration spellings, RFC-822 variants, explicit variants, slug/path layout, enclosure-extension selection, stripHTML, and the SSRF matrix (private/loopback/link-local/multicast/mapped-v6 blocked; a loopback httptest server PROVES the production client refuses it). suites green: full integration run 161s / 0 failures; vitest 12 files 163 tests. Contract widening: TestContractPin_MediaListBothBranches' raw-row allowlist gains the 15 podcast episode columns (additive; documented in docs/contract_pins.md — inert defaults on scan rows). Bruno: bruno/ podcasts/ mirrors the §8 endpoints (12 requests) + Bookhoard env vars. tests/ui/COVERAGE.md rows 18-23: podcasts pages/lifecycle/RLS/chain — Playwright sweep pending.
73 lines
1.5 KiB
YAML
73 lines
1.5 KiB
YAML
name: Bookhoard
|
|
variables:
|
|
- secret: true
|
|
name: device_id
|
|
- secret: true
|
|
name: rule_id
|
|
- secret: true
|
|
name: annotation_id
|
|
- secret: true
|
|
name: alias_id
|
|
- secret: true
|
|
name: track_index
|
|
- secret: true
|
|
name: registration_id
|
|
- secret: true
|
|
name: unlinked_book_id
|
|
- secret: true
|
|
name: device_token
|
|
- name: base_url
|
|
value: http://localhost:8765
|
|
- secret: true
|
|
name: media_item_id
|
|
- secret: true
|
|
name: fake_book_id
|
|
- secret: true
|
|
name: user_id
|
|
- secret: true
|
|
name: highlight_id
|
|
- secret: true
|
|
name: note_id
|
|
- secret: true
|
|
name: ebook_library_id
|
|
- secret: true
|
|
name: job_id
|
|
- name: rating
|
|
value: "5"
|
|
- name: is_visible
|
|
value: "true"
|
|
- name: library_folder
|
|
value: /app/uploads
|
|
- name: opds_base_url
|
|
value: http://localhost:8765/opds
|
|
- secret: true
|
|
name: token
|
|
- secret: true
|
|
name: refresh_token
|
|
- secret: true
|
|
name: kobo_device_token
|
|
- secret: true
|
|
name: other_device_id
|
|
- secret: true
|
|
name: collection_id
|
|
- secret: true
|
|
name: library_folder_id
|
|
- secret: true
|
|
name: comic_library_id
|
|
- secret: true
|
|
name: manga_library_id
|
|
- secret: true
|
|
name: book_sha256
|
|
- secret: true
|
|
name: book_uuid
|
|
- secret: true
|
|
name: podcasts_library_id
|
|
- name: podcast_feed_url
|
|
value: https://example.com/feed.xml
|
|
- secret: true
|
|
name: podcast_feed_id
|
|
- secret: true
|
|
name: podcast_episode_id
|
|
- name: podcast_search_query
|
|
value: episode
|