import { fireEvent, render, screen, waitFor } from '@testing-library/react';
import { beforeEach, describe, expect, it, vi } from 'vitest';
import { ProvidersSettings } from '@/components/settings/ProvidersSettings';
const baseProviderState = {
statuses: [
{
id: 'moonshot-existing',
name: 'Moonshot Existing',
type: 'moonshot',
model: 'kimi-k2.6',
enabled: true,
createdAt: '2026-06-19T00:00:00.000Z',
updatedAt: '2026-06-19T00:00:00.000Z',
hasKey: true,
keyMasked: 'sk-***',
},
],
accounts: [
{
id: 'moonshot-existing',
vendorId: 'moonshot',
label: 'Moonshot Existing',
authMode: 'api_key',
model: 'kimi-k2.6',
enabled: true,
isDefault: true,
createdAt: '2026-06-19T00:00:00.000Z',
updatedAt: '2026-06-19T00:00:00.000Z',
},
],
vendors: [],
defaultAccountId: 'moonshot-existing',
loading: false,
refreshProviderSnapshot: vi.fn().mockResolvedValue(undefined),
createAccount: vi.fn().mockResolvedValue(undefined),
removeAccount: vi.fn().mockResolvedValue(undefined),
updateAccount: vi.fn().mockResolvedValue(undefined),
setDefaultAccount: vi.fn().mockResolvedValue(undefined),
importUserModelConfig: vi.fn().mockResolvedValue({
account: {
id: 'niancode-user-models',
vendorId: 'custom',
label: 'Makelore Models',
authMode: 'api_key',
enabled: true,
isDefault: true,
createdAt: '2026-06-19T00:00:00.000Z',
updatedAt: '2026-06-19T00:00:00.000Z',
},
importedModels: ['gpt-4.1-mini'],
}),
validateAccountApiKey: vi.fn().mockResolvedValue({ valid: true }),
};
let providerState: typeof baseProviderState;
const authState = {
accessToken: null as string | null,
};
vi.mock('@/stores/settings', () => ({
useSettingsStore: (selector: (state: { devModeUnlocked: boolean }) => unknown) => selector({ devModeUnlocked: true }),
}));
vi.mock('@/stores/auth', () => ({
useAuthStore: (selector: (state: { accessToken: string | null }) => unknown) => selector(authState),
}));
vi.mock('@/stores/providers', () => ({
useProviderStore: () => providerState,
}));
vi.mock('react-i18next', () => ({
useTranslation: () => ({
i18n: { language: 'en' },
t: (key: string, fallback?: string) => fallback ?? key,
}),
}));
describe('ProvidersSettings', () => {
beforeEach(() => {
providerState = {
...baseProviderState,
statuses: [...baseProviderState.statuses],
accounts: [...baseProviderState.accounts],
importUserModelConfig: vi.fn().mockResolvedValue({
account: {
id: 'niancode-user-models',
vendorId: 'custom',
label: 'Makelore Models',
authMode: 'api_key',
enabled: true,
isDefault: true,
createdAt: '2026-06-19T00:00:00.000Z',
updatedAt: '2026-06-19T00:00:00.000Z',
},
importedModels: ['gpt-4.1-mini'],
}),
};
authState.accessToken = null;
vi.clearAllMocks();
});
it('keeps add, edit, and delete controls available after one provider is configured', () => {
render();
const editButton = screen.getByTestId('provider-edit-moonshot-existing');
const deleteButton = screen.getByTestId('provider-delete-moonshot-existing');
expect(editButton).toBeVisible();
expect(deleteButton).toBeVisible();
expect(editButton.parentElement).not.toHaveClass('opacity-0');
fireEvent.click(screen.getByTestId('providers-add-button'));
expect(screen.getByTestId('add-provider-type-moonshot')).toBeVisible();
});
it('syncs current user model config even when the NianCode model account already exists', async () => {
authState.accessToken = 'access-token';
providerState.accounts = [
{
id: 'niancode-user-models',
vendorId: 'custom',
label: 'Old Makelore Models',
authMode: 'api_key',
model: 'old-model',
fallbackModels: ['old-fallback'],
enabled: true,
isDefault: true,
createdAt: '2026-06-19T00:00:00.000Z',
updatedAt: '2026-06-19T00:00:00.000Z',
},
];
render();
await waitFor(() => {
expect(providerState.importUserModelConfig).toHaveBeenCalledWith('access-token');
});
});
});