mirror of
https://github.com/nexu-io/open-design.git
synced 2026-10-27 09:51:12 +01:00
* fix(media): route legacy image templates through Vela * fix(codex): preserve packaged node mode in tool shells * fix(media): resume submitted Vela image tasks
294 lines
8.7 KiB
TypeScript
294 lines
8.7 KiB
TypeScript
// @vitest-environment jsdom
|
|
|
|
import { cleanup, fireEvent, render, screen, waitFor } from '@testing-library/react';
|
|
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
|
import { NewProjectPanel } from '../../src/components/NewProjectPanel';
|
|
|
|
describe('NewProjectPanel media provider badges', () => {
|
|
beforeEach(() => {
|
|
vi.stubGlobal('ResizeObserver', class {
|
|
observe() {}
|
|
disconnect() {}
|
|
unobserve() {}
|
|
});
|
|
Element.prototype.scrollIntoView = vi.fn();
|
|
});
|
|
|
|
afterEach(() => {
|
|
cleanup();
|
|
vi.unstubAllGlobals();
|
|
});
|
|
|
|
it('treats daemon-restored apiKeyConfigured providers as configured', () => {
|
|
render(
|
|
<NewProjectPanel
|
|
skills={[]}
|
|
designSystems={[]}
|
|
defaultDesignSystemId={null}
|
|
templates={[]}
|
|
onDeleteTemplate={vi.fn()}
|
|
promptTemplates={[]}
|
|
onCreate={vi.fn()}
|
|
mediaProviders={{
|
|
openai: {
|
|
apiKey: '',
|
|
apiKeyConfigured: true,
|
|
apiKeyTail: '1234',
|
|
baseUrl: '',
|
|
},
|
|
}}
|
|
/>,
|
|
);
|
|
|
|
fireEvent.click(screen.getByRole('tab', { name: 'Media' }));
|
|
fireEvent.click(screen.getByRole('tab', { name: 'Image' }));
|
|
// Model picker is now a combobox — open the popover so the
|
|
// provider group + status badge become visible in the DOM.
|
|
fireEvent.click(screen.getByTestId('model-picker-trigger'));
|
|
|
|
const openaiGroup = screen.getByText('OpenAI').closest('.ds-picker-group');
|
|
expect(openaiGroup?.textContent).toContain('Configured');
|
|
expect(openaiGroup?.textContent).not.toContain('Integrated');
|
|
});
|
|
|
|
it('hides provider models until the provider has usable credentials', () => {
|
|
render(
|
|
<NewProjectPanel
|
|
skills={[]}
|
|
designSystems={[]}
|
|
defaultDesignSystemId={null}
|
|
templates={[]}
|
|
onDeleteTemplate={vi.fn()}
|
|
promptTemplates={[]}
|
|
onCreate={vi.fn()}
|
|
mediaProviders={{}}
|
|
/>,
|
|
);
|
|
|
|
fireEvent.click(screen.getByRole('tab', { name: 'Media' }));
|
|
fireEvent.click(screen.getByRole('tab', { name: 'Image' }));
|
|
fireEvent.click(screen.getByTestId('model-picker-trigger'));
|
|
|
|
expect(screen.queryByText('OpenAI')).toBeNull();
|
|
expect(screen.queryByTestId('model-picker-option-gpt-image-2')).toBeNull();
|
|
});
|
|
|
|
it('uses Vela as the default image provider without media API credentials', async () => {
|
|
const onCreate = vi.fn();
|
|
render(
|
|
<NewProjectPanel
|
|
skills={[]}
|
|
designSystems={[]}
|
|
defaultDesignSystemId={null}
|
|
templates={[]}
|
|
onDeleteTemplate={vi.fn()}
|
|
promptTemplates={[]}
|
|
onCreate={onCreate}
|
|
mediaProviders={{}}
|
|
/>,
|
|
);
|
|
|
|
fireEvent.click(screen.getByRole('tab', { name: 'Media' }));
|
|
fireEvent.click(screen.getByRole('tab', { name: 'Image' }));
|
|
await waitFor(() => {
|
|
expect(screen.getByTestId('model-picker-trigger').textContent).toContain('gpt-image-2 (Cloud)');
|
|
});
|
|
fireEvent.change(screen.getByTestId('new-project-name'), {
|
|
target: { value: 'Vela default image' },
|
|
});
|
|
fireEvent.click(screen.getByTestId('create-project'));
|
|
|
|
expect(onCreate).toHaveBeenCalledWith(
|
|
expect.objectContaining({
|
|
metadata: expect.objectContaining({
|
|
kind: 'image',
|
|
imageModel: 'vela/gpt-image-2',
|
|
imageAspect: '1:1',
|
|
}),
|
|
}),
|
|
);
|
|
});
|
|
|
|
it('treats a legacy template gpt-image-2 recommendation as the managed Cloud route', async () => {
|
|
const template = {
|
|
id: 'legacy-gpt-image-template',
|
|
surface: 'image' as const,
|
|
title: 'Legacy GPT image template',
|
|
summary: 'A legacy first-party image template.',
|
|
category: 'Poster',
|
|
tags: ['legacy'],
|
|
model: 'gpt-image-2',
|
|
aspect: '16:9' as const,
|
|
source: {
|
|
repo: 'example/templates',
|
|
license: 'MIT',
|
|
},
|
|
};
|
|
vi.stubGlobal('fetch', vi.fn(async () => new Response(JSON.stringify({
|
|
promptTemplate: {
|
|
...template,
|
|
prompt: 'A detailed cinematic image prompt with enough content for validation.',
|
|
},
|
|
}), {
|
|
status: 200,
|
|
headers: { 'content-type': 'application/json' },
|
|
})));
|
|
const onCreate = vi.fn();
|
|
|
|
render(
|
|
<NewProjectPanel
|
|
skills={[]}
|
|
designSystems={[]}
|
|
defaultDesignSystemId={null}
|
|
templates={[]}
|
|
onDeleteTemplate={vi.fn()}
|
|
promptTemplates={[template]}
|
|
onCreate={onCreate}
|
|
mediaProviders={{
|
|
openai: {
|
|
apiKey: '',
|
|
apiKeyConfigured: true,
|
|
apiKeyTail: '1234',
|
|
baseUrl: '',
|
|
},
|
|
}}
|
|
/>,
|
|
);
|
|
|
|
fireEvent.click(screen.getByRole('tab', { name: 'Media' }));
|
|
fireEvent.click(screen.getByRole('tab', { name: 'Image' }));
|
|
fireEvent.click(screen.getByTestId('prompt-template-trigger'));
|
|
fireEvent.click(screen.getByRole('option', { name: /Legacy GPT image template/ }));
|
|
await waitFor(() => {
|
|
expect(screen.getByTestId('prompt-template-body')).toHaveValue(
|
|
'A detailed cinematic image prompt with enough content for validation.',
|
|
);
|
|
});
|
|
fireEvent.change(screen.getByTestId('new-project-name'), {
|
|
target: { value: 'Managed template image' },
|
|
});
|
|
fireEvent.click(screen.getByTestId('create-project'));
|
|
|
|
expect(onCreate).toHaveBeenCalledWith(
|
|
expect.objectContaining({
|
|
metadata: expect.objectContaining({
|
|
kind: 'image',
|
|
imageModel: 'vela/gpt-image-2',
|
|
imageAspect: '16:9',
|
|
promptTemplate: expect.objectContaining({
|
|
model: 'vela/gpt-image-2',
|
|
}),
|
|
}),
|
|
}),
|
|
);
|
|
});
|
|
|
|
it('preserves an explicit OpenAI model picker selection as BYOK', () => {
|
|
const onCreate = vi.fn();
|
|
render(
|
|
<NewProjectPanel
|
|
skills={[]}
|
|
designSystems={[]}
|
|
defaultDesignSystemId={null}
|
|
templates={[]}
|
|
onDeleteTemplate={vi.fn()}
|
|
promptTemplates={[]}
|
|
onCreate={onCreate}
|
|
mediaProviders={{
|
|
openai: {
|
|
apiKey: '',
|
|
apiKeyConfigured: true,
|
|
apiKeyTail: '1234',
|
|
baseUrl: '',
|
|
},
|
|
}}
|
|
/>,
|
|
);
|
|
|
|
fireEvent.click(screen.getByRole('tab', { name: 'Media' }));
|
|
fireEvent.click(screen.getByRole('tab', { name: 'Image' }));
|
|
fireEvent.click(screen.getByTestId('model-picker-trigger'));
|
|
fireEvent.click(screen.getByTestId('model-picker-option-gpt-image-2'));
|
|
fireEvent.change(screen.getByTestId('new-project-name'), {
|
|
target: { value: 'Explicit BYOK image' },
|
|
});
|
|
fireEvent.click(screen.getByTestId('create-project'));
|
|
|
|
expect(onCreate).toHaveBeenCalledWith(
|
|
expect.objectContaining({
|
|
metadata: expect.objectContaining({
|
|
imageModel: 'gpt-image-2',
|
|
}),
|
|
}),
|
|
);
|
|
});
|
|
|
|
it('does not treat OpenAI OAuth-only markers as usable image credentials', () => {
|
|
render(
|
|
<NewProjectPanel
|
|
skills={[]}
|
|
designSystems={[]}
|
|
defaultDesignSystemId={null}
|
|
templates={[]}
|
|
onDeleteTemplate={vi.fn()}
|
|
promptTemplates={[]}
|
|
onCreate={vi.fn()}
|
|
mediaProviders={{
|
|
openai: {
|
|
apiKey: '',
|
|
apiKeyConfigured: true,
|
|
apiKeyTail: '',
|
|
source: 'oauth-codex',
|
|
baseUrl: '',
|
|
},
|
|
}}
|
|
/>,
|
|
);
|
|
|
|
fireEvent.click(screen.getByRole('tab', { name: 'Media' }));
|
|
fireEvent.click(screen.getByRole('tab', { name: 'Image' }));
|
|
fireEvent.click(screen.getByTestId('model-picker-trigger'));
|
|
|
|
expect(screen.queryByText('OpenAI')).toBeNull();
|
|
expect(screen.queryByTestId('model-picker-option-gpt-image-2')).toBeNull();
|
|
});
|
|
|
|
it('keeps the managed Vela default when another provider is configured', () => {
|
|
const onCreate = vi.fn();
|
|
render(
|
|
<NewProjectPanel
|
|
skills={[]}
|
|
designSystems={[]}
|
|
defaultDesignSystemId={null}
|
|
templates={[]}
|
|
onDeleteTemplate={vi.fn()}
|
|
promptTemplates={[]}
|
|
onCreate={onCreate}
|
|
mediaProviders={{
|
|
volcengine: {
|
|
apiKey: '',
|
|
apiKeyConfigured: true,
|
|
apiKeyTail: '5678',
|
|
baseUrl: '',
|
|
},
|
|
}}
|
|
/>,
|
|
);
|
|
|
|
fireEvent.click(screen.getByRole('tab', { name: 'Media' }));
|
|
fireEvent.click(screen.getByRole('tab', { name: 'Image' }));
|
|
fireEvent.change(screen.getByTestId('new-project-name'), {
|
|
target: { value: 'Configured provider image' },
|
|
});
|
|
fireEvent.click(screen.getByTestId('create-project'));
|
|
|
|
expect(onCreate).toHaveBeenCalledWith(
|
|
expect.objectContaining({
|
|
metadata: expect.objectContaining({
|
|
imageModel: 'vela/gpt-image-2',
|
|
}),
|
|
}),
|
|
);
|
|
});
|
|
});
|