/ packages / git-diff / spec / git-diff-spec.js
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  });