test(git): implement backend and frontend test coverage for git integration
This commit is contained in:
245
frontend/src/services/__tests__/gitService.test.js
Normal file
245
frontend/src/services/__tests__/gitService.test.js
Normal file
@@ -0,0 +1,245 @@
|
||||
// [DEF:frontend.src.services.__tests__.gitService_test:Module]
|
||||
// @RELATION: VERIFIES -> ../gitService.js
|
||||
// @PURPOSE: API client tests ensuring correct endpoints are called per contract
|
||||
|
||||
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
||||
import { gitService } from '../gitService';
|
||||
import { requestApi } from '../../lib/api';
|
||||
|
||||
vi.mock('../../lib/api', () => ({
|
||||
requestApi: vi.fn()
|
||||
}));
|
||||
|
||||
describe('gitService', () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
describe('Config Management', () => {
|
||||
// @PRE User authenticated
|
||||
// @POST Returns list of Git configs
|
||||
it('getConfigs calls /git/config', async () => {
|
||||
requestApi.mockResolvedValue([]);
|
||||
const result = await gitService.getConfigs();
|
||||
expect(requestApi).toHaveBeenCalledWith('/git/config');
|
||||
expect(result).toEqual([]);
|
||||
});
|
||||
|
||||
// @PRE Config object must be valid
|
||||
// @POST New config created and returned
|
||||
it('createConfig calls POST /git/config', async () => {
|
||||
const config = { name: 'Test', provider: 'GITHUB' };
|
||||
requestApi.mockResolvedValue({ id: '1', ...config });
|
||||
const result = await gitService.createConfig(config);
|
||||
expect(requestApi).toHaveBeenCalledWith('/git/config', 'POST', config);
|
||||
expect(result.id).toBe('1');
|
||||
});
|
||||
|
||||
// @PRE configId must exist
|
||||
// @POST Config deleted
|
||||
it('deleteConfig calls DELETE /git/config/:id', async () => {
|
||||
requestApi.mockResolvedValue({ status: 'success' });
|
||||
await gitService.deleteConfig('config-123');
|
||||
expect(requestApi).toHaveBeenCalledWith('/git/config/config-123', 'DELETE');
|
||||
});
|
||||
|
||||
// @PRE configId must exist
|
||||
// @POST Config updated
|
||||
it('updateConfig calls PUT /git/config/:id', async () => {
|
||||
const config = { name: 'Updated' };
|
||||
requestApi.mockResolvedValue({ id: 'config-123', ...config });
|
||||
await gitService.updateConfig('config-123', config);
|
||||
expect(requestApi).toHaveBeenCalledWith('/git/config/config-123', 'PUT', config);
|
||||
});
|
||||
|
||||
// @PRE Config must contain valid URL and PAT
|
||||
// @POST Returns connection status
|
||||
it('testConnection calls POST /git/config/test', async () => {
|
||||
const config = { url: 'https://github.com', pat: 'secret' };
|
||||
requestApi.mockResolvedValue({ status: 'success' });
|
||||
await gitService.testConnection(config);
|
||||
expect(requestApi).toHaveBeenCalledWith('/git/config/test', 'POST', config);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Remote Repository Management', () => {
|
||||
// @PRE configId references GITEA
|
||||
// @POST Returns repo metadata
|
||||
it('listGiteaRepositories calls GET /git/config/:id/gitea/repos', async () => {
|
||||
requestApi.mockResolvedValue([]);
|
||||
await gitService.listGiteaRepositories('conf-1');
|
||||
expect(requestApi).toHaveBeenCalledWith('/git/config/conf-1/gitea/repos');
|
||||
});
|
||||
|
||||
// @PRE configId references GITEA
|
||||
// @POST Repo created on Gitea
|
||||
it('createGiteaRepository calls POST /git/config/:id/gitea/repos', async () => {
|
||||
const payload = { name: 'new-repo' };
|
||||
requestApi.mockResolvedValue({ name: 'new-repo' });
|
||||
await gitService.createGiteaRepository('conf-1', payload);
|
||||
expect(requestApi).toHaveBeenCalledWith('/git/config/conf-1/gitea/repos', 'POST', payload);
|
||||
});
|
||||
|
||||
// @PRE configId references supported provider
|
||||
// @POST Remote repo created
|
||||
it('createRemoteRepository calls POST /git/config/:id/repositories', async () => {
|
||||
const payload = { name: 'new-remote' };
|
||||
requestApi.mockResolvedValue({ name: 'new-remote' });
|
||||
await gitService.createRemoteRepository('conf-1', payload);
|
||||
expect(requestApi).toHaveBeenCalledWith('/git/config/conf-1/repositories', 'POST', payload);
|
||||
});
|
||||
|
||||
// @PRE configId references GITEA
|
||||
// @POST Repo deleted on Gitea
|
||||
it('deleteGiteaRepository calls DELETE with encoded owner and repo', async () => {
|
||||
requestApi.mockResolvedValue({ status: 'success' });
|
||||
await gitService.deleteGiteaRepository('conf-1', 'my-org', 'my-repo');
|
||||
expect(requestApi).toHaveBeenCalledWith('/git/config/conf-1/gitea/repos/my-org/my-repo', 'DELETE');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Dashboard Repository Operations', () => {
|
||||
// @PRE Dashboard exists and config_id valid
|
||||
// @POST Repo initialized
|
||||
it('initRepository calls POST with remote_url and config_id', async () => {
|
||||
requestApi.mockResolvedValue({});
|
||||
await gitService.initRepository(123, 'conf-1', 'http://remote.git');
|
||||
expect(requestApi).toHaveBeenCalledWith('/git/repositories/123/init', 'POST', {
|
||||
config_id: 'conf-1', remote_url: 'http://remote.git'
|
||||
});
|
||||
});
|
||||
|
||||
// @PRE Repo initialized
|
||||
// @POST Returns binding
|
||||
it('getRepositoryBinding calls GET', async () => {
|
||||
requestApi.mockResolvedValue({});
|
||||
await gitService.getRepositoryBinding('dash-slug');
|
||||
expect(requestApi).toHaveBeenCalledWith('/git/repositories/dash-slug');
|
||||
});
|
||||
|
||||
// @PRE Repo initialized
|
||||
// @POST Returns branches
|
||||
it('getBranches calls GET /branches', async () => {
|
||||
requestApi.mockResolvedValue([]);
|
||||
await gitService.getBranches(123);
|
||||
expect(requestApi).toHaveBeenCalledWith('/git/repositories/123/branches');
|
||||
});
|
||||
|
||||
// @PRE Source branch exists
|
||||
// @POST New branch created
|
||||
it('createBranch calls POST /branches with name and from_branch', async () => {
|
||||
requestApi.mockResolvedValue({});
|
||||
await gitService.createBranch(123, 'feature', 'main');
|
||||
expect(requestApi).toHaveBeenCalledWith('/git/repositories/123/branches', 'POST', {
|
||||
name: 'feature', from_branch: 'main'
|
||||
});
|
||||
});
|
||||
|
||||
// @PRE Target branch exists
|
||||
// @POST Repo checked out
|
||||
it('checkoutBranch calls POST /checkout', async () => {
|
||||
requestApi.mockResolvedValue({});
|
||||
await gitService.checkoutBranch(123, 'feature');
|
||||
expect(requestApi).toHaveBeenCalledWith('/git/repositories/123/checkout', 'POST', { name: 'feature' });
|
||||
});
|
||||
|
||||
// @PRE Message not empty
|
||||
// @POST Changes committed
|
||||
it('commit calls POST /commit with message and files', async () => {
|
||||
requestApi.mockResolvedValue({});
|
||||
await gitService.commit(123, 'Initial commit', ['file.txt']);
|
||||
expect(requestApi).toHaveBeenCalledWith('/git/repositories/123/commit', 'POST', {
|
||||
message: 'Initial commit', files: ['file.txt']
|
||||
});
|
||||
});
|
||||
|
||||
// @PRE Remote configured
|
||||
// @POST Remote updated
|
||||
it('push calls POST /push', async () => {
|
||||
requestApi.mockResolvedValue({});
|
||||
await gitService.push(123);
|
||||
expect(requestApi).toHaveBeenCalledWith('/git/repositories/123/push', 'POST');
|
||||
});
|
||||
|
||||
// @PRE Dashboard ref valid
|
||||
// @POST Repo deleted
|
||||
it('deleteRepository calls DELETE', async () => {
|
||||
requestApi.mockResolvedValue({});
|
||||
await gitService.deleteRepository(123);
|
||||
expect(requestApi).toHaveBeenCalledWith('/git/repositories/123', 'DELETE');
|
||||
});
|
||||
|
||||
// @PRE Remote configured
|
||||
// @POST Local repo updated
|
||||
it('pull calls POST /pull', async () => {
|
||||
requestApi.mockResolvedValue({});
|
||||
await gitService.pull(123);
|
||||
expect(requestApi).toHaveBeenCalledWith('/git/repositories/123/pull', 'POST');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Other Operations', () => {
|
||||
// @POST Returns list of environments
|
||||
it('getEnvironments calls GET /environments', async () => {
|
||||
requestApi.mockResolvedValue([]);
|
||||
await gitService.getEnvironments();
|
||||
expect(requestApi).toHaveBeenCalledWith('/git/environments');
|
||||
});
|
||||
|
||||
// @PRE Environment active
|
||||
// @POST Dashboard deployed
|
||||
it('deploy calls POST /deploy with environment_id', async () => {
|
||||
requestApi.mockResolvedValue({});
|
||||
await gitService.deploy(123, 'env-1');
|
||||
expect(requestApi).toHaveBeenCalledWith('/git/repositories/123/deploy', 'POST', { environment_id: 'env-1' });
|
||||
});
|
||||
|
||||
// @POST Returns commit history
|
||||
it('getHistory calls GET /history with limit', async () => {
|
||||
requestApi.mockResolvedValue([]);
|
||||
await gitService.getHistory(123, 10);
|
||||
expect(requestApi).toHaveBeenCalledWith('/git/repositories/123/history?limit=10');
|
||||
});
|
||||
|
||||
// @POST Syncs local and remote
|
||||
it('sync calls POST /sync with optional params', async () => {
|
||||
requestApi.mockResolvedValue({});
|
||||
await gitService.sync(123, 'env-source', 'env-target');
|
||||
expect(requestApi).toHaveBeenCalledWith('/git/repositories/123/sync?source_env_id=env-source&env_id=env-target', 'POST');
|
||||
});
|
||||
|
||||
// @PRE Dashboard id valid
|
||||
// @POST Returns status
|
||||
it('getStatus calls GET /status', async () => {
|
||||
requestApi.mockResolvedValue({});
|
||||
await gitService.getStatus(123);
|
||||
expect(requestApi).toHaveBeenCalledWith('/git/repositories/123/status');
|
||||
});
|
||||
|
||||
// @PRE Dashboard ids array
|
||||
// @POST Returns batch statuses
|
||||
it('getStatusesBatch calls POST /status/batch', async () => {
|
||||
requestApi.mockResolvedValue({});
|
||||
await gitService.getStatusesBatch([1, 2, 3]);
|
||||
expect(requestApi).toHaveBeenCalledWith('/git/repositories/status/batch', 'POST', { dashboard_ids: [1, 2, 3] });
|
||||
});
|
||||
|
||||
// @PRE Dashboard id valid
|
||||
// @POST Returns diff
|
||||
it('getDiff calls GET /diff with params', async () => {
|
||||
requestApi.mockResolvedValue('');
|
||||
await gitService.getDiff(123, 'file.txt', true, 'env-1');
|
||||
expect(requestApi).toHaveBeenCalledWith('/git/repositories/123/diff?file_path=file.txt&staged=true&env_id=env-1');
|
||||
});
|
||||
|
||||
// @PRE Repo initialized
|
||||
// @POST Returns promotion metadata
|
||||
it('promote calls POST /promote with payload', async () => {
|
||||
const payload = { from_branch: 'dev', to_branch: 'main', mode: 'mr' };
|
||||
requestApi.mockResolvedValue({});
|
||||
await gitService.promote(123, payload);
|
||||
expect(requestApi).toHaveBeenCalledWith('/git/repositories/123/promote', 'POST', payload);
|
||||
});
|
||||
});
|
||||
});
|
||||
// [/DEF:frontend.src.services.__tests__.gitService_test:Module]
|
||||
Reference in New Issue
Block a user