open-design/apps/web/tests/components/NewProjectPanel.media.test.tsx
xinsngx 41b1cd763e
fix(media): hide OpenAI OAuth-only image credentials (#3308)
* fix(media): ignore OpenAI OAuth tokens

Agent-Model: gpt-5

Agent-Family: openai

Agent-Session: 019e6ceb-c33d-7cd3-bff0-cbc20c642197

Agent-Step: 0.0.1

* fix(media): hide unavailable model providers

Agent-Model: gpt-5

Agent-Family: openai

Agent-Session: 019e6ceb-c33d-7cd3-bff0-cbc20c642197

Agent-Step: 0.0.2

* fix(media): clear unavailable picker models

Agent-Model: gpt-5
Agent-Family: openai
Agent-Session: 019e6ceb-c33d-7cd3-bff0-cbc20c642197
Agent-Step: 0.0.3

* fix(media): keep missing-model projects executable

Agent-Model: gpt-5
Agent-Family: openai
Agent-Session: 019e6ceb-c33d-7cd3-bff0-cbc20c642197
Agent-Step: 0.0.8

---------

Co-authored-by: Codex <gpt-5@openai.com>
2026-05-30 04:12:10 +00:00

179 lines
5.3 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('does not submit a hidden default model when no image provider is eligible', 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('Pick a model');
});
fireEvent.change(screen.getByTestId('new-project-name'), {
target: { value: 'No configured image model' },
});
fireEvent.click(screen.getByTestId('create-project'));
expect(onCreate).toHaveBeenCalledWith(
expect.objectContaining({
metadata: expect.objectContaining({
kind: 'image',
imageAspect: '1:1',
}),
}),
);
expect(onCreate.mock.calls[0]?.[0].metadata).not.toHaveProperty('imageModel');
});
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('switches away from the default OpenAI model when only 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: 'doubao-seedream-3-0-t2i-250415',
}),
}),
);
});
});