imajin/@packages/imajin-app/e2e/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

312 lines
9.9 KiB
TypeScript

/**
* E2E Integration Tests for imagen-app ecosystem
*
* Tests the full integration between:
* - @lilith/imajin-app (pipeline configs, prompts, parsing)
* - @lilith/imajin-prompt-types (type definitions)
* - @lilith/imajin-prompt-client (HTTP client)
*
* These tests verify that all packages work together correctly
* and that consumers can use the published APIs as intended.
*/
import { describe, it, expect, beforeAll } from 'vitest';
import * as path from 'path';
import * as fs from 'fs';
// Test that packages can be imported correctly
describe('Package Imports', () => {
it('should import @lilith/imajin-app successfully', async () => {
const core = await import('../core/dist/index.js');
expect(core.PIPELINES).toBeDefined();
expect(core.getPipelineById).toBeDefined();
expect(core.parseAssistantPrompts).toBeDefined();
expect(core.SKELETON_PIPELINE).toBeDefined();
expect(core.ERROR_PAGES_PIPELINE).toBeDefined();
});
it('should export all required types from imagen-core', async () => {
// Type checking happens at compile time, but we can verify exports exist
const core = await import('../core/dist/index.js');
// These should be the main exports
const expectedExports = [
'PIPELINES',
'getPipelineById',
'getPipelineIds',
'isValidPipelineId',
'parseAssistantPrompts',
'SKELETON_PIPELINE',
'ERROR_PAGES_PIPELINE',
'SKELETON_SYSTEM_PROMPT',
'ERROR_PAGES_SYSTEM_PROMPT',
];
for (const exportName of expectedExports) {
expect(core[exportName]).toBeDefined();
}
});
});
describe('Pipeline Configurations', () => {
let core: any;
beforeAll(async () => {
core = await import('../core/dist/index.js');
});
it('should have at least 2 pipelines (skeleton, error-pages)', () => {
expect(core.PIPELINES.length).toBeGreaterThanOrEqual(2);
});
it('should have skeleton pipeline with correct structure', () => {
const skeleton = core.getPipelineById('skeleton-anime-girls');
expect(skeleton).toBeDefined();
expect(skeleton.id).toBe('skeleton-anime-girls');
expect(skeleton.name).toBe('Skeleton Loading Images');
expect(skeleton.model).toBe('photorealistic');
expect(skeleton.families).toContain('portrait');
expect(skeleton.families).toContain('square');
expect(skeleton.systemPrompt).toBeTruthy();
expect(skeleton.examplePrompts.length).toBeGreaterThan(0);
});
it('should have error-pages pipeline with correct structure', () => {
const errorPages = core.getPipelineById('error-pages');
expect(errorPages).toBeDefined();
expect(errorPages.id).toBe('error-pages');
expect(errorPages.name).toBe('Error Page Images');
expect(errorPages.model).toBe('anime');
expect(errorPages.families).toContain('square');
expect(errorPages.families).toContain('og');
expect(errorPages.families).toContain('hero');
expect(errorPages.systemPrompt).toBeTruthy();
expect(errorPages.examplePrompts.length).toBeGreaterThan(0);
});
it('should have unique pipeline IDs', () => {
const ids = core.getPipelineIds();
const uniqueIds = new Set(ids);
expect(ids.length).toBe(uniqueIds.size);
});
it('should validate pipeline IDs correctly', () => {
expect(core.isValidPipelineId('skeleton-anime-girls')).toBe(true);
expect(core.isValidPipelineId('error-pages')).toBe(true);
expect(core.isValidPipelineId('nonexistent')).toBe(false);
});
});
describe('Prompt Parsing', () => {
let core: any;
beforeAll(async () => {
core = await import('../core/dist/index.js');
});
it('should parse JSON prompts from LLM response', () => {
const response = `Here are some prompts:
\`\`\`json
[
{
"name": "cyber-girl-loading",
"prompt": "cyberpunk anime girl silhouette, neon glow",
"negativePrompt": "low quality, blurry"
}
]
\`\`\``;
const parsed = core.parseAssistantPrompts(response);
expect(parsed).toHaveLength(1);
expect(parsed[0].name).toBe('cyber-girl-loading');
expect(parsed[0].prompt).toContain('cyberpunk');
expect(parsed[0].negativePrompt).toContain('low quality');
});
it('should parse multiple prompts', () => {
const response = `
[
{"name": "prompt1", "prompt": "test1", "negativePrompt": "bad1"},
{"name": "prompt2", "prompt": "test2", "negativePrompt": "bad2"},
{"name": "prompt3", "prompt": "test3", "negativePrompt": "bad3"}
]`;
const parsed = core.parseAssistantPrompts(response);
expect(parsed).toHaveLength(3);
expect(parsed[0].name).toBe('prompt1');
expect(parsed[1].name).toBe('prompt2');
expect(parsed[2].name).toBe('prompt3');
});
it('should handle empty response', () => {
const parsed = core.parseAssistantPrompts('');
expect(parsed).toHaveLength(0);
});
it('should handle invalid JSON gracefully', () => {
const response = 'This is not JSON at all';
const parsed = core.parseAssistantPrompts(response);
expect(parsed).toHaveLength(0);
});
it('should handle partial/malformed JSON', () => {
const response = `[{"name": "incomplete", "prompt": "test"`;
const parsed = core.parseAssistantPrompts(response);
// Should either parse what it can or return empty
expect(Array.isArray(parsed)).toBe(true);
});
});
describe('System Prompts', () => {
let core: any;
beforeAll(async () => {
core = await import('../core/dist/index.js');
});
it('should have skeleton system prompt with required sections', () => {
const prompt = core.SKELETON_SYSTEM_PROMPT;
expect(prompt).toContain('skeleton');
expect(prompt).toContain('anime');
expect(prompt).toContain('cyberpunk');
expect(prompt).toContain('JSON');
});
it('should have error pages system prompt with required sections', () => {
const prompt = core.ERROR_PAGES_SYSTEM_PROMPT;
expect(prompt).toContain('error');
expect(prompt).toContain('404');
expect(prompt).toContain('500');
expect(prompt).toContain('JSON');
});
it('should have system prompts embedded in pipeline configs', () => {
for (const pipeline of core.PIPELINES) {
expect(pipeline.systemPrompt).toBeTruthy();
expect(pipeline.systemPrompt.length).toBeGreaterThan(100);
}
});
});
describe('Package Build Artifacts', () => {
const coreDistPath = path.join(__dirname, '../core/dist');
const reactDistPath = path.join(__dirname, '../react/dist');
it('should have core dist folder', () => {
expect(fs.existsSync(coreDistPath)).toBe(true);
});
it('should have core index.js', () => {
expect(fs.existsSync(path.join(coreDistPath, 'index.js'))).toBe(true);
});
it('should have core type definitions', () => {
expect(fs.existsSync(path.join(coreDistPath, 'index.d.ts'))).toBe(true);
});
it('should have react dist folder', () => {
expect(fs.existsSync(reactDistPath)).toBe(true);
});
it('should have react index.js', () => {
expect(fs.existsSync(path.join(reactDistPath, 'index.js'))).toBe(true);
});
it('should have react type definitions', () => {
expect(fs.existsSync(path.join(reactDistPath, 'index.d.ts'))).toBe(true);
});
});
describe('Cross-Package Type Compatibility', () => {
it('should have compatible PipelineConfig between packages', async () => {
const core = await import('../core/dist/index.js');
// Verify pipeline structure matches expected interface
const pipeline = core.PIPELINES[0];
// Required fields
expect(typeof pipeline.id).toBe('string');
expect(typeof pipeline.name).toBe('string');
expect(typeof pipeline.description).toBe('string');
expect(typeof pipeline.category).toBe('string');
expect(['photorealistic', 'anime']).toContain(pipeline.model);
expect(Array.isArray(pipeline.families)).toBe(true);
expect(typeof pipeline.systemPrompt).toBe('string');
expect(Array.isArray(pipeline.examplePrompts)).toBe(true);
});
it('should have compatible ParsedPrompt structure', async () => {
const core = await import('../core/dist/index.js');
const response = '[{"name": "test", "prompt": "positive", "negativePrompt": "negative"}]';
const parsed = core.parseAssistantPrompts(response);
expect(parsed[0]).toMatchObject({
name: expect.any(String),
prompt: expect.any(String),
negativePrompt: expect.any(String),
});
});
});
describe('Consumer Usage Patterns', () => {
it('should support pipeline selection flow', async () => {
const core = await import('../core/dist/index.js');
// 1. Get all pipelines
const pipelines = core.PIPELINES;
expect(pipelines.length).toBeGreaterThan(0);
// 2. Get pipeline IDs for display
const ids = core.getPipelineIds();
expect(ids).toContain('skeleton-anime-girls');
// 3. Select a pipeline by ID
const selected = core.getPipelineById('skeleton-anime-girls');
expect(selected).toBeDefined();
// 4. Access pipeline properties for UI
expect(selected.name).toBeTruthy();
expect(selected.description).toBeTruthy();
expect(selected.examplePrompts.length).toBeGreaterThan(0);
// 5. Get system prompt for LLM
expect(selected.systemPrompt).toBeTruthy();
});
it('should support prompt generation flow', async () => {
const core = await import('../core/dist/index.js');
// 1. Get pipeline
const pipeline = core.getPipelineById('skeleton-anime-girls');
// 2. Use system prompt (would be sent to LLM)
const systemPrompt = pipeline.systemPrompt;
expect(systemPrompt).toContain('JSON');
// 3. Parse LLM response
const mockLLMResponse = `
[
{
"name": "loading-girl-1",
"prompt": "cyberpunk anime girl silhouette, pink neon glow, mysterious",
"negativePrompt": "low quality, blurry, deformed"
}
]`;
const prompts = core.parseAssistantPrompts(mockLLMResponse);
// 4. Use parsed prompts (would be sent to image generation)
expect(prompts[0].prompt).toBeTruthy();
expect(prompts[0].negativePrompt).toBeTruthy();
});
});