git-diff-spec.js
1 const path = require('path'); 2 const fs = require('fs-plus'); 3 const temp = require('temp'); 4 5 describe('GitDiff package', () => { 6 let editor, editorElement, projectPath; 7 8 beforeEach(() => { 9 spyOn(window, 'setImmediate').andCallFake(fn => fn()); 10 11 projectPath = temp.mkdirSync('git-diff-spec-'); 12 const otherPath = temp.mkdirSync('some-other-path-'); 13 14 fs.copySync(path.join(__dirname, 'fixtures', 'working-dir'), projectPath); 15 fs.moveSync( 16 path.join(projectPath, 'git.git'), 17 path.join(projectPath, '.git') 18 ); 19 atom.project.setPaths([otherPath, projectPath]); 20 21 jasmine.attachToDOM(atom.workspace.getElement()); 22 23 waitsForPromise(() => 24 atom.workspace.open(path.join(projectPath, 'sample.js')) 25 ); 26 27 runs(() => { 28 editor = atom.workspace.getActiveTextEditor(); 29 editorElement = editor.getElement(); 30 }); 31 32 waitsForPromise(() => atom.packages.activatePackage('git-diff')); 33 }); 34 35 describe('when the editor has modified lines', () => { 36 it('highlights the modified lines', () => { 37 expect(editorElement.querySelectorAll('.git-line-modified').length).toBe( 38 0 39 ); 40 editor.insertText('a'); 41 advanceClock(editor.getBuffer().stoppedChangingDelay); 42 expect(editorElement.querySelectorAll('.git-line-modified').length).toBe( 43 1 44 ); 45 expect(editorElement.querySelector('.git-line-modified')).toHaveData( 46 'buffer-row', 47 0 48 ); 49 }); 50 }); 51 52 describe('when the editor has added lines', () => { 53 it('highlights the added lines', () => { 54 expect(editorElement.querySelectorAll('.git-line-added').length).toBe(0); 55 editor.moveToEndOfLine(); 56 editor.insertNewline(); 57 editor.insertText('a'); 58 advanceClock(editor.getBuffer().stoppedChangingDelay); 59 expect(editorElement.querySelectorAll('.git-line-added').length).toBe(1); 60 expect(editorElement.querySelector('.git-line-added')).toHaveData( 61 'buffer-row', 62 1 63 ); 64 }); 65 }); 66 67 describe('when the editor has removed lines', () => { 68 it('highlights the line preceeding the deleted lines', () => { 69 expect(editorElement.querySelectorAll('.git-line-added').length).toBe(0); 70 editor.setCursorBufferPosition([5]); 71 editor.deleteLine(); 72 advanceClock(editor.getBuffer().stoppedChangingDelay); 73 expect(editorElement.querySelectorAll('.git-line-removed').length).toBe( 74 1 75 ); 76 expect(editorElement.querySelector('.git-line-removed')).toHaveData( 77 'buffer-row', 78 4 79 ); 80 }); 81 }); 82 83 describe('when the editor has removed the first line', () => { 84 it('highlights the line preceeding the deleted lines', () => { 85 expect(editorElement.querySelectorAll('.git-line-added').length).toBe(0); 86 editor.setCursorBufferPosition([0, 0]); 87 editor.deleteLine(); 88 advanceClock(editor.getBuffer().stoppedChangingDelay); 89 expect( 90 editorElement.querySelectorAll('.git-previous-line-removed').length 91 ).toBe(1); 92 expect( 93 editorElement.querySelector('.git-previous-line-removed') 94 ).toHaveData('buffer-row', 0); 95 }); 96 }); 97 98 describe('when a modified line is restored to the HEAD version contents', () => { 99 it('removes the diff highlight', () => { 100 expect(editorElement.querySelectorAll('.git-line-modified').length).toBe( 101 0 102 ); 103 editor.insertText('a'); 104 advanceClock(editor.getBuffer().stoppedChangingDelay); 105 expect(editorElement.querySelectorAll('.git-line-modified').length).toBe( 106 1 107 ); 108 editor.backspace(); 109 advanceClock(editor.getBuffer().stoppedChangingDelay); 110 expect(editorElement.querySelectorAll('.git-line-modified').length).toBe( 111 0 112 ); 113 }); 114 }); 115 116 describe('when a modified file is opened', () => { 117 it('highlights the changed lines', () => { 118 fs.writeFileSync( 119 path.join(projectPath, 'sample.txt'), 120 'Some different text.' 121 ); 122 let nextTick = false; 123 124 waitsForPromise(() => 125 atom.workspace.open(path.join(projectPath, 'sample.txt')) 126 ); 127 128 runs(() => { 129 editorElement = atom.workspace.getActiveTextEditor().getElement(); 130 }); 131 132 setImmediate(() => { 133 nextTick = true; 134 }); 135 136 waitsFor(() => nextTick); 137 138 runs(() => { 139 expect( 140 editorElement.querySelectorAll('.git-line-modified').length 141 ).toBe(1); 142 expect(editorElement.querySelector('.git-line-modified')).toHaveData( 143 'buffer-row', 144 0 145 ); 146 }); 147 }); 148 }); 149 150 describe('when the project paths change', () => { 151 it("doesn't try to use the destroyed git repository", () => { 152 editor.deleteLine(); 153 atom.project.setPaths([temp.mkdirSync('no-repository')]); 154 advanceClock(editor.getBuffer().stoppedChangingDelay); 155 }); 156 }); 157 158 describe('move-to-next-diff/move-to-previous-diff events', () => { 159 it('moves the cursor to first character of the next/previous diff line', () => { 160 editor.insertText('a'); 161 editor.setCursorBufferPosition([5]); 162 editor.deleteLine(); 163 advanceClock(editor.getBuffer().stoppedChangingDelay); 164 165 editor.setCursorBufferPosition([0]); 166 atom.commands.dispatch(editorElement, 'git-diff:move-to-next-diff'); 167 expect(editor.getCursorBufferPosition()).toEqual([4, 4]); 168 169 atom.commands.dispatch(editorElement, 'git-diff:move-to-previous-diff'); 170 expect(editor.getCursorBufferPosition()).toEqual([0, 0]); 171 }); 172 173 it('wraps around to the first/last diff in the file', () => { 174 editor.insertText('a'); 175 editor.setCursorBufferPosition([5]); 176 editor.deleteLine(); 177 advanceClock(editor.getBuffer().stoppedChangingDelay); 178 179 editor.setCursorBufferPosition([0]); 180 atom.commands.dispatch(editorElement, 'git-diff:move-to-next-diff'); 181 expect(editor.getCursorBufferPosition()).toEqual([4, 4]); 182 183 atom.commands.dispatch(editorElement, 'git-diff:move-to-next-diff'); 184 expect(editor.getCursorBufferPosition()).toEqual([0, 0]); 185 186 atom.commands.dispatch(editorElement, 'git-diff:move-to-previous-diff'); 187 expect(editor.getCursorBufferPosition()).toEqual([4, 4]); 188 }); 189 190 describe('when the wrapAroundOnMoveToDiff config option is false', () => { 191 beforeEach(() => 192 atom.config.set('git-diff.wrapAroundOnMoveToDiff', false) 193 ); 194 195 it('does not wraps around to the first/last diff in the file', () => { 196 editor.insertText('a'); 197 editor.setCursorBufferPosition([5]); 198 editor.deleteLine(); 199 advanceClock(editor.getBuffer().stoppedChangingDelay); 200 201 editor.setCursorBufferPosition([0]); 202 atom.commands.dispatch(editorElement, 'git-diff:move-to-next-diff'); 203 expect(editor.getCursorBufferPosition()).toEqual([4, 4]); 204 205 atom.commands.dispatch(editorElement, 'git-diff:move-to-next-diff'); 206 expect(editor.getCursorBufferPosition()).toEqual([4, 4]); 207 208 atom.commands.dispatch(editorElement, 'git-diff:move-to-previous-diff'); 209 expect(editor.getCursorBufferPosition()).toEqual([0, 0]); 210 211 atom.commands.dispatch(editorElement, 'git-diff:move-to-previous-diff'); 212 expect(editor.getCursorBufferPosition()).toEqual([0, 0]); 213 }); 214 }); 215 }); 216 217 describe('when the showIconsInEditorGutter config option is true', () => { 218 beforeEach(() => { 219 atom.config.set('git-diff.showIconsInEditorGutter', true); 220 }); 221 222 it('the gutter has a git-diff-icon class', () => 223 expect(editorElement.querySelector('.gutter')).toHaveClass( 224 'git-diff-icon' 225 )); 226 227 it('keeps the git-diff-icon class when editor.showLineNumbers is toggled', () => { 228 atom.config.set('editor.showLineNumbers', false); 229 expect(editorElement.querySelector('.gutter')).not.toHaveClass( 230 'git-diff-icon' 231 ); 232 233 atom.config.set('editor.showLineNumbers', true); 234 expect(editorElement.querySelector('.gutter')).toHaveClass( 235 'git-diff-icon' 236 ); 237 }); 238 239 it('removes the git-diff-icon class when the showIconsInEditorGutter config option set to false', () => { 240 atom.config.set('git-diff.showIconsInEditorGutter', false); 241 expect(editorElement.querySelector('.gutter')).not.toHaveClass( 242 'git-diff-icon' 243 ); 244 }); 245 }); 246 });