@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 #