banatie-service/tests/api/test-03-aliases.ts

257 lines
8.6 KiB
TypeScript

// tests/api/03-aliases.ts
import { join } from 'path';
import { api, log, runTest, saveImage, uploadFile, waitForGeneration, testContext } from './utils';
import { config, endpoints } from './config';
async function main() {
log.section('ALIAS TESTS');
// Test 1: Upload with project-scoped alias
await runTest('Upload with project alias', async () => {
const fixturePath = join(__dirname, config.fixturesDir, 'test-image.png');
const response = await uploadFile(fixturePath, {
alias: '@brand-logo',
description: 'Brand logo for project-wide use',
});
if (!response.image.alias || response.image.alias !== '@brand-logo') {
throw new Error('Alias not set correctly');
}
log.detail('Image ID', response.image.id);
log.detail('Project alias', response.image.alias);
log.detail('Flow ID', response.image.flowId || 'null (project-scoped)');
});
// Test 2: Upload with flow-scoped alias
await runTest('Upload with flow alias', async () => {
const fixturePath = join(__dirname, config.fixturesDir, 'test-image.png');
const response = await uploadFile(fixturePath, {
flowAlias: '@temp-logo',
flowId: testContext.flowId,
description: 'Temporary logo for flow use',
});
if (!response.flow || !response.flow.aliases['@temp-logo']) {
throw new Error('Flow alias not set');
}
log.detail('Image ID', response.image.id);
log.detail('Flow ID', response.image.flowId);
log.detail('Flow aliases', JSON.stringify(response.flow.aliases));
});
// Test 3: Upload with BOTH project and flow aliases
await runTest('Upload with dual aliases', async () => {
const fixturePath = join(__dirname, config.fixturesDir, 'test-image.png');
const response = await uploadFile(fixturePath, {
alias: '@global-asset',
flowAlias: '@flow-asset',
flowId: testContext.flowId,
description: 'Image with both alias types',
});
if (!response.image.alias || response.image.alias !== '@global-asset') {
throw new Error('Project alias not set');
}
if (!response.flow || !response.flow.aliases['@flow-asset']) {
throw new Error('Flow alias not set');
}
log.detail('Image ID', response.image.id);
log.detail('Project alias', response.image.alias);
log.detail('Flow alias', '@flow-asset');
});
// Test 4: Resolve project-scoped alias
await runTest('Resolve project alias', async () => {
const result = await api(`${endpoints.images}/resolve/@brand-logo`);
if (!result.data.image) {
throw new Error('Image not resolved');
}
if (result.data.scope !== 'project') {
throw new Error(`Wrong scope: ${result.data.scope}`);
}
log.detail('Image ID', result.data.image.id);
log.detail('Scope', result.data.scope);
log.detail('Alias', result.data.image.alias);
});
// Test 5: Resolve flow-scoped alias
await runTest('Resolve flow alias', async () => {
const result = await api(`${endpoints.images}/resolve/@temp-logo?flowId=${testContext.flowId}`);
if (!result.data.image) {
throw new Error('Image not resolved');
}
if (result.data.scope !== 'flow') {
throw new Error(`Wrong scope: ${result.data.scope}`);
}
log.detail('Image ID', result.data.image.id);
log.detail('Scope', result.data.scope);
log.detail('Flow ID', result.data.flow?.id);
});
// Test 6: Resolve @last technical alias
await runTest('Resolve @last technical alias', async () => {
const result = await api(`${endpoints.images}/resolve/@last?flowId=${testContext.flowId}`);
if (!result.data.image) {
throw new Error('Image not resolved');
}
if (result.data.scope !== 'technical') {
throw new Error(`Wrong scope: ${result.data.scope}`);
}
log.detail('Image ID', result.data.image.id);
log.detail('Scope', result.data.scope);
log.detail('Technical alias', '@last');
});
// Test 7: Resolve @first technical alias
await runTest('Resolve @first technical alias', async () => {
const result = await api(`${endpoints.images}/resolve/@first?flowId=${testContext.flowId}`);
if (!result.data.image) {
throw new Error('Image not resolved');
}
if (result.data.scope !== 'technical') {
throw new Error(`Wrong scope: ${result.data.scope}`);
}
log.detail('Image ID', result.data.image.id);
log.detail('Scope', result.data.scope);
});
// Test 8: Resolve @upload technical alias
await runTest('Resolve @upload technical alias', async () => {
const result = await api(`${endpoints.images}/resolve/@upload?flowId=${testContext.flowId}`);
if (!result.data.image) {
throw new Error('Image not resolved');
}
if (result.data.scope !== 'technical') {
throw new Error(`Wrong scope: ${result.data.scope}`);
}
log.detail('Image ID', result.data.image.id);
log.detail('Scope', result.data.scope);
log.detail('Source', result.data.image.source);
});
// Test 9: Generate with assignAlias (project-scoped)
await runTest('Generate with project alias assignment', async () => {
const result = await api(endpoints.generations, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
prompt: 'A minimalist logo design',
aspectRatio: '1:1',
assignAlias: '@generated-logo',
}),
});
log.info('Waiting for generation to complete...');
const generation = await waitForGeneration(result.data.generation.id);
if (generation.status !== 'success') {
throw new Error(`Generation failed: ${generation.errorMessage}`);
}
// Check if alias was assigned
const imageResult = await api(`${endpoints.images}/${generation.outputImageId}`);
if (imageResult.data.image.alias !== '@generated-logo') {
throw new Error('Alias not assigned to generated image');
}
log.detail('Output image', generation.outputImageId);
log.detail('Assigned alias', imageResult.data.image.alias);
// Save image
const imageUrl = imageResult.data.image.storageUrl;
const imageResponse = await fetch(imageUrl);
const imageBuffer = await imageResponse.arrayBuffer();
await saveImage(imageBuffer, 'generated-with-alias.png');
});
// Test 10: Generate with assignFlowAlias (flow-scoped)
await runTest('Generate with flow alias assignment', async () => {
const result = await api(endpoints.generations, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
prompt: 'A vibrant abstract pattern',
aspectRatio: '1:1',
flowId: testContext.flowId,
assignFlowAlias: '@pattern',
}),
});
log.info('Waiting for generation to complete...');
const generation = await waitForGeneration(result.data.generation.id);
if (generation.status !== 'success') {
throw new Error(`Generation failed: ${generation.errorMessage}`);
}
// Check if flow alias was assigned
const flowResult = await api(`${endpoints.flows}/${testContext.flowId}`);
if (!flowResult.data.flow.aliases['@pattern']) {
throw new Error('Flow alias not assigned');
}
log.detail('Output image', generation.outputImageId);
log.detail('Flow alias assigned', '@pattern');
});
// Test 11: Alias precedence (flow > project)
await runTest('Test alias precedence', async () => {
// Create project alias @test
const fixturePath = join(__dirname, config.fixturesDir, 'test-image.png');
const projectResponse = await uploadFile(fixturePath, {
alias: '@precedence-test',
});
const projectImageId = projectResponse.image.id;
// Create flow alias @test (different image)
const flowResponse = await uploadFile(fixturePath, {
flowAlias: '@precedence-test',
flowId: testContext.flowId,
});
const flowImageId = flowResponse.image.id;
// Resolve without flowId (should get project alias)
const withoutFlow = await api(`${endpoints.images}/resolve/@precedence-test`);
if (withoutFlow.data.image.id !== projectImageId) {
throw new Error('Should resolve to project alias');
}
log.detail('Without flow context', 'resolved to project alias ✓');
// Resolve with flowId (should get flow alias)
const withFlow = await api(`${endpoints.images}/resolve/@precedence-test?flowId=${testContext.flowId}`);
if (withFlow.data.image.id !== flowImageId) {
throw new Error('Should resolve to flow alias');
}
log.detail('With flow context', 'resolved to flow alias ✓');
});
log.section('ALIAS TESTS COMPLETED');
}
main().catch(console.error);