test(api): add Bruno API collection for saved filters
Add comprehensive Bruno OpenCollection YAML files for testing
the saved filters API with 9 request files and scenarios.
Main CRUD Requests (4 files):
1. List Saved Filters.yml
- GET /api/saved-filters?resource_type=media-items
- Documents resource_type parameter requirement
- Example responses with JSONB filters
2. Create Saved Filter.yml
- POST /api/saved-filters
- Complete request body documentation
- All filter field examples (genre, author, sort, year, etc.)
- Validation rules (max 100 chars, uniqueness)
3. Update Saved Filter.yml
- PUT /api/saved-filters/{filter_id}
- Immutability notes (resource_type can't change)
- Duplicate name validation
- Updated timestamp behavior
4. Delete Saved Filter.yml
- DELETE /api/saved-filters/{filter_id}
- 204 No Content response
- Security considerations
Scenario Test Files (5 files):
1. Duplicate Name Validation.yml
- Tests 409 Conflict on duplicate names
- Per-user + per-resource-type uniqueness
- Example bash test script
2. User Isolation - Cross-User Access.yml
- Tests users can't access each other's filters
- Security: 404 instead of 403 (prevents enumeration)
- Complete multi-user test scenario
- Database-level isolation documentation
3. Multiple Resource Types.yml
- Tests generic design with different resource types
- Same name allowed for different types (media-items, collections, devices)
- Examples for each resource type
- Extensibility benefits explained
4. Complete CRUD Workflow.yml
- End-to-end lifecycle test (6.5K file)
- Shell script with all steps: Create → Read → Update → Delete → Verify
- Success criteria checklist
- Copy-paste ready test script
5. Filter Validation - Edge Cases.yml
- 12 different validation test cases
- Empty names, missing fields, invalid UUIDs
- Unicode support (emoji, CJK characters)
- Malformed JSON handling
- Special characters and XSS attempts
Documentation Features:
- {{base_url}} variable substitution
- auth: inherit for authentication
- Comprehensive docs: sections with examples
- Shell commands ready to copy-paste
- Expected status codes and responses
- Error handling examples
- Security best practices
Total: 9 YAML files covering all CRUD operations and edge cases
Usage:
- Import into Bruno/Postman for API testing
- Use for manual testing during development
- Reference for API contract validation
- Example curl commands for documentation
Part of: Saved Filters Implementation (Phase 5: Testing & Documentation)
Related: #saved-filters-feature
This commit is contained in:
@@ -0,0 +1,114 @@
|
||||
info:
|
||||
name: Create Saved Filter
|
||||
type: http
|
||||
seq: 2
|
||||
http:
|
||||
method: POST
|
||||
url: '{{base_url}}/api/saved-filters'
|
||||
auth: inherit
|
||||
body:
|
||||
type: json
|
||||
jsonBody: "{\n \"name\": \"My Sci-Fi Books\",\n \"resource_type\":\
|
||||
\ \"media-items\",\n \"filters\": {\n \"genre_filter\": \"Science Fiction\"\
|
||||
,\n \"sort\": \"title ASC\",\n \"author_filter\": \"\"\n }\n\
|
||||
}"
|
||||
|
||||
docs: |-
|
||||
## Create Saved Filter
|
||||
|
||||
Creates a new saved filter for the authenticated user.
|
||||
|
||||
**Method:** POST
|
||||
|
||||
**Endpoint:** /api/saved-filters
|
||||
|
||||
**Authentication:** Required (Bearer token)
|
||||
|
||||
**Request Body:**
|
||||
```json
|
||||
{
|
||||
"name": "My Sci-Fi Books",
|
||||
"resource_type": "media-items",
|
||||
"filters": {
|
||||
"genre_filter": "Science Fiction",
|
||||
"sort": "title ASC",
|
||||
"author_filter": "",
|
||||
"series_filter": ""
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Required Fields:**
|
||||
- `name` (string, required): Filter name
|
||||
- Must be unique per user + resource type combination
|
||||
- Maximum 100 characters
|
||||
- Cannot be empty
|
||||
- `resource_type` (string, required): Type of resource to filter
|
||||
- Examples: "media-items", "collections", "devices"
|
||||
- Must match valid resource types
|
||||
- `filters` (object, required): Key-value pairs of filter criteria
|
||||
- Flexible structure - any valid filter fields
|
||||
- Serialized as JSONB in database
|
||||
|
||||
**Common Filter Fields for media-items:**
|
||||
- `search`: General search term
|
||||
- `author_filter`: Filter by author name
|
||||
- `genre_filter`: Filter by genre
|
||||
- `series_filter`: Filter by series
|
||||
- `language_filter`: Filter by language
|
||||
- `year_min`: Minimum copyright year
|
||||
- `year_max`: Maximum copyright year
|
||||
- `has_cover`: Boolean for cover image
|
||||
- `sort`: Sort order (e.g., "title ASC", "created_at DESC")
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"id": "550e8400-e29b-41d4-a716-446655440000",
|
||||
"name": "My Sci-Fi Books",
|
||||
"resource_type": "media-items",
|
||||
"filters": {
|
||||
"genre_filter": "Science Fiction",
|
||||
"sort": "title ASC"
|
||||
},
|
||||
"created_at": "2024-03-20T12:00:00Z",
|
||||
"updated_at": "2024-03-20T12:00:00Z"
|
||||
}
|
||||
```
|
||||
|
||||
**Status Codes:**
|
||||
- 201: Created - Filter successfully created
|
||||
- 400: Bad Request - Invalid request body or missing required fields
|
||||
- 401: Unauthorized - Invalid or missing authentication token
|
||||
- 409: Conflict - Filter with this name already exists for this resource type
|
||||
|
||||
**Error Response Examples:**
|
||||
|
||||
Duplicate name error:
|
||||
```json
|
||||
{
|
||||
"error": "filter with name 'My Sci-Fi Books' already exists for this resource type"
|
||||
}
|
||||
```
|
||||
|
||||
**Example Usage:**
|
||||
```bash
|
||||
curl -X POST \
|
||||
-H "Authorization: Bearer YOUR_TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"name": "My Sci-Fi Books",
|
||||
"resource_type": "media-items",
|
||||
"filters": {
|
||||
"genre_filter": "Science Fiction",
|
||||
"sort": "title ASC"
|
||||
}
|
||||
}' \
|
||||
"{{base_url}}/api/saved-filters"
|
||||
```
|
||||
|
||||
**Validation Rules:**
|
||||
- Name must be unique per user + resource type
|
||||
- Name cannot be empty or whitespace only
|
||||
- Resource type must be valid
|
||||
- Filters object must be provided (can be empty object {})
|
||||
Reference in New Issue
Block a user