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:
@@ -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.
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user