test(git): implement backend and frontend test coverage for git integration
This commit is contained in:
@@ -0,0 +1,209 @@
|
||||
// [DEF:frontend.src.routes.settings.git.__tests__.git_settings_page_ux_test:Module]
|
||||
// @RELATION: VERIFIES -> ../+page.svelte
|
||||
// @PURPOSE: Test UX states and transitions for the Git Settings page
|
||||
|
||||
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
||||
import { render, screen, fireEvent, waitFor } from '@testing-library/svelte';
|
||||
import GitSettingsPage from '../+page.svelte';
|
||||
import { gitService } from '../../../../services/gitService';
|
||||
import { addToast } from '$lib/toasts';
|
||||
|
||||
vi.mock('../../../../services/gitService', () => ({
|
||||
gitService: {
|
||||
getConfigs: vi.fn(),
|
||||
createConfig: vi.fn(),
|
||||
updateConfig: vi.fn(),
|
||||
deleteConfig: vi.fn(),
|
||||
testConnection: vi.fn(),
|
||||
listGiteaRepositories: vi.fn(),
|
||||
createGiteaRepository: vi.fn(),
|
||||
deleteGiteaRepository: vi.fn()
|
||||
}
|
||||
}));
|
||||
|
||||
vi.mock('$lib/toasts', () => ({
|
||||
addToast: vi.fn()
|
||||
}));
|
||||
|
||||
vi.mock('$lib/i18n', () => ({
|
||||
t: {
|
||||
subscribe: (fn) => {
|
||||
fn({
|
||||
settings: {
|
||||
configured_servers: 'Configured Servers',
|
||||
add_git_server: 'Add Git Server',
|
||||
edit_git_server: 'Edit Git Server',
|
||||
display_name: 'Display Name',
|
||||
server_url: 'Server URL',
|
||||
personal_access_token: 'Personal Access Token',
|
||||
default_repository_optional: 'Default Repository (Optional)',
|
||||
default_branch: 'Default Branch',
|
||||
save_configuration: 'Save Configuration',
|
||||
update_configuration: 'Update Configuration',
|
||||
connection_success: 'Connection successful',
|
||||
connection_failed_short: 'Connection failed',
|
||||
git_config_saved: 'Git configuration saved',
|
||||
git_config_updated: 'Git configuration updated',
|
||||
git_delete_confirm: 'Are you sure?',
|
||||
git_config_deleted: 'Git configuration deleted'
|
||||
},
|
||||
llm: { type: 'Type', test: 'Test' },
|
||||
nav: { settings_git: 'Git Settings' },
|
||||
git: { no_servers_configured: 'No servers configured' },
|
||||
common: { edit: 'Edit', delete: 'Delete', cancel: 'Cancel' }
|
||||
});
|
||||
return () => { };
|
||||
}
|
||||
},
|
||||
_: vi.fn((key) => key)
|
||||
}));
|
||||
|
||||
// Mock window.scrollTo
|
||||
Object.defineProperty(window, 'scrollTo', { value: vi.fn(), writable: true });
|
||||
|
||||
describe('GitSettingsPage UX Contracts', () => {
|
||||
const mockConfigs = [
|
||||
{
|
||||
id: 'conf-1',
|
||||
name: 'Dev GitLab',
|
||||
provider: 'GITLAB',
|
||||
url: 'https://gitlab.com',
|
||||
pat: '********',
|
||||
status: 'CONNECTED'
|
||||
}
|
||||
];
|
||||
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
// Default confirm to always accept for tests
|
||||
global.confirm = vi.fn(() => true);
|
||||
});
|
||||
|
||||
// @UX_STATE: Initial Load
|
||||
it('should display configured servers on mount', async () => {
|
||||
gitService.getConfigs.mockResolvedValue(mockConfigs);
|
||||
render(GitSettingsPage);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(screen.getByText('Dev GitLab')).toBeTruthy();
|
||||
expect(screen.getByText('GITLAB')).toBeTruthy();
|
||||
expect(screen.getByText('https://gitlab.com')).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
it('should show empty state when no servers configured', async () => {
|
||||
gitService.getConfigs.mockResolvedValue([]);
|
||||
render(GitSettingsPage);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(screen.getByText('No servers configured')).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
// @UX_FEEDBACK: Connection testing feedback
|
||||
it('should test connection successfully and show success toast', async () => {
|
||||
gitService.getConfigs.mockResolvedValue([]);
|
||||
gitService.testConnection.mockResolvedValue({ status: 'success' });
|
||||
|
||||
render(GitSettingsPage);
|
||||
await waitFor(() => expect(screen.getByText('Add Git Server')).toBeTruthy());
|
||||
|
||||
// Fill form
|
||||
await fireEvent.input(screen.getByLabelText('Display Name'), { target: { value: 'New Gitea' } });
|
||||
await fireEvent.input(screen.getByLabelText('Server URL'), { target: { value: 'https://gitea.local' } });
|
||||
await fireEvent.input(screen.getByLabelText('Personal Access Token'), { target: { value: 'token123' } });
|
||||
|
||||
// Click Test
|
||||
await fireEvent.click(screen.getByText('Test'));
|
||||
|
||||
await waitFor(() => {
|
||||
expect(gitService.testConnection).toHaveBeenCalledWith(expect.objectContaining({
|
||||
name: 'New Gitea',
|
||||
url: 'https://gitea.local',
|
||||
pat: 'token123'
|
||||
}));
|
||||
expect(addToast).toHaveBeenCalledWith('Connection successful', 'success');
|
||||
});
|
||||
});
|
||||
|
||||
// @UX_FEEDBACK: Save configuration
|
||||
it('should save configuration and show success toast', async () => {
|
||||
gitService.getConfigs.mockResolvedValue([]);
|
||||
gitService.createConfig.mockResolvedValue({
|
||||
id: 'conf-2',
|
||||
name: 'New Server',
|
||||
provider: 'GITHUB',
|
||||
url: 'https://github.com',
|
||||
pat: '********',
|
||||
status: 'CONNECTED'
|
||||
});
|
||||
|
||||
render(GitSettingsPage);
|
||||
await waitFor(() => expect(screen.getByText('Add Git Server')).toBeTruthy());
|
||||
|
||||
await fireEvent.input(screen.getByLabelText('Display Name'), { target: { value: 'New Server' } });
|
||||
await fireEvent.click(screen.getByText('Save Configuration'));
|
||||
|
||||
await waitFor(() => {
|
||||
expect(gitService.createConfig).toHaveBeenCalled();
|
||||
expect(addToast).toHaveBeenCalledWith('Git configuration saved', 'success');
|
||||
// Check that it's added to the list
|
||||
expect(screen.getByText('New Server')).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
// @UX_STATE: Delete configuration
|
||||
it('should delete configuration upon confirmation', async () => {
|
||||
gitService.getConfigs.mockResolvedValue([...mockConfigs]);
|
||||
gitService.deleteConfig.mockResolvedValue({ status: 'success' });
|
||||
|
||||
render(GitSettingsPage);
|
||||
await waitFor(() => expect(screen.getByText('Dev GitLab')).toBeTruthy());
|
||||
|
||||
// Click delete button
|
||||
const deleteButton = screen.getByTitle('Delete');
|
||||
await fireEvent.click(deleteButton);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(global.confirm).toHaveBeenCalledWith('Are you sure?');
|
||||
expect(gitService.deleteConfig).toHaveBeenCalledWith('conf-1');
|
||||
expect(addToast).toHaveBeenCalledWith('Git configuration deleted', 'success');
|
||||
expect(screen.queryByText('Dev GitLab')).toBeNull(); // Should be removed from DOM
|
||||
});
|
||||
});
|
||||
|
||||
// @UX_STATE: Editing form state
|
||||
it('should load config into form when edit is clicked', async () => {
|
||||
gitService.getConfigs.mockResolvedValue([...mockConfigs]);
|
||||
|
||||
render(GitSettingsPage);
|
||||
await waitFor(() => expect(screen.getByText('Dev GitLab')).toBeTruthy());
|
||||
|
||||
// Click edit button
|
||||
const editButton = screen.getByTitle('Edit');
|
||||
await fireEvent.click(editButton);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(screen.getByText('Edit Git Server')).toBeTruthy();
|
||||
const nameInput = screen.getByLabelText('Display Name');
|
||||
expect(nameInput.value).toBe('Dev GitLab');
|
||||
});
|
||||
|
||||
// Save changes
|
||||
gitService.updateConfig.mockResolvedValue({
|
||||
...mockConfigs[0],
|
||||
name: 'Updated GitLab'
|
||||
});
|
||||
|
||||
await fireEvent.input(screen.getByLabelText('Display Name'), { target: { value: 'Updated GitLab' } });
|
||||
await fireEvent.click(screen.getByText('Update Configuration'));
|
||||
|
||||
await waitFor(() => {
|
||||
expect(gitService.updateConfig).toHaveBeenCalledWith('conf-1', expect.objectContaining({
|
||||
name: 'Updated GitLab'
|
||||
}));
|
||||
expect(screen.getByText('Updated GitLab')).toBeTruthy();
|
||||
});
|
||||
});
|
||||
});
|
||||
// [/DEF:frontend.src.routes.settings.git.__tests__.git_settings_page_ux_test:Module]
|
||||
Reference in New Issue
Block a user