refactor(bruno): migrate API tests to Bruno DSL format

- Convert all existing .bru files from JSON to Bruno DSL format
- Remove obsolete files (conflicts/api.bru, kobo/Kobo Initialization.bru)
- Update auth configuration to use 'inherit' instead of explicit bearer tokens
- Add comprehensive documentation to all test files
- Improve test scripts with proper assertions and error handling
This commit is contained in:
2026-02-08 20:49:06 -05:00
parent cb76b9ca05
commit 3117ce54ec
93 changed files with 3974 additions and 1576 deletions
+56 -22
View File
@@ -1,24 +1,58 @@
{
"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
}
meta {
name: Auto-Link Unlinked Books
type: http
seq: 1
}
post {
url: {{baseUrl}}/sync/auto-link-books
body: json
auth: inherit
}
headers {
Content-Type: application/json
Authorization: Bearer {{authToken}}
}
body:json {
{
"confidence_threshold": 0.8,
"limit": 50
}
}
settings {
encodeUrl: true
timeout: 0
}
docs {
## Auto-Link Unlinked Books
Automatically links unlinked books to media items based on title and author matching with a configurable confidence threshold.
**Method:** POST
**Endpoint:** /sync/auto-link-books
**Authentication:** Bearer token
**Request Body:**
- `confidence_threshold` (number, optional): Minimum confidence score for auto-linking (0-1, default: 0.8)
- `limit` (number, optional): Maximum number of books to auto-link (default: 50)
**Response:**
- `results` (array): Results for each auto-link attempt
- `total` (number): Total number of books processed
- `success` (number): Number of successful links
- `failed` (number): Number of failed links
**Status Codes:**
- 200: Success
- 400: Invalid request data
- 401: Unauthorized
- 500: Internal server error
**Note:** Higher confidence thresholds produce fewer but more accurate matches. Consider the tradeoff between automation and accuracy.
}
+64 -28
View File
@@ -1,34 +1,70 @@
{
"meta": {
"name": "Bulk Link Unlinked Books",
"type": "http"
},
"req": {
"url": "{{baseUrl}}/sync/bulk-link-books",
"method": "POST",
"header": [
meta {
name: Bulk Link Unlinked Books
type: http
seq: 1
}
post {
url: {{baseUrl}}/sync/bulk-link-books
body: json
auth: inherit
}
headers {
Content-Type: application/json
Authorization: Bearer {{authToken}}
}
body:json {
{
"links": [
{
"key": "Content-Type",
"value": "application/json"
"unlinked_book_id": "{{unlinkedBookId1}}",
"media_item_id": "{{mediaItemId1}}",
"confidence_score": 1.0
},
{
"key": "Authorization",
"value": "Bearer {{authToken}}"
"unlinked_book_id": "{{unlinkedBookId2}}",
"media_item_id": "{{mediaItemId2}}",
"confidence_score": 0.9
}
],
"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
}
]
}
]
}
}
settings {
encodeUrl: true
timeout: 0
}
docs {
## Bulk Link Unlinked Books
Links multiple unlinked books to media items in a single request.
**Method:** POST
**Endpoint:** /sync/bulk-link-books
**Authentication:** Bearer token
**Request Body:**
- `links` (array): Array of link objects
- `unlinked_book_id` (string): Unlinked book UUID
- `media_item_id` (string): Media item UUID to link to
- `confidence_score` (number): Match confidence (0-1)
**Response:**
- `results` (array): Results for each link attempt
- `total` (number): Total number of links processed
- `success` (number): Number of successful links
- `failed` (number): Number of failed links
**Status Codes:**
- 200: Success
- 400: Invalid request data
- 401: Unauthorized
- 500: Internal server error
**Note:** Use this endpoint after reviewing suggestions from the Get Unlinked Book Suggestions endpoint.
}
@@ -1,16 +1,50 @@
{
"meta": {
"name": "Get Unlinked Book Suggestions",
"type": "http"
},
"req": {
"url": "{{baseUrl}}/sync/unlinked-books/{{unlinkedBookId}}/suggestions",
"method": "GET",
"header": [
{
"key": "Authorization",
"value": "Bearer {{authToken}}"
}
]
}
meta {
name: Get Unlinked Book Suggestions
type: http
seq: 1
}
get {
url: {{baseUrl}}/sync/unlinked-books/{{unlinkedBookId}}/suggestions
body: none
auth: inherit
}
headers {
Authorization: Bearer {{authToken}}
}
settings {
encodeUrl: true
timeout: 0
}
docs {
## Get Unlinked Book Suggestions
Retrieves suggested media items from the library that match an unlinked book, enabling manual linking.
**Method:** GET
**Endpoint:** /sync/unlinked-books/{unlinkedBookId}/suggestions
**Authentication:** Bearer token
**Path Parameters:**
- `unlinkedBookId` (string): Unlinked book UUID
**Response:**
- Array of suggested media items with:
- `id` (string): Media item UUID
- `title` (string): Media item title
- `author` (string): Media item author
- `confidence_score` (number): Match confidence (0-1)
- `match_reasons` (array): Reasons for the suggestion
**Status Codes:**
- 200: Success
- 401: Unauthorized
- 404: Unlinked book not found
**Note:** Suggestions are generated based on title similarity, author matching, and other metadata comparisons.
}
+49 -10
View File
@@ -1,5 +1,5 @@
meta {
name: "Get Unlinked Books - User View"
name: Get Unlinked Books - User View
type: http
seq: 4
}
@@ -7,15 +7,54 @@ meta {
get {
url: {{base_url}}/api/sync/unlinked-books
body: none
auth: {
type: bearer
bearer: {{user_token}}
}
auth: inherit
}
assert {
response.status == 200
response.body.unlinked exists()
response.body.total exists()
response.body.total >= 0
headers {
Authorization: Bearer {{user_token}}
Content-Type: application/json
}
script:post-response {
function onResponse(res) {
if (res.getStatus() === 200) {
const body = res.getBody();
tests('Has unlinked array', body.unlinked !== undefined);
tests('Has total count', body.total !== undefined);
tests('Total >= 0', body.total >= 0);
}
}
onResponse(res);
}
settings {
encodeUrl: true
timeout: 0
}
docs {
## Get Unlinked Books - User View
Retrieves all unlinked books for the authenticated user that need manual linking.
**Method:** GET
**Endpoint:** /api/sync/unlinked-books
**Authentication:** Bearer token
**Response:**
- `unlinked` (array): Array of unlinked book objects
- `id` (string): Unlinked book UUID
- `title` (string): Book title
- `author` (string): Book author
- `device_id` (string): Source device ID
- `device_name` (string): Source device name
- `detected_at` (string): Detection timestamp
- `total` (number): Total count of unlinked books
**Status Codes:**
- 200: Success
- 401: Unauthorized
- 500: Internal server error
}
+58 -12
View File
@@ -1,26 +1,72 @@
meta {
name: "Link Unlinked Book - Manual Resolution"
name: Link Unlinked Book - Manual Resolution
type: http
seq: 5
}
post {
url: {{base_url}}/api/sync/link-book
body: json({
body: json
auth: inherit
}
headers {
Authorization: Bearer {{user_token}}
Content-Type: application/json
}
body:json {
{
"unlinked_book_id": "{{unlinked_book_id}}",
"media_item_id": "{{media_item_id}}",
"confidence_score": 1.0
})
auth: {
type: bearer
bearer: {{user_token}}
}
}
assert {
response.status == 200
response.body.status == "linked"
response.body.unlinked_book_id exists()
response.body.media_item_id exists()
response.body.message exists()
script:post-response {
function onResponse(res) {
if (res.getStatus() === 200) {
const body = res.getBody();
tests['Status is linked'] = body.status === "linked";
tests('Has unlinked_book_id', body.unlinked_book_id !== undefined);
tests('Has media_item_id', body.media_item_id !== undefined);
tests('Has message', body.message !== undefined);
}
}
onResponse(res);
}
settings {
encodeUrl: true
timeout: 0
}
docs {
## Link Unlinked Book - Manual Resolution
Manually links an unlinked book to a media item in the library.
**Method:** POST
**Endpoint:** /api/sync/link-book
**Authentication:** Bearer token
**Request Body:**
- `unlinked_book_id` (string): Unlinked book UUID
- `media_item_id` (string): Media item UUID to link to
- `confidence_score` (number): Match confidence (0-1, 1.0 for manual)
**Response:**
- `status` (string): Link status (linked)
- `unlinked_book_id` (string): Unlinked book UUID
- `media_item_id` (string): Media item UUID
- `message` (string): Success message
**Status Codes:**
- 200: Success - book linked
- 400: Invalid request
- 401: Unauthorized
- 404: Book or media item not found
- 500: Internal server error
}