summaryrefslogtreecommitdiff
path: root/web
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2026-05-07 00:35:07 +0300
committerPaul Buetow <paul@buetow.org>2026-05-07 00:35:07 +0300
commit1898db985f708f0ff54d04d2d77303c633bc1ba2 (patch)
treef608db9059478d72673149a30dd5bfb650b1e025 /web
parent9458bf6d9861a6e09c616c8d290cce56fc61ac9f (diff)
Fix podcast episode pagination arguments (p0)
Diffstat (limited to 'web')
-rw-r--r--web/js/api.js15
-rw-r--r--web/js/tests/podcast-episodes-api.test.js74
2 files changed, 88 insertions, 1 deletions
diff --git a/web/js/api.js b/web/js/api.js
index deabf20..28954a1 100644
--- a/web/js/api.js
+++ b/web/js/api.js
@@ -86,7 +86,20 @@ export const API = {
delPermissions: (body) => api('/api/admin/permissions', { method: 'DELETE', body }),
rescan: () => api('/api/admin/rescan', { method: 'POST' }),
podcasts: () => api('/api/podcasts'),
- podcastEpisodes: (setId, limit = 50, offset = 0) => {
+ podcastEpisodes: (setId, pagination, legacyOffset) => {
+ let limit = 50;
+ let offset = 0;
+ if (typeof pagination === 'number') {
+ if (typeof legacyOffset === 'number') {
+ limit = pagination;
+ offset = legacyOffset;
+ } else {
+ offset = pagination;
+ }
+ } else if (pagination) {
+ limit = pagination.limit ?? limit;
+ offset = pagination.offset ?? offset;
+ }
const params = new URLSearchParams({ limit, offset });
return api(`/api/podcasts/${setId}/episodes?${params}`);
},
diff --git a/web/js/tests/podcast-episodes-api.test.js b/web/js/tests/podcast-episodes-api.test.js
new file mode 100644
index 0000000..d46d782
--- /dev/null
+++ b/web/js/tests/podcast-episodes-api.test.js
@@ -0,0 +1,74 @@
+import { API } from '../api.js';
+
+const failures = [];
+const requested = [];
+
+function assert(cond, msg) {
+ if (!cond) failures.push(msg || 'assertion failed');
+}
+
+globalThis.fetch = async (url) => {
+ requested.push(url);
+ return new Response('[]', {
+ status: 200,
+ headers: { 'content-type': 'application/json' },
+ });
+};
+
+globalThis.location = { pathname: '/', href: '' };
+
+async function capturesUrl(fn) {
+ requested.length = 0;
+ await fn();
+ return requested[0];
+}
+
+function paramsFrom(url) {
+ return new URL(url, 'http://player.test').searchParams;
+}
+
+async function testDefaults() {
+ const params = paramsFrom(await capturesUrl(() => API.podcastEpisodes(5)));
+ assert(params.get('limit') === '50', 'default limit should be 50');
+ assert(params.get('offset') === '0', 'default offset should be 0');
+}
+
+async function testSecondArgumentIsOffset() {
+ const params = paramsFrom(await capturesUrl(() => API.podcastEpisodes(5, 0)));
+ assert(params.get('limit') === '50', 'single numeric argument should keep default limit');
+ assert(params.get('offset') === '0', 'single numeric argument should set explicit offset');
+}
+
+async function testOptionsObject() {
+ const params = paramsFrom(await capturesUrl(() => API.podcastEpisodes(5, { limit: 25, offset: 75 })));
+ assert(params.get('limit') === '25', 'options object should set limit');
+ assert(params.get('offset') === '75', 'options object should set offset');
+}
+
+async function testOptionsObjectKeepsZeroLimit() {
+ const params = paramsFrom(await capturesUrl(() => API.podcastEpisodes(5, { limit: 0 })));
+ assert(params.get('limit') === '0', 'options object should preserve explicit zero limit');
+ assert(params.get('offset') === '0', 'options object should default offset to 0');
+}
+
+async function testLegacyLimitOffset() {
+ const params = paramsFrom(await capturesUrl(() => API.podcastEpisodes(5, 10, 20)));
+ assert(params.get('limit') === '10', 'legacy third-argument form should preserve limit');
+ assert(params.get('offset') === '20', 'legacy third-argument form should preserve offset');
+}
+
+console.log('Running podcast episodes API pagination tests...');
+await testDefaults();
+await testSecondArgumentIsOffset();
+await testOptionsObject();
+await testOptionsObjectKeepsZeroLimit();
+await testLegacyLimitOffset();
+
+if (failures.length) {
+ console.error('FAILURES:');
+ failures.forEach((m) => console.error(' - ' + m));
+ process.exit(1);
+} else {
+ console.log('All podcast episodes API pagination tests passed.');
+ process.exit(0);
+}