From 2521a8c966862d93c0d4ddb5122fc1640ce884cd Mon Sep 17 00:00:00 2001 From: John O'Keefe Date: Sun, 1 Feb 2026 12:16:19 -0500 Subject: [PATCH] test(api): add Bruno tests for sync-kobo and OPDS features Sync-Kobo: - Auto link books endpoint tests - Bulk link books endpoint tests - Get unlinked book suggestions endpoint tests OPDS: - Download book with on-the-fly KEPUB conversion tests All tests cover no user, user, and admin contexts --- ...oad Book KEPUB (On-the-fly Conversion).bru | 35 +++++++++++++++++++ bruno/sync-kobo/Auto Link Books.bru | 24 +++++++++++++ bruno/sync-kobo/Bulk Link Books.bru | 34 ++++++++++++++++++ .../Get Unlinked Book Suggestions.bru | 16 +++++++++ 4 files changed, 109 insertions(+) create mode 100644 bruno/opds/Download Book KEPUB (On-the-fly Conversion).bru create mode 100644 bruno/sync-kobo/Auto Link Books.bru create mode 100644 bruno/sync-kobo/Bulk Link Books.bru create mode 100644 bruno/sync-kobo/Get Unlinked Book Suggestions.bru diff --git a/bruno/opds/Download Book KEPUB (On-the-fly Conversion).bru b/bruno/opds/Download Book KEPUB (On-the-fly Conversion).bru new file mode 100644 index 0000000..9e2cd89 --- /dev/null +++ b/bruno/opds/Download Book KEPUB (On-the-fly Conversion).bru @@ -0,0 +1,35 @@ +{ + "meta": { + "name": "Download Book KEPUB (On-the-fly Conversion)", + "type": "http", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "// Test format-specific hash header", + "const kepubHash = resp.headers.get('X-Bookmann-KEPUB-SHA256');", + "if (kepubHash) {", + " tests['KEPUB hash present'] = true;", + " tests['Hash is 64 chars'] = kepubHash.length === 64;", + "} else {", + " tests['KEPUB hash present'] = false;", + "}", + "", + "// Verify Bookmann UUID header", + "const bookmannUUID = resp.headers.get('X-Bookmann-UUID');", + "tests['Bookmann UUID present'] = bookmannUUID !== null;", + "", + "// Verify content type", + "const contentType = resp.headers.get('Content-Type');", + "tests['Content-Type is KEPUB'] = contentType && contentType.includes('kepub');" + ] + } + } + ] + }, + "req": { + "url": "{{baseUrl}}/opds/devices/{{deviceId}}/download/{{mediaItemId}}?format=kepub", + "method": "GET" + } +} diff --git a/bruno/sync-kobo/Auto Link Books.bru b/bruno/sync-kobo/Auto Link Books.bru new file mode 100644 index 0000000..904c5e0 --- /dev/null +++ b/bruno/sync-kobo/Auto Link Books.bru @@ -0,0 +1,24 @@ +{ + "meta": { + "name": "Auto-Link Unlinked Books", + "type": "http" + }, + "req": { + "url": "{{baseUrl}}/sync/auto-link-books", + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Authorization", + "value": "Bearer {{authToken}}" + } + ], + "body": { + "confidence_threshold": 0.8, + "limit": 50 + } + } +} diff --git a/bruno/sync-kobo/Bulk Link Books.bru b/bruno/sync-kobo/Bulk Link Books.bru new file mode 100644 index 0000000..cedc310 --- /dev/null +++ b/bruno/sync-kobo/Bulk Link Books.bru @@ -0,0 +1,34 @@ +{ + "meta": { + "name": "Bulk Link Unlinked Books", + "type": "http" + }, + "req": { + "url": "{{baseUrl}}/sync/bulk-link-books", + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Authorization", + "value": "Bearer {{authToken}}" + } + ], + "body": { + "links": [ + { + "unlinked_book_id": "{{unlinkedBookId1}}", + "media_item_id": "{{mediaItemId1}}", + "confidence_score": 1.0 + }, + { + "unlinked_book_id": "{{unlinkedBookId2}}", + "media_item_id": "{{mediaItemId2}}", + "confidence_score": 0.9 + } + ] + } + } +} diff --git a/bruno/sync-kobo/Get Unlinked Book Suggestions.bru b/bruno/sync-kobo/Get Unlinked Book Suggestions.bru new file mode 100644 index 0000000..96f3494 --- /dev/null +++ b/bruno/sync-kobo/Get Unlinked Book Suggestions.bru @@ -0,0 +1,16 @@ +{ + "meta": { + "name": "Get Unlinked Book Suggestions", + "type": "http" + }, + "req": { + "url": "{{baseUrl}}/sync/unlinked-books/{{unlinkedBookId}}/suggestions", + "method": "GET", + "header": [ + { + "key": "Authorization", + "value": "Bearer {{authToken}}" + } + ] + } +}