diff --git a/tests/api/03-flows.rest b/tests/api/03-flows.rest new file mode 100644 index 0000000..ee8ab7f --- /dev/null +++ b/tests/api/03-flows.rest @@ -0,0 +1,296 @@ +@base = http://localhost:3000 +@apiKey = bnt_727d2f4f72bd03ed96da5278bb971a00cb0a2454d4d70f9748b5c39f3f69d88d + +############################################################################### +# FLOW LIFECYCLE TESTS +# Tests: Lazy flow creation, Eager flow creation, Flow operations +# +# Test Coverage: +# 1. Lazy flow pattern - first generation without flowId +# 2. Lazy flow - verify flow not created yet +# 3. Lazy flow - second generation creates flow +# 4. Eager flow creation with flowAlias +# 5. List all flows +# 6. Get flow with computed counts +# 7. List flow generations +# 8. List flow images +# 9. Update flow aliases +# 10. Remove specific flow alias +# 11. Regenerate flow +############################################################################### + + +############################################################################### +# TEST 1: Lazy Flow Pattern - First Generation +# Generation without flowId should return auto-generated flowId +# but NOT create flow in database yet (Section 4.1) +############################################################################### + +### Step 1.1: Create Generation without flowId +# @name lazyFlowGen1 +POST {{base}}/api/v1/generations +Content-Type: application/json +X-API-Key: {{apiKey}} + +{ + "prompt": "A red sports car on a mountain road", + "aspectRatio": "16:9" +} + +### + +@lazyFlowId = {{lazyFlowGen1.response.body.$.data.flowId}} +@lazyGenId1 = {{lazyFlowGen1.response.body.$.data.id}} + +### Step 1.2: Poll Generation Status +# @name checkLazyGen1 +GET {{base}}/api/v1/generations/{{lazyGenId1}} +X-API-Key: {{apiKey}} + +### +# Verify: +# - flowId is returned (auto-generated UUID) +# - status = "success" + + +############################################################################### +# TEST 2: Verify Lazy Flow Not Created Yet +# Flow should NOT exist in database after first generation +############################################################################### + +### Step 2.1: Try to get flow (should return 404) +# @name checkLazyFlowNotExists +GET {{base}}/api/v1/flows/{{lazyFlowId}} +X-API-Key: {{apiKey}} + +### +# Expected: 404 Not Found +# Flow record not created yet (lazy creation pattern) + + +############################################################################### +# TEST 3: Lazy Flow - Second Generation Creates Flow +# Using same flowId should create the flow record +############################################################################### + +### Step 3.1: Create second generation with same flowId +# @name lazyFlowGen2 +POST {{base}}/api/v1/generations +Content-Type: application/json +X-API-Key: {{apiKey}} + +{ + "prompt": "Same car but blue color", + "aspectRatio": "16:9", + "flowId": "{{lazyFlowId}}" +} + +### + +@lazyGenId2 = {{lazyFlowGen2.response.body.$.data.id}} + +### Step 3.2: Poll Generation Status +# @name checkLazyGen2 +GET {{base}}/api/v1/generations/{{lazyGenId2}} +X-API-Key: {{apiKey}} + +### + +### Step 3.3: Verify flow now exists +# @name verifyLazyFlowExists +GET {{base}}/api/v1/flows/{{lazyFlowId}} +X-API-Key: {{apiKey}} + +### +# Expected: 200 OK +# Flow record now exists after second use + + +############################################################################### +# TEST 4: Eager Flow Creation with flowAlias +# Using flowAlias should create flow immediately +############################################################################### + +### Step 4.1: Create generation with flowAlias +# @name eagerFlowGen +POST {{base}}/api/v1/generations +Content-Type: application/json +X-API-Key: {{apiKey}} + +{ + "prompt": "A hero banner image", + "aspectRatio": "21:9", + "flowAlias": "@hero-flow" +} + +### + +@eagerFlowId = {{eagerFlowGen.response.body.$.data.flowId}} +@eagerGenId = {{eagerFlowGen.response.body.$.data.id}} + +### Step 4.2: Poll Generation Status +# @name checkEagerGen +GET {{base}}/api/v1/generations/{{eagerGenId}} +X-API-Key: {{apiKey}} + +### + +### Step 4.3: Verify flow exists immediately (eager creation) +# @name verifyEagerFlowExists +GET {{base}}/api/v1/flows/{{eagerFlowId}} +X-API-Key: {{apiKey}} + +### +# Verify: +# - Flow exists immediately +# - aliases contains "@hero-flow" + + +############################################################################### +# TEST 5: List All Flows +############################################################################### + +### Step 5.1: List flows +# @name listFlows +GET {{base}}/api/v1/flows +X-API-Key: {{apiKey}} + +### +# Verify: +# - Returns array of flows +# - Contains our lazyFlowId and eagerFlowId + + +############################################################################### +# TEST 6: Get Flow with Computed Counts +############################################################################### + +### Step 6.1: Get flow details +# @name getFlowDetails +GET {{base}}/api/v1/flows/{{lazyFlowId}} +X-API-Key: {{apiKey}} + +### +# Verify: +# - generationCount is number (should be 2) +# - imageCount is number (should be 2) +# - aliases object present + + +############################################################################### +# TEST 7: List Flow Generations +############################################################################### + +### Step 7.1: Get flow's generations +# @name getFlowGenerations +GET {{base}}/api/v1/flows/{{lazyFlowId}}/generations +X-API-Key: {{apiKey}} + +### +# Verify: +# - Returns array of generations +# - Contains 2 generations from lazy flow tests + + +############################################################################### +# TEST 8: List Flow Images +############################################################################### + +### Step 8.1: Get flow's images +# @name getFlowImages +GET {{base}}/api/v1/flows/{{lazyFlowId}}/images +X-API-Key: {{apiKey}} + +### +# Verify: +# - Returns array of images +# - Contains output images from generations + + +############################################################################### +# TEST 9: Update Flow Aliases +############################################################################### + +### Step 9.1: Update flow aliases +# @name updateFlowAliases +PUT {{base}}/api/v1/flows/{{lazyFlowId}}/aliases +Content-Type: application/json +X-API-Key: {{apiKey}} + +{ + "aliases": { + "@latest": "{{checkLazyGen2.response.body.$.data.outputImageId}}", + "@best": "{{checkLazyGen2.response.body.$.data.outputImageId}}" + } +} + +### +# Verify: +# - Returns updated flow with new aliases +# - aliases contains @latest and @best + + +### Step 9.2: Verify aliases set +# @name verifyAliasesSet +GET {{base}}/api/v1/flows/{{lazyFlowId}} +X-API-Key: {{apiKey}} + +### + + +############################################################################### +# TEST 10: Remove Specific Flow Alias +############################################################################### + +### Step 10.1: Delete @best alias +# @name deleteFlowAlias +DELETE {{base}}/api/v1/flows/{{lazyFlowId}}/aliases/@best +X-API-Key: {{apiKey}} + +### + +### Step 10.2: Verify alias removed +# @name verifyAliasRemoved +GET {{base}}/api/v1/flows/{{lazyFlowId}} +X-API-Key: {{apiKey}} + +### +# Verify: +# - @best not in aliases +# - @latest still in aliases + + +############################################################################### +# TEST 11: Regenerate Flow +# Regenerates the most recent generation in a flow +############################################################################### + +### Step 11.1: Trigger regeneration +# @name regenerateFlow +POST {{base}}/api/v1/flows/{{lazyFlowId}}/regenerate +Content-Type: application/json +X-API-Key: {{apiKey}} + +{} + +### +# Verify: +# - Returns new generation object +# - New generation is in the same flow + + +############################################################################### +# NOTES +############################################################################### +# +# Lazy Flow Pattern (Section 4.1): +# 1. First request without flowId -> return generated flowId, but DO NOT create in DB +# 2. Any request with valid flowId -> create flow in DB if doesn't exist +# 3. If flowAlias specified -> create flow immediately (eager creation) +# +# Flow Aliases: +# - Stored in flow.aliases JSONB field +# - Map alias names to image IDs +# - Can be updated via PUT /flows/:id/aliases +# - Individual aliases deleted via DELETE /flows/:id/aliases/:alias +# diff --git a/tests/api/04-aliases.rest b/tests/api/04-aliases.rest new file mode 100644 index 0000000..cf50eda --- /dev/null +++ b/tests/api/04-aliases.rest @@ -0,0 +1,590 @@ +@base = http://localhost:3000 +@apiKey = bnt_727d2f4f72bd03ed96da5278bb971a00cb0a2454d4d70f9748b5c39f3f69d88d + +############################################################################### +# ALIAS RESOLUTION TESTS +# Tests: 3-Tier Alias Resolution (Technical -> Flow -> Project) +# +# Test Coverage: +# 1. Technical alias @last +# 2. Technical alias @first +# 3. Technical alias @upload +# 4. Technical alias requires flowId +# 5. Flow-scoped alias resolution +# 6. Project-scoped alias resolution +# 7. Alias precedence (flow > project) +# 8. Reserved aliases cannot be assigned +# 9. Alias reassignment removes old +# 10. Same alias in different flows +# 11. Technical alias in generation prompt +# 12. Upload with both project and flow alias +############################################################################### + + +############################################################################### +# SETUP: Create Test Flow +############################################################################### + +### Setup: Create flow for alias tests +# @name setupGen +POST {{base}}/api/v1/generations +Content-Type: application/json +X-API-Key: {{apiKey}} + +{ + "prompt": "Setup image for alias tests", + "aspectRatio": "1:1", + "flowAlias": "@alias-test-flow" +} + +### + +@aliasFlowId = {{setupGen.response.body.$.data.flowId}} +@setupGenId = {{setupGen.response.body.$.data.id}} + +### Poll setup generation +# @name checkSetupGen +GET {{base}}/api/v1/generations/{{setupGenId}} +X-API-Key: {{apiKey}} + +### + +@setupImageId = {{checkSetupGen.response.body.$.data.outputImageId}} + + +############################################################################### +# TEST 1: Technical Alias @last +# Resolves to last generated image in flow +############################################################################### + +### Step 1.1: Resolve @last (requires flowId) +# @name resolveLast +GET {{base}}/api/v1/images/@last?flowId={{aliasFlowId}} +X-API-Key: {{apiKey}} + +### +# Verify: +# - Returns image (status 200) +# - Returns the most recently generated image in the flow + + +############################################################################### +# TEST 2: Technical Alias @first +# Resolves to first generated image in flow +############################################################################### + +### Step 2.1: Resolve @first (requires flowId) +# @name resolveFirst +GET {{base}}/api/v1/images/@first?flowId={{aliasFlowId}} +X-API-Key: {{apiKey}} + +### +# Verify: +# - Returns image (status 200) +# - Returns the first generated image in the flow + + +############################################################################### +# TEST 3: Technical Alias @upload +# Resolves to last uploaded image in flow +############################################################################### + +### Step 3.1: Upload image to flow +# @name uploadForTest +POST {{base}}/api/v1/images/upload +X-API-Key: {{apiKey}} +Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW + +------WebKitFormBoundary7MA4YWxkTrZu0gW +Content-Disposition: form-data; name="file"; filename="test-image.png" +Content-Type: image/png + +< ./fixture/test-image.png +------WebKitFormBoundary7MA4YWxkTrZu0gW +Content-Disposition: form-data; name="flowId" + +{{aliasFlowId}} +------WebKitFormBoundary7MA4YWxkTrZu0gW +Content-Disposition: form-data; name="description" + +Uploaded for @upload test +------WebKitFormBoundary7MA4YWxkTrZu0gW-- + +### + +@uploadedImageId = {{uploadForTest.response.body.$.data.id}} + +### Step 3.2: Resolve @upload (requires flowId) +# @name resolveUpload +GET {{base}}/api/v1/images/@upload?flowId={{aliasFlowId}} +X-API-Key: {{apiKey}} + +### +# Verify: +# - Returns image (status 200) +# - Returns uploaded image (source = "uploaded") + + +############################################################################### +# TEST 4: Technical Alias Requires Flow Context +# @last, @first, @upload require flowId parameter +############################################################################### + +### Step 4.1: Try @last without flowId (should fail) +# @name resolveLastNoFlow +GET {{base}}/api/v1/images/@last +X-API-Key: {{apiKey}} + +### +# Expected: 404 with error "Technical aliases require flowId" + + +############################################################################### +# TEST 5: Flow-Scoped Alias Resolution +############################################################################### + +### Step 5.1: Create generation with flow alias +# @name flowAliasGen +POST {{base}}/api/v1/generations +Content-Type: application/json +X-API-Key: {{apiKey}} + +{ + "prompt": "Image for flow alias test", + "aspectRatio": "1:1", + "flowId": "{{aliasFlowId}}", + "flowAlias": "@flow-hero" +} + +### + +@flowAliasGenId = {{flowAliasGen.response.body.$.data.id}} + +### Step 5.2: Poll generation +# @name checkFlowAliasGen +GET {{base}}/api/v1/generations/{{flowAliasGenId}} +X-API-Key: {{apiKey}} + +### + +@flowHeroImageId = {{checkFlowAliasGen.response.body.$.data.outputImageId}} + +### Step 5.3: Resolve flow alias +# @name resolveFlowAlias +GET {{base}}/api/v1/images/@flow-hero?flowId={{aliasFlowId}} +X-API-Key: {{apiKey}} + +### +# Verify: +# - Returns the image from step 5.1 +# - Only works with flowId parameter + + +############################################################################### +# TEST 6: Project-Scoped Alias Resolution +############################################################################### + +### Step 6.1: Create generation with project alias +# @name projectAliasGen +POST {{base}}/api/v1/generations +Content-Type: application/json +X-API-Key: {{apiKey}} + +{ + "prompt": "Image for project alias test", + "aspectRatio": "1:1", + "alias": "@project-logo", + "flowId": null +} + +### + +@projectAliasGenId = {{projectAliasGen.response.body.$.data.id}} + +### Step 6.2: Poll generation +# @name checkProjectAliasGen +GET {{base}}/api/v1/generations/{{projectAliasGenId}} +X-API-Key: {{apiKey}} + +### + +@projectLogoImageId = {{checkProjectAliasGen.response.body.$.data.outputImageId}} + +### Step 6.3: Resolve project alias (no flowId needed) +# @name resolveProjectAlias +GET {{base}}/api/v1/images/@project-logo +X-API-Key: {{apiKey}} + +### +# Verify: +# - Returns the image from step 6.1 +# - Works without flowId parameter + + +############################################################################### +# TEST 7: Alias Precedence (Flow > Project) +############################################################################### + +### Step 7.1: Create project-scoped alias @priority-test +# @name priorityProject +POST {{base}}/api/v1/generations +Content-Type: application/json +X-API-Key: {{apiKey}} + +{ + "prompt": "Project scoped image for priority test", + "aspectRatio": "1:1", + "alias": "@priority-test", + "flowId": null +} + +### + +@priorityProjectGenId = {{priorityProject.response.body.$.data.id}} + +### Step 7.2: Poll generation +# @name checkPriorityProject +GET {{base}}/api/v1/generations/{{priorityProjectGenId}} +X-API-Key: {{apiKey}} + +### + +@priorityProjectImageId = {{checkPriorityProject.response.body.$.data.outputImageId}} + +### Step 7.3: Create flow-scoped alias @priority-test (same name) +# @name priorityFlow +POST {{base}}/api/v1/generations +Content-Type: application/json +X-API-Key: {{apiKey}} + +{ + "prompt": "Flow scoped image for priority test", + "aspectRatio": "1:1", + "flowId": "{{aliasFlowId}}", + "flowAlias": "@priority-test" +} + +### + +@priorityFlowGenId = {{priorityFlow.response.body.$.data.id}} + +### Step 7.4: Poll generation +# @name checkPriorityFlow +GET {{base}}/api/v1/generations/{{priorityFlowGenId}} +X-API-Key: {{apiKey}} + +### + +@priorityFlowImageId = {{checkPriorityFlow.response.body.$.data.outputImageId}} + +### Step 7.5: Resolve WITHOUT flowId (should get project) +# @name resolvePriorityNoFlow +GET {{base}}/api/v1/images/@priority-test +X-API-Key: {{apiKey}} + +### +# Verify: Returns project image ({{priorityProjectImageId}}) + +### Step 7.6: Resolve WITH flowId (should get flow) +# @name resolvePriorityWithFlow +GET {{base}}/api/v1/images/@priority-test?flowId={{aliasFlowId}} +X-API-Key: {{apiKey}} + +### +# Verify: Returns flow image ({{priorityFlowImageId}}) + + +############################################################################### +# TEST 8: Reserved Aliases Cannot Be Assigned +############################################################################### + +### Step 8.1: Try to use @last as alias (should fail or warn) +# @name reservedLast +POST {{base}}/api/v1/generations +Content-Type: application/json +X-API-Key: {{apiKey}} + +{ + "prompt": "Test reserved alias", + "aspectRatio": "1:1", + "alias": "@last" +} + +### +# Expected: 400 validation error OR generation succeeds but @last not assigned + +### Step 8.2: Try to use @first as alias +# @name reservedFirst +POST {{base}}/api/v1/generations +Content-Type: application/json +X-API-Key: {{apiKey}} + +{ + "prompt": "Test reserved alias", + "aspectRatio": "1:1", + "alias": "@first" +} + +### + +### Step 8.3: Try to use @upload as alias +# @name reservedUpload +POST {{base}}/api/v1/generations +Content-Type: application/json +X-API-Key: {{apiKey}} + +{ + "prompt": "Test reserved alias", + "aspectRatio": "1:1", + "alias": "@upload" +} + +### + + +############################################################################### +# TEST 9: Alias Reassignment (Override Behavior) +############################################################################### + +### Step 9.1: Create first image with alias +# @name reassign1 +POST {{base}}/api/v1/generations +Content-Type: application/json +X-API-Key: {{apiKey}} + +{ + "prompt": "First image for reassign test", + "aspectRatio": "1:1", + "alias": "@reassign-test", + "flowId": null +} + +### + +@reassign1GenId = {{reassign1.response.body.$.data.id}} + +### Step 9.2: Poll first generation +# @name checkReassign1 +GET {{base}}/api/v1/generations/{{reassign1GenId}} +X-API-Key: {{apiKey}} + +### + +@reassign1ImageId = {{checkReassign1.response.body.$.data.outputImageId}} + +### Step 9.3: Create second image with SAME alias +# @name reassign2 +POST {{base}}/api/v1/generations +Content-Type: application/json +X-API-Key: {{apiKey}} + +{ + "prompt": "Second image for reassign test", + "aspectRatio": "1:1", + "alias": "@reassign-test", + "flowId": null +} + +### + +@reassign2GenId = {{reassign2.response.body.$.data.id}} + +### Step 9.4: Poll second generation +# @name checkReassign2 +GET {{base}}/api/v1/generations/{{reassign2GenId}} +X-API-Key: {{apiKey}} + +### + +@reassign2ImageId = {{checkReassign2.response.body.$.data.outputImageId}} + +### Step 9.5: Resolve alias (should be second image) +# @name resolveReassign +GET {{base}}/api/v1/images/@reassign-test +X-API-Key: {{apiKey}} + +### +# Verify: Returns second image ({{reassign2ImageId}}) + +### Step 9.6: Check first image lost alias +# @name checkFirstLostAlias +GET {{base}}/api/v1/images/{{reassign1ImageId}} +X-API-Key: {{apiKey}} + +### +# Verify: alias = null + + +############################################################################### +# TEST 10: Same Alias in Different Flows +############################################################################### + +### Step 10.1: Create flow 1 with @shared-name alias +# @name sharedFlow1 +POST {{base}}/api/v1/generations +Content-Type: application/json +X-API-Key: {{apiKey}} + +{ + "prompt": "Flow 1 image with shared name", + "aspectRatio": "1:1", + "flowAlias": "@shared-name" +} + +### + +@sharedFlow1Id = {{sharedFlow1.response.body.$.data.flowId}} +@sharedGen1Id = {{sharedFlow1.response.body.$.data.id}} + +### Step 10.2: Poll generation 1 +# @name checkSharedGen1 +GET {{base}}/api/v1/generations/{{sharedGen1Id}} +X-API-Key: {{apiKey}} + +### + +@sharedImage1Id = {{checkSharedGen1.response.body.$.data.outputImageId}} + +### Step 10.3: Create flow 2 with SAME @shared-name alias +# @name sharedFlow2 +POST {{base}}/api/v1/generations +Content-Type: application/json +X-API-Key: {{apiKey}} + +{ + "prompt": "Flow 2 image with shared name", + "aspectRatio": "1:1", + "flowAlias": "@shared-name" +} + +### + +@sharedFlow2Id = {{sharedFlow2.response.body.$.data.flowId}} +@sharedGen2Id = {{sharedFlow2.response.body.$.data.id}} + +### Step 10.4: Poll generation 2 +# @name checkSharedGen2 +GET {{base}}/api/v1/generations/{{sharedGen2Id}} +X-API-Key: {{apiKey}} + +### + +@sharedImage2Id = {{checkSharedGen2.response.body.$.data.outputImageId}} + +### Step 10.5: Resolve @shared-name in flow 1 +# @name resolveSharedFlow1 +GET {{base}}/api/v1/images/@shared-name?flowId={{sharedFlow1Id}} +X-API-Key: {{apiKey}} + +### +# Verify: Returns {{sharedImage1Id}} + +### Step 10.6: Resolve @shared-name in flow 2 +# @name resolveSharedFlow2 +GET {{base}}/api/v1/images/@shared-name?flowId={{sharedFlow2Id}} +X-API-Key: {{apiKey}} + +### +# Verify: Returns {{sharedImage2Id}} (different from flow 1) + + +############################################################################### +# TEST 11: Technical Alias in Generation Prompt +############################################################################### + +### Step 11.1: Generate using @last in prompt +# @name techAliasPrompt +POST {{base}}/api/v1/generations +Content-Type: application/json +X-API-Key: {{apiKey}} + +{ + "prompt": "New variation based on @last", + "aspectRatio": "1:1", + "flowId": "{{aliasFlowId}}" +} + +### + +@techAliasGenId = {{techAliasPrompt.response.body.$.data.id}} + +### Step 11.2: Poll generation +# @name checkTechAliasGen +GET {{base}}/api/v1/generations/{{techAliasGenId}} +X-API-Key: {{apiKey}} + +### +# Verify: +# - status = "success" +# - referencedImages contains @last alias + + +############################################################################### +# TEST 12: Upload with Both Project and Flow Alias +############################################################################### + +### Step 12.1: Upload with both aliases +# @name dualAliasUpload +POST {{base}}/api/v1/images/upload +X-API-Key: {{apiKey}} +Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW + +------WebKitFormBoundary7MA4YWxkTrZu0gW +Content-Disposition: form-data; name="file"; filename="test-image.png" +Content-Type: image/png + +< ./fixture/test-image.png +------WebKitFormBoundary7MA4YWxkTrZu0gW +Content-Disposition: form-data; name="alias" + +@dual-project +------WebKitFormBoundary7MA4YWxkTrZu0gW +Content-Disposition: form-data; name="flowId" + +{{aliasFlowId}} +------WebKitFormBoundary7MA4YWxkTrZu0gW +Content-Disposition: form-data; name="flowAlias" + +@dual-flow +------WebKitFormBoundary7MA4YWxkTrZu0gW-- + +### + +@dualAliasImageId = {{dualAliasUpload.response.body.$.data.id}} + +### Step 12.2: Resolve project alias +# @name resolveDualProject +GET {{base}}/api/v1/images/@dual-project +X-API-Key: {{apiKey}} + +### +# Verify: Returns {{dualAliasImageId}} + +### Step 12.3: Resolve flow alias +# @name resolveDualFlow +GET {{base}}/api/v1/images/@dual-flow?flowId={{aliasFlowId}} +X-API-Key: {{apiKey}} + +### +# Verify: Returns {{dualAliasImageId}} (same image) + + +############################################################################### +# NOTES +############################################################################### +# +# 3-Tier Alias Resolution Order: +# 1. Technical (@last, @first, @upload) - require flowId +# 2. Flow-scoped (stored in flow.aliases) - require flowId +# 3. Project-scoped (stored in images.alias) - no flowId needed +# +# Alias Format: +# - Must start with @ +# - Alphanumeric + hyphens only +# - Reserved: @last, @first, @upload +# +# Override Behavior (Section 5.2): +# - New alias assignment takes priority +# - Previous image loses its alias +# - Previous image is NOT deleted +# diff --git a/tests/api/05-live.rest b/tests/api/05-live.rest new file mode 100644 index 0000000..51b0139 --- /dev/null +++ b/tests/api/05-live.rest @@ -0,0 +1,217 @@ +@base = http://localhost:3000 +@apiKey = bnt_727d2f4f72bd03ed96da5278bb971a00cb0a2454d4d70f9748b5c39f3f69d88d + +############################################################################### +# LIVE URL & SCOPE MANAGEMENT TESTS +# Tests: Live generation with caching, Scope management +# +# Test Coverage: +# 1. Create live scope +# 2. List all scopes +# 3. Get scope details +# 4. Update scope settings +# 5. Live URL - basic generation +# 6. Regenerate scope images +# 7. Delete scope +############################################################################### + + +############################################################################### +# TEST 1: Create Live Scope +############################################################################### + +### Step 1.1: Create scope +# @name createScope +POST {{base}}/api/v1/live/scopes +Content-Type: application/json +X-API-Key: {{apiKey}} + +{ + "slug": "test-scope", + "allowNewGenerations": true, + "newGenerationsLimit": 50 +} + +### +# Verify: +# - Returns scope object +# - slug = "test-scope" +# - allowNewGenerations = true +# - newGenerationsLimit = 50 + + +############################################################################### +# TEST 2: List All Scopes +############################################################################### + +### Step 2.1: List scopes +# @name listScopes +GET {{base}}/api/v1/live/scopes +X-API-Key: {{apiKey}} + +### +# Verify: +# - Returns array of scopes +# - Contains "test-scope" + + +############################################################################### +# TEST 3: Get Scope Details +############################################################################### + +### Step 3.1: Get scope by slug +# @name getScope +GET {{base}}/api/v1/live/scopes/test-scope +X-API-Key: {{apiKey}} + +### +# Verify: +# - Returns scope object +# - slug = "test-scope" +# - currentGenerations is number + + +############################################################################### +# TEST 4: Update Scope Settings +############################################################################### + +### Step 4.1: Disable new generations +# @name updateScopeDisable +PUT {{base}}/api/v1/live/scopes/test-scope +Content-Type: application/json +X-API-Key: {{apiKey}} + +{ + "allowNewGenerations": false, + "newGenerationsLimit": 100 +} + +### +# Verify: +# - allowNewGenerations = false +# - newGenerationsLimit = 100 + + +### Step 4.2: Re-enable for testing +# @name updateScopeEnable +PUT {{base}}/api/v1/live/scopes/test-scope +Content-Type: application/json +X-API-Key: {{apiKey}} + +{ + "allowNewGenerations": true +} + +### + + +############################################################################### +# TEST 5: Live URL - Basic Generation +# GET /api/v1/live?prompt=... +# Returns image bytes directly with cache headers +############################################################################### + +### Step 5.1: Generate via live URL +# @name liveGenerate +GET {{base}}/api/v1/live?prompt=A%20simple%20blue%20square%20on%20white%20background +X-API-Key: {{apiKey}} + +### +# Verify: +# - Returns 200 +# - Response is image bytes (Content-Type: image/*) +# - X-Cache-Status header (HIT or MISS) + + +### Step 5.2: Same prompt again (should be cached) +# @name liveGenerateCached +GET {{base}}/api/v1/live?prompt=A%20simple%20blue%20square%20on%20white%20background +X-API-Key: {{apiKey}} + +### +# Verify: +# - X-Cache-Status: HIT +# - Faster response time + + +### Step 5.3: Different prompt +# @name liveGenerateNew +GET {{base}}/api/v1/live?prompt=A%20red%20circle%20on%20black%20background +X-API-Key: {{apiKey}} + +### +# Verify: +# - X-Cache-Status: MISS (new prompt) + + +### Step 5.4: With aspect ratio +# @name liveGenerateWithAspect +GET {{base}}/api/v1/live?prompt=A%20landscape%20scene&aspectRatio=16:9 +X-API-Key: {{apiKey}} + +### + + +############################################################################### +# TEST 6: Regenerate Scope Images +############################################################################### + +### Step 6.1: Trigger regeneration +# @name regenerateScope +POST {{base}}/api/v1/live/scopes/test-scope/regenerate +Content-Type: application/json +X-API-Key: {{apiKey}} + +{} + +### +# Verify: +# - Returns 200 +# - Regeneration triggered + + +############################################################################### +# TEST 7: Delete Scope +############################################################################### + +### Step 7.1: Delete scope +# @name deleteScope +DELETE {{base}}/api/v1/live/scopes/test-scope +X-API-Key: {{apiKey}} + +### +# Verify: +# - Returns 200 + + +### Step 7.2: Verify deleted (should 404) +# @name verifyScopeDeleted +GET {{base}}/api/v1/live/scopes/test-scope +X-API-Key: {{apiKey}} + +### +# Expected: 404 Not Found + + +############################################################################### +# NOTES +############################################################################### +# +# Live URL Endpoint: +# - GET /api/v1/live?prompt=... +# - Returns image bytes directly (not JSON) +# - Supports prompt caching via SHA-256 hash +# +# Response Headers: +# - Content-Type: image/jpeg (or image/png, etc.) +# - X-Cache-Status: HIT | MISS +# - X-Cache-Hit-Count: number (on HIT) +# - X-Generation-Id: UUID (on MISS) +# - X-Image-Id: UUID +# - Cache-Control: public, max-age=31536000 +# +# Scope Management: +# - Scopes group generations for management +# - allowNewGenerations controls if new prompts generate +# - newGenerationsLimit caps generations per scope +# diff --git a/tests/api/06-edge-cases.rest b/tests/api/06-edge-cases.rest new file mode 100644 index 0000000..28856f9 --- /dev/null +++ b/tests/api/06-edge-cases.rest @@ -0,0 +1,315 @@ +@base = http://localhost:3000 +@apiKey = bnt_727d2f4f72bd03ed96da5278bb971a00cb0a2454d4d70f9748b5c39f3f69d88d + +############################################################################### +# EDGE CASES & VALIDATION TESTS +# Tests: Input validation, Error handling, Edge cases +# +# Test Coverage: +# 1. Invalid alias format +# 2. Invalid aspect ratio +# 3. Missing required fields +# 4. 404 for non-existent resources +# 5. Regenerate generation +# 6. CDN endpoints +############################################################################### + + +############################################################################### +# TEST 1: Invalid Alias Format +# Aliases must start with @ and contain only alphanumeric + hyphens +############################################################################### + +### Step 1.1: Alias without @ symbol (should fail) +# @name invalidNoAt +POST {{base}}/api/v1/generations +Content-Type: application/json +X-API-Key: {{apiKey}} + +{ + "prompt": "Test invalid alias", + "aspectRatio": "1:1", + "alias": "no-at-symbol" +} + +### +# Expected: 400 validation error OR 500 with alias error + +### Step 1.2: Alias with spaces (should fail) +# @name invalidWithSpaces +POST {{base}}/api/v1/generations +Content-Type: application/json +X-API-Key: {{apiKey}} + +{ + "prompt": "Test invalid alias", + "aspectRatio": "1:1", + "alias": "@has spaces" +} + +### +# Expected: 400 validation error + +### Step 1.3: Alias with special characters (should fail) +# @name invalidSpecialChars +POST {{base}}/api/v1/generations +Content-Type: application/json +X-API-Key: {{apiKey}} + +{ + "prompt": "Test invalid alias", + "aspectRatio": "1:1", + "alias": "@special!chars" +} + +### +# Expected: 400 validation error + +### Step 1.4: Empty alias (should fail or be ignored) +# @name invalidEmpty +POST {{base}}/api/v1/generations +Content-Type: application/json +X-API-Key: {{apiKey}} + +{ + "prompt": "Test invalid alias", + "aspectRatio": "1:1", + "alias": "" +} + +### + + +############################################################################### +# TEST 2: Invalid Aspect Ratio +############################################################################### + +### Step 2.1: Invalid aspect ratio string +# @name invalidAspectRatio +POST {{base}}/api/v1/generations +Content-Type: application/json +X-API-Key: {{apiKey}} + +{ + "prompt": "Test invalid aspect ratio", + "aspectRatio": "invalid" +} + +### +# Expected: 400 validation error + +### Step 2.2: Unsupported aspect ratio +# @name unsupportedAspectRatio +POST {{base}}/api/v1/generations +Content-Type: application/json +X-API-Key: {{apiKey}} + +{ + "prompt": "Test unsupported aspect ratio", + "aspectRatio": "5:7" +} + +### +# Expected: 400 validation error (only 1:1, 16:9, 9:16, 4:3, 3:4, 21:9 supported) + + +############################################################################### +# TEST 3: Missing Required Fields +############################################################################### + +### Step 3.1: Missing prompt +# @name missingPrompt +POST {{base}}/api/v1/generations +Content-Type: application/json +X-API-Key: {{apiKey}} + +{ + "aspectRatio": "1:1" +} + +### +# Expected: 400 - "Prompt is required" + +### Step 3.2: Empty body +# @name emptyBody +POST {{base}}/api/v1/generations +Content-Type: application/json +X-API-Key: {{apiKey}} + +{} + +### +# Expected: 400 - "Prompt is required" + + +############################################################################### +# TEST 4: 404 for Non-Existent Resources +############################################################################### + +### Step 4.1: Non-existent image +# @name notFoundImage +GET {{base}}/api/v1/images/00000000-0000-0000-0000-000000000000 +X-API-Key: {{apiKey}} + +### +# Expected: 404 Not Found + +### Step 4.2: Non-existent generation +# @name notFoundGeneration +GET {{base}}/api/v1/generations/00000000-0000-0000-0000-000000000000 +X-API-Key: {{apiKey}} + +### +# Expected: 404 Not Found + +### Step 4.3: Non-existent flow +# @name notFoundFlow +GET {{base}}/api/v1/flows/00000000-0000-0000-0000-000000000000 +X-API-Key: {{apiKey}} + +### +# Expected: 404 Not Found + +### Step 4.4: Non-existent alias +# @name notFoundAlias +GET {{base}}/api/v1/images/@non-existent-alias +X-API-Key: {{apiKey}} + +### +# Expected: 404 - "Alias '@non-existent-alias' not found" + + +############################################################################### +# TEST 5: Regenerate Generation +############################################################################### + +### Step 5.1: Create generation for regenerate test +# @name createForRegen +POST {{base}}/api/v1/generations +Content-Type: application/json +X-API-Key: {{apiKey}} + +{ + "prompt": "Test image for regenerate", + "aspectRatio": "1:1" +} + +### + +@regenSourceId = {{createForRegen.response.body.$.data.id}} + +### Step 5.2: Poll until success +# @name checkForRegen +GET {{base}}/api/v1/generations/{{regenSourceId}} +X-API-Key: {{apiKey}} + +### + +### Step 5.3: Regenerate +# @name regenerateGen +POST {{base}}/api/v1/generations/{{regenSourceId}}/regenerate +Content-Type: application/json +X-API-Key: {{apiKey}} + +{} + +### +# Verify: +# - Returns new generation +# - New generation has same prompt + +### Step 5.4: Regenerate non-existent generation (should 404) +# @name regenerateNotFound +POST {{base}}/api/v1/generations/00000000-0000-0000-0000-000000000000/regenerate +Content-Type: application/json +X-API-Key: {{apiKey}} + +{} + +### +# Expected: 404 Not Found + + +############################################################################### +# TEST 6: CDN Endpoints +############################################################################### + +### Step 6.1: CDN image by path (if implemented) +# @name cdnImage +GET {{base}}/api/v1/cdn/default/test-project/generated/2024-01/test.jpg +X-API-Key: {{apiKey}} + +### +# Note: Endpoint structure check only - actual paths depend on storage + +### Step 6.2: Health check +# @name healthCheck +GET {{base}}/health + +### +# Expected: 200 with status info + + +############################################################################### +# TEST 7: Authentication Errors +############################################################################### + +### Step 7.1: Missing API key +# @name noApiKey +GET {{base}}/api/v1/generations + +### +# Expected: 401 Unauthorized + +### Step 7.2: Invalid API key +# @name invalidApiKey +GET {{base}}/api/v1/generations +X-API-Key: bnt_invalid_key_12345 + +### +# Expected: 401 Unauthorized + + +############################################################################### +# TEST 8: Malformed Requests +############################################################################### + +### Step 8.1: Invalid JSON +# @name invalidJson +POST {{base}}/api/v1/generations +Content-Type: application/json +X-API-Key: {{apiKey}} + +{invalid json} + +### +# Expected: 400 Bad Request + +### Step 8.2: Wrong content type +# @name wrongContentType +POST {{base}}/api/v1/generations +Content-Type: text/plain +X-API-Key: {{apiKey}} + +prompt=test&aspectRatio=1:1 + +### + + +############################################################################### +# NOTES +############################################################################### +# +# Validation Rules: +# - Prompt: required, non-empty string +# - Aspect ratio: must be supported (1:1, 16:9, 9:16, 4:3, 3:4, 21:9) +# - Alias: must start with @, alphanumeric + hyphens only +# - UUID: must be valid UUID format +# +# Error Responses: +# - 400: Validation error (missing/invalid fields) +# - 401: Authentication error (missing/invalid API key) +# - 404: Resource not found +# - 429: Rate limit exceeded +# - 500: Internal server error +# diff --git a/tests/api/07-known-issues.rest b/tests/api/07-known-issues.rest new file mode 100644 index 0000000..62dc935 --- /dev/null +++ b/tests/api/07-known-issues.rest @@ -0,0 +1,259 @@ +@base = http://localhost:3000 +@apiKey = bnt_727d2f4f72bd03ed96da5278bb971a00cb0a2454d4d70f9748b5c39f3f69d88d + +############################################################################### +# KNOWN ISSUES TESTS +# These tests document known bugs and implementation gaps +# +# ⚠️ EXPECTED TO FAIL until issues are fixed +# +# Test Coverage: +# 1. Project alias on flow image +# 2. Flow delete cascades non-aliased images +# 3. Flow delete preserves aliased images +# 4. Flow delete cascades generations +############################################################################### + + +############################################################################### +# ISSUE 1: Project Alias on Flow Image +# An image in a flow should be able to have a project-scoped alias +############################################################################### + +### Step 1.1: Create image with both flow and project alias +# @name issue1Gen +POST {{base}}/api/v1/generations +Content-Type: application/json +X-API-Key: {{apiKey}} + +{ + "prompt": "Image in flow with project alias", + "aspectRatio": "1:1", + "flowAlias": "@flow-test", + "alias": "@project-test" +} + +### + +@issue1FlowId = {{issue1Gen.response.body.$.data.flowId}} +@issue1GenId = {{issue1Gen.response.body.$.data.id}} + +### Step 1.2: Poll generation +# @name checkIssue1Gen +GET {{base}}/api/v1/generations/{{issue1GenId}} +X-API-Key: {{apiKey}} + +### + +@issue1ImageId = {{checkIssue1Gen.response.body.$.data.outputImageId}} + +### Step 1.3: Resolve project alias (via deprecated /resolve endpoint) +# @name resolveProjectOnFlow +GET {{base}}/api/v1/images/resolve/@project-test +X-API-Key: {{apiKey}} + +### +# BUG: Project alias on flow image should be resolvable +# Expected: Returns image with id = {{issue1ImageId}} + +### Step 1.4: Resolve project alias (via direct path - Section 6.2) +# @name resolveProjectOnFlowDirect +GET {{base}}/api/v1/images/@project-test +X-API-Key: {{apiKey}} + +### +# This should work after Section 6.2 implementation + + +############################################################################### +# ISSUE 2: Flow Delete Cascades Non-Aliased Images +# When deleting a flow, images without project alias should be deleted +############################################################################### + +### Step 2.1: Create flow with non-aliased image +# @name issue2Gen1 +POST {{base}}/api/v1/generations +Content-Type: application/json +X-API-Key: {{apiKey}} + +{ + "prompt": "No alias image", + "aspectRatio": "1:1", + "flowAlias": "@issue-flow" +} + +### + +@issue2FlowId = {{issue2Gen1.response.body.$.data.flowId}} +@issue2Gen1Id = {{issue2Gen1.response.body.$.data.id}} + +### Step 2.2: Poll generation +# @name checkIssue2Gen1 +GET {{base}}/api/v1/generations/{{issue2Gen1Id}} +X-API-Key: {{apiKey}} + +### + +@issue2Image1Id = {{checkIssue2Gen1.response.body.$.data.outputImageId}} + +### Step 2.3: Add aliased image to same flow +# @name issue2Gen2 +POST {{base}}/api/v1/generations +Content-Type: application/json +X-API-Key: {{apiKey}} + +{ + "prompt": "With alias image", + "aspectRatio": "1:1", + "flowId": "{{issue2FlowId}}", + "alias": "@protected-image" +} + +### + +@issue2Gen2Id = {{issue2Gen2.response.body.$.data.id}} + +### Step 2.4: Poll generation +# @name checkIssue2Gen2 +GET {{base}}/api/v1/generations/{{issue2Gen2Id}} +X-API-Key: {{apiKey}} + +### + +@issue2Image2Id = {{checkIssue2Gen2.response.body.$.data.outputImageId}} + +### Step 2.5: Delete flow +# @name deleteIssue2Flow +DELETE {{base}}/api/v1/flows/{{issue2FlowId}} +X-API-Key: {{apiKey}} + +### + +### Step 2.6: Check non-aliased image (should be 404) +# @name checkIssue2Image1Deleted +GET {{base}}/api/v1/images/{{issue2Image1Id}} +X-API-Key: {{apiKey}} + +### +# Expected: 404 - Non-aliased image should be deleted with flow + +### Step 2.7: Check aliased image (should still exist) +# @name checkIssue2Image2Exists +GET {{base}}/api/v1/images/{{issue2Image2Id}} +X-API-Key: {{apiKey}} + +### +# Expected: 200 - Aliased image should be preserved + + +############################################################################### +# ISSUE 3: Flow Delete Preserves Aliased Images +# Aliased images should have flowId set to null after flow deletion +############################################################################### + +### Step 3.1: Create flow with aliased image +# @name issue3Gen +POST {{base}}/api/v1/generations +Content-Type: application/json +X-API-Key: {{apiKey}} + +{ + "prompt": "Protected image", + "aspectRatio": "1:1", + "flowAlias": "@test-flow-2", + "alias": "@keep-this" +} + +### + +@issue3FlowId = {{issue3Gen.response.body.$.data.flowId}} +@issue3GenId = {{issue3Gen.response.body.$.data.id}} + +### Step 3.2: Poll generation +# @name checkIssue3Gen +GET {{base}}/api/v1/generations/{{issue3GenId}} +X-API-Key: {{apiKey}} + +### + +@issue3ImageId = {{checkIssue3Gen.response.body.$.data.outputImageId}} + +### Step 3.3: Delete flow +# @name deleteIssue3Flow +DELETE {{base}}/api/v1/flows/{{issue3FlowId}} +X-API-Key: {{apiKey}} + +### + +### Step 3.4: Check aliased image (should exist with flowId=null) +# @name checkIssue3ImagePreserved +GET {{base}}/api/v1/images/{{issue3ImageId}} +X-API-Key: {{apiKey}} + +### +# Expected: 200 with flowId = null +# BUG: flowId might not be set to null + + +############################################################################### +# ISSUE 4: Flow Delete Cascades Generations +# Generations should be deleted when flow is deleted +############################################################################### + +### Step 4.1: Create flow with generation +# @name issue4Gen +POST {{base}}/api/v1/generations +Content-Type: application/json +X-API-Key: {{apiKey}} + +{ + "prompt": "Test generation", + "aspectRatio": "1:1", + "flowAlias": "@gen-flow" +} + +### + +@issue4FlowId = {{issue4Gen.response.body.$.data.flowId}} +@issue4GenId = {{issue4Gen.response.body.$.data.id}} + +### Step 4.2: Poll generation +# @name checkIssue4Gen +GET {{base}}/api/v1/generations/{{issue4GenId}} +X-API-Key: {{apiKey}} + +### + +### Step 4.3: Delete flow +# @name deleteIssue4Flow +DELETE {{base}}/api/v1/flows/{{issue4FlowId}} +X-API-Key: {{apiKey}} + +### + +### Step 4.4: Check generation (should be 404) +# @name checkIssue4GenDeleted +GET {{base}}/api/v1/generations/{{issue4GenId}} +X-API-Key: {{apiKey}} + +### +# Expected: 404 - Generation should be deleted with flow + + +############################################################################### +# NOTES +############################################################################### +# +# Flow Deletion Cascade (per api-refactoring-final.md): +# - Flow record → DELETE +# - All generations → DELETE +# - Images without alias → DELETE (with MinIO cleanup) +# - Images with project alias → KEEP (unlink: flowId = NULL) +# +# Known Issues: +# 1. Project alias on flow images may not resolve properly +# 2. Flow deletion may not properly cascade deletions +# 3. Aliased images may not have flowId set to null +# +# These tests document expected behavior that may not be implemented yet. +# diff --git a/tests/api/08-auto-enhance.rest b/tests/api/08-auto-enhance.rest new file mode 100644 index 0000000..6afe68c --- /dev/null +++ b/tests/api/08-auto-enhance.rest @@ -0,0 +1,248 @@ +@base = http://localhost:3000 +@apiKey = bnt_727d2f4f72bd03ed96da5278bb971a00cb0a2454d4d70f9748b5c39f3f69d88d + +############################################################################### +# AUTO-ENHANCE TESTS +# Tests: Prompt auto-enhancement feature +# +# Test Coverage: +# 1. Generate without autoEnhance param (defaults to true) +# 2. Generate with autoEnhance: false +# 3. Generate with autoEnhance: true +# 4. Verify enhancement quality +# 5. List generations with autoEnhance field +# 6. Verify response structure +############################################################################### + + +############################################################################### +# TEST 1: Generate Without autoEnhance Parameter +# Should default to true (enhancement enabled) +############################################################################### + +### Step 1.1: Create generation without autoEnhance param +# @name genDefaultEnhance +POST {{base}}/api/v1/generations +Content-Type: application/json +X-API-Key: {{apiKey}} + +{ + "prompt": "a simple test image", + "aspectRatio": "1:1" +} + +### + +@genDefaultId = {{genDefaultEnhance.response.body.$.data.id}} + +### Step 1.2: Poll generation +# @name checkGenDefault +GET {{base}}/api/v1/generations/{{genDefaultId}} +X-API-Key: {{apiKey}} + +### +# Verify: +# - autoEnhance = true +# - originalPrompt = "a simple test image" +# - prompt != originalPrompt (was enhanced) + + +############################################################################### +# TEST 2: Generate with autoEnhance: false +# Should NOT enhance the prompt +############################################################################### + +### Step 2.1: Create generation with autoEnhance: false +# @name genNoEnhance +POST {{base}}/api/v1/generations +Content-Type: application/json +X-API-Key: {{apiKey}} + +{ + "prompt": "another test image", + "aspectRatio": "1:1", + "autoEnhance": false +} + +### + +@genNoEnhanceId = {{genNoEnhance.response.body.$.data.id}} + +### Step 2.2: Poll generation +# @name checkGenNoEnhance +GET {{base}}/api/v1/generations/{{genNoEnhanceId}} +X-API-Key: {{apiKey}} + +### +# Verify: +# - autoEnhance = false +# - originalPrompt = "another test image" +# - prompt = "another test image" (same, NOT enhanced) + + +############################################################################### +# TEST 3: Generate with autoEnhance: true +# Should enhance the prompt +############################################################################### + +### Step 3.1: Create generation with explicit autoEnhance: true +# @name genExplicitEnhance +POST {{base}}/api/v1/generations +Content-Type: application/json +X-API-Key: {{apiKey}} + +{ + "prompt": "third test image", + "aspectRatio": "1:1", + "autoEnhance": true +} + +### + +@genExplicitId = {{genExplicitEnhance.response.body.$.data.id}} + +### Step 3.2: Poll generation +# @name checkGenExplicit +GET {{base}}/api/v1/generations/{{genExplicitId}} +X-API-Key: {{apiKey}} + +### +# Verify: +# - autoEnhance = true +# - originalPrompt = "third test image" +# - prompt != originalPrompt (was enhanced) +# - prompt is longer and more descriptive + + +############################################################################### +# TEST 4: Verify Enhancement Quality +# Enhanced prompt should be longer and more descriptive +############################################################################### + +### Step 4.1: Get enhanced generation +# @name getEnhancedGen +GET {{base}}/api/v1/generations/{{genDefaultId}} +X-API-Key: {{apiKey}} + +### +# Verify: +# - Enhanced prompt is longer than original +# - Enhanced prompt may contain: "photorealistic", "detailed", "scene", etc. +# - Compare: prompt.length > originalPrompt.length + + +############################################################################### +# TEST 5: List Generations with autoEnhance Field +############################################################################### + +### Step 5.1: List all generations +# @name listGens +GET {{base}}/api/v1/generations +X-API-Key: {{apiKey}} + +### +# Verify: +# - Each generation has autoEnhance field (boolean) +# - Some generations have autoEnhance = true +# - Some generations have autoEnhance = false + + +### Step 5.2: Filter by status to see recent ones +# @name listSuccessGens +GET {{base}}/api/v1/generations?status=success&limit=10 +X-API-Key: {{apiKey}} + +### + + +############################################################################### +# TEST 6: Verify Response Structure +############################################################################### + +### Step 6.1: Get generation and check fields +# @name verifyStructure +GET {{base}}/api/v1/generations/{{genDefaultId}} +X-API-Key: {{apiKey}} + +### +# Expected fields: +# - prompt: string (final prompt, possibly enhanced) +# - originalPrompt: string (original input prompt) +# - autoEnhance: boolean (whether enhancement was applied) +# - status: string +# - outputImageId: string (on success) +# - processingTimeMs: number (on completion) + + +############################################################################### +# ADDITIONAL TEST CASES +############################################################################### + +### Complex prompt that might be enhanced differently +# @name complexPrompt +POST {{base}}/api/v1/generations +Content-Type: application/json +X-API-Key: {{apiKey}} + +{ + "prompt": "a cat sitting on a windowsill", + "aspectRatio": "16:9" +} + +### + +@complexId = {{complexPrompt.response.body.$.data.id}} + +### Check complex prompt enhancement +# @name checkComplexPrompt +GET {{base}}/api/v1/generations/{{complexId}} +X-API-Key: {{apiKey}} + +### +# Verify: Enhanced prompt should add details like lighting, perspective, style, etc. + + +### Short prompt enhancement +# @name shortPrompt +POST {{base}}/api/v1/generations +Content-Type: application/json +X-API-Key: {{apiKey}} + +{ + "prompt": "sunset", + "aspectRatio": "21:9" +} + +### + +@shortId = {{shortPrompt.response.body.$.data.id}} + +### Check short prompt enhancement +# @name checkShortPrompt +GET {{base}}/api/v1/generations/{{shortId}} +X-API-Key: {{apiKey}} + +### +# Verify: Very short prompts should be significantly enhanced + + +############################################################################### +# NOTES +############################################################################### +# +# Auto-Enhance Feature: +# - Default: autoEnhance = true (prompts are enhanced by AI) +# - Set autoEnhance: false to disable enhancement +# - Enhanced prompts are more detailed and descriptive +# +# Response Fields: +# - prompt: The final prompt (enhanced if autoEnhance was true) +# - originalPrompt: The user's original input +# - autoEnhance: Boolean flag indicating if enhancement was applied +# +# Enhancement adds: +# - Descriptive adjectives +# - Lighting and atmosphere details +# - Perspective and composition hints +# - Style and rendering suggestions +#