diff --git a/src/sourceFiles/index.ts b/src/sourceFiles/index.ts index 23b5ebd56..67685ee70 100644 --- a/src/sourceFiles/index.ts +++ b/src/sourceFiles/index.ts @@ -144,6 +144,51 @@ export class SourceFiles extends CrowdinApi { return this.patch(url, request, this.defaultConfig()); } + /** + * @param projectId project identifier + * @param branchId branch identifier + * @param request request body + * @see https://support.crowdin.com/developer/api/v2/string-based/#tag/Branches/operation/api.projects.branches.merges.post + */ + mergeBranch( + projectId: number, + branchId: number, + request: SourceFilesModel.MergeBranchRequest, + ): Promise>> { + const url = `${this.url}/projects/${projectId}/branches/${branchId}/merges`; + return this.post(url, request, this.defaultConfig()); + } + + /** + * @param projectId project identifier + * @param branchId branch identifier + * @param mergeId merge branch identifier + * @see https://support.crowdin.com/developer/api/v2/string-based/#tag/Branches/operation/api.projects.branches.merges.get + */ + checkBranchMergeStatus( + projectId: number, + branchId: number, + mergeId: string, + ): Promise>> { + const url = `${this.url}/projects/${projectId}/branches/${branchId}/merges/${mergeId}`; + return this.get(url, this.defaultConfig()); + } + + /** + * @param projectId project identifier + * @param branchId branch identifier + * @param mergeId merge branch identifier + * @see https://support.crowdin.com/developer/api/v2/string-based/#tag/Branches/operation/api.projects.branches.merges.summary.get + */ + getBranchMergeSummary( + projectId: number, + branchId: number, + mergeId: string, + ): Promise> { + const url = `${this.url}/projects/${projectId}/branches/${branchId}/merges/${mergeId}/summary`; + return this.get(url, this.defaultConfig()); + } + /** * @param projectId project identifier * @param options optional parameters for the request @@ -540,6 +585,30 @@ export namespace SourceFilesModel { title?: string; } + export interface MergeBranchRequest { + deleteAfterMerge?: boolean; + sourceBranchId: number; + dryRun?: boolean; + } + + export interface MergeBranchAttributes { + sourceBranchId: number; + deleteAfterMerge: boolean; + } + + export interface MergeBranchSummary { + status: string; + sourceBranchId: number; + targetBranchId: number; + dryRun: boolean; + details: { + added: number; + deleted: number; + updated: number; + conflicted: number; + }; + } + export type Priority = 'low' | 'normal' | 'high'; export interface ListProjectDirectoriesOptions extends PaginationOptions { diff --git a/tests/sourceFiles/api.test.ts b/tests/sourceFiles/api.test.ts index 4f1571f33..cebbc30ca 100644 --- a/tests/sourceFiles/api.test.ts +++ b/tests/sourceFiles/api.test.ts @@ -16,6 +16,9 @@ describe('Source Files API', () => { const fileRevisionId = 888; const branchId = 12; + const sourceBranchId = 14; + const mergeBranchId = 'merge-123'; + const mergeBranchStatus = 'merged'; const branchName = 'master'; const branchTitle = 'testTitle'; const storageId = 123; @@ -160,6 +163,42 @@ describe('Source Files API', () => { title: branchTitle, }, }) + .post( + `/projects/${projectId}/branches/${branchId}/merges`, + { + sourceBranchId, + }, + { + reqheaders: { + Authorization: `Bearer ${api.token}`, + }, + }, + ) + .reply(200, { + data: { + identifier: mergeBranchId, + }, + }) + .get(`/projects/${projectId}/branches/${branchId}/merges/${mergeBranchId}`, undefined, { + reqheaders: { + Authorization: `Bearer ${api.token}`, + }, + }) + .reply(200, { + data: { + identifier: mergeBranchId, + }, + }) + .get(`/projects/${projectId}/branches/${branchId}/merges/${mergeBranchId}/summary`, undefined, { + reqheaders: { + Authorization: `Bearer ${api.token}`, + }, + }) + .reply(200, { + data: { + status: mergeBranchStatus, + }, + }) .get(`/projects/${projectId}/directories`, undefined, { reqheaders: { Authorization: `Bearer ${api.token}`, @@ -506,6 +545,23 @@ describe('Source Files API', () => { expect(branch.data.title).toBe(branchTitle); }); + it('Merge branch', async () => { + const mergeStatus = await api.mergeBranch(projectId, branchId, { + sourceBranchId, + }); + expect(mergeStatus.data.identifier).toBe(mergeBranchId); + }); + + it('Check Branch Merge Status', async () => { + const mergeStatus = await api.checkBranchMergeStatus(projectId, branchId, mergeBranchId); + expect(mergeStatus.data.identifier).toBe(mergeBranchId); + }); + + it('Get Branch Merge Summary', async () => { + const mergeStatus = await api.getBranchMergeSummary(projectId, branchId, mergeBranchId); + expect(mergeStatus.data.status).toBe(mergeBranchStatus); + }); + it('List project directories', async () => { const directories = await api.listProjectDirectories(projectId); expect(directories.data.length).toBe(1);