Skip to main content
Glama
feature.spec.unit.ts5.31 kB
import { Readable } from 'stream'; import { createCommit } from './feature'; import { AzureDevOpsError } from '../../../shared/errors'; import { createTwoFilesPatch } from 'diff'; import { VersionControlChangeType } from 'azure-devops-node-api/interfaces/GitInterfaces'; describe('createCommit unit', () => { test('should create push with provided changes', async () => { const createPush = jest.fn().mockResolvedValue({}); const mockConnection: any = { getGitApi: jest.fn().mockResolvedValue({ getBranch: jest .fn() .mockResolvedValue({ commit: { commitId: 'base' } }), getItemContent: jest .fn() .mockResolvedValue(Readable.from(['console.log("hello");\n'])), createPush, }), }; await createCommit(mockConnection, { projectId: 'p', repositoryId: 'r', branchName: 'main', commitMessage: 'msg', changes: [ { path: '/file.ts', patch: createTwoFilesPatch( '/file.ts', '/file.ts', 'console.log("hello");\n', 'console.log("world");\n', ), }, { path: '/new.txt', patch: createTwoFilesPatch('/dev/null', '/new.txt', '', 'hi\n'), }, ], }); expect(createPush).toHaveBeenCalled(); const payload = createPush.mock.calls[0][0]; expect(payload.commits[0].changes).toHaveLength(2); }); test('should throw when snippet not found', async () => { const mockConnection: any = { getGitApi: jest.fn().mockResolvedValue({ getBranch: jest .fn() .mockResolvedValue({ commit: { commitId: 'base' } }), getItemContent: jest .fn() .mockResolvedValue(Readable.from(['nothing here'])), }), }; await expect( createCommit(mockConnection, { projectId: 'p', repositoryId: 'r', branchName: 'main', commitMessage: 'msg', changes: [ { path: '/file.ts', patch: createTwoFilesPatch( '/file.ts', '/file.ts', 'console.log("hello");\n', 'console.log("world");\n', ), }, ], }), ).rejects.toThrow(AzureDevOpsError); }); test('should create delete change when patch removes a file', async () => { const createPush = jest.fn().mockResolvedValue({}); const mockConnection: any = { getGitApi: jest.fn().mockResolvedValue({ getBranch: jest .fn() .mockResolvedValue({ commit: { commitId: 'base' } }), getItemContent: jest .fn() .mockResolvedValue(Readable.from(['goodbye\n'])), createPush, }), }; await createCommit(mockConnection, { projectId: 'p', repositoryId: 'r', branchName: 'main', commitMessage: 'msg', changes: [ { patch: createTwoFilesPatch('/old.txt', '/dev/null', 'goodbye\n', ''), }, ], }); expect(createPush).toHaveBeenCalled(); const payload = createPush.mock.calls[0][0]; const change = payload.commits[0].changes[0]; expect(change.changeType).toBe(VersionControlChangeType.Delete); expect(change.item).toEqual({ path: '/old.txt' }); expect(change.newContent).toBeUndefined(); }); test('should handle search/replace format', async () => { const createPush = jest.fn().mockResolvedValue({}); const fileContent = 'const x = 1;\nconsole.log("hello");\n'; const mockConnection: any = { getGitApi: jest.fn().mockResolvedValue({ getBranch: jest .fn() .mockResolvedValue({ commit: { commitId: 'base' } }), getItemContent: jest .fn() .mockImplementation(() => Readable.from([fileContent])), createPush, }), }; await createCommit(mockConnection, { projectId: 'p', repositoryId: 'r', branchName: 'main', commitMessage: 'msg', changes: [ { path: '/file.ts', search: 'console.log("hello");', replace: 'console.log("world");', }, ], }); expect(createPush).toHaveBeenCalled(); const payload = createPush.mock.calls[0][0]; expect(payload.commits[0].changes).toHaveLength(1); const change = payload.commits[0].changes[0]; expect(change.changeType).toBe(VersionControlChangeType.Edit); expect(change.newContent?.content).toContain('console.log("world");'); }); test('should throw when search string not found', async () => { const mockConnection: any = { getGitApi: jest.fn().mockResolvedValue({ getBranch: jest .fn() .mockResolvedValue({ commit: { commitId: 'base' } }), getItemContent: jest .fn() .mockResolvedValue(Readable.from(['const x = 1;\n'])), }), }; await expect( createCommit(mockConnection, { projectId: 'p', repositoryId: 'r', branchName: 'main', commitMessage: 'msg', changes: [ { path: '/file.ts', search: 'NOT_FOUND', replace: 'something', }, ], }), ).rejects.toThrow(AzureDevOpsError); }); });

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Tiberriver256/mcp-server-azure-devops'

If you have feedback or need assistance with the MCP directory API, please join our Discord server