const helpers = require('../lib/helpers'); const { TextEditor } = require('atom'); const path = require('path'); describe('line ending selector', () => { let lineEndingTile; beforeEach(() => { jasmine.useRealClock(); waitsForPromise(() => { return atom.packages.activatePackage('status-bar'); }); waitsForPromise(() => { return atom.packages.activatePackage('line-ending-selector'); }); waits(1); runs(() => { const statusBar = atom.workspace.getFooterPanels()[0].getItem(); lineEndingTile = statusBar.getRightTiles()[0].getItem(); expect(lineEndingTile.element.className).toMatch(/line-ending-tile/); expect(lineEndingTile.element.textContent).toBe(''); }); }); describe('Commands', () => { let editor, editorElement; beforeEach(() => { waitsForPromise(() => { return atom.workspace.open(path.join(__dirname, 'fixtures', 'mixed-endings.md')).then(e => { editor = e; editorElement = atom.views.getView(editor); jasmine.attachToDOM(editorElement); }); }); }); describe('When "line-ending-selector:convert-to-LF" is run', () => { it('converts the file to LF line endings', () => { editorElement.focus(); atom.commands.dispatch( document.activeElement, 'line-ending-selector:convert-to-LF' ); expect(editor.getText()).toBe('Hello\nGoodbye\nMixed\n'); }); }); describe('When "line-ending-selector:convert-to-LF" is run', () => { it('converts the file to CRLF line endings', () => { editorElement.focus(); atom.commands.dispatch( document.activeElement, 'line-ending-selector:convert-to-CRLF' ); expect(editor.getText()).toBe('Hello\r\nGoodbye\r\nMixed\r\n'); }); }); }); describe('Status bar tile', () => { describe('when an empty file is opened', () => { it('uses the default line endings for the platform', () => { waitsFor(done => { spyOn(helpers, 'getProcessPlatform').andReturn('win32'); atom.workspace.open('').then(editor => { const subscription = lineEndingTile.onDidChange(() => { subscription.dispose(); expect(lineEndingTile.element.textContent).toBe('CRLF'); expect(editor.getBuffer().getPreferredLineEnding()).toBe('\r\n'); expect(getTooltipText(lineEndingTile.element)).toBe( 'File uses CRLF (Windows) line endings' ); done(); }); }); }); waitsFor(done => { helpers.getProcessPlatform.andReturn('darwin'); atom.workspace.open('').then(editor => { const subscription = lineEndingTile.onDidChange(() => { subscription.dispose(); expect(lineEndingTile.element.textContent).toBe('LF'); expect(editor.getBuffer().getPreferredLineEnding()).toBe('\n'); expect(getTooltipText(lineEndingTile.element)).toBe( 'File uses LF (Unix) line endings' ); done(); }); }); }); }); describe('when the "defaultLineEnding" setting is set to "LF"', () => { beforeEach(() => { atom.config.set('line-ending-selector.defaultLineEnding', 'LF'); }); it('uses LF line endings, regardless of the platform', () => { waitsFor(done => { spyOn(helpers, 'getProcessPlatform').andReturn('win32'); atom.workspace.open('').then(editor => { lineEndingTile.onDidChange(() => { expect(lineEndingTile.element.textContent).toBe('LF'); expect(editor.getBuffer().getPreferredLineEnding()).toBe('\n'); done(); }); }); }); }); }); describe('when the "defaultLineEnding" setting is set to "CRLF"', () => { beforeEach(() => { atom.config.set('line-ending-selector.defaultLineEnding', 'CRLF'); }); it('uses CRLF line endings, regardless of the platform', () => { waitsFor(done => { atom.workspace.open('').then(editor => { lineEndingTile.onDidChange(() => { expect(lineEndingTile.element.textContent).toBe('CRLF'); expect(editor.getBuffer().getPreferredLineEnding()).toBe( '\r\n' ); done(); }); }); }); }); }); }); describe('when a file is opened that contains only CRLF line endings', () => { it('displays "CRLF" as the line ending', () => { waitsFor(done => { atom.workspace.open(path.join(__dirname, 'fixtures', 'windows-endings.md')).then(() => { lineEndingTile.onDidChange(() => { expect(lineEndingTile.element.textContent).toBe('CRLF'); done(); }); }); }); }); }); describe('when a file is opened that contains only LF line endings', () => { it('displays "LF" as the line ending', () => { waitsFor(done => { atom.workspace.open(path.join(__dirname, 'fixtures', 'unix-endings.md')).then(editor => { lineEndingTile.onDidChange(() => { expect(lineEndingTile.element.textContent).toBe('LF'); expect(editor.getBuffer().getPreferredLineEnding()).toBe(null); done(); }); }); }); }); }); describe('when a file is opened that contains mixed line endings', () => { it('displays "Mixed" as the line ending', () => { waitsFor(done => { atom.workspace.open(path.join(__dirname, 'fixtures', 'mixed-endings.md')).then(() => { lineEndingTile.onDidChange(() => { expect(lineEndingTile.element.textContent).toBe('Mixed'); done(); }); }); }); }); }); describe('clicking the tile', () => { let lineEndingModal, lineEndingSelector; beforeEach(() => { jasmine.attachToDOM(atom.views.getView(atom.workspace)); waitsFor(done => atom.workspace .open(path.join(__dirname, 'fixtures', 'unix-endings.md')) .then(() => lineEndingTile.onDidChange(done)) ); }); describe('when the text editor has focus', () => { it('opens the line ending selector modal for the text editor', () => { atom.workspace.getCenter().activate(); const item = atom.workspace.getActivePaneItem(); expect(item.getFileName && item.getFileName()).toBe( 'unix-endings.md' ); lineEndingTile.element.dispatchEvent(new MouseEvent('click', {})); lineEndingModal = atom.workspace.getModalPanels()[0]; lineEndingSelector = lineEndingModal.getItem(); expect(lineEndingModal.isVisible()).toBe(true); expect( lineEndingSelector.element.contains(document.activeElement) ).toBe(true); let listItems = lineEndingSelector.element.querySelectorAll('li'); expect(listItems[0].textContent).toBe('LF'); expect(listItems[1].textContent).toBe('CRLF'); }); }); describe('when the text editor does not have focus', () => { it('opens the line ending selector modal for the active text editor', () => { atom.workspace.getLeftDock().activate(); const item = atom.workspace.getActivePaneItem(); expect(item instanceof TextEditor).toBe(false); lineEndingTile.element.dispatchEvent(new MouseEvent('click', {})); lineEndingModal = atom.workspace.getModalPanels()[0]; lineEndingSelector = lineEndingModal.getItem(); expect(lineEndingModal.isVisible()).toBe(true); expect( lineEndingSelector.element.contains(document.activeElement) ).toBe(true); let listItems = lineEndingSelector.element.querySelectorAll('li'); expect(listItems[0].textContent).toBe('LF'); expect(listItems[1].textContent).toBe('CRLF'); }); }); describe('when selecting a different line ending for the file', () => { it('changes the line endings in the buffer', () => { lineEndingTile.element.dispatchEvent(new MouseEvent('click', {})); lineEndingModal = atom.workspace.getModalPanels()[0]; lineEndingSelector = lineEndingModal.getItem(); const lineEndingChangedPromise = new Promise(resolve => { lineEndingTile.onDidChange(() => { expect(lineEndingTile.element.textContent).toBe('CRLF'); const editor = atom.workspace.getActiveTextEditor(); expect(editor.getText()).toBe('Hello\r\nGoodbye\r\nUnix\r\n'); expect(editor.getBuffer().getPreferredLineEnding()).toBe('\r\n'); resolve(); }); }); lineEndingSelector.refs.queryEditor.setText('CR'); lineEndingSelector.confirmSelection(); expect(lineEndingModal.isVisible()).toBe(false); waitsForPromise(() => lineEndingChangedPromise); }); }); describe('when modal is exited', () => { it('leaves the tile selection as-is', () => { lineEndingTile.element.dispatchEvent(new MouseEvent('click', {})); lineEndingModal = atom.workspace.getModalPanels()[0]; lineEndingSelector = lineEndingModal.getItem(); lineEndingSelector.cancelSelection(); expect(lineEndingTile.element.textContent).toBe('LF'); }); }); }); describe('closing the last text editor', () => { it('displays no line ending in the status bar', () => { waitsForPromise(() => { return atom.workspace.open(path.join(__dirname, 'fixtures', 'unix-endings.md')).then(() => { atom.workspace.getActivePane().destroy(); expect(lineEndingTile.element.textContent).toBe(''); }); }); }); }); describe("when the buffer's line endings change", () => { let editor; beforeEach(() => { waitsFor(done => { atom.workspace.open(path.join(__dirname, 'fixtures', 'unix-endings.md')).then(e => { editor = e; lineEndingTile.onDidChange(done); }); }); }); it('updates the line ending text in the tile', () => { let tileText = lineEndingTile.element.textContent; let tileUpdateCount = 0; Object.defineProperty(lineEndingTile.element, 'textContent', { get() { return tileText; }, set(text) { tileUpdateCount++; tileText = text; } }); expect(lineEndingTile.element.textContent).toBe('LF'); expect(getTooltipText(lineEndingTile.element)).toBe( 'File uses LF (Unix) line endings' ); waitsFor(done => { editor.setTextInBufferRange([[0, 0], [0, 0]], '... '); editor.setTextInBufferRange([[0, Infinity], [1, 0]], '\r\n', { normalizeLineEndings: false }); lineEndingTile.onDidChange(done); }); runs(() => { expect(tileUpdateCount).toBe(1); expect(lineEndingTile.element.textContent).toBe('Mixed'); expect(getTooltipText(lineEndingTile.element)).toBe( 'File uses mixed line endings' ); }); waitsFor(done => { atom.commands.dispatch( editor.getElement(), 'line-ending-selector:convert-to-CRLF' ); lineEndingTile.onDidChange(done); }); runs(() => { expect(tileUpdateCount).toBe(2); expect(lineEndingTile.element.textContent).toBe('CRLF'); expect(getTooltipText(lineEndingTile.element)).toBe( 'File uses CRLF (Windows) line endings' ); }); waitsFor(done => { atom.commands.dispatch( editor.getElement(), 'line-ending-selector:convert-to-LF' ); lineEndingTile.onDidChange(done); }); runs(() => { expect(tileUpdateCount).toBe(3); expect(lineEndingTile.element.textContent).toBe('LF'); }); runs(() => { editor.setTextInBufferRange([[0, 0], [0, 0]], '\n'); }); waits(100); runs(() => { expect(tileUpdateCount).toBe(3); }); }); }); }); }); function getTooltipText(element) { const [tooltip] = atom.tooltips.findTooltips(element); return tooltip.getTitle(); }