import gitGraphAst from './gitGraphAst.js'; import { parser } from './parser/gitGraph.jison'; describe('when parsing a gitGraph', function () { beforeEach(function () { parser.yy = gitGraphAst; parser.yy.clear(); }); it('should handle a gitGraph commit with NO pararms, get auto-generated reandom ID', function () { const str = `gitGraph: commit `; parser.parse(str); const commits = parser.yy.getCommits(); //console.info(commits); expect(Object.keys(commits).length).toBe(1); expect(parser.yy.getCurrentBranch()).toBe('main'); expect(parser.yy.getDirection()).toBe('LR'); expect(Object.keys(parser.yy.getBranches()).length).toBe(1); const key = Object.keys(commits)[0]; expect(commits[key].message).toBe(''); expect(commits[key].id).not.toBeNull(); expect(commits[key].tag).toBe(''); expect(commits[key].type).toBe(0); }); it('should handle a gitGraph commit with custom commit id only', function () { const str = `gitGraph: commit id:"1111" `; parser.parse(str); const commits = parser.yy.getCommits(); expect(Object.keys(commits).length).toBe(1); expect(parser.yy.getCurrentBranch()).toBe('main'); expect(parser.yy.getDirection()).toBe('LR'); expect(Object.keys(parser.yy.getBranches()).length).toBe(1); const key = Object.keys(commits)[0]; expect(commits[key].message).toBe(''); expect(commits[key].id).toBe('1111'); expect(commits[key].tag).toBe(''); expect(commits[key].type).toBe(0); }); it('should handle a gitGraph commit with custom commit tag only', function () { const str = `gitGraph: commit tag:"test" `; parser.parse(str); const commits = parser.yy.getCommits(); expect(Object.keys(commits).length).toBe(1); expect(parser.yy.getCurrentBranch()).toBe('main'); expect(parser.yy.getDirection()).toBe('LR'); expect(Object.keys(parser.yy.getBranches()).length).toBe(1); const key = Object.keys(commits)[0]; expect(commits[key].message).toBe(''); expect(commits[key].id).not.toBeNull(); expect(commits[key].tag).toBe('test'); expect(commits[key].type).toBe(0); }); it('should handle a gitGraph commit with custom commit type HIGHLIGHT only', function () { const str = `gitGraph: commit type: HIGHLIGHT `; parser.parse(str); const commits = parser.yy.getCommits(); expect(Object.keys(commits).length).toBe(1); expect(parser.yy.getCurrentBranch()).toBe('main'); expect(parser.yy.getDirection()).toBe('LR'); expect(Object.keys(parser.yy.getBranches()).length).toBe(1); const key = Object.keys(commits)[0]; expect(commits[key].message).toBe(''); expect(commits[key].id).not.toBeNull(); expect(commits[key].tag).toBe(''); expect(commits[key].type).toBe(2); }); it('should handle a gitGraph commit with custom commit type REVERSE only', function () { const str = `gitGraph: commit type: REVERSE `; parser.parse(str); const commits = parser.yy.getCommits(); expect(Object.keys(commits).length).toBe(1); expect(parser.yy.getCurrentBranch()).toBe('main'); expect(parser.yy.getDirection()).toBe('LR'); expect(Object.keys(parser.yy.getBranches()).length).toBe(1); const key = Object.keys(commits)[0]; expect(commits[key].message).toBe(''); expect(commits[key].id).not.toBeNull(); expect(commits[key].tag).toBe(''); expect(commits[key].type).toBe(1); }); it('should handle a gitGraph commit with custom commit type NORMAL only', function () { const str = `gitGraph: commit type: NORMAL `; parser.parse(str); const commits = parser.yy.getCommits(); expect(Object.keys(commits).length).toBe(1); expect(parser.yy.getCurrentBranch()).toBe('main'); expect(parser.yy.getDirection()).toBe('LR'); expect(Object.keys(parser.yy.getBranches()).length).toBe(1); const key = Object.keys(commits)[0]; expect(commits[key].message).toBe(''); expect(commits[key].id).not.toBeNull(); expect(commits[key].tag).toBe(''); expect(commits[key].type).toBe(0); }); it('should handle a gitGraph commit with custom commit msg only', function () { const str = `gitGraph: commit "test commit" `; parser.parse(str); const commits = parser.yy.getCommits(); expect(Object.keys(commits).length).toBe(1); expect(parser.yy.getCurrentBranch()).toBe('main'); expect(parser.yy.getDirection()).toBe('LR'); expect(Object.keys(parser.yy.getBranches()).length).toBe(1); const key = Object.keys(commits)[0]; expect(commits[key].message).toBe('test commit'); expect(commits[key].id).not.toBeNull(); expect(commits[key].tag).toBe(''); expect(commits[key].type).toBe(0); }); it('should handle a gitGraph commit with custom commit "msg:" key only', function () { const str = `gitGraph: commit msg: "test commit" `; parser.parse(str); const commits = parser.yy.getCommits(); expect(Object.keys(commits).length).toBe(1); expect(parser.yy.getCurrentBranch()).toBe('main'); expect(parser.yy.getDirection()).toBe('LR'); expect(Object.keys(parser.yy.getBranches()).length).toBe(1); const key = Object.keys(commits)[0]; expect(commits[key].message).toBe('test commit'); expect(commits[key].id).not.toBeNull(); expect(commits[key].tag).toBe(''); expect(commits[key].type).toBe(0); }); it('should handle a gitGraph commit with custom commit id, tag only', function () { const str = `gitGraph: commit id:"1111" tag: "test tag" `; parser.parse(str); const commits = parser.yy.getCommits(); expect(Object.keys(commits).length).toBe(1); expect(parser.yy.getCurrentBranch()).toBe('main'); expect(parser.yy.getDirection()).toBe('LR'); expect(Object.keys(parser.yy.getBranches()).length).toBe(1); const key = Object.keys(commits)[0]; expect(commits[key].message).toBe(''); expect(commits[key].id).toBe('1111'); expect(commits[key].tag).toBe('test tag'); expect(commits[key].type).toBe(0); }); it('should handle a gitGraph commit with custom commit type, tag only', function () { const str = `gitGraph: commit type:HIGHLIGHT tag: "test tag" `; parser.parse(str); const commits = parser.yy.getCommits(); expect(Object.keys(commits).length).toBe(1); expect(parser.yy.getCurrentBranch()).toBe('main'); expect(parser.yy.getDirection()).toBe('LR'); expect(Object.keys(parser.yy.getBranches()).length).toBe(1); const key = Object.keys(commits)[0]; expect(commits[key].message).toBe(''); expect(commits[key].id).not.toBeNull(); expect(commits[key].tag).toBe('test tag'); expect(commits[key].type).toBe(2); }); it('should handle a gitGraph commit with custom commit tag and type only', function () { const str = `gitGraph: commit tag: "test tag" type:HIGHLIGHT `; parser.parse(str); const commits = parser.yy.getCommits(); expect(Object.keys(commits).length).toBe(1); expect(parser.yy.getCurrentBranch()).toBe('main'); expect(parser.yy.getDirection()).toBe('LR'); expect(Object.keys(parser.yy.getBranches()).length).toBe(1); const key = Object.keys(commits)[0]; expect(commits[key].message).toBe(''); expect(commits[key].id).not.toBeNull(); expect(commits[key].tag).toBe('test tag'); expect(commits[key].type).toBe(2); }); it('should handle a gitGraph commit with custom commit id, type and tag only', function () { const str = `gitGraph: commit id:"1111" type:REVERSE tag: "test tag" `; parser.parse(str); const commits = parser.yy.getCommits(); expect(Object.keys(commits).length).toBe(1); expect(parser.yy.getCurrentBranch()).toBe('main'); expect(parser.yy.getDirection()).toBe('LR'); expect(Object.keys(parser.yy.getBranches()).length).toBe(1); const key = Object.keys(commits)[0]; expect(commits[key].message).toBe(''); expect(commits[key].id).toBe('1111'); expect(commits[key].tag).toBe('test tag'); expect(commits[key].type).toBe(1); }); it('should handle a gitGraph commit with custom commit id, type, tag and msg', function () { const str = `gitGraph: commit id:"1111" type:REVERSE tag: "test tag" msg:"test msg" `; parser.parse(str); const commits = parser.yy.getCommits(); expect(Object.keys(commits).length).toBe(1); expect(parser.yy.getCurrentBranch()).toBe('main'); expect(parser.yy.getDirection()).toBe('LR'); expect(Object.keys(parser.yy.getBranches()).length).toBe(1); const key = Object.keys(commits)[0]; expect(commits[key].message).toBe('test msg'); expect(commits[key].id).toBe('1111'); expect(commits[key].tag).toBe('test tag'); expect(commits[key].type).toBe(1); }); it('should handle a gitGraph commit with custom type,tag, msg, commit id,', function () { const str = `gitGraph: commit type:REVERSE tag: "test tag" msg: "test msg" id: "1111" `; parser.parse(str); const commits = parser.yy.getCommits(); expect(Object.keys(commits).length).toBe(1); expect(parser.yy.getCurrentBranch()).toBe('main'); expect(parser.yy.getDirection()).toBe('LR'); expect(Object.keys(parser.yy.getBranches()).length).toBe(1); const key = Object.keys(commits)[0]; expect(commits[key].message).toBe('test msg'); expect(commits[key].id).toBe('1111'); expect(commits[key].tag).toBe('test tag'); expect(commits[key].type).toBe(1); }); it('should handle a gitGraph commit with custom tag, msg, commit id, type,', function () { const str = `gitGraph: commit tag: "test tag" msg:"test msg" id:"1111" type:REVERSE `; parser.parse(str); const commits = parser.yy.getCommits(); expect(Object.keys(commits).length).toBe(1); expect(parser.yy.getCurrentBranch()).toBe('main'); expect(parser.yy.getDirection()).toBe('LR'); expect(Object.keys(parser.yy.getBranches()).length).toBe(1); const key = Object.keys(commits)[0]; expect(commits[key].message).toBe('test msg'); expect(commits[key].id).toBe('1111'); expect(commits[key].tag).toBe('test tag'); expect(commits[key].type).toBe(1); }); it('should handle a gitGraph commit with custom msg, commit id, type,tag', function () { const str = `gitGraph: commit msg:"test msg" id:"1111" type:REVERSE tag: "test tag" `; parser.parse(str); const commits = parser.yy.getCommits(); expect(Object.keys(commits).length).toBe(1); expect(parser.yy.getCurrentBranch()).toBe('main'); expect(parser.yy.getDirection()).toBe('LR'); expect(Object.keys(parser.yy.getBranches()).length).toBe(1); const key = Object.keys(commits)[0]; expect(commits[key].message).toBe('test msg'); expect(commits[key].id).toBe('1111'); expect(commits[key].tag).toBe('test tag'); expect(commits[key].type).toBe(1); }); it('should handle 3 straight commits', function () { const str = `gitGraph: commit commit commit `; parser.parse(str); const commits = parser.yy.getCommits(); expect(Object.keys(commits).length).toBe(3); expect(parser.yy.getCurrentBranch()).toBe('main'); expect(parser.yy.getDirection()).toBe('LR'); expect(Object.keys(parser.yy.getBranches()).length).toBe(1); }); it('should handle new branch creation', function () { const str = `gitGraph: commit branch testBranch `; parser.parse(str); const commits = parser.yy.getCommits(); expect(Object.keys(commits).length).toBe(1); expect(parser.yy.getCurrentBranch()).toBe('testBranch'); expect(parser.yy.getDirection()).toBe('LR'); expect(Object.keys(parser.yy.getBranches()).length).toBe(2); }); it('should allow quoted branch names', function () { const str = `gitGraph: commit branch "branch" checkout "branch" commit checkout main merge "branch" `; parser.parse(str); const commits = parser.yy.getCommits(); expect(Object.keys(commits).length).toBe(3); expect(parser.yy.getCurrentBranch()).toBe('main'); expect(parser.yy.getDirection()).toBe('LR'); expect(Object.keys(parser.yy.getBranches()).length).toBe(2); const commit1 = Object.keys(commits)[0]; const commit2 = Object.keys(commits)[1]; const commit3 = Object.keys(commits)[2]; expect(commits[commit1].branch).toBe('main'); expect(commits[commit2].branch).toBe('branch'); expect(commits[commit3].branch).toBe('main'); expect(parser.yy.getBranchesAsObjArray()).toStrictEqual([{ name: 'main' }, { name: 'branch' }]); }); it('should allow _-./ characters in branch names', function () { const str = `gitGraph: commit branch azAZ_-./test `; parser.parse(str); const commits = parser.yy.getCommits(); expect(Object.keys(commits).length).toBe(1); expect(parser.yy.getCurrentBranch()).toBe('azAZ_-./test'); expect(parser.yy.getDirection()).toBe('LR'); expect(Object.keys(parser.yy.getBranches()).length).toBe(2); }); it('should allow branch names starting with numbers', function () { const str = `gitGraph: commit %% branch names starting with numbers are not recommended, but are supported by git branch 1.0.1 `; parser.parse(str); const commits = parser.yy.getCommits(); expect(Object.keys(commits).length).toBe(1); expect(parser.yy.getCurrentBranch()).toBe('1.0.1'); expect(parser.yy.getDirection()).toBe('LR'); expect(Object.keys(parser.yy.getBranches()).length).toBe(2); }); it('should allow branch names starting with unusual prefixes', function () { const str = `gitGraph: commit %% branch names starting with numbers are not recommended, but are supported by git branch branch01 branch checkout02 branch cherry-pick03 branch branch/example-branch branch merge/test_merge %% single character branch name branch A `; parser.parse(str); const commits = parser.yy.getCommits(); expect(Object.keys(commits).length).toBe(1); expect(parser.yy.getCurrentBranch()).toBe('A'); expect(parser.yy.getDirection()).toBe('LR'); expect(Object.keys(parser.yy.getBranches()).length).toBe(7); expect(Object.keys(parser.yy.getBranches())).toEqual( expect.arrayContaining([ 'branch01', 'checkout02', 'cherry-pick03', 'branch/example-branch', 'merge/test_merge', 'A', ]) ); }); it('should handle new branch checkout', function () { const str = `gitGraph: commit branch testBranch checkout testBranch `; parser.parse(str); const commits = parser.yy.getCommits(); expect(Object.keys(commits).length).toBe(1); expect(parser.yy.getCurrentBranch()).toBe('testBranch'); expect(parser.yy.getDirection()).toBe('LR'); expect(Object.keys(parser.yy.getBranches()).length).toBe(2); }); it('should handle new branch checkout with order', function () { const str = `gitGraph: commit branch test1 order: 3 branch test2 order: 2 branch test3 order: 1 `; parser.parse(str); const commits = parser.yy.getCommits(); expect(Object.keys(commits).length).toBe(1); expect(parser.yy.getCurrentBranch()).toBe('test3'); expect(Object.keys(parser.yy.getBranches()).length).toBe(4); expect(parser.yy.getBranchesAsObjArray()).toStrictEqual([ { name: 'main' }, { name: 'test3' }, { name: 'test2' }, { name: 'test1' }, ]); }); it('should handle new branch checkout with and without order', function () { const str = `gitGraph: commit branch test1 order: 1 branch test2 branch test3 `; parser.parse(str); const commits = parser.yy.getCommits(); expect(Object.keys(commits).length).toBe(1); expect(parser.yy.getCurrentBranch()).toBe('test3'); expect(Object.keys(parser.yy.getBranches()).length).toBe(4); expect(parser.yy.getBranchesAsObjArray()).toStrictEqual([ { name: 'main' }, { name: 'test2' }, { name: 'test3' }, { name: 'test1' }, ]); }); it('should handle new branch checkout & commit', function () { const str = `gitGraph: commit branch testBranch checkout testBranch commit `; parser.parse(str); const commits = parser.yy.getCommits(); expect(Object.keys(commits).length).toBe(2); expect(parser.yy.getCurrentBranch()).toBe('testBranch'); expect(parser.yy.getDirection()).toBe('LR'); expect(Object.keys(parser.yy.getBranches()).length).toBe(2); const commit1 = Object.keys(commits)[0]; const commit2 = Object.keys(commits)[1]; expect(commits[commit1].branch).toBe('main'); expect(commits[commit1].parents).toStrictEqual([]); expect(commits[commit2].branch).toBe('testBranch'); expect(commits[commit2].parents).toStrictEqual([commit1]); }); it('should handle new branch checkout & commit and merge', function () { const str = `gitGraph: commit branch testBranch checkout testBranch commit commit checkout main merge testBranch `; parser.parse(str); const commits = parser.yy.getCommits(); expect(Object.keys(commits).length).toBe(4); expect(parser.yy.getCurrentBranch()).toBe('main'); expect(parser.yy.getDirection()).toBe('LR'); expect(Object.keys(parser.yy.getBranches()).length).toBe(2); const commit1 = Object.keys(commits)[0]; const commit2 = Object.keys(commits)[1]; const commit3 = Object.keys(commits)[2]; const commit4 = Object.keys(commits)[3]; expect(commits[commit1].branch).toBe('main'); expect(commits[commit1].parents).toStrictEqual([]); expect(commits[commit2].branch).toBe('testBranch'); expect(commits[commit2].parents).toStrictEqual([commits[commit1].id]); expect(commits[commit3].branch).toBe('testBranch'); expect(commits[commit3].parents).toStrictEqual([commits[commit2].id]); expect(commits[commit4].branch).toBe('main'); expect(commits[commit4].parents).toStrictEqual([commits[commit1].id, commits[commit3].id]); expect(parser.yy.getBranchesAsObjArray()).toStrictEqual([ { name: 'main' }, { name: 'testBranch' }, ]); }); it('should handle merge tags', function () { const str = `gitGraph: commit branch testBranch checkout testBranch commit checkout main merge testBranch tag: "merge-tag" `; parser.parse(str); const commits = parser.yy.getCommits(); expect(Object.keys(commits).length).toBe(3); expect(parser.yy.getCurrentBranch()).toBe('main'); expect(parser.yy.getDirection()).toBe('LR'); expect(Object.keys(parser.yy.getBranches()).length).toBe(2); const commit1 = Object.keys(commits)[0]; const commit2 = Object.keys(commits)[1]; const commit3 = Object.keys(commits)[2]; expect(commits[commit1].branch).toBe('main'); expect(commits[commit1].parents).toStrictEqual([]); expect(commits[commit2].branch).toBe('testBranch'); expect(commits[commit2].parents).toStrictEqual([commits[commit1].id]); expect(commits[commit3].branch).toBe('main'); expect(commits[commit3].parents).toStrictEqual([commits[commit1].id, commits[commit2].id]); expect(commits[commit3].tag).toBe('merge-tag'); expect(parser.yy.getBranchesAsObjArray()).toStrictEqual([ { name: 'main' }, { name: 'testBranch' }, ]); }); it('should handle merge with custom ids, tags and typr', function () { const str = `gitGraph: commit branch testBranch checkout testBranch commit checkout main %% Merge Tag and ID merge testBranch tag: "merge-tag" id: "2-222" branch testBranch2 checkout testBranch2 commit checkout main %% Merge ID and Tag (reverse order) merge testBranch2 id: "4-444" tag: "merge-tag2" type:HIGHLIGHT branch testBranch3 checkout testBranch3 commit checkout main %% just Merge ID merge testBranch3 id: "6-666" `; parser.parse(str); const commits = parser.yy.getCommits(); expect(Object.keys(commits).length).toBe(7); expect(parser.yy.getCurrentBranch()).toBe('main'); expect(parser.yy.getDirection()).toBe('LR'); // The order of these commits is in alphabetical order of IDs const [ mainCommit, testBranchCommit, testBranchMerge, testBranch2Commit, testBranch2Merge, testBranch3Commit, testBranch3Merge, ] = Object.values(commits); expect(mainCommit.branch).toBe('main'); expect(mainCommit.parents).toStrictEqual([]); expect(testBranchCommit.branch).toBe('testBranch'); expect(testBranchCommit.parents).toStrictEqual([mainCommit.id]); expect(testBranchMerge.branch).toBe('main'); expect(testBranchMerge.parents).toStrictEqual([mainCommit.id, testBranchCommit.id]); expect(testBranchMerge.tag).toBe('merge-tag'); expect(testBranchMerge.id).toBe('2-222'); expect(testBranch2Merge.branch).toBe('main'); expect(testBranch2Merge.parents).toStrictEqual([testBranchMerge.id, testBranch2Commit.id]); expect(testBranch2Merge.tag).toBe('merge-tag2'); expect(testBranch2Merge.id).toBe('4-444'); expect(testBranch2Merge.customType).toBe(2); expect(testBranch2Merge.customId).toBe(true); expect(testBranch3Merge.branch).toBe('main'); expect(testBranch3Merge.parents).toStrictEqual([testBranch2Merge.id, testBranch3Commit.id]); expect(testBranch3Merge.id).toBe('6-666'); expect(parser.yy.getBranchesAsObjArray()).toStrictEqual([ { name: 'main' }, { name: 'testBranch' }, { name: 'testBranch2' }, { name: 'testBranch3' }, ]); }); it('should support cherry-picking commits', function () { const str = `gitGraph commit id: "ZERO" branch develop commit id:"A" checkout main cherry-pick id:"A" `; parser.parse(str); const commits = parser.yy.getCommits(); const cherryPickCommitID = Object.keys(commits)[2]; expect(commits[cherryPickCommitID].tag).toBe('cherry-pick:A'); expect(commits[cherryPickCommitID].branch).toBe('main'); }); it('should support cherry-picking commits with custom tag', function () { const str = `gitGraph commit id: "ZERO" branch develop commit id:"A" checkout main cherry-pick id:"A" tag:"MyTag" `; parser.parse(str); const commits = parser.yy.getCommits(); const cherryPickCommitID = Object.keys(commits)[2]; expect(commits[cherryPickCommitID].tag).toBe('MyTag'); expect(commits[cherryPickCommitID].branch).toBe('main'); }); it('should support cherry-picking commits with no tag', function () { const str = `gitGraph commit id: "ZERO" branch develop commit id:"A" checkout main cherry-pick id:"A" tag:"" `; parser.parse(str); const commits = parser.yy.getCommits(); const cherryPickCommitID = Object.keys(commits)[2]; expect(commits[cherryPickCommitID].tag).toBe(''); expect(commits[cherryPickCommitID].branch).toBe('main'); }); it('should support cherry-picking of merge commits', function () { const str = `gitGraph commit id: "ZERO" branch feature branch release checkout feature commit id: "A" commit id: "B" checkout main merge feature id: "M" checkout release cherry-pick id: "M" parent:"B" `; parser.parse(str); const commits = parser.yy.getCommits(); const cherryPickCommitID = Object.keys(commits)[4]; expect(commits[cherryPickCommitID].tag).toBe('cherry-pick:M|parent:B'); expect(commits[cherryPickCommitID].branch).toBe('release'); }); it('should support cherry-picking of merge commits with tag', function () { const str = `gitGraph commit id: "ZERO" branch feature branch release checkout feature commit id: "A" commit id: "B" checkout main merge feature id: "M" checkout release cherry-pick id: "M" parent:"ZERO" tag: "v1.0" `; parser.parse(str); const commits = parser.yy.getCommits(); const cherryPickCommitID = Object.keys(commits)[4]; expect(commits[cherryPickCommitID].tag).toBe('v1.0'); expect(commits[cherryPickCommitID].branch).toBe('release'); }); it('should support cherry-picking of merge commits with additional commit', function () { const str = `gitGraph commit id: "ZERO" branch feature branch release checkout feature commit id: "A" commit id: "B" checkout main merge feature id: "M" checkout release commit id: "C" cherry-pick id: "M" tag: "v2.1:ZERO" parent:"ZERO" commit id: "D" `; parser.parse(str); const commits = parser.yy.getCommits(); const cherryPickCommitID = Object.keys(commits)[5]; expect(commits[cherryPickCommitID].tag).toBe('v2.1:ZERO'); expect(commits[cherryPickCommitID].branch).toBe('release'); }); it('should support cherry-picking of merge commits with empty tag', function () { const str = `gitGraph commit id: "ZERO" branch feature branch release checkout feature commit id: "A" commit id: "B" checkout main merge feature id: "M" checkout release commit id: "C" cherry-pick id:"M" parent: "ZERO" tag:"" commit id: "D" cherry-pick id:"M" tag:"" parent: "B" `; parser.parse(str); const commits = parser.yy.getCommits(); const cherryPickCommitID = Object.keys(commits)[5]; const cherryPickCommitID2 = Object.keys(commits)[7]; expect(commits[cherryPickCommitID].tag).toBe(''); expect(commits[cherryPickCommitID2].tag).toBe(''); expect(commits[cherryPickCommitID].branch).toBe('release'); }); it('should fail cherry-picking of merge commits if the parent of merge commits is not specified', function () { expect(() => parser .parse( `gitGraph commit id: "ZERO" branch feature branch release checkout feature commit id: "A" commit id: "B" checkout main merge feature id: "M" checkout release commit id: "C" cherry-pick id:"M" ` ) .toThrow( 'Incorrect usage of cherry-pick: If the source commit is a merge commit, an immediate parent commit must be specified.' ) ); }); it('should fail cherry-picking of merge commits when the parent provided is not an immediate parent of cherry picked commit', function () { expect(() => parser .parse( `gitGraph commit id: "ZERO" branch feature branch release checkout feature commit id: "A" commit id: "B" checkout main merge feature id: "M" checkout release commit id: "C" cherry-pick id:"M" parent: "A" ` ) .toThrow( 'Invalid operation: The specified parent commit is not an immediate parent of the cherry-picked commit.' ) ); }); it('should throw error when try to branch existing branch: main', function () { const str = `gitGraph commit branch testBranch commit branch main commit checkout main merge testBranch `; try { parser.parse(str); // Fail test if above expression doesn't throw anything. expect(true).toBe(false); } catch (e) { expect(e.message).toBe( 'Trying to create an existing branch. (Help: Either use a new name if you want create a new branch or try using "checkout main")' ); } }); it('should throw error when try to branch existing branch: testBranch', function () { const str = `gitGraph commit branch testBranch commit branch testBranch commit checkout main merge testBranch `; try { parser.parse(str); // Fail test if above expression doesn't throw anything. expect(true).toBe(false); } catch (e) { expect(e.message).toBe( 'Trying to create an existing branch. (Help: Either use a new name if you want create a new branch or try using "checkout testBranch")' ); } }); it('should throw error when try to checkout unknown branch: testBranch', function () { const str = `gitGraph commit checkout testBranch commit branch testBranch commit checkout main merge testBranch `; try { parser.parse(str); // Fail test if above expression doesn't throw anything. expect(true).toBe(false); } catch (e) { expect(e.message).toBe( 'Trying to checkout branch which is not yet created. (Help try using "branch testBranch")' ); } }); it('should throw error when trying to merge, when current branch has no commits', function () { const str = `gitGraph merge testBranch commit checkout testBranch commit branch testBranch commit checkout main merge testBranch `; try { parser.parse(str); // Fail test if above expression doesn't throw anything. expect(true).toBe(false); } catch (e) { expect(e.message).toBe('Incorrect usage of "merge". Current branch (main)has no commits'); } }); it('should throw error when trying to merge unknown branch', function () { const str = `gitGraph commit merge testBranch commit checkout testBranch commit branch testBranch commit checkout main merge testBranch `; try { parser.parse(str); // Fail test if above expression doesn't throw anything. expect(true).toBe(false); } catch (e) { expect(e.message).toBe( 'Incorrect usage of "merge". Branch to be merged (testBranch) does not exist' ); } }); it('should throw error when trying to merge branch to itself', function () { const str = `gitGraph commit branch testBranch merge testBranch `; try { parser.parse(str); // Fail test if above expression doesn't throw anything. expect(true).toBe(false); } catch (e) { expect(e.message).toBe('Incorrect usage of "merge". Cannot merge a branch to itself'); } }); it('should throw error when using existing id as merge ID', function () { const str = `gitGraph commit id: "1-111" branch testBranch commit id: "2-222" commit id: "3-333" checkout main merge testBranch id: "1-111" `; try { parser.parse(str); // Fail test if above expression doesn't throw anything. expect(true).toBe(false); } catch (e) { expect(e.message).toBe( 'Incorrect usage of "merge". Commit with id:1-111 already exists, use different custom Id' ); } }); it('should throw error when trying to merge branches having same heads', function () { const str = `gitGraph commit branch testBranch checkout main merge testBranch `; try { parser.parse(str); // Fail test if above expression doesn't throw anything. expect(true).toBe(false); } catch (e) { expect(e.message).toBe('Incorrect usage of "merge". Both branches have same head'); } }); it('should throw error when trying to merge branch which has no commits', function () { const str = `gitGraph branch test1 checkout main commit merge test1 `; try { parser.parse(str); // Fail test if above expression doesn't throw anything. expect(true).toBe(false); } catch (e) { expect(e.message).toBe( 'Incorrect usage of "merge". Branch to be merged (test1) has no commits' ); } }); describe('accessibility', () => { it('should handle a title and a description (accDescr)', () => { const str = `gitGraph: accTitle: This is a title accDescr: This is a description commit `; parser.parse(str); expect(parser.yy.getAccTitle()).toBe('This is a title'); expect(parser.yy.getAccDescription()).toBe('This is a description'); }); it('should handle a title and a multiline description (accDescr)', () => { const str = `gitGraph: accTitle: This is a title accDescr { This is a description using multiple lines } commit `; parser.parse(str); expect(parser.yy.getAccTitle()).toBe('This is a title'); expect(parser.yy.getAccDescription()).toBe('This is a description\nusing multiple lines'); }); }); });