Update expo application
This commit is contained in:
@@ -0,0 +1,187 @@
|
||||
import { fireEvent, render, screen, waitFor } from '@testing-library/react';
|
||||
import { describe, expect, test, vi } from 'vitest';
|
||||
|
||||
import { AiProviderProfileForm } from '../../src/components/settings/ai-provider-profile-form';
|
||||
import { SpoonAgentSettingsForm } from '../../src/components/spoons/spoon-agent-settings-form';
|
||||
import { SpoonSecretsPanel } from '../../src/components/spoons/spoon-secrets-panel';
|
||||
|
||||
describe('mobile forms', () => {
|
||||
test('SpoonSecretsPanel previews secret names only and imports parsed env values', async () => {
|
||||
const onImportSecrets = vi.fn().mockResolvedValue(undefined);
|
||||
|
||||
render(
|
||||
<SpoonSecretsPanel
|
||||
adding={false}
|
||||
importing={false}
|
||||
removingId={undefined}
|
||||
secrets={[]}
|
||||
onAddSecret={vi.fn()}
|
||||
onImportSecrets={onImportSecrets}
|
||||
onRemoveSecret={vi.fn()}
|
||||
/>,
|
||||
);
|
||||
|
||||
fireEvent.change(screen.getByPlaceholderText('AUTH_SECRET=...'), {
|
||||
target: {
|
||||
value: 'AUTH_SECRET=super-secret\nexport AUTHENTIK_CLIENT_ID=client',
|
||||
},
|
||||
});
|
||||
|
||||
expect(screen.getAllByText(/AUTH_SECRET/).length).toBeGreaterThan(0);
|
||||
expect(screen.getAllByText(/AUTHENTIK_CLIENT_ID/).length).toBeGreaterThan(
|
||||
0,
|
||||
);
|
||||
expect(screen.getByText(/valid secrets found/).textContent).not.toContain(
|
||||
'super-secret',
|
||||
);
|
||||
|
||||
fireEvent.click(screen.getByText('Import secrets'));
|
||||
|
||||
await waitFor(() =>
|
||||
expect(onImportSecrets).toHaveBeenCalledWith([
|
||||
{ name: 'AUTH_SECRET', value: 'super-secret' },
|
||||
{ name: 'AUTHENTIK_CLIENT_ID', value: 'client' },
|
||||
]),
|
||||
);
|
||||
});
|
||||
|
||||
test('SpoonSecretsPanel disables import with no parsed secrets', () => {
|
||||
render(
|
||||
<SpoonSecretsPanel
|
||||
adding={false}
|
||||
importing={false}
|
||||
removingId={undefined}
|
||||
secrets={[]}
|
||||
onAddSecret={vi.fn()}
|
||||
onImportSecrets={vi.fn()}
|
||||
onRemoveSecret={vi.fn()}
|
||||
/>,
|
||||
);
|
||||
|
||||
expect(screen.getByText('Import secrets').closest('button')).toBeDisabled();
|
||||
});
|
||||
|
||||
test('AiProviderProfileForm selects default model from model options', async () => {
|
||||
const onSubmit = vi.fn().mockResolvedValue(undefined);
|
||||
|
||||
render(
|
||||
<AiProviderProfileForm
|
||||
saving={false}
|
||||
onSubmit={onSubmit}
|
||||
existing={{
|
||||
_id: 'profile' as never,
|
||||
authType: 'api_key',
|
||||
defaultModel: 'gpt-5.1-codex',
|
||||
enabled: true,
|
||||
modelOptions: ['gpt-5.1-codex', 'gpt-5.5'],
|
||||
name: 'OpenAI',
|
||||
provider: 'openai',
|
||||
reasoningEffort: 'medium',
|
||||
}}
|
||||
/>,
|
||||
);
|
||||
|
||||
fireEvent.click(screen.getByText('gpt-5.1-codex'));
|
||||
fireEvent.click(screen.getByText('gpt-5.5'));
|
||||
fireEvent.click(screen.getByText('Save provider'));
|
||||
|
||||
await waitFor(() =>
|
||||
expect(onSubmit).toHaveBeenCalledWith(
|
||||
expect.objectContaining({ defaultModel: 'gpt-5.5' }),
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
test('AiProviderProfileForm shows Codex auth JSON instructions', () => {
|
||||
render(
|
||||
<AiProviderProfileForm
|
||||
saving={false}
|
||||
onSubmit={vi.fn()}
|
||||
existing={{
|
||||
_id: 'profile' as never,
|
||||
authType: 'opencode_auth_json',
|
||||
defaultModel: 'gpt-5.1-codex',
|
||||
enabled: true,
|
||||
modelOptions: ['gpt-5.1-codex'],
|
||||
name: 'Codex',
|
||||
provider: 'opencode_openai_login',
|
||||
reasoningEffort: 'medium',
|
||||
}}
|
||||
/>,
|
||||
);
|
||||
|
||||
expect(screen.getByText(/~\/.codex\/auth.json/)).toBeTruthy();
|
||||
});
|
||||
|
||||
test('SpoonAgentSettingsForm disables provider/model controls without provider profiles', () => {
|
||||
render(
|
||||
<SpoonAgentSettingsForm
|
||||
profiles={[]}
|
||||
onUpdate={vi.fn()}
|
||||
agent={{
|
||||
agentModel: '',
|
||||
autoDetectCommands: true,
|
||||
branchPrefix: 'spoon/agent',
|
||||
enabled: true,
|
||||
materializeEnvFileByDefault: false,
|
||||
reasoningEffort: 'medium',
|
||||
}}
|
||||
/>,
|
||||
);
|
||||
|
||||
expect(
|
||||
screen.getByText('Configure an AI provider in Settings'),
|
||||
).toBeTruthy();
|
||||
expect(
|
||||
screen.getByText('No models available').closest('button'),
|
||||
).toBeDisabled();
|
||||
});
|
||||
|
||||
test('SpoonAgentSettingsForm applies selected provider defaults', async () => {
|
||||
const onUpdate = vi.fn().mockResolvedValue(undefined);
|
||||
|
||||
render(
|
||||
<SpoonAgentSettingsForm
|
||||
agent={{
|
||||
agentModel: 'gpt-5.1-codex',
|
||||
autoDetectCommands: true,
|
||||
branchPrefix: 'spoon/agent',
|
||||
enabled: true,
|
||||
materializeEnvFileByDefault: false,
|
||||
reasoningEffort: 'high',
|
||||
}}
|
||||
profiles={[
|
||||
{
|
||||
_id: 'profile-a' as never,
|
||||
defaultModel: 'gpt-5.1-codex',
|
||||
enabled: true,
|
||||
modelOptions: ['gpt-5.1-codex'],
|
||||
name: 'OpenAI',
|
||||
reasoningEffort: 'medium',
|
||||
},
|
||||
{
|
||||
_id: 'profile-b' as never,
|
||||
defaultModel: 'claude-sonnet-4-5',
|
||||
enabled: true,
|
||||
modelOptions: ['claude-sonnet-4-5'],
|
||||
name: 'Anthropic',
|
||||
reasoningEffort: 'low',
|
||||
},
|
||||
]}
|
||||
onUpdate={onUpdate}
|
||||
/>,
|
||||
);
|
||||
|
||||
fireEvent.click(screen.getByText('OpenAI'));
|
||||
fireEvent.click(screen.getByText('Anthropic'));
|
||||
|
||||
await waitFor(() =>
|
||||
expect(onUpdate).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
agentModel: 'claude-sonnet-4-5',
|
||||
reasoningEffort: 'low',
|
||||
}),
|
||||
),
|
||||
);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user