imajin/@packages/imajin-app/e2e/platform-admin-integration.test.ts
Claude Code 2dd98de686 deps-upgrade(packages-specific): ⬆️ Update dependencies in package configurations across the monorepo
Co-Authored-By: Lilith Autocommit <noreply@atlilith.com>
2026-03-28 14:57:10 -07:00

302 lines
10 KiB
TypeScript

/**
* Platform-Admin Integration Tests
*
* These tests verify that @lilith/imajin-app integrates correctly
* with platform-admin's actual usage patterns.
*
* Based on real code from:
* - platform-admin/frontend-admin/src/pages/image-generation/ImagePipelinesPage.tsx
* - platform-admin/frontend-admin/src/pages/image-generation/ImageGenAssistant.tsx
*/
import { describe, it, expect, beforeAll } from 'vitest';
describe('Platform-Admin Integration', () => {
let core: any;
beforeAll(async () => {
core = await import('../core/dist/index.js');
});
describe('ImagePipelinesPage pattern', () => {
// Tests the import pattern used in platform-admin
// import { PIPELINES, type PipelineConfig } from '@lilith/imajin-app';
it('should import PIPELINES array', () => {
expect(core.PIPELINES).toBeDefined();
expect(Array.isArray(core.PIPELINES)).toBe(true);
});
it('should use PipelineConfig type correctly', () => {
const pipeline = core.PIPELINES[0];
// Platform-admin accesses these fields:
expect(pipeline.id).toBeDefined();
expect(pipeline.name).toBeDefined();
expect(pipeline.description).toBeDefined();
expect(pipeline.category).toBeDefined();
expect(pipeline.model).toBeDefined();
expect(pipeline.families).toBeDefined();
});
it('should support pipeline card rendering pattern', () => {
// platform-admin maps over PIPELINES to render cards
const cards = core.PIPELINES.map((pipeline: any) => ({
key: pipeline.id,
name: pipeline.name,
description: pipeline.description,
category: pipeline.category,
}));
expect(cards.length).toBeGreaterThan(0);
cards.forEach((card: any) => {
expect(card.key).toBeTruthy();
expect(card.name).toBeTruthy();
expect(card.description).toBeTruthy();
});
});
it('should support gallery category filtering', () => {
// platform-admin uses pipeline.category for gallery filtering
const categories = [...new Set(core.PIPELINES.map((p: any) => p.category))];
expect(categories.length).toBeGreaterThan(0);
categories.forEach((cat: any) => {
expect(typeof cat).toBe('string');
expect(cat.length).toBeGreaterThan(0);
});
});
it('should support families for derivative generation', () => {
// platform-admin uses pipeline.families to create image derivatives
for (const pipeline of core.PIPELINES) {
expect(Array.isArray(pipeline.families)).toBe(true);
expect(pipeline.families.length).toBeGreaterThan(0);
// Verify family names are strings
pipeline.families.forEach((family: any) => {
expect(typeof family).toBe('string');
});
}
});
});
describe('ImageGenAssistant pattern', () => {
// Tests the import pattern used in ImageGenAssistant
// import type { PipelineConfig } from '@lilith/imajin-app';
// import { parseAssistantPrompts } from '@lilith/imajin-app';
it('should import parseAssistantPrompts function', () => {
expect(core.parseAssistantPrompts).toBeDefined();
expect(typeof core.parseAssistantPrompts).toBe('function');
});
it('should access pipeline.systemPrompt for LLM', () => {
// ImageGenAssistant passes systemPrompt to Ollama
for (const pipeline of core.PIPELINES) {
expect(pipeline.systemPrompt).toBeDefined();
expect(typeof pipeline.systemPrompt).toBe('string');
expect(pipeline.systemPrompt.length).toBeGreaterThan(100);
}
});
it('should access pipeline.examplePrompts for UI buttons', () => {
// ImageGenAssistant renders example prompts as clickable buttons
for (const pipeline of core.PIPELINES) {
expect(Array.isArray(pipeline.examplePrompts)).toBe(true);
expect(pipeline.examplePrompts.length).toBeGreaterThan(0);
pipeline.examplePrompts.forEach((example: string) => {
expect(typeof example).toBe('string');
expect(example.length).toBeGreaterThan(0);
});
}
});
it('should parse JSON prompts from LLM response', () => {
// Simulates actual LLM response parsing
const llmResponse = `Here are some prompts for skeleton loading images:
\`\`\`json
[
{
"name": "cyber-girl-1",
"prompt": "cyberpunk anime girl silhouette, pink neon glow, mysterious dark background",
"negativePrompt": "low quality, blurry, deformed"
},
{
"name": "cyber-girl-2",
"prompt": "holographic anime girl figure, blue circuit patterns, futuristic",
"negativePrompt": "low quality, blurry, ugly"
}
]
\`\`\`
These prompts focus on the cyberpunk aesthetic that works well for skeleton loaders.`;
const parsed = core.parseAssistantPrompts(llmResponse);
expect(parsed).toHaveLength(2);
expect(parsed[0].name).toBe('cyber-girl-1');
expect(parsed[0].prompt).toContain('cyberpunk');
expect(parsed[0].negativePrompt).toContain('low quality');
});
it('should build CreateVariationRequest from parsed prompts', () => {
// ImageGenAssistant builds these requests for image-generator API
const pipeline = core.PIPELINES[0];
const llmResponse = `[{"name": "test", "prompt": "test prompt", "negativePrompt": "bad quality"}]`;
const parsed = core.parseAssistantPrompts(llmResponse);
// Simulate the request building pattern from ImageGenAssistant
const request = {
name: `${pipeline.category}-${parsed[0].name}-${Date.now()}-0`,
category: pipeline.category,
families: pipeline.families,
generation: {
prompt: parsed[0].prompt,
negativePrompt: parsed[0].negativePrompt,
model: pipeline.model,
seed: 42424242,
guidanceScale: 7.5,
inferenceSteps: 30,
},
};
expect(request.name).toContain(pipeline.category);
expect(request.families).toEqual(pipeline.families);
expect(request.generation.model).toBe(pipeline.model);
expect(['photorealistic', 'anime']).toContain(request.generation.model);
});
});
describe('API Types Compatibility', () => {
// These tests verify that the types exported from imagen-core
// are compatible with what platform-admin expects
it('should have ImageModel type compatible values', () => {
// platform-admin uses ImageModel type for generation params
const validModels = ['photorealistic', 'anime'];
for (const pipeline of core.PIPELINES) {
expect(validModels).toContain(pipeline.model);
}
});
it('should have PipelineConfig with all required fields', () => {
const requiredFields = [
'id',
'name',
'description',
'category',
'model',
'families',
'systemPrompt',
'examplePrompts',
];
for (const pipeline of core.PIPELINES) {
for (const field of requiredFields) {
expect(pipeline[field]).toBeDefined();
}
}
});
it('should have ParsedPrompt with all required fields', () => {
const response = '[{"name": "test", "prompt": "positive", "negativePrompt": "negative"}]';
const parsed = core.parseAssistantPrompts(response);
expect(parsed[0]).toHaveProperty('name');
expect(parsed[0]).toHaveProperty('prompt');
expect(parsed[0]).toHaveProperty('negativePrompt');
});
});
describe('Pipeline Selection Flow', () => {
// Tests the full flow platform-admin uses for pipeline selection
it('should support selecting pipeline by ID', () => {
// User clicks on a pipeline card, gets full pipeline config
const pipelineId = core.PIPELINES[0].id;
const selected = core.getPipelineById(pipelineId);
expect(selected).toBeDefined();
expect(selected.id).toBe(pipelineId);
});
it('should validate pipeline IDs correctly', () => {
// For URL routing and validation
const validIds = core.getPipelineIds();
for (const id of validIds) {
expect(core.isValidPipelineId(id)).toBe(true);
}
expect(core.isValidPipelineId('invalid-pipeline-id')).toBe(false);
});
it('should support modal state pattern', () => {
// platform-admin uses useState<PipelineConfig | null> for modal
let selectedPipeline: any = null;
// Simulate clicking "Open Assistant"
selectedPipeline = core.getPipelineById('skeleton-anime-girls');
expect(selectedPipeline).not.toBeNull();
expect(selectedPipeline.name).toBe('Skeleton Loading Images');
// Simulate closing modal
selectedPipeline = null;
expect(selectedPipeline).toBeNull();
});
});
describe('Queue Stats Integration', () => {
// Tests that pipeline.category is usable for queue stats queries
it('should provide category for queue stats queries', () => {
// platform-admin queries: getQueueStats(pipeline.category)
for (const pipeline of core.PIPELINES) {
expect(pipeline.category).toBeDefined();
expect(typeof pipeline.category).toBe('string');
expect(pipeline.category.length).toBeGreaterThan(0);
}
});
it('should have unique categories per pipeline', () => {
// Each pipeline should have its own category for isolation
const categoryCounts: Record<string, number> = {};
for (const pipeline of core.PIPELINES) {
categoryCounts[pipeline.category] = (categoryCounts[pipeline.category] || 0) + 1;
}
// Currently we expect skeleton and error-pages categories
expect(Object.keys(categoryCounts).length).toBeGreaterThanOrEqual(2);
});
});
describe('Gallery Integration', () => {
// Tests gallery-related pipeline features
it('should support family-based derivative selection', () => {
// platform-admin selects best derivative: portrait > square > first
const skeletonPipeline = core.getPipelineById('skeleton-anime-girls');
expect(skeletonPipeline.families).toContain('portrait');
expect(skeletonPipeline.families).toContain('square');
});
it('should support image naming convention', () => {
// platform-admin creates names like: category-promptName-timestamp-index
const pipeline = core.PIPELINES[0];
const promptName = 'test-image';
const timestamp = Date.now();
const index = 0;
const imageName = `${pipeline.category}-${promptName}-${timestamp}-${index}`;
expect(imageName).toContain(pipeline.category);
expect(imageName).toContain(promptName);
});
});
});