From e033f2cdbb08b6db32be922be732ebcc7f338b25 Mon Sep 17 00:00:00 2001 From: Benjamin Gray Date: Wed, 16 Sep 2020 18:00:39 +1000 Subject: [PATCH 01/10] more assertions --- spec/results-view-spec.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/spec/results-view-spec.js b/spec/results-view-spec.js index 828eaa65..c15c3707 100644 --- a/spec/results-view-spec.js +++ b/spec/results-view-spec.js @@ -303,7 +303,13 @@ describe('ResultsView', () => { const {listView} = resultsView.refs; expect(listView.element.querySelectorAll('li').length).toBeLessThan(resultsView.model.getPathCount() + resultsView.model.getMatchCount()); + expect(listView.element.querySelectorAll('li').length).toBeGreaterThan(0); + expect(resultsView.resultRows.length).toBeGreaterThan(0); + await resultsView.moveToBottom(); + + expect(listView.element.querySelectorAll('.match-row').length).toBeGreaterThan(0); + expect(_.last(listView.element.querySelectorAll('.match-row'))).toHaveClass('selected'); expect(listView.element.scrollTop).not.toBe(0); From e4e10a22183afc27f82cf2d52b15ab315d755a1a Mon Sep 17 00:00:00 2001 From: Benjamin Gray Date: Wed, 16 Sep 2020 18:05:43 +1000 Subject: [PATCH 02/10] minimise CI work --- .travis.yml | 6 +++--- appveyor.yml | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.travis.yml b/.travis.yml index ffe863a8..dc4589bc 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,14 +6,14 @@ notifications: on_failure: change env: -- ATOM_CHANNEL=stable -- ATOM_CHANNEL=beta +# - ATOM_CHANNEL=stable +# - ATOM_CHANNEL=beta - ATOM_CHANNEL=dev script: 'curl -s https://raw.githubusercontent.com/atom/ci/master/build-package.sh | sh' git: - depth: 10 + depth: 3 branches: only: diff --git a/appveyor.yml b/appveyor.yml index f9f2370f..4d802c03 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -6,7 +6,7 @@ branches: only: - master -clone_depth: 10 +clone_depth: 3 skip_tags: true @@ -14,8 +14,8 @@ environment: APM_TEST_PACKAGES: matrix: - - ATOM_CHANNEL: stable - - ATOM_CHANNEL: beta + # - ATOM_CHANNEL: stable + # - ATOM_CHANNEL: beta - ATOM_CHANNEL: dev install: From c1c54f49e73d81bbaf6858481bd11ce1e9f49725 Mon Sep 17 00:00:00 2001 From: Benjamin Gray Date: Wed, 16 Sep 2020 18:11:45 +1000 Subject: [PATCH 03/10] use node 12.16.3 in appveyor --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index 4d802c03..dda66e9f 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -19,7 +19,7 @@ environment: - ATOM_CHANNEL: dev install: - - ps: Install-Product node 4 + - ps: Install-Product node 12.16.3 build_script: - ps: iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/atom/ci/master/build-package.ps1')) From ab796cd6d72afaa82bc352a818f9db178f5ee9a9 Mon Sep 17 00:00:00 2001 From: Benjamin Gray Date: Wed, 16 Sep 2020 18:44:59 +1000 Subject: [PATCH 04/10] Trigger CI From 07603cf18cb93e23b63d9a61698c76aab1115f09 Mon Sep 17 00:00:00 2001 From: Benjamin Gray Date: Wed, 16 Sep 2020 18:59:58 +1000 Subject: [PATCH 05/10] Trigger CI From 8ac16f40bf23cc8a226c7c95d58b7c8016eb2097 Mon Sep 17 00:00:00 2001 From: Benjamin Gray Date: Wed, 16 Sep 2020 19:09:59 +1000 Subject: [PATCH 06/10] comment out new assertions --- spec/results-view-spec.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/spec/results-view-spec.js b/spec/results-view-spec.js index c15c3707..e18caf80 100644 --- a/spec/results-view-spec.js +++ b/spec/results-view-spec.js @@ -303,12 +303,12 @@ describe('ResultsView', () => { const {listView} = resultsView.refs; expect(listView.element.querySelectorAll('li').length).toBeLessThan(resultsView.model.getPathCount() + resultsView.model.getMatchCount()); - expect(listView.element.querySelectorAll('li').length).toBeGreaterThan(0); - expect(resultsView.resultRows.length).toBeGreaterThan(0); + // expect(listView.element.querySelectorAll('li').length).toBeGreaterThan(0); + // expect(resultsView.resultRows.length).toBeGreaterThan(0); await resultsView.moveToBottom(); - expect(listView.element.querySelectorAll('.match-row').length).toBeGreaterThan(0); + // expect(listView.element.querySelectorAll('.match-row').length).toBeGreaterThan(0); expect(_.last(listView.element.querySelectorAll('.match-row'))).toHaveClass('selected'); expect(listView.element.scrollTop).not.toBe(0); From cb858a67da596164e791eb6ed972863fd77e6c6a Mon Sep 17 00:00:00 2001 From: Benjamin Gray Date: Thu, 17 Sep 2020 23:55:13 +1000 Subject: [PATCH 07/10] add back assertions --- spec/results-view-spec.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/spec/results-view-spec.js b/spec/results-view-spec.js index e18caf80..c15c3707 100644 --- a/spec/results-view-spec.js +++ b/spec/results-view-spec.js @@ -303,12 +303,12 @@ describe('ResultsView', () => { const {listView} = resultsView.refs; expect(listView.element.querySelectorAll('li').length).toBeLessThan(resultsView.model.getPathCount() + resultsView.model.getMatchCount()); - // expect(listView.element.querySelectorAll('li').length).toBeGreaterThan(0); - // expect(resultsView.resultRows.length).toBeGreaterThan(0); + expect(listView.element.querySelectorAll('li').length).toBeGreaterThan(0); + expect(resultsView.resultRows.length).toBeGreaterThan(0); await resultsView.moveToBottom(); - // expect(listView.element.querySelectorAll('.match-row').length).toBeGreaterThan(0); + expect(listView.element.querySelectorAll('.match-row').length).toBeGreaterThan(0); expect(_.last(listView.element.querySelectorAll('.match-row'))).toHaveClass('selected'); expect(listView.element.scrollTop).not.toBe(0); From be93383babdf68bb654a61f0f5f6f2cda8a4a097 Mon Sep 17 00:00:00 2001 From: Benjamin Gray Date: Fri, 18 Sep 2020 01:33:46 +1000 Subject: [PATCH 08/10] focus tests --- spec/buffer-search-spec.js | 1268 +++++------ spec/find-spec.js | 98 +- spec/find-view-spec.js | 3706 ++++++++++++++++---------------- spec/project-find-view-spec.js | 3346 ++++++++++++++-------------- spec/result-row-spec.js | 196 +- spec/results-model-spec.js | 292 +-- spec/results-view-spec.js | 1702 +++++++-------- spec/select-next-spec.js | 1272 +++++------ 8 files changed, 5940 insertions(+), 5940 deletions(-) diff --git a/spec/buffer-search-spec.js b/spec/buffer-search-spec.js index 98d59e1b..40208aa4 100644 --- a/spec/buffer-search-spec.js +++ b/spec/buffer-search-spec.js @@ -1,634 +1,634 @@ -const dedent = require('dedent') -const {TextEditor, Range} = require('atom'); -const FindOptions = require('../lib/find-options'); -const BufferSearch = require('../lib/buffer-search'); - -describe('BufferSearch', () => { - let model, editor, buffer, markersListener, currentResultListener, searchSpy; - - beforeEach(() => { - editor = new TextEditor(); - buffer = editor.getBuffer(); - - // TODO - remove this conditional after Atom 1.25 ships - if (buffer.findAndMarkAllInRangeSync) { - searchSpy = spyOn(buffer, 'findAndMarkAllInRangeSync').andCallThrough(); - } else { - searchSpy = spyOn(buffer, 'scanInRange').andCallThrough(); - } - - editor.setText(dedent` - ----------- - aaa bbb ccc - ddd aaa bbb - ccc ddd aaa - ----------- - aaa bbb ccc - ddd aaa bbb - ccc ddd aaa - ----------- - `); - advanceClock(buffer.stoppedChangingDelay); - - const findOptions = new FindOptions({findPattern: "a+"}); - model = new BufferSearch(findOptions); - - markersListener = jasmine.createSpy('markersListener'); - model.onDidUpdate(markersListener); - - currentResultListener = jasmine.createSpy('currentResultListener'); - model.onDidChangeCurrentResult(currentResultListener); - - model.setEditor(editor); - markersListener.reset(); - - model.search("a+", { - caseSensitive: false, - useRegex: true, - wholeWord: false - }); - }); - - afterEach(() => { - model.destroy(); - editor.destroy(); - }); - - function getHighlightedRanges() { - const ranges = []; - const decorations = editor.decorationsStateForScreenRowRange(0, editor.getLineCount()) - for (const id in decorations) { - const decoration = decorations[id]; - if (['find-result', 'current-result'].includes(decoration.properties.class)) { - ranges.push(decoration.screenRange); - } - } - return ranges - .sort((a, b) => a.compare(b)) - .map(range => range.serialize()); - }; - - function expectUpdateEvent() { - expect(markersListener.callCount).toBe(1); - const emittedMarkerRanges = markersListener - .mostRecentCall.args[0] - .map(marker => marker.getBufferRange().serialize()); - expect(emittedMarkerRanges).toEqual(getHighlightedRanges()); - markersListener.reset(); - }; - - function expectNoUpdateEvent() { - expect(markersListener).not.toHaveBeenCalled(); - } - - function scannedRanges() { - return searchSpy.argsForCall.map(args => args.find(arg => arg instanceof Range)) - } - - it("highlights all the occurrences of the search regexp", () => { - expectUpdateEvent(); - expect(getHighlightedRanges()).toEqual([ - [[1, 0], [1, 3]], - [[2, 4], [2, 7]], - [[3, 8], [3, 11]], - [[5, 0], [5, 3]], - [[6, 4], [6, 7]], - [[7, 8], [7, 11]] - ]); - - expect(scannedRanges()).toEqual([ - [[0, 0], [Infinity, Infinity]] - ]); - }); - - describe("when the buffer changes", () => { - beforeEach(() => { - markersListener.reset(); - searchSpy.reset(); - }); - - describe("when changes occur in the middle of the buffer", () => { - it("removes any invalidated search results and recreates markers in the changed regions", () => { - editor.setCursorBufferPosition([2, 5]); - editor.addCursorAtBufferPosition([6, 5]); - editor.insertText("."); - editor.insertText("."); - - expectNoUpdateEvent(); - expect(getHighlightedRanges()).toEqual([ - [[1, 0], [1, 3]], - [[3, 8], [3, 11]], - [[5, 0], [5, 3]], - [[7, 8], [7, 11]] - ]); - - advanceClock(buffer.stoppedChangingDelay); - - expectUpdateEvent(); - expect(getHighlightedRanges()).toEqual([ - [[1, 0], [1, 3]], - [[2, 4], [2, 5]], - [[2, 7], [2, 9]], - [[3, 8], [3, 11]], - [[5, 0], [5, 3]], - [[6, 4], [6, 5]], - [[6, 7], [6, 9]], - [[7, 8], [7, 11]] - ]); - - expect(scannedRanges()).toEqual([ - [[1, 0], [3, 11]], - [[5, 0], [7, 11]] - ]); - }) - }); - - describe("when changes occur within the first search result", () => { - it("rescans the buffer from the beginning to the first valid marker", () => { - editor.setCursorBufferPosition([1, 2]); - editor.insertText("."); - editor.insertText("."); - - expectNoUpdateEvent(); - expect(getHighlightedRanges()).toEqual([ - [[2, 4], [2, 7]], - [[3, 8], [3, 11]], - [[5, 0], [5, 3]], - [[6, 4], [6, 7]], - [[7, 8], [7, 11]] - ]); - - advanceClock(buffer.stoppedChangingDelay); - - expectUpdateEvent(); - expect(getHighlightedRanges()).toEqual([ - [[1, 0], [1, 2]], - [[1, 4], [1, 5]], - [[2, 4], [2, 7]], - [[3, 8], [3, 11]], - [[5, 0], [5, 3]], - [[6, 4], [6, 7]], - [[7, 8], [7, 11]] - ]); - - expect(scannedRanges()).toEqual([ - [[0, 0], [2, 7]] - ]); - }) - }); - - describe("when changes occur within the last search result", () => { - it("rescans the buffer from the last valid marker to the end", () => { - editor.setCursorBufferPosition([7, 9]); - editor.insertText("."); - editor.insertText("."); - - expectNoUpdateEvent(); - expect(getHighlightedRanges()).toEqual([ - [[1, 0], [1, 3]], - [[2, 4], [2, 7]], - [[3, 8], [3, 11]], - [[5, 0], [5, 3]], - [[6, 4], [6, 7]] - ]); - - advanceClock(buffer.stoppedChangingDelay); - - expectUpdateEvent(); - expect(getHighlightedRanges()).toEqual([ - [[1, 0], [1, 3]], - [[2, 4], [2, 7]], - [[3, 8], [3, 11]], - [[5, 0], [5, 3]], - [[6, 4], [6, 7]], - [[7, 8], [7, 9]], - [[7, 11], [7, 13]] - ]); - - expect(scannedRanges()).toEqual([ - [[6, 4], [Infinity, Infinity]] - ]); - }) - }); - - describe("when changes occur within two adjacent markers", () => { - it("rescans the changed region in a single scan", () => { - editor.setCursorBufferPosition([2, 5]); - editor.addCursorAtBufferPosition([3, 9]); - editor.insertText("."); - editor.insertText("."); - - expectNoUpdateEvent(); - expect(getHighlightedRanges()).toEqual([ - [[1, 0], [1, 3]], - [[5, 0], [5, 3]], - [[6, 4], [6, 7]], - [[7, 8], [7, 11]] - ]); - - advanceClock(buffer.stoppedChangingDelay); - - expectUpdateEvent(); - expect(getHighlightedRanges()).toEqual([ - [[1, 0], [1, 3]], - [[2, 4], [2, 5]], - [[2, 7], [2, 9]], - [[3, 8], [3, 9]], - [[3, 11], [3, 13]], - [[5, 0], [5, 3]], - [[6, 4], [6, 7]], - [[7, 8], [7, 11]] - ]); - - expect(scannedRanges()).toEqual([ - [[1, 0], [5, 3]] - ]); - }) - }); - - describe("when changes extend an existing search result", () => { - it("updates the results with the new extended ranges", () => { - editor.setCursorBufferPosition([2, 4]); - editor.addCursorAtBufferPosition([6, 7]); - editor.insertText("a"); - editor.insertText("a"); - - expectNoUpdateEvent(); - expect(getHighlightedRanges()).toEqual([ - [[1, 0], [1, 3]], - [[2, 6], [2, 9]], - [[3, 8], [3, 11]], - [[5, 0], [5, 3]], - [[6, 4], [6, 7]], - [[7, 8], [7, 11]] - ]); - - advanceClock(buffer.stoppedChangingDelay); - - expectUpdateEvent(); - expect(getHighlightedRanges()).toEqual([ - [[1, 0], [1, 3]], - [[2, 4], [2, 9]], - [[3, 8], [3, 11]], - [[5, 0], [5, 3]], - [[6, 4], [6, 9]], - [[7, 8], [7, 11]] - ]); - }) - }); - - describe("when the changes are before any marker", () => { - it("doesn't change the markers", () => { - editor.setCursorBufferPosition([0, 3]); - editor.insertText(".."); - - expectNoUpdateEvent(); - expect(getHighlightedRanges()).toEqual([ - [[1, 0], [1, 3]], - [[2, 4], [2, 7]], - [[3, 8], [3, 11]], - [[5, 0], [5, 3]], - [[6, 4], [6, 7]], - [[7, 8], [7, 11]] - ]); - - advanceClock(buffer.stoppedChangingDelay); - - expect(getHighlightedRanges()).toEqual([ - [[1, 0], [1, 3]], - [[2, 4], [2, 7]], - [[3, 8], [3, 11]], - [[5, 0], [5, 3]], - [[6, 4], [6, 7]], - [[7, 8], [7, 11]] - ]); - - expect(scannedRanges()).toEqual([ - [[0, 0], [1, 3]] - ]); - }) - }); - - describe("when the changes are between markers", () => { - it("doesn't change the markers", () => { - editor.setCursorBufferPosition([3, 1]); - editor.insertText(".."); - - expectNoUpdateEvent(); - expect(getHighlightedRanges()).toEqual([ - [[1, 0], [1, 3]], - [[2, 4], [2, 7]], - [[3, 10], [3, 13]], - [[5, 0], [5, 3]], - [[6, 4], [6, 7]], - [[7, 8], [7, 11]] - ]); - - advanceClock(buffer.stoppedChangingDelay); - - expectUpdateEvent(); - expect(getHighlightedRanges()).toEqual([ - [[1, 0], [1, 3]], - [[2, 4], [2, 7]], - [[3, 10], [3, 13]], - [[5, 0], [5, 3]], - [[6, 4], [6, 7]], - [[7, 8], [7, 11]] - ]); - - expect(scannedRanges()).toEqual([ - [[2, 4], [3, 13]] - ]); - }) - }); - - describe("when the changes are after all the markers", () => { - it("doesn't change the markers", () => { - editor.setCursorBufferPosition([8, 3]); - editor.insertText(".."); - - expectNoUpdateEvent(); - expect(getHighlightedRanges()).toEqual([ - [[1, 0], [1, 3]], - [[2, 4], [2, 7]], - [[3, 8], [3, 11]], - [[5, 0], [5, 3]], - [[6, 4], [6, 7]], - [[7, 8], [7, 11]] - ]); - - advanceClock(buffer.stoppedChangingDelay); - - expectUpdateEvent(); - expect(getHighlightedRanges()).toEqual([ - [[1, 0], [1, 3]], - [[2, 4], [2, 7]], - [[3, 8], [3, 11]], - [[5, 0], [5, 3]], - [[6, 4], [6, 7]], - [[7, 8], [7, 11]] - ]); - - expect(scannedRanges()).toEqual([ - [[7, 8], [Infinity, Infinity]] - ]); - }) - }); - - describe("when the changes are undone", () => { - it("recreates any temporarily-invalidated markers", () => { - editor.setCursorBufferPosition([2, 5]); - editor.insertText("."); - editor.insertText("."); - editor.backspace(); - editor.backspace(); - - expectNoUpdateEvent(); - expect(getHighlightedRanges()).toEqual([ - [[1, 0], [1, 3]], - [[3, 8], [3, 11]], - [[5, 0], [5, 3]], - [[6, 4], [6, 7]], - [[7, 8], [7, 11]] - ]); - - advanceClock(buffer.stoppedChangingDelay); - - expect(getHighlightedRanges()).toEqual([ - [[1, 0], [1, 3]], - [[2, 4], [2, 7]], - [[3, 8], [3, 11]], - [[5, 0], [5, 3]], - [[6, 4], [6, 7]], - [[7, 8], [7, 11]] - ]); - - expect(scannedRanges()).toEqual([]); - }) - }); - }); - - describe("when the 'in current selection' option is set to true", () => { - beforeEach(() => { - model.setFindOptions({inCurrentSelection: true}) - }) - - describe("if the current selection is non-empty", () => { - beforeEach(() => { - editor.setSelectedBufferRange([[1, 3], [4, 5]]); - }) - - it("only searches in the given selection", () => { - model.search("a+"); - expect(scannedRanges().pop()).toEqual([[1, 3], [4, 5]]); - expect(getHighlightedRanges()).toEqual([ - [[2, 4], [2, 7]], - [[3, 8], [3, 11]] - ]); - }) - - it("executes another search if the current selection is different from the last search's selection", () => { - model.search("a+"); - - editor.setSelectedBufferRange([[5, 0], [5, 2]]); - - model.search("a+"); - expect(scannedRanges().pop()).toEqual([[5, 0], [5, 2]]); - expect(getHighlightedRanges()).toEqual([ - [[5, 0], [5, 2]] - ]); - }) - - it("does not execute another search if the current selection is idential to the last search's selection", () => { - spyOn(model, 'recreateMarkers').andCallThrough() - - model.search("a+"); - model.search("a+"); - expect(model.recreateMarkers.callCount).toBe(1) - }) - }) - - describe("if there are multiple non-empty selections", () => { - beforeEach(() => { - editor.setSelectedBufferRanges([ - [[1, 3], [2, 11]], - [[5, 2], [8, 0]], - ]); - }) - - it("searches in all the selections", () => { - model.search("a+"); - - expect(getHighlightedRanges()).toEqual([ - [[2, 4], [2, 7]], - [[5, 2], [5, 3]], - [[6, 4], [6, 7]], - [[7, 8], [7, 11]] - ]); - }) - - it("executes another search if the current selection is different from the last search's selection", () => { - spyOn(model, 'recreateMarkers').andCallThrough() - - model.search("a+"); - editor.setSelectedBufferRanges([ - [[1, 3], [2, 11]], - [[5, 1], [8, 0]], - ]); - model.search("a+"); - - expect(model.recreateMarkers.callCount).toBe(2) - expect(getHighlightedRanges()).toEqual([ - [[2, 4], [2, 7]], - [[5, 1], [5, 3]], - [[6, 4], [6, 7]], - [[7, 8], [7, 11]] - ]); - }) - - it("does not execute another search if the current selection is idential to the last search's selection", () => { - spyOn(model, 'recreateMarkers').andCallThrough() - editor.setSelectedBufferRanges([ - [[1, 3], [2, 11]], - [[5, 1], [8, 0]], - ]); - model.search("a+"); - model.search("a+"); - expect(model.recreateMarkers.callCount).toBe(1) - }) - }) - - describe("if the current selection is empty", () => { - beforeEach(() => { - editor.setSelectedBufferRange([[0, 0], [0, 0]]); - }) - - it("ignores the option and searches the entire buffer", () => { - model.search("a+"); - expect(getHighlightedRanges()).toEqual([ - [[1, 0], [1, 3]], - [[2, 4], [2, 7]], - [[3, 8], [3, 11]], - [[5, 0], [5, 3]], - [[6, 4], [6, 7]], - [[7, 8], [7, 11]] - ]); - - expect(scannedRanges().pop()).toEqual([[0, 0], [Infinity, Infinity]]); - }) - }) - }) - - describe("replacing a search result", () => { - beforeEach(() => { - searchSpy.reset() - }); - - it("replaces the marked text with the given string", () => { - const markers = markersListener.mostRecentCall.args[0]; - markersListener.reset(); - - editor.setSelectedBufferRange(markers[1].getBufferRange()); - expect(currentResultListener).toHaveBeenCalledWith(markers[1]); - currentResultListener.reset(); - - model.replace([markers[1]], "new-text"); - - expect(editor.getText()).toBe(dedent` - ----------- - aaa bbb ccc - ddd new-text bbb - ccc ddd aaa - ----------- - aaa bbb ccc - ddd aaa bbb - ccc ddd aaa - ----------- - `); - - expectUpdateEvent(); - expect(getHighlightedRanges()).toEqual([ - [[1, 0], [1, 3]], - [[3, 8], [3, 11]], - [[5, 0], [5, 3]], - [[6, 4], [6, 7]], - [[7, 8], [7, 11]] - ]); - - const markerToSelect = markers[2]; - const rangeToSelect = markerToSelect.getBufferRange(); - - editor.setSelectedBufferRange(rangeToSelect); - expect(currentResultListener).toHaveBeenCalledWith(markerToSelect); - currentResultListener.reset(); - - advanceClock(buffer.stoppedChangingDelay); - - expectUpdateEvent(); - expect(getHighlightedRanges()).toEqual([ - [[1, 0], [1, 3]], - [[3, 8], [3, 11]], - [[5, 0], [5, 3]], - [[6, 4], [6, 7]], - [[7, 8], [7, 11]] - ]); - expect(scannedRanges()).toEqual([ - [[1, 0], [3, 11]] - ]); - - expect(currentResultListener).toHaveBeenCalled(); - expect(currentResultListener.mostRecentCall.args[0].getBufferRange()).toEqual(rangeToSelect); - expect(currentResultListener.mostRecentCall.args[0].isDestroyed()).toBe(false); - }); - - it("replaces the marked text with the given string that contains escaped escape sequence", () => { - const markers = markersListener.mostRecentCall.args[0]; - markersListener.reset(); - - model.replace(markers, "new-text\\\\n"); - - expect(editor.getText()).toBe([ - '-----------', - 'new-text\\n bbb ccc', - 'ddd new-text\\n bbb', - 'ccc ddd new-text\\n', - '-----------', - 'new-text\\n bbb ccc', - 'ddd new-text\\n bbb', - 'ccc ddd new-text\\n', - '-----------', - ].join('\n')); - }); - }); - - describe(".prototype.resultsMarkerLayerForTextEditor(editor)", () => - it("creates or retrieves the results marker layer for the given editor", () => { - const layer1 = model.resultsMarkerLayerForTextEditor(editor); - - // basic check that this is the expected results layer - expect(layer1.findMarkers().length).toBeGreaterThan(0); - for (const marker of layer1.findMarkers()) { - expect(editor.getTextInBufferRange(marker.getBufferRange())).toMatch(/a+/); - } - - const editor2 = new TextEditor(); - model.setEditor(editor2); - const layer2 = model.resultsMarkerLayerForTextEditor(editor2); - - model.setEditor(editor); - expect(model.resultsMarkerLayerForTextEditor(editor)).toBe(layer1); - expect(model.resultsMarkerLayerForTextEditor(editor2)).toBe(layer2); - - model.search("c+", { - caseSensitive: false, - useRegex: true, - wholeWord: false - }); - - expect(layer1.findMarkers().length).toBeGreaterThan(0); - for (const marker of layer1.findMarkers()) { - expect(editor.getTextInBufferRange(marker.getBufferRange())).toMatch(/c+/); - } - }) - ); -}); +// const dedent = require('dedent') +// const {TextEditor, Range} = require('atom'); +// const FindOptions = require('../lib/find-options'); +// const BufferSearch = require('../lib/buffer-search'); +// +// describe('BufferSearch', () => { +// let model, editor, buffer, markersListener, currentResultListener, searchSpy; +// +// beforeEach(() => { +// editor = new TextEditor(); +// buffer = editor.getBuffer(); +// +// // TODO - remove this conditional after Atom 1.25 ships +// if (buffer.findAndMarkAllInRangeSync) { +// searchSpy = spyOn(buffer, 'findAndMarkAllInRangeSync').andCallThrough(); +// } else { +// searchSpy = spyOn(buffer, 'scanInRange').andCallThrough(); +// } +// +// editor.setText(dedent` +// ----------- +// aaa bbb ccc +// ddd aaa bbb +// ccc ddd aaa +// ----------- +// aaa bbb ccc +// ddd aaa bbb +// ccc ddd aaa +// ----------- +// `); +// advanceClock(buffer.stoppedChangingDelay); +// +// const findOptions = new FindOptions({findPattern: "a+"}); +// model = new BufferSearch(findOptions); +// +// markersListener = jasmine.createSpy('markersListener'); +// model.onDidUpdate(markersListener); +// +// currentResultListener = jasmine.createSpy('currentResultListener'); +// model.onDidChangeCurrentResult(currentResultListener); +// +// model.setEditor(editor); +// markersListener.reset(); +// +// model.search("a+", { +// caseSensitive: false, +// useRegex: true, +// wholeWord: false +// }); +// }); +// +// afterEach(() => { +// model.destroy(); +// editor.destroy(); +// }); +// +// function getHighlightedRanges() { +// const ranges = []; +// const decorations = editor.decorationsStateForScreenRowRange(0, editor.getLineCount()) +// for (const id in decorations) { +// const decoration = decorations[id]; +// if (['find-result', 'current-result'].includes(decoration.properties.class)) { +// ranges.push(decoration.screenRange); +// } +// } +// return ranges +// .sort((a, b) => a.compare(b)) +// .map(range => range.serialize()); +// }; +// +// function expectUpdateEvent() { +// expect(markersListener.callCount).toBe(1); +// const emittedMarkerRanges = markersListener +// .mostRecentCall.args[0] +// .map(marker => marker.getBufferRange().serialize()); +// expect(emittedMarkerRanges).toEqual(getHighlightedRanges()); +// markersListener.reset(); +// }; +// +// function expectNoUpdateEvent() { +// expect(markersListener).not.toHaveBeenCalled(); +// } +// +// function scannedRanges() { +// return searchSpy.argsForCall.map(args => args.find(arg => arg instanceof Range)) +// } +// +// it("highlights all the occurrences of the search regexp", () => { +// expectUpdateEvent(); +// expect(getHighlightedRanges()).toEqual([ +// [[1, 0], [1, 3]], +// [[2, 4], [2, 7]], +// [[3, 8], [3, 11]], +// [[5, 0], [5, 3]], +// [[6, 4], [6, 7]], +// [[7, 8], [7, 11]] +// ]); +// +// expect(scannedRanges()).toEqual([ +// [[0, 0], [Infinity, Infinity]] +// ]); +// }); +// +// describe("when the buffer changes", () => { +// beforeEach(() => { +// markersListener.reset(); +// searchSpy.reset(); +// }); +// +// describe("when changes occur in the middle of the buffer", () => { +// it("removes any invalidated search results and recreates markers in the changed regions", () => { +// editor.setCursorBufferPosition([2, 5]); +// editor.addCursorAtBufferPosition([6, 5]); +// editor.insertText("."); +// editor.insertText("."); +// +// expectNoUpdateEvent(); +// expect(getHighlightedRanges()).toEqual([ +// [[1, 0], [1, 3]], +// [[3, 8], [3, 11]], +// [[5, 0], [5, 3]], +// [[7, 8], [7, 11]] +// ]); +// +// advanceClock(buffer.stoppedChangingDelay); +// +// expectUpdateEvent(); +// expect(getHighlightedRanges()).toEqual([ +// [[1, 0], [1, 3]], +// [[2, 4], [2, 5]], +// [[2, 7], [2, 9]], +// [[3, 8], [3, 11]], +// [[5, 0], [5, 3]], +// [[6, 4], [6, 5]], +// [[6, 7], [6, 9]], +// [[7, 8], [7, 11]] +// ]); +// +// expect(scannedRanges()).toEqual([ +// [[1, 0], [3, 11]], +// [[5, 0], [7, 11]] +// ]); +// }) +// }); +// +// describe("when changes occur within the first search result", () => { +// it("rescans the buffer from the beginning to the first valid marker", () => { +// editor.setCursorBufferPosition([1, 2]); +// editor.insertText("."); +// editor.insertText("."); +// +// expectNoUpdateEvent(); +// expect(getHighlightedRanges()).toEqual([ +// [[2, 4], [2, 7]], +// [[3, 8], [3, 11]], +// [[5, 0], [5, 3]], +// [[6, 4], [6, 7]], +// [[7, 8], [7, 11]] +// ]); +// +// advanceClock(buffer.stoppedChangingDelay); +// +// expectUpdateEvent(); +// expect(getHighlightedRanges()).toEqual([ +// [[1, 0], [1, 2]], +// [[1, 4], [1, 5]], +// [[2, 4], [2, 7]], +// [[3, 8], [3, 11]], +// [[5, 0], [5, 3]], +// [[6, 4], [6, 7]], +// [[7, 8], [7, 11]] +// ]); +// +// expect(scannedRanges()).toEqual([ +// [[0, 0], [2, 7]] +// ]); +// }) +// }); +// +// describe("when changes occur within the last search result", () => { +// it("rescans the buffer from the last valid marker to the end", () => { +// editor.setCursorBufferPosition([7, 9]); +// editor.insertText("."); +// editor.insertText("."); +// +// expectNoUpdateEvent(); +// expect(getHighlightedRanges()).toEqual([ +// [[1, 0], [1, 3]], +// [[2, 4], [2, 7]], +// [[3, 8], [3, 11]], +// [[5, 0], [5, 3]], +// [[6, 4], [6, 7]] +// ]); +// +// advanceClock(buffer.stoppedChangingDelay); +// +// expectUpdateEvent(); +// expect(getHighlightedRanges()).toEqual([ +// [[1, 0], [1, 3]], +// [[2, 4], [2, 7]], +// [[3, 8], [3, 11]], +// [[5, 0], [5, 3]], +// [[6, 4], [6, 7]], +// [[7, 8], [7, 9]], +// [[7, 11], [7, 13]] +// ]); +// +// expect(scannedRanges()).toEqual([ +// [[6, 4], [Infinity, Infinity]] +// ]); +// }) +// }); +// +// describe("when changes occur within two adjacent markers", () => { +// it("rescans the changed region in a single scan", () => { +// editor.setCursorBufferPosition([2, 5]); +// editor.addCursorAtBufferPosition([3, 9]); +// editor.insertText("."); +// editor.insertText("."); +// +// expectNoUpdateEvent(); +// expect(getHighlightedRanges()).toEqual([ +// [[1, 0], [1, 3]], +// [[5, 0], [5, 3]], +// [[6, 4], [6, 7]], +// [[7, 8], [7, 11]] +// ]); +// +// advanceClock(buffer.stoppedChangingDelay); +// +// expectUpdateEvent(); +// expect(getHighlightedRanges()).toEqual([ +// [[1, 0], [1, 3]], +// [[2, 4], [2, 5]], +// [[2, 7], [2, 9]], +// [[3, 8], [3, 9]], +// [[3, 11], [3, 13]], +// [[5, 0], [5, 3]], +// [[6, 4], [6, 7]], +// [[7, 8], [7, 11]] +// ]); +// +// expect(scannedRanges()).toEqual([ +// [[1, 0], [5, 3]] +// ]); +// }) +// }); +// +// describe("when changes extend an existing search result", () => { +// it("updates the results with the new extended ranges", () => { +// editor.setCursorBufferPosition([2, 4]); +// editor.addCursorAtBufferPosition([6, 7]); +// editor.insertText("a"); +// editor.insertText("a"); +// +// expectNoUpdateEvent(); +// expect(getHighlightedRanges()).toEqual([ +// [[1, 0], [1, 3]], +// [[2, 6], [2, 9]], +// [[3, 8], [3, 11]], +// [[5, 0], [5, 3]], +// [[6, 4], [6, 7]], +// [[7, 8], [7, 11]] +// ]); +// +// advanceClock(buffer.stoppedChangingDelay); +// +// expectUpdateEvent(); +// expect(getHighlightedRanges()).toEqual([ +// [[1, 0], [1, 3]], +// [[2, 4], [2, 9]], +// [[3, 8], [3, 11]], +// [[5, 0], [5, 3]], +// [[6, 4], [6, 9]], +// [[7, 8], [7, 11]] +// ]); +// }) +// }); +// +// describe("when the changes are before any marker", () => { +// it("doesn't change the markers", () => { +// editor.setCursorBufferPosition([0, 3]); +// editor.insertText(".."); +// +// expectNoUpdateEvent(); +// expect(getHighlightedRanges()).toEqual([ +// [[1, 0], [1, 3]], +// [[2, 4], [2, 7]], +// [[3, 8], [3, 11]], +// [[5, 0], [5, 3]], +// [[6, 4], [6, 7]], +// [[7, 8], [7, 11]] +// ]); +// +// advanceClock(buffer.stoppedChangingDelay); +// +// expect(getHighlightedRanges()).toEqual([ +// [[1, 0], [1, 3]], +// [[2, 4], [2, 7]], +// [[3, 8], [3, 11]], +// [[5, 0], [5, 3]], +// [[6, 4], [6, 7]], +// [[7, 8], [7, 11]] +// ]); +// +// expect(scannedRanges()).toEqual([ +// [[0, 0], [1, 3]] +// ]); +// }) +// }); +// +// describe("when the changes are between markers", () => { +// it("doesn't change the markers", () => { +// editor.setCursorBufferPosition([3, 1]); +// editor.insertText(".."); +// +// expectNoUpdateEvent(); +// expect(getHighlightedRanges()).toEqual([ +// [[1, 0], [1, 3]], +// [[2, 4], [2, 7]], +// [[3, 10], [3, 13]], +// [[5, 0], [5, 3]], +// [[6, 4], [6, 7]], +// [[7, 8], [7, 11]] +// ]); +// +// advanceClock(buffer.stoppedChangingDelay); +// +// expectUpdateEvent(); +// expect(getHighlightedRanges()).toEqual([ +// [[1, 0], [1, 3]], +// [[2, 4], [2, 7]], +// [[3, 10], [3, 13]], +// [[5, 0], [5, 3]], +// [[6, 4], [6, 7]], +// [[7, 8], [7, 11]] +// ]); +// +// expect(scannedRanges()).toEqual([ +// [[2, 4], [3, 13]] +// ]); +// }) +// }); +// +// describe("when the changes are after all the markers", () => { +// it("doesn't change the markers", () => { +// editor.setCursorBufferPosition([8, 3]); +// editor.insertText(".."); +// +// expectNoUpdateEvent(); +// expect(getHighlightedRanges()).toEqual([ +// [[1, 0], [1, 3]], +// [[2, 4], [2, 7]], +// [[3, 8], [3, 11]], +// [[5, 0], [5, 3]], +// [[6, 4], [6, 7]], +// [[7, 8], [7, 11]] +// ]); +// +// advanceClock(buffer.stoppedChangingDelay); +// +// expectUpdateEvent(); +// expect(getHighlightedRanges()).toEqual([ +// [[1, 0], [1, 3]], +// [[2, 4], [2, 7]], +// [[3, 8], [3, 11]], +// [[5, 0], [5, 3]], +// [[6, 4], [6, 7]], +// [[7, 8], [7, 11]] +// ]); +// +// expect(scannedRanges()).toEqual([ +// [[7, 8], [Infinity, Infinity]] +// ]); +// }) +// }); +// +// describe("when the changes are undone", () => { +// it("recreates any temporarily-invalidated markers", () => { +// editor.setCursorBufferPosition([2, 5]); +// editor.insertText("."); +// editor.insertText("."); +// editor.backspace(); +// editor.backspace(); +// +// expectNoUpdateEvent(); +// expect(getHighlightedRanges()).toEqual([ +// [[1, 0], [1, 3]], +// [[3, 8], [3, 11]], +// [[5, 0], [5, 3]], +// [[6, 4], [6, 7]], +// [[7, 8], [7, 11]] +// ]); +// +// advanceClock(buffer.stoppedChangingDelay); +// +// expect(getHighlightedRanges()).toEqual([ +// [[1, 0], [1, 3]], +// [[2, 4], [2, 7]], +// [[3, 8], [3, 11]], +// [[5, 0], [5, 3]], +// [[6, 4], [6, 7]], +// [[7, 8], [7, 11]] +// ]); +// +// expect(scannedRanges()).toEqual([]); +// }) +// }); +// }); +// +// describe("when the 'in current selection' option is set to true", () => { +// beforeEach(() => { +// model.setFindOptions({inCurrentSelection: true}) +// }) +// +// describe("if the current selection is non-empty", () => { +// beforeEach(() => { +// editor.setSelectedBufferRange([[1, 3], [4, 5]]); +// }) +// +// it("only searches in the given selection", () => { +// model.search("a+"); +// expect(scannedRanges().pop()).toEqual([[1, 3], [4, 5]]); +// expect(getHighlightedRanges()).toEqual([ +// [[2, 4], [2, 7]], +// [[3, 8], [3, 11]] +// ]); +// }) +// +// it("executes another search if the current selection is different from the last search's selection", () => { +// model.search("a+"); +// +// editor.setSelectedBufferRange([[5, 0], [5, 2]]); +// +// model.search("a+"); +// expect(scannedRanges().pop()).toEqual([[5, 0], [5, 2]]); +// expect(getHighlightedRanges()).toEqual([ +// [[5, 0], [5, 2]] +// ]); +// }) +// +// it("does not execute another search if the current selection is idential to the last search's selection", () => { +// spyOn(model, 'recreateMarkers').andCallThrough() +// +// model.search("a+"); +// model.search("a+"); +// expect(model.recreateMarkers.callCount).toBe(1) +// }) +// }) +// +// describe("if there are multiple non-empty selections", () => { +// beforeEach(() => { +// editor.setSelectedBufferRanges([ +// [[1, 3], [2, 11]], +// [[5, 2], [8, 0]], +// ]); +// }) +// +// it("searches in all the selections", () => { +// model.search("a+"); +// +// expect(getHighlightedRanges()).toEqual([ +// [[2, 4], [2, 7]], +// [[5, 2], [5, 3]], +// [[6, 4], [6, 7]], +// [[7, 8], [7, 11]] +// ]); +// }) +// +// it("executes another search if the current selection is different from the last search's selection", () => { +// spyOn(model, 'recreateMarkers').andCallThrough() +// +// model.search("a+"); +// editor.setSelectedBufferRanges([ +// [[1, 3], [2, 11]], +// [[5, 1], [8, 0]], +// ]); +// model.search("a+"); +// +// expect(model.recreateMarkers.callCount).toBe(2) +// expect(getHighlightedRanges()).toEqual([ +// [[2, 4], [2, 7]], +// [[5, 1], [5, 3]], +// [[6, 4], [6, 7]], +// [[7, 8], [7, 11]] +// ]); +// }) +// +// it("does not execute another search if the current selection is idential to the last search's selection", () => { +// spyOn(model, 'recreateMarkers').andCallThrough() +// editor.setSelectedBufferRanges([ +// [[1, 3], [2, 11]], +// [[5, 1], [8, 0]], +// ]); +// model.search("a+"); +// model.search("a+"); +// expect(model.recreateMarkers.callCount).toBe(1) +// }) +// }) +// +// describe("if the current selection is empty", () => { +// beforeEach(() => { +// editor.setSelectedBufferRange([[0, 0], [0, 0]]); +// }) +// +// it("ignores the option and searches the entire buffer", () => { +// model.search("a+"); +// expect(getHighlightedRanges()).toEqual([ +// [[1, 0], [1, 3]], +// [[2, 4], [2, 7]], +// [[3, 8], [3, 11]], +// [[5, 0], [5, 3]], +// [[6, 4], [6, 7]], +// [[7, 8], [7, 11]] +// ]); +// +// expect(scannedRanges().pop()).toEqual([[0, 0], [Infinity, Infinity]]); +// }) +// }) +// }) +// +// describe("replacing a search result", () => { +// beforeEach(() => { +// searchSpy.reset() +// }); +// +// it("replaces the marked text with the given string", () => { +// const markers = markersListener.mostRecentCall.args[0]; +// markersListener.reset(); +// +// editor.setSelectedBufferRange(markers[1].getBufferRange()); +// expect(currentResultListener).toHaveBeenCalledWith(markers[1]); +// currentResultListener.reset(); +// +// model.replace([markers[1]], "new-text"); +// +// expect(editor.getText()).toBe(dedent` +// ----------- +// aaa bbb ccc +// ddd new-text bbb +// ccc ddd aaa +// ----------- +// aaa bbb ccc +// ddd aaa bbb +// ccc ddd aaa +// ----------- +// `); +// +// expectUpdateEvent(); +// expect(getHighlightedRanges()).toEqual([ +// [[1, 0], [1, 3]], +// [[3, 8], [3, 11]], +// [[5, 0], [5, 3]], +// [[6, 4], [6, 7]], +// [[7, 8], [7, 11]] +// ]); +// +// const markerToSelect = markers[2]; +// const rangeToSelect = markerToSelect.getBufferRange(); +// +// editor.setSelectedBufferRange(rangeToSelect); +// expect(currentResultListener).toHaveBeenCalledWith(markerToSelect); +// currentResultListener.reset(); +// +// advanceClock(buffer.stoppedChangingDelay); +// +// expectUpdateEvent(); +// expect(getHighlightedRanges()).toEqual([ +// [[1, 0], [1, 3]], +// [[3, 8], [3, 11]], +// [[5, 0], [5, 3]], +// [[6, 4], [6, 7]], +// [[7, 8], [7, 11]] +// ]); +// expect(scannedRanges()).toEqual([ +// [[1, 0], [3, 11]] +// ]); +// +// expect(currentResultListener).toHaveBeenCalled(); +// expect(currentResultListener.mostRecentCall.args[0].getBufferRange()).toEqual(rangeToSelect); +// expect(currentResultListener.mostRecentCall.args[0].isDestroyed()).toBe(false); +// }); +// +// it("replaces the marked text with the given string that contains escaped escape sequence", () => { +// const markers = markersListener.mostRecentCall.args[0]; +// markersListener.reset(); +// +// model.replace(markers, "new-text\\\\n"); +// +// expect(editor.getText()).toBe([ +// '-----------', +// 'new-text\\n bbb ccc', +// 'ddd new-text\\n bbb', +// 'ccc ddd new-text\\n', +// '-----------', +// 'new-text\\n bbb ccc', +// 'ddd new-text\\n bbb', +// 'ccc ddd new-text\\n', +// '-----------', +// ].join('\n')); +// }); +// }); +// +// describe(".prototype.resultsMarkerLayerForTextEditor(editor)", () => +// it("creates or retrieves the results marker layer for the given editor", () => { +// const layer1 = model.resultsMarkerLayerForTextEditor(editor); +// +// // basic check that this is the expected results layer +// expect(layer1.findMarkers().length).toBeGreaterThan(0); +// for (const marker of layer1.findMarkers()) { +// expect(editor.getTextInBufferRange(marker.getBufferRange())).toMatch(/a+/); +// } +// +// const editor2 = new TextEditor(); +// model.setEditor(editor2); +// const layer2 = model.resultsMarkerLayerForTextEditor(editor2); +// +// model.setEditor(editor); +// expect(model.resultsMarkerLayerForTextEditor(editor)).toBe(layer1); +// expect(model.resultsMarkerLayerForTextEditor(editor2)).toBe(layer2); +// +// model.search("c+", { +// caseSensitive: false, +// useRegex: true, +// wholeWord: false +// }); +// +// expect(layer1.findMarkers().length).toBeGreaterThan(0); +// for (const marker of layer1.findMarkers()) { +// expect(editor.getTextInBufferRange(marker.getBufferRange())).toMatch(/c+/); +// } +// }) +// ); +// }); diff --git a/spec/find-spec.js b/spec/find-spec.js index 01298a8e..400e3f8c 100644 --- a/spec/find-spec.js +++ b/spec/find-spec.js @@ -1,49 +1,49 @@ -const BufferSearch = require('../lib/buffer-search') -const EmbeddedEditorItem = require('./item/embedded-editor-item') -const DeferredEditorItem = require('./item/deferred-editor-item'); -const UnrecognizedItem = require('./item/unrecognized-item'); - -describe('Find', () => { - describe('updating the find model', () => { - beforeEach(async () => { - atom.workspace.addOpener(EmbeddedEditorItem.opener) - atom.workspace.addOpener(UnrecognizedItem.opener) - atom.workspace.addOpener(DeferredEditorItem.opener) - - const activationPromise = atom.packages.activatePackage('find-and-replace') - atom.commands.dispatch(atom.views.getView(atom.workspace), 'find-and-replace:show') - await activationPromise - - spyOn(BufferSearch.prototype, 'setEditor') - }) - - it("sets the find model's editor whenever an editor is focused", async () => { - let editor = await atom.workspace.open() - expect(BufferSearch.prototype.setEditor).toHaveBeenCalledWith(editor) - - editor = await atom.workspace.open('sample.js') - expect(BufferSearch.prototype.setEditor).toHaveBeenCalledWith(editor) - }) - - it("sets the find model's editor to an embedded text editor", async () => { - const embedded = await atom.workspace.open(EmbeddedEditorItem.uri) - expect(BufferSearch.prototype.setEditor).toHaveBeenCalledWith(embedded.refs.theEditor) - }) - - it("sets the find model's editor to an embedded text editor after activation", async () => { - const deferred = await atom.workspace.open(DeferredEditorItem.uri) - expect(BufferSearch.prototype.setEditor).not.toHaveBeenCalled() - - await deferred.showEditor() - expect(BufferSearch.prototype.setEditor).toHaveBeenCalledWith(deferred.refs.theEditor) - - await deferred.hideEditor() - expect(BufferSearch.prototype.setEditor).toHaveBeenCalledWith(null) - }) - - it("sets the find model's editor to null if a non-editor is focused", async () => { - await atom.workspace.open(UnrecognizedItem.uri) - expect(BufferSearch.prototype.setEditor).toHaveBeenCalledWith(null) - }) - }) -}) +// const BufferSearch = require('../lib/buffer-search') +// const EmbeddedEditorItem = require('./item/embedded-editor-item') +// const DeferredEditorItem = require('./item/deferred-editor-item'); +// const UnrecognizedItem = require('./item/unrecognized-item'); +// +// describe('Find', () => { +// describe('updating the find model', () => { +// beforeEach(async () => { +// atom.workspace.addOpener(EmbeddedEditorItem.opener) +// atom.workspace.addOpener(UnrecognizedItem.opener) +// atom.workspace.addOpener(DeferredEditorItem.opener) +// +// const activationPromise = atom.packages.activatePackage('find-and-replace') +// atom.commands.dispatch(atom.views.getView(atom.workspace), 'find-and-replace:show') +// await activationPromise +// +// spyOn(BufferSearch.prototype, 'setEditor') +// }) +// +// it("sets the find model's editor whenever an editor is focused", async () => { +// let editor = await atom.workspace.open() +// expect(BufferSearch.prototype.setEditor).toHaveBeenCalledWith(editor) +// +// editor = await atom.workspace.open('sample.js') +// expect(BufferSearch.prototype.setEditor).toHaveBeenCalledWith(editor) +// }) +// +// it("sets the find model's editor to an embedded text editor", async () => { +// const embedded = await atom.workspace.open(EmbeddedEditorItem.uri) +// expect(BufferSearch.prototype.setEditor).toHaveBeenCalledWith(embedded.refs.theEditor) +// }) +// +// it("sets the find model's editor to an embedded text editor after activation", async () => { +// const deferred = await atom.workspace.open(DeferredEditorItem.uri) +// expect(BufferSearch.prototype.setEditor).not.toHaveBeenCalled() +// +// await deferred.showEditor() +// expect(BufferSearch.prototype.setEditor).toHaveBeenCalledWith(deferred.refs.theEditor) +// +// await deferred.hideEditor() +// expect(BufferSearch.prototype.setEditor).toHaveBeenCalledWith(null) +// }) +// +// it("sets the find model's editor to null if a non-editor is focused", async () => { +// await atom.workspace.open(UnrecognizedItem.uri) +// expect(BufferSearch.prototype.setEditor).toHaveBeenCalledWith(null) +// }) +// }) +// }) diff --git a/spec/find-view-spec.js b/spec/find-view-spec.js index 68385b1c..225612a8 100644 --- a/spec/find-view-spec.js +++ b/spec/find-view-spec.js @@ -1,1853 +1,1853 @@ -/** @babel */ - -const path = require("path"); - -describe("FindView", () => { - let workspaceElement, editorView, editor, findView, activationPromise; - - function getFindAtomPanel() { - return workspaceElement.querySelector(".find-and-replace").parentNode; - } - - function getResultDecorations(editor, clazz) { - const result = []; - const decorations = editor.decorationsStateForScreenRowRange(0, editor.getLineCount()) - for (let id in decorations) { - const decoration = decorations[id] - if (decoration.properties.class === clazz) { - result.push(decoration); - } - } - return result; - } - - beforeEach(async () => { - spyOn(atom, "beep"); - workspaceElement = atom.views.getView(atom.workspace); - workspaceElement.style.height = '800px' - atom.project.setPaths([path.join(__dirname, "fixtures")]); - - await atom.workspace.open("sample.js"); - - jasmine.attachToDOM(workspaceElement); - editor = atom.workspace.getCenter().getActiveTextEditor(); - editorView = editor.element; - - activationPromise = atom.packages.activatePackage("find-and-replace").then(function({mainModule}) { - mainModule.createViews(); - ({findView} = mainModule); - }); - }); - - describe("when find-and-replace:show is triggered", () => { - it("attaches FindView to the root view", async () => { - atom.commands.dispatch(editorView, "find-and-replace:show"); - await activationPromise; - - expect(workspaceElement.querySelector(".find-and-replace")).toBeDefined(); - }); - - it("populates the findEditor with selection when there is a selection", async () => { - editor.setSelectedBufferRange([[2, 8], [2, 13]]); - - atom.commands.dispatch(editorView, "find-and-replace:show"); - await activationPromise; - - expect(getFindAtomPanel()).toBeVisible(); - expect(findView.findEditor.getText()).toBe("items"); - - findView.findEditor.setText(""); - editor.setSelectedBufferRange([[2, 14], [2, 20]]); - atom.commands.dispatch(editorView, "find-and-replace:show"); - expect(getFindAtomPanel()).toBeVisible(); - expect(findView.findEditor.getText()).toBe("length"); - }); - - it("does not change the findEditor text when there is no selection", async () => { - editor.setSelectedBufferRange([[2, 8], [2, 8]]); - - atom.commands.dispatch(editorView, "find-and-replace:show"); - await activationPromise; - - findView.findEditor.setText("kitten"); - atom.commands.dispatch(editorView, "find-and-replace:show"); - expect(findView.findEditor.getText()).toBe("kitten"); - }); - - it("does not change the findEditor text when there is a multiline selection", async () => { - editor.setSelectedBufferRange([[2, 8], [3, 12]]); - - atom.commands.dispatch(editorView, "find-and-replace:show"); - await activationPromise; - - expect(getFindAtomPanel()).toBeVisible(); - expect(findView.findEditor.getText()).toBe(""); - }); - - it("honors config settings for find options", async () => { - atom.config.set("find-and-replace.useRegex", true); - atom.config.set("find-and-replace.caseSensitive", true); - atom.config.set("find-and-replace.inCurrentSelection", true); - - atom.commands.dispatch(editorView, "find-and-replace:show"); - await activationPromise; - - expect(findView.refs.caseOptionButton).toHaveClass("selected"); - expect(findView.refs.regexOptionButton).toHaveClass("selected"); - expect(findView.refs.selectionOptionButton).toHaveClass("selected"); - }); - - it("places selected text into the find editor and escapes it when Regex is enabled", async () => { - atom.config.set("find-and-replace.useRegex", true); - editor.setSelectedBufferRange([[6, 6], [6, 65]]); - - atom.commands.dispatch(editorView, "find-and-replace:show"); - await activationPromise; - - expect(findView.findEditor.getText()).toBe( - "current < pivot \\? left\\.push\\(current\\) : right\\.push\\(current\\);" - ); - }); - - it('selects the text to find when the panel is re-shown', async () => { - atom.commands.dispatch(editorView, "find-and-replace:show"); - await activationPromise; - - const stringToSearch = "not found"; - const findEditor = findView.findEditor; - - findEditor.setText(stringToSearch); - - atom.commands.dispatch(findEditor.element, "core:confirm"); - atom.commands.dispatch(document.activeElement, "core:cancel"); - atom.commands.dispatch(editorView, "find-and-replace:show"); - - expect(findEditor.getSelectedBufferRange()).toEqual([[0, 0], [0, stringToSearch.length]]); - - const selectionElement = findEditor.getElement().querySelector('.highlight.selection .selection'); - - expect(selectionElement.getBoundingClientRect().width).toBeGreaterThan(0); - }); - }); - - describe("when find-and-replace:toggle is triggered", () => { - it("toggles the visibility of the FindView", async () => { - atom.commands.dispatch(workspaceElement, "find-and-replace:toggle"); - await activationPromise; - - expect(getFindAtomPanel()).toBeVisible(); - atom.commands.dispatch(workspaceElement, "find-and-replace:toggle"); - expect(getFindAtomPanel()).not.toBeVisible(); - }); - }); - - describe("when the find-view is focused and window:focus-next-pane is triggered", () => { - it("attaches FindView to the root view", async () => { - atom.commands.dispatch(editorView, "find-and-replace:show"); - await activationPromise; - - expect(workspaceElement.querySelector(".find-and-replace")).toHaveFocus(); - atom.commands.dispatch(findView.findEditor.element, "window:focus-next-pane"); - expect(workspaceElement.querySelector(".find-and-replace")).not.toHaveFocus(); - }); - }); - - describe("find-and-replace:show-replace", () => { - it("focuses the replace editor", async () => { - atom.commands.dispatch(editorView, "find-and-replace:show-replace"); - await activationPromise; - - expect(findView.replaceEditor.element).toHaveFocus(); - }); - - it("places the current selection in the replace editor", async () => { - editor.setSelectedBufferRange([[0, 16], [0, 27]]); - - atom.commands.dispatch(editorView, "find-and-replace:show-replace"); - await activationPromise; - - expect(findView.replaceEditor.getText()).toBe("function ()"); - }); - - it("does not escape the text when the regex option is enabled", async () => { - editor.setSelectedBufferRange([[0, 16], [0, 27]]); - - atom.commands.dispatch(editorView, "find-and-replace:show"); - atom.commands.dispatch(editorView, "find-and-replace:toggle-regex-option"); - atom.commands.dispatch(editorView, "find-and-replace:show-replace"); - await activationPromise; - - expect(findView.replaceEditor.getText()).toBe("function ()"); - }); - }); - - describe("when find-and-replace:clear-history is triggered", () => { - it("clears the find and replace histories", async () => { - atom.commands.dispatch(editorView, "find-and-replace:show"); - await activationPromise; - - findView.findEditor.setText("items"); - findView.replaceEditor.setText("cat"); - findView.replaceAll(); - findView.findEditor.setText("sort"); - findView.replaceEditor.setText("dog"); - findView.replaceNext(); - atom.commands.dispatch(editorView, "find-and-replace:clear-history"); - atom.commands.dispatch(findView.findEditor.element, "core:move-up"); - expect(findView.findEditor.getText()).toBe(""); - - atom.commands.dispatch(findView.replaceEditor.element, "core:move-up"); - expect(findView.replaceEditor.getText()).toBe(""); - }); - }); - - describe("core:cancel", () => { - beforeEach(async () => { - atom.commands.dispatch(editorView, "find-and-replace:show"); - await activationPromise; - - findView.findEditor.setText("items"); - atom.commands.dispatch(findView.findEditor.element, "core:confirm"); - findView.element.focus(); - }); - - describe("when core:cancel is triggered on the find view", () => { - it("detaches from the workspace view", () => { - atom.commands.dispatch(document.activeElement, "core:cancel"); - expect(getFindAtomPanel()).not.toBeVisible(); - }); - - it("removes highlighted matches", () => { - expect(workspaceElement).toHaveClass("find-visible"); - atom.commands.dispatch(document.activeElement, "core:cancel"); - expect(workspaceElement).not.toHaveClass("find-visible"); - }); - }); - - describe("when core:cancel is triggered on an empty pane", () => { - it("hides the find panel", () => { - const paneElement = atom.views.getView(atom.workspace.getCenter().getActivePane()); - paneElement.focus(); - atom.commands.dispatch(paneElement, "core:cancel"); - expect(getFindAtomPanel()).not.toBeVisible(); - }); - }); - - describe("when core:cancel is triggered on an editor", () => { - it("detaches from the workspace view", async () => { - atom.workspace.open(); - atom.commands.dispatch(editorView, "core:cancel"); - expect(getFindAtomPanel()).not.toBeVisible(); - }); - }); - - describe("when core:cancel is triggered on a mini editor", () => { - it("leaves the find view attached", () => { - const miniEditor = document.createElement("atom-text-editor"); - miniEditor.setAttribute("mini", ""); - - atom.workspace.addTopPanel({ - item: miniEditor - }); - - miniEditor.focus(); - atom.commands.dispatch(miniEditor, "core:cancel"); - expect(getFindAtomPanel()).toBeVisible(); - }); - }); - }); - - describe("serialization", () => { - it("serializes find and replace history", async () => { - atom.commands.dispatch(editorView, "find-and-replace:show"); - await activationPromise; - - findView.findEditor.setText("items"); - findView.replaceEditor.setText("cat"); - findView.replaceAll(); - findView.findEditor.setText("sort"); - findView.replaceEditor.setText("dog"); - findView.replaceNext(); - findView.findEditor.setText("shift"); - findView.replaceEditor.setText("ok"); - findView.findNext(false); - - await atom.packages.deactivatePackage("find-and-replace"); - activationPromise = atom.packages.activatePackage("find-and-replace").then(function({mainModule}) { - mainModule.createViews(); - ({findView} = mainModule); - }); - atom.commands.dispatch(editorView, "find-and-replace:show"); - await activationPromise; - - atom.commands.dispatch(findView.findEditor.element, "core:move-up"); - expect(findView.findEditor.getText()).toBe("shift"); - atom.commands.dispatch(findView.findEditor.element, "core:move-up"); - expect(findView.findEditor.getText()).toBe("sort"); - atom.commands.dispatch(findView.findEditor.element, "core:move-up"); - expect(findView.findEditor.getText()).toBe("items"); - atom.commands.dispatch(findView.replaceEditor.element, "core:move-up"); - expect(findView.replaceEditor.getText()).toBe("dog"); - atom.commands.dispatch(findView.replaceEditor.element, "core:move-up"); - expect(findView.replaceEditor.getText()).toBe("cat"); - }); - - it("serializes find options ", async () => { - atom.commands.dispatch(editorView, "find-and-replace:show"); - await activationPromise; - - expect(findView.refs.caseOptionButton).not.toHaveClass("selected"); - expect(findView.refs.regexOptionButton).not.toHaveClass("selected"); - expect(findView.refs.selectionOptionButton).not.toHaveClass("selected"); - expect(findView.refs.wholeWordOptionButton).not.toHaveClass("selected"); - - findView.refs.caseOptionButton.click(); - findView.refs.regexOptionButton.click(); - findView.refs.selectionOptionButton.click(); - findView.refs.wholeWordOptionButton.click(); - expect(findView.refs.caseOptionButton).toHaveClass("selected"); - expect(findView.refs.regexOptionButton).toHaveClass("selected"); - expect(findView.refs.selectionOptionButton).toHaveClass("selected"); - expect(findView.refs.wholeWordOptionButton).toHaveClass("selected"); - - await atom.packages.deactivatePackage("find-and-replace"); - activationPromise = atom.packages.activatePackage("find-and-replace").then(function({mainModule}) { - mainModule.createViews(); - ({findView} = mainModule); - }); - atom.commands.dispatch(editorView, "find-and-replace:show"); - await activationPromise; - - expect(findView.refs.caseOptionButton).toHaveClass("selected"); - expect(findView.refs.regexOptionButton).toHaveClass("selected"); - expect(findView.refs.selectionOptionButton).toHaveClass("selected"); - expect(findView.refs.wholeWordOptionButton).toHaveClass("selected"); - }); - }); - - describe("finding", () => { - beforeEach(async () => { - atom.config.set("find-and-replace.focusEditorAfterSearch", false); - editor.setCursorBufferPosition([2, 0]); - - atom.commands.dispatch(editorView, "find-and-replace:show"); - await activationPromise; - - findView.findEditor.setText("items"); - atom.commands.dispatch(findView.findEditor.element, "core:confirm"); - }); - - describe("when find-and-replace:confirm is triggered", () => { - it("runs a search", () => { - findView.findEditor.setText("notinthefile"); - atom.commands.dispatch(findView.findEditor.element, "find-and-replace:confirm"); - expect(getResultDecorations(editor, "find-result")).toHaveLength(0); - - findView.findEditor.setText("items"); - atom.commands.dispatch(findView.findEditor.element, "find-and-replace:confirm"); - expect(getResultDecorations(editor, "find-result")).toHaveLength(5); - }); - }); - - describe("when no results are found", () => { - it("adds a .has-no-results class", () => { - findView.findEditor.setText("notinthefile"); - atom.commands.dispatch(findView.findEditor.element, "find-and-replace:confirm"); - expect(findView.element).toHaveClass("has-no-results"); - }); - }); - - describe("when results are found", () => { - it("adds a .has-results class", () => { - findView.findEditor.setText("items"); - atom.commands.dispatch(findView.findEditor.element, "find-and-replace:confirm"); - expect(findView.element).toHaveClass("has-results"); - }); - }); - - describe("when the find string contains an escaped char", () => { - beforeEach(() => { - editor.setText("\t\n\\t\\\\"); - editor.setCursorBufferPosition([0, 0]); - }); - - describe("when regex search is enabled", () => { - beforeEach(() => { - atom.commands.dispatch(findView.findEditor.element, "find-and-replace:toggle-regex-option"); - }); - - it("finds a backslash", () => { - findView.findEditor.setText("\\\\"); - atom.commands.dispatch(findView.findEditor.element, "core:confirm"); - expect(editor.getSelectedBufferRange()).toEqual([[1, 0], [1, 1]]); - }); - - it("finds a newline", () => { - findView.findEditor.setText("\\n"); - atom.commands.dispatch(findView.findEditor.element, "core:confirm"); - expect(editor.getSelectedBufferRange()).toEqual([[0, 1], [1, 0]]); - }); - - it("finds a tab character", () => { - findView.findEditor.setText("\\t"); - atom.commands.dispatch(findView.findEditor.element, "core:confirm"); - expect(editor.getSelectedBufferRange()).toEqual([[0, 0], [0, 1]]); - }); - }); - - describe("when regex search is disabled", () => { - it("finds the literal backslash t", () => { - findView.findEditor.setText("\\t"); - atom.commands.dispatch(findView.findEditor.element, "core:confirm"); - expect(editor.getSelectedBufferRange()).toEqual([[1, 0], [1, 2]]); - }); - - it("finds a backslash", () => { - findView.findEditor.setText("\\"); - atom.commands.dispatch(findView.findEditor.element, "core:confirm"); - expect(editor.getSelectedBufferRange()).toEqual([[1, 0], [1, 1]]); - }); - - it("finds two backslashes", () => { - findView.findEditor.setText('\\\\'); - atom.commands.dispatch(findView.findEditor.element, "core:confirm"); - expect(editor.getSelectedBufferRange()).toEqual([[1, 2], [1, 4]]); - }); - - it("doesn't find when escaped", () => { - findView.findEditor.setText("\\\\t"); - atom.commands.dispatch(findView.findEditor.element, "core:confirm"); - expect(editor.getSelectedBufferRange()).toEqual([[0, 0], [0, 0]]); - }); - }); - }); - - describe("when focusEditorAfterSearch is set", () => { - beforeEach(() => { - atom.config.set("find-and-replace.focusEditorAfterSearch", true); - atom.commands.dispatch(findView.findEditor.element, "core:confirm"); - }); - - it("selects the first match following the cursor and correctly focuses the editor", () => { - expect(findView.refs.resultCounter.textContent).toEqual("3 of 6"); - expect(editor.getSelectedBufferRange()).toEqual([[2, 34], [2, 39]]); - expect(editorView).toHaveFocus(); - }); - }); - - describe("when whole-word search is enabled", () => { - beforeEach(() => { - editor.setText("-----\nswhole-wordy\nwhole-word\nword\nwhole-swords"); - editor.setCursorBufferPosition([0, 0]); - atom.commands.dispatch(findView.findEditor.element, "find-and-replace:toggle-whole-word-option"); - }); - - it("finds the whole words", () => { - findView.findEditor.setText("word"); - atom.commands.dispatch(findView.findEditor.element, "core:confirm"); - expect(editor.getSelectedBufferRange()).toEqual([[2, 6], [2, 10]]); - }); - - it("doesn't highlight the search inside words", () => { - findView.findEditor.setText("word"); - atom.commands.dispatch(findView.findEditor.element, "core:confirm"); - expect(getResultDecorations(editor, "find-result")).toHaveLength(1); - expect(getResultDecorations(editor, "current-result")).toHaveLength(1); - }); - }); - - it("doesn't change the selection, beeps if there are no matches and keeps focus on the find view", () => { - editor.setCursorBufferPosition([2, 0]); - findView.findEditor.setText("notinthefilebro"); - findView.findEditor.element.focus(); - atom.commands.dispatch(findView.findEditor.element, "core:confirm"); - expect(editor.getCursorBufferPosition()).toEqual([2, 0]); - expect(atom.beep).toHaveBeenCalled(); - expect(findView.element).toHaveFocus(); - expect(findView.refs.descriptionLabel.textContent).toEqual("No results found for 'notinthefilebro'"); - }); - - describe("updating the replace button enablement", () => { - it("enables the replace buttons when are search results", () => { - findView.findEditor.setText("item"); - atom.commands.dispatch(findView.findEditor.element, "core:confirm"); - expect(findView.refs.replaceAllButton).not.toHaveClass("disabled"); - expect(findView.refs.replaceNextButton).not.toHaveClass("disabled"); - - const disposable = findView.replaceTooltipSubscriptions; - spyOn(disposable, "dispose"); - findView.findEditor.setText("it"); - atom.commands.dispatch(findView.findEditor.element, "core:confirm"); - expect(findView.refs.replaceAllButton).not.toHaveClass("disabled"); - expect(findView.refs.replaceNextButton).not.toHaveClass("disabled"); - expect(disposable.dispose).not.toHaveBeenCalled(); - - findView.findEditor.setText("nopenotinthefile"); - atom.commands.dispatch(findView.findEditor.element, "core:confirm"); - expect(findView.refs.replaceAllButton).toHaveClass("disabled"); - expect(findView.refs.replaceNextButton).toHaveClass("disabled"); - expect(disposable.dispose).toHaveBeenCalled(); - - findView.findEditor.setText("i"); - atom.commands.dispatch(findView.findEditor.element, "core:confirm"); - expect(findView.refs.replaceAllButton).not.toHaveClass("disabled"); - expect(findView.refs.replaceNextButton).not.toHaveClass("disabled"); - - findView.findEditor.setText(""); - atom.commands.dispatch(findView.findEditor.element, "core:confirm"); - expect(findView.refs.replaceAllButton).toHaveClass("disabled"); - expect(findView.refs.replaceNextButton).toHaveClass("disabled"); - }); - }); - - describe("updating the descriptionLabel", () => { - it("properly updates the info message", () => { - findView.findEditor.setText("item"); - atom.commands.dispatch(findView.findEditor.element, "core:confirm"); - expect(findView.refs.descriptionLabel.textContent).toEqual("6 results found for 'item'"); - - findView.findEditor.setText("notinthefilenope"); - atom.commands.dispatch(findView.findEditor.element, "core:confirm"); - expect(findView.refs.descriptionLabel.textContent).toEqual("No results found for 'notinthefilenope'"); - - findView.findEditor.setText("item"); - atom.commands.dispatch(findView.findEditor.element, "core:confirm"); - expect(findView.refs.descriptionLabel.textContent).toEqual("6 results found for 'item'"); - - findView.findEditor.setText(""); - atom.commands.dispatch(findView.findEditor.element, "core:confirm"); - expect(findView.refs.descriptionLabel.textContent).toContain("Find in Current Buffer"); - }); - - describe("when there is an error", () => { - describe("when the regex search string is invalid", () => { - beforeEach(() => { - atom.commands.dispatch(findView.findEditor.element, "find-and-replace:toggle-regex-option"); - findView.findEditor.setText("i[t"); - atom.commands.dispatch(findView.findEditor.element, "core:confirm"); - }); - - it("displays the error", () => { - expect(findView.refs.descriptionLabel).toHaveClass("text-error"); - expect(findView.refs.descriptionLabel.textContent).toContain("Invalid regular expression"); - }); - - it("will be reset when there is no longer an error", () => { - expect(findView.refs.descriptionLabel).toHaveClass("text-error"); - - findView.findEditor.setText(""); - atom.commands.dispatch(findView.findEditor.element, "core:confirm"); - expect(findView.refs.descriptionLabel).not.toHaveClass("text-error"); - expect(findView.refs.descriptionLabel.textContent).toContain("Find in Current Buffer"); - - findView.findEditor.setText("item"); - atom.commands.dispatch(findView.findEditor.element, "core:confirm"); - expect(findView.refs.descriptionLabel).not.toHaveClass("text-error"); - expect(findView.refs.descriptionLabel.textContent).toContain("6 results"); - }); - }); - - describe("when the search string is too large", () => { - beforeEach(() => { - findView.findEditor.setText("x".repeat(50000)); - atom.commands.dispatch(findView.findEditor.element, "core:confirm"); - }); - - it("displays the error", () => { - expect(findView.refs.descriptionLabel).toHaveClass("text-error"); - expect(findView.refs.descriptionLabel.textContent).toBe("regular expression is too large"); - }); - - it("will be reset when there is no longer an error", () => { - findView.findEditor.setText(""); - atom.commands.dispatch(findView.findEditor.element, "core:confirm"); - expect(findView.refs.descriptionLabel).not.toHaveClass("text-error"); - expect(findView.refs.descriptionLabel.textContent).toContain("Find in Current Buffer"); - - findView.findEditor.setText("item"); - atom.commands.dispatch(findView.findEditor.element, "core:confirm"); - expect(findView.refs.descriptionLabel).not.toHaveClass("text-error"); - expect(findView.refs.descriptionLabel.textContent).toContain("6 results"); - }); - }); - }); - }); - - it("selects the first match following the cursor", () => { - expect(findView.refs.resultCounter.textContent).toEqual("2 of 6"); - expect(editor.getSelectedBufferRange()).toEqual([[2, 8], [2, 13]]); - - atom.commands.dispatch(findView.findEditor.element, "core:confirm"); - expect(findView.refs.resultCounter.textContent).toEqual("3 of 6"); - expect(editor.getSelectedBufferRange()).toEqual([[2, 34], [2, 39]]); - expect(findView.findEditor.element).toHaveFocus(); - }); - - it("selects the next match when the next match button is pressed", () => { - findView.refs.nextButton.click(); - expect(findView.refs.resultCounter.textContent).toEqual("3 of 6"); - expect(editor.getSelectedBufferRange()).toEqual([[2, 34], [2, 39]]); - }); - - it("selects the previous match when the next match button is pressed while holding shift", () => { - findView.refs.nextButton.dispatchEvent(new MouseEvent("click", { - shiftKey: true - })); - - expect(findView.refs.resultCounter.textContent).toEqual("1 of 6"); - expect(editor.getSelectedBufferRange()).toEqual([[1, 22], [1, 27]]); - }); - - it("selects the next match when the 'find-and-replace:find-next' event is triggered and correctly focuses the editor", () => { - expect(findView.element).toHaveFocus(); - atom.commands.dispatch(editorView, "find-and-replace:find-next"); - expect(findView.refs.resultCounter.textContent).toEqual("3 of 6"); - expect(editor.getSelectedBufferRange()).toEqual([[2, 34], [2, 39]]); - expect(editorView).toHaveFocus(); - }); - - it("selects the previous match before the cursor when the 'find-and-replace:show-previous' event is triggered", () => { - expect(findView.refs.resultCounter.textContent).toEqual("2 of 6"); - expect(editor.getSelectedBufferRange()).toEqual([[2, 8], [2, 13]]); - atom.commands.dispatch(findView.findEditor.element, "find-and-replace:show-previous"); - expect(findView.refs.resultCounter.textContent).toEqual("1 of 6"); - expect(editor.getSelectedBufferRange()).toEqual([[1, 22], [1, 27]]); - expect(findView.findEditor.element).toHaveFocus(); - }); - - describe("when the match is folded", () => { - it("unfolds the match", () => { - editor.foldAll(); - atom.commands.dispatch(findView.findEditor.element, "core:confirm"); - expect(editor.getSelectedBufferRange()).toEqual([[2, 34], [2, 39]]); - expect(editor.isFoldedAtBufferRow(2)).toBe(false); - expect(editor.getCursorBufferPosition()).toEqual([2, 39]); - }) - }) - - it("will re-run search if 'find-and-replace:find-next' is triggered after changing the findEditor's text", () => { - findView.findEditor.setText("sort"); - atom.commands.dispatch(findView.findEditor.element, "find-and-replace:find-next"); - expect(findView.refs.resultCounter.textContent).toEqual("3 of 5"); - expect(editor.getSelectedBufferRange()).toEqual([[8, 11], [8, 15]]); - }); - - it("'find-and-replace:find-next' adds to the findEditor's history", () => { - findView.findEditor.setText("sort"); - atom.commands.dispatch(findView.findEditor.element, "find-and-replace:find-next"); - expect(findView.refs.resultCounter.textContent).toEqual("3 of 5"); - - findView.findEditor.setText("nope"); - atom.commands.dispatch(findView.findEditor.element, "core:move-up"); - expect(findView.findEditor.getText()).toEqual("sort"); - }); - - it("selects the previous match when the 'find-and-replace:find-previous' event is triggered and correctly focuses the editor", () => { - expect(findView.element).toHaveFocus(); - - atom.commands.dispatch(editorView, "find-and-replace:find-previous"); - expect(findView.refs.resultCounter.textContent).toEqual("1 of 6"); - expect(editor.getSelectedBufferRange()).toEqual([[1, 27], [1, 22]]); - expect(editorView).toHaveFocus(); - }); - - it("will re-run search if 'find-and-replace:find-previous' is triggered after changing the findEditor's text", () => { - findView.findEditor.setText("sort"); - atom.commands.dispatch(findView.findEditor.element, "find-and-replace:find-previous"); - expect(findView.refs.resultCounter.textContent).toEqual("2 of 5"); - expect(editor.getSelectedBufferRange()).toEqual([[1, 6], [1, 10]]); - }); - - it("selects all matches when 'find-and-replace:find-all' is triggered and correctly focuses the editor", () => { - expect(findView.element).toHaveFocus(); - atom.commands.dispatch(findView.findEditor.element, "find-and-replace:find-all"); - - expect(editor.getSelectedBufferRanges()).toEqual([ - [[1, 27], [1, 22]], - [[2, 8], [2, 13]], - [[2, 34], [2, 39]], - [[3, 16], [3, 21]], - [[4, 10], [4, 15]], - [[5, 16], [5, 21]] - ]); - expect(editorView).toHaveFocus(); - }); - - it("will re-run search if 'find-and-replace:find-all' is triggered after changing the findEditor's text", () => { - findView.findEditor.setText("sort"); - atom.commands.dispatch(findView.findEditor.element, "find-and-replace:find-all"); - - expect(editor.getSelectedBufferRanges()).toEqual([ - [[0, 9], [0, 13]], - [[1, 6], [1, 10]], - [[8, 11], [8, 15]], - [[8, 43], [8, 47]], - [[11, 9], [11, 13]] - ]); - }); - - it("replaces results counter with number of results found when user moves the cursor", () => { - editor.moveDown(); - expect(findView.refs.resultCounter.textContent).toBe("6 found"); - }); - - it("replaces results counter x of y text when user selects a marked range", () => { - editor.moveDown(); - editor.setSelectedBufferRange([[2, 34], [2, 39]]); - expect(findView.refs.resultCounter.textContent).toEqual("3 of 6"); - }); - - it("shows an icon when search wraps around and the editor scrolls", () => { - editorView.style.height = "80px"; - - editorView.component.measureDimensions(); - expect(editor.getLastVisibleScreenRow()).toBe(3); - expect(findView.refs.resultCounter.textContent).toEqual("2 of 6"); - expect(findView.wrapIcon).not.toBeVisible(); - - atom.commands.dispatch(editorView, "find-and-replace:find-previous"); - expect(findView.refs.resultCounter.textContent).toEqual("1 of 6"); - expect(editor.getLastVisibleScreenRow()).toBe(3); - expect(findView.wrapIcon).not.toBeVisible(); - - atom.commands.dispatch(editorView, "find-and-replace:find-previous"); - expect(findView.refs.resultCounter.textContent).toEqual("6 of 6"); - expect(editor.getLastVisibleScreenRow()).toBe(7); - expect(findView.wrapIcon).toBeVisible(); - expect(findView.wrapIcon).toHaveClass("icon-move-down"); - - atom.commands.dispatch(editorView, "find-and-replace:find-next"); - expect(findView.refs.resultCounter.textContent).toEqual("1 of 6"); - expect(editor.getLastVisibleScreenRow()).toBe(3); - expect(findView.wrapIcon).toBeVisible(); - expect(findView.wrapIcon).toHaveClass("icon-move-up"); - }); - - it("does not show the wrap icon when the editor does not scroll", () => { - editorView.style.height = "400px"; - editor.update({autoHeight: false}) - - editorView.component.measureDimensions(); - expect(editor.getVisibleRowRange()).toEqual([0, 12]); - - atom.commands.dispatch(editorView, "find-and-replace:find-previous"); - expect(findView.refs.resultCounter.textContent).toEqual("1 of 6"); - - atom.commands.dispatch(editorView, "find-and-replace:find-previous"); - expect(findView.refs.resultCounter.textContent).toEqual("6 of 6"); - expect(editor.getVisibleRowRange()).toEqual([0, 12]); - expect(findView.wrapIcon).not.toBeVisible(); - - atom.commands.dispatch(editorView, "find-and-replace:find-next"); - expect(findView.refs.resultCounter.textContent).toEqual("1 of 6"); - expect(editor.getVisibleRowRange()).toEqual([0, 12]); - expect(findView.wrapIcon).not.toBeVisible(); - }); - - it("allows searching for dashes in combination with non-ascii characters (regression)", () => { - editor.setText("123-Âbc"); - findView.findEditor.setText("3-â"); - atom.commands.dispatch(findView.findEditor.element, "find-and-replace:find-next"); - expect(findView.refs.descriptionLabel).not.toHaveClass("text-error"); - expect(editor.getSelectedBufferRange()).toEqual([[0, 2], [0, 5]]); - }); - - describe("when find-and-replace:use-selection-as-find-pattern is triggered", () => { - it("places the selected text into the find editor", () => { - editor.setSelectedBufferRange([[1, 6], [1, 10]]); - atom.commands.dispatch(workspaceElement, "find-and-replace:use-selection-as-find-pattern"); - expect(findView.findEditor.getText()).toBe("sort"); - expect(editor.getSelectedBufferRange()).toEqual([[1, 6], [1, 10]]); - - atom.commands.dispatch(workspaceElement, "find-and-replace:find-next"); - expect(editor.getSelectedBufferRange()).toEqual([[8, 11], [8, 15]]); - - atom.workspace.destroyActivePane(); - atom.commands.dispatch(workspaceElement, "find-and-replace:use-selection-as-find-pattern"); - expect(findView.findEditor.getText()).toBe("sort"); - }); - - it("places the word under the cursor into the find editor", () => { - editor.setSelectedBufferRange([[1, 8], [1, 8]]); - atom.commands.dispatch(workspaceElement, "find-and-replace:use-selection-as-find-pattern"); - expect(findView.findEditor.getText()).toBe("sort"); - expect(editor.getSelectedBufferRange()).toEqual([[1, 8], [1, 8]]); - - atom.commands.dispatch(workspaceElement, "find-and-replace:find-next"); - expect(editor.getSelectedBufferRange()).toEqual([[8, 11], [8, 15]]); - }); - - it("places the previously selected text into the find editor if no selection", () => { - editor.setSelectedBufferRange([[1, 6], [1, 10]]); - atom.commands.dispatch(workspaceElement, "find-and-replace:use-selection-as-find-pattern"); - expect(findView.findEditor.getText()).toBe("sort"); - - editor.setSelectedBufferRange([[1, 1], [1, 1]]); - atom.commands.dispatch(workspaceElement, "find-and-replace:use-selection-as-find-pattern"); - expect(findView.findEditor.getText()).toBe("sort"); - }); - - it("places selected text into the find editor and escapes it when Regex is enabled", () => { - atom.commands.dispatch(findView.findEditor.element, "find-and-replace:toggle-regex-option"); - editor.setSelectedBufferRange([[6, 6], [6, 65]]); - atom.commands.dispatch(workspaceElement, "find-and-replace:use-selection-as-find-pattern"); - - expect(findView.findEditor.getText()).toBe( - "current < pivot \\? left\\.push\\(current\\) : right\\.push\\(current\\);" - ); - }); - - it("searches for the amount of results", () => { - spyOn(findView, 'liveSearch') // ignore live search - we're interested in the explicit search call - - editor.setSelectedBufferRange([[1, 8], [1, 8]]); - atom.commands.dispatch(workspaceElement, "find-and-replace:use-selection-as-find-pattern"); - expect(findView.refs.resultCounter.textContent).toEqual("5 found"); - }) - }); - - describe("when find-and-replace:use-selection-as-replace-pattern is triggered", () => { - it("places the selected text into the replace editor", () => { - editor.setSelectedBufferRange([[3, 8], [3, 13]]); - atom.commands.dispatch(workspaceElement, 'find-and-replace:use-selection-as-replace-pattern'); - expect(findView.replaceEditor.getText()).toBe('pivot'); - expect(editor.getSelectedBufferRange()).toEqual([[3, 8], [3, 13]]); - - findView.findEditor.setText('sort'); - atom.commands.dispatch(workspaceElement, 'find-and-replace:find-next'); - expect(editor.getSelectedBufferRange()).toEqual([[8, 11], [8, 15]]); - expect(editor.getTextInBufferRange(editor.getSelectedBufferRange())).toEqual('sort'); - atom.commands.dispatch(workspaceElement, 'find-and-replace:replace-next'); - expect(editor.getTextInBufferRange([[8, 11], [8, 16]])).toEqual('pivot'); - expect(editor.getSelectedBufferRange()).toEqual([[8, 44], [8, 48]]); - expect(editor.getTextInBufferRange(editor.getSelectedBufferRange())).toEqual('sort'); - }); - - it("places the word under the cursor into the replace editor", () => { - editor.setSelectedBufferRange([[3, 8], [3, 8]]); - atom.commands.dispatch(workspaceElement, 'find-and-replace:use-selection-as-replace-pattern'); - expect(findView.replaceEditor.getText()).toBe('pivot'); - expect(editor.getSelectedBufferRange()).toEqual([[3, 8], [3, 8]]); - - findView.findEditor.setText('sort'); - atom.commands.dispatch(workspaceElement, 'find-and-replace:find-next'); - expect(editor.getSelectedBufferRange()).toEqual([[8, 11], [8, 15]]); - expect(editor.getTextInBufferRange(editor.getSelectedBufferRange())).toEqual('sort'); - atom.commands.dispatch(workspaceElement, 'find-and-replace:replace-next'); - expect(editor.getTextInBufferRange([[8, 11], [8, 16]])).toEqual('pivot'); - expect(editor.getSelectedBufferRange()).toEqual([[8, 44], [8, 48]]); - expect(editor.getTextInBufferRange(editor.getSelectedBufferRange())).toEqual('sort'); - }); - - it("places the previously selected text into the replace editor if no selection", () => { - editor.setSelectedBufferRange([[1, 6], [1, 10]]); - atom.commands.dispatch(workspaceElement, 'find-and-replace:use-selection-as-replace-pattern'); - expect(findView.replaceEditor.getText()).toBe('sort'); - - editor.setSelectedBufferRange([[1, 1], [1, 1]]); - atom.commands.dispatch(workspaceElement, 'find-and-replace:use-selection-as-replace-pattern'); - expect(findView.replaceEditor.getText()).toBe('sort'); - }); - - it("places selected text into the replace editor and escapes it when Regex is enabled", () => { - atom.commands.dispatch(findView.replaceEditor.element, 'find-and-replace:toggle-regex-option'); - editor.setSelectedBufferRange([[6, 6], [6, 65]]); - atom.commands.dispatch(workspaceElement, 'find-and-replace:use-selection-as-replace-pattern'); - expect(findView.replaceEditor.getText()).toBe('current < pivot \\? left\\.push\\(current\\) : right\\.push\\(current\\);'); - }); - }); - - describe("when find-and-replace:find-next-selected is triggered", () => { - it("places the selected text into the find editor and finds the next occurrence", () => { - editor.setSelectedBufferRange([[0, 9], [0, 13]]); - atom.commands.dispatch(workspaceElement, "find-and-replace:find-next-selected"); - expect(findView.findEditor.getText()).toBe("sort"); - expect(editor.getSelectedBufferRange()).toEqual([[1, 6], [1, 10]]); - }); - - it("places the word under the cursor into the find editor and finds the next occurrence", () => { - editor.setSelectedBufferRange([[1, 8], [1, 8]]); - atom.commands.dispatch(workspaceElement, "find-and-replace:find-next-selected"); - expect(findView.findEditor.getText()).toBe("sort"); - expect(editor.getSelectedBufferRange()).toEqual([[8, 11], [8, 15]]); - }); - }); - - describe("when find-and-replace:find-previous-selected is triggered", () => { - it("places the selected text into the find editor and finds the previous occurrence ", () => { - editor.setSelectedBufferRange([[0, 9], [0, 13]]); - atom.commands.dispatch(workspaceElement, "find-and-replace:find-previous-selected"); - expect(findView.findEditor.getText()).toBe("sort"); - expect(editor.getSelectedBufferRange()).toEqual([[11, 9], [11, 13]]); - }); - - it("places the word under the cursor into the find editor and finds the previous occurrence", () => { - editor.setSelectedBufferRange([[8, 13], [8, 13]]); - atom.commands.dispatch(workspaceElement, "find-and-replace:find-previous-selected"); - expect(findView.findEditor.getText()).toBe("sort"); - expect(editor.getSelectedBufferRange()).toEqual([[1, 6], [1, 10]]); - }); - }); - - it("does not highlight the found text when the find view is hidden", () => { - atom.commands.dispatch(findView.findEditor.element, "core:cancel"); - atom.commands.dispatch(findView.findEditor.element, "find-and-replace:find-next"); - }); - - describe("when the active pane item changes", () => { - beforeEach(() => { - editor.setSelectedBufferRange([[0, 0], [0, 0]]); - }); - - describe("when a new editor is activated", () => { - it("reruns the search on the new editor", async () => { - await atom.workspace.open("sample.coffee"); - editor = atom.workspace.getCenter().getActivePaneItem(); - expect(findView.refs.resultCounter.textContent).toEqual("7 found"); - expect(editor.getSelectedBufferRange()).toEqual([[0, 0], [0, 0]]); - }); - - it("initially highlights the found text in the new editor", async () => { - expect(getResultDecorations(editor, "find-result")).toHaveLength(6); - - await atom.workspace.open("sample.coffee"); - expect(getResultDecorations(editor, "find-result")).toHaveLength(0); - - const newEditor = atom.workspace.getCenter().getActiveTextEditor(); - expect(getResultDecorations(newEditor, "find-result")).toHaveLength(7); - }); - - it("highlights the found text in the new editor when find next is triggered", async () => { - await atom.workspace.open("sample.coffee"); - - atom.commands.dispatch(findView.findEditor.element, "find-and-replace:find-next"); - const newEditor = atom.workspace.getCenter().getActiveTextEditor(); - expect(getResultDecorations(newEditor, "find-result")).toHaveLength(6); - expect(getResultDecorations(newEditor, "current-result")).toHaveLength(1); - }); - }); - - describe("when all active pane items are closed", () => { - it("updates the result count", () => { - atom.commands.dispatch(editorView, "core:close"); - expect(findView.refs.resultCounter.textContent).toEqual("no results"); - }); - }); - - describe("when the active pane item is not an editor", () => { - let openerDisposable; - - beforeEach(() => { - openerDisposable = atom.workspace.addOpener(function(pathToOpen, options) { - return document.createElement("div"); - }); - }); - - afterEach(() => { - openerDisposable.dispose(); - }); - - it("updates the result view", async () => { - await atom.workspace.open("another"); - expect(findView.refs.resultCounter.textContent).toEqual("no results"); - }); - }); - - describe("when the active pane is in a dock", () => { - it("does nothing", async () => { - const dock = atom.workspace.getLeftDock() - dock.show() - dock.getActivePane().activateItem(document.createElement('div')) - dock.getActivePane().activate() - expect(findView.refs.resultCounter.textContent).not.toEqual("no results"); - }); - }); - - describe("when a new editor is activated on a different pane", () => { - it("initially highlights all the sample.js results", () => { - expect(getResultDecorations(editor, "find-result")).toHaveLength(6); - }); - - it("reruns the search on the new editor", async () => { - let newEditor - if (atom.workspace.createItemForURI) { - newEditor = await atom.workspace.createItemForURI("sample.coffee"); - } else { - newEditor = await atom.workspace.open("sample.coffee", {activateItem: false}) - } - - newEditor = atom.workspace.paneForItem(editor).splitRight({ - items: [newEditor] - }).getActiveItem(); - - expect(getResultDecorations(newEditor, "find-result")).toHaveLength(7); - expect(findView.refs.resultCounter.textContent).toEqual("7 found"); - expect(newEditor.getSelectedBufferRange()).toEqual([[0, 0], [0, 0]]); - - atom.commands.dispatch(findView.findEditor.element, "find-and-replace:find-next"); - expect(findView.refs.resultCounter.textContent).toEqual("1 of 7"); - expect(newEditor.getSelectedBufferRange()).toEqual([[1, 9], [1, 14]]); - }); - - it("highlights the found text in the new editor (and removes the highlights from the other)", async () => { - const newEditor = await atom.workspace.open("sample.coffee") - expect(getResultDecorations(editor, "find-result")).toHaveLength(0); - expect(getResultDecorations(newEditor, "find-result")).toHaveLength(7); - }); - - it("will still highlight results after the split pane has been destroyed", async () => { - const newEditor = await atom.workspace.open("sample.coffee") - const originalPane = atom.workspace.paneForItem(editor); - const splitPane = atom.workspace.paneForItem(editor).splitRight(); - originalPane.moveItemToPane(newEditor, splitPane, 0); - expect(getResultDecorations(newEditor, "find-result")).toHaveLength(7); - - atom.commands.dispatch(editor.element, "core:close"); - editorView.focus(); - expect(atom.workspace.getCenter().getActiveTextEditor()).toBe(editor); - expect(getResultDecorations(editor, "find-result")).toHaveLength(6); - }); - }); - }); - - describe("when the buffer contents change", () => { - it("re-runs the search", () => { - editor.setSelectedBufferRange([[1, 26], [1, 27]]); - editor.insertText(""); - window.advanceClock(1000); - expect(findView.refs.resultCounter.textContent).toEqual("5 found"); - - editor.insertText("s"); - window.advanceClock(1000); - expect(findView.refs.resultCounter.textContent).toEqual("6 found"); - }); - - it("does not beep if no matches were found", () => { - editor.setCursorBufferPosition([2, 0]); - findView.findEditor.setText("notinthefilebro"); - atom.commands.dispatch(findView.findEditor.element, "core:confirm"); - atom.beep.reset(); - editor.insertText("blah blah"); - expect(atom.beep).not.toHaveBeenCalled(); - }); - }); - - describe("when in current selection is toggled", () => { - beforeEach(() => { - editor.setSelectedBufferRange([[2, 0], [4, 0]]); - }); - - it("toggles find within a selection via an event and only finds matches within the selection", () => { - findView.findEditor.setText("items"); - atom.commands.dispatch(findView.findEditor.element, "find-and-replace:toggle-selection-option"); - expect(editor.getSelectedBufferRange()).toEqual([[2, 0], [4, 0]]); - expect(findView.refs.resultCounter.textContent).toEqual("3 found"); - }); - - it("toggles find within a selection via button and only finds matches within the selection", () => { - findView.findEditor.setText("items"); - findView.refs.selectionOptionButton.click(); - expect(editor.getSelectedBufferRange()).toEqual([[2, 0], [4, 0]]); - expect(findView.refs.resultCounter.textContent).toEqual("3 found"); - }); - - describe("when there is no selection", () => { - beforeEach(() => { - editor.setSelectedBufferRange([[0, 0], [0, 0]]); - }); - - it("toggles find within a selection via an event", () => { - findView.findEditor.setText("items"); - atom.commands.dispatch(findView.findEditor.element, "find-and-replace:toggle-selection-option"); - expect(editor.getSelectedBufferRange()).toEqual([[1, 22], [1, 27]]); - expect(findView.refs.resultCounter.textContent).toEqual("1 of 6"); - }); - }); - }); - - describe("when regex is toggled", () => { - it("toggles regex via an event and finds text matching the pattern", () => { - editor.setCursorBufferPosition([2, 0]); - atom.commands.dispatch(findView.findEditor.element, "find-and-replace:toggle-regex-option"); - findView.findEditor.setText("i[t]em+s"); - expect(editor.getSelectedBufferRange()).toEqual([[2, 8], [2, 13]]); - }); - - it("toggles regex via a button and finds text matching the pattern", () => { - editor.setCursorBufferPosition([2, 0]); - findView.refs.regexOptionButton.click(); - findView.findEditor.setText("i[t]em+s"); - expect(editor.getSelectedBufferRange()).toEqual([[2, 8], [2, 13]]); - }); - - it("re-runs the search using the new find text when toggled", () => { - editor.setCursorBufferPosition([1, 0]); - findView.findEditor.setText("s(o)rt"); - atom.commands.dispatch(findView.findEditor.element, "find-and-replace:toggle-regex-option"); - expect(editor.getSelectedBufferRange()).toEqual([[1, 6], [1, 10]]); - }); - - describe("when an invalid regex is entered", () => { - it("displays an error", () => { - editor.setCursorBufferPosition([2, 0]); - atom.commands.dispatch(findView.findEditor.element, "find-and-replace:toggle-regex-option"); - findView.findEditor.setText("i[t"); - atom.commands.dispatch(findView.findEditor.element, "core:confirm"); - expect(findView.refs.descriptionLabel).toHaveClass("text-error"); - }); - }); - - describe("when there are existing selections", () => { - it("does not jump to the next match when any selections match the pattern", () => { - findView.model.setFindOptions({ - useRegex: false - }); - - findView.findEditor.setText("items.length"); - editor.setSelectedBufferRange([[2, 8], [2, 20]]); - findView.refs.regexOptionButton.click(); - expect(editor.getSelectedBufferRange()).toEqual([[2, 8], [2, 20]]); - - findView.refs.regexOptionButton.click(); - expect(editor.getSelectedBufferRange()).toEqual([[2, 8], [2, 20]]); - }); - - it("jumps to the next match when no selections match the pattern", () => { - findView.model.setFindOptions({ - useRegex: false - }); - - findView.findEditor.setText("pivot ?"); - editor.setSelectedBufferRange([[6, 16], [6, 23]]); - findView.refs.regexOptionButton.click(); - expect(editor.getSelectedBufferRange()).toEqual([[8, 29], [8, 34]]); - - findView.refs.regexOptionButton.click(); - expect(editor.getSelectedBufferRange()).toEqual([[6, 16], [6, 23]]); - }); - }); - - it("matches astral-plane unicode characters with .", () => { - if (!editor.getBuffer().hasAstral) { - console.log('Skipping astral-plane test case') - return - } - - editor.setText("\n\nbefore😄after\n\n"); - atom.commands.dispatch(findView.findEditor.element, "find-and-replace:toggle-regex-option"); - findView.findEditor.setText("before.after"); - atom.commands.dispatch(findView.findEditor.element, "core:confirm"); - expect(editor.getSelectedBufferRange()).toEqual([[2, 0], [2, 13]]) - }); - }); - - describe("when whole-word is toggled", () => { - it("toggles whole-word via an event and finds text matching the pattern", () => { - editor.setCursorBufferPosition([0, 0]); - findView.findEditor.setText("sort"); - atom.commands.dispatch(findView.findEditor.element, "core:confirm"); - expect(editor.getSelectedBufferRange()).toEqual([[0, 9], [0, 13]]); - - atom.commands.dispatch(findView.findEditor.element, "find-and-replace:toggle-whole-word-option"); - expect(editor.getSelectedBufferRange()).toEqual([[1, 6], [1, 10]]); - }); - - it("toggles whole-word via a button and finds text matching the pattern", () => { - editor.setCursorBufferPosition([0, 0]); - findView.findEditor.setText("sort"); - atom.commands.dispatch(findView.findEditor.element, "core:confirm"); - expect(editor.getSelectedBufferRange()).toEqual([[0, 9], [0, 13]]); - - findView.refs.wholeWordOptionButton.click(); - expect(editor.getSelectedBufferRange()).toEqual([[1, 6], [1, 10]]); - }); - - it("re-runs the search using the new find text when toggled", () => { - editor.setCursorBufferPosition([8, 0]); - findView.findEditor.setText("apply"); - atom.commands.dispatch(findView.findEditor.element, "find-and-replace:toggle-whole-word-option"); - expect(editor.getSelectedBufferRange()).toEqual([[11, 20], [11, 25]]); - }); - - describe("when there are existing selections", () => { - it("does not jump to the next match when any selections match the pattern", () => { - findView.model.setFindOptions({ - wholeWord: false - }); - - findView.findEditor.setText("sort"); - editor.setSelectedBufferRange([[1, 6], [1, 10]]); - findView.refs.wholeWordOptionButton.click(); - expect(editor.getSelectedBufferRange()).toEqual([[1, 6], [1, 10]]); - - findView.refs.wholeWordOptionButton.click(); - expect(editor.getSelectedBufferRange()).toEqual([[1, 6], [1, 10]]); - }); - - it("jumps to the next match when no selections match the pattern", () => { - findView.model.setFindOptions({ - wholeWord: false - }); - - findView.findEditor.setText("sort"); - editor.setSelectedBufferRange([[0, 9], [0, 13]]); - findView.refs.wholeWordOptionButton.click(); - expect(editor.getSelectedBufferRange()).toEqual([[1, 6], [1, 10]]); - - editor.setSelectedBufferRange([[0, 0], [0, 5]]); - findView.refs.wholeWordOptionButton.click(); - expect(editor.getSelectedBufferRange()).toEqual([[0, 9], [0, 13]]); - }); - }); - }); - - describe("when case sensitivity is toggled", () => { - beforeEach(() => { - editor.setText("-----\nwords\nWORDs\n"); - editor.setCursorBufferPosition([0, 0]); - }); - - it("toggles case sensitivity via an event and finds text matching the pattern", () => { - findView.findEditor.setText("WORDs"); - atom.commands.dispatch(findView.findEditor.element, "core:confirm"); - expect(editor.getSelectedBufferRange()).toEqual([[1, 0], [1, 5]]); - - editor.setCursorBufferPosition([0, 0]); - atom.commands.dispatch(findView.findEditor.element, "find-and-replace:toggle-case-option"); - expect(editor.getSelectedBufferRange()).toEqual([[2, 0], [2, 5]]); - }); - - it("toggles case sensitivity via a button and finds text matching the pattern", () => { - findView.findEditor.setText("WORDs"); - atom.commands.dispatch(findView.findEditor.element, "core:confirm"); - expect(editor.getSelectedBufferRange()).toEqual([[1, 0], [1, 5]]); - - editor.setCursorBufferPosition([0, 0]); - findView.refs.caseOptionButton.click(); - expect(editor.getSelectedBufferRange()).toEqual([[2, 0], [2, 5]]); - }); - - describe("when there are existing selections", () => { - it("does not jump to the next match when any selections match the pattern", () => { - findView.model.setFindOptions({ - caseSensitive: false - }); - - findView.findEditor.setText("WORDs"); - editor.setSelectedBufferRange([[2, 0], [2, 5]]); - findView.refs.caseOptionButton.click(); - expect(editor.getSelectedBufferRange()).toEqual([[2, 0], [2, 5]]); - - findView.refs.caseOptionButton.click(); - expect(editor.getSelectedBufferRange()).toEqual([[2, 0], [2, 5]]); - }); - - it("jumps to the next match when no selections match the pattern", () => { - findView.model.setFindOptions({ - caseSensitive: false - }); - - findView.findEditor.setText("WORDs"); - editor.setSelectedBufferRange([[1, 0], [1, 5]]); - findView.refs.caseOptionButton.click(); - expect(editor.getSelectedBufferRange()).toEqual([[2, 0], [2, 5]]); - - editor.setSelectedBufferRange([[0, 0], [0, 5]]); - findView.refs.caseOptionButton.click(); - expect(editor.getSelectedBufferRange()).toEqual([[1, 0], [1, 5]]); - }); - }); - - it("finds unicode characters with case folding", () => { - if (!editor.getBuffer().hasAstral) { - console.log('Skipping unicode test case') - return - } - - editor.setText("---\n> április\n---\n") - findView.findEditor.setText("Április") - atom.commands.dispatch(findView.findEditor.element, "core:confirm") - expect(editor.getSelectedBufferRange()).toEqual([[1, 2], [1, 9]]) - }); - }); - - describe("highlighting search results", () => { - function getResultDecoration(clazz) { - return getResultDecorations(editor, clazz)[0]; - } - - it("only highlights matches", () => { - expect(getResultDecorations(editor, "find-result")).toHaveLength(5); - findView.findEditor.setText("notinthefilebro"); - atom.commands.dispatch(findView.findEditor.element, "core:confirm"); - expect(getResultDecorations(editor, "find-result")).toHaveLength(0); - }); - - it("adds a class to the current match indicating it is the current match", () => { - const firstResultMarker = getResultDecoration("current-result"); - expect(getResultDecorations(editor, "find-result")).toHaveLength(5); - - atom.commands.dispatch(findView.findEditor.element, "core:confirm"); - atom.commands.dispatch(findView.findEditor.element, "core:confirm"); - const nextResultMarker = getResultDecoration("current-result"); - expect(nextResultMarker).not.toEqual(firstResultMarker); - - atom.commands.dispatch(findView.findEditor.element, "find-and-replace:find-previous"); - atom.commands.dispatch(findView.findEditor.element, "find-and-replace:find-previous"); - const originalResultMarker = getResultDecoration("current-result"); - expect(originalResultMarker).toEqual(firstResultMarker); - }); - - it("adds a class to the result when the current selection equals the result's range", () => { - const originalResultMarker = getResultDecoration("current-result"); - expect(originalResultMarker).toBeDefined(); - - editor.setSelectedBufferRange([[5, 16], [5, 20]]); - expect(getResultDecoration("current-result")).toBeUndefined(); - - editor.setSelectedBufferRange([[5, 16], [5, 21]]); - const newResultMarker = getResultDecoration("current-result"); - expect(newResultMarker).toBeDefined(); - expect(newResultMarker).not.toBe(originalResultMarker); - }); - }); - - describe("when user types in the find editor", () => { - function advance() { - advanceClock(findView.findEditor.getBuffer().stoppedChangingDelay + 1); - } - - beforeEach(() => { - findView.findEditor.element.focus(); - }); - - it("scrolls to the first match if the settings scrollToResultOnLiveSearch is true", () => { - editorView.style.height = "3px"; - editor.update({autoHeight: false}) - - editorView.component.measureDimensions(); - editor.moveToTop(); - atom.config.set("find-and-replace.scrollToResultOnLiveSearch", true); - findView.findEditor.setText("Array"); - advance(); - expect(editorView.getScrollTop()).toBeGreaterThan(0); - expect(editor.getSelectedBufferRange()).toEqual([[11, 14], [11, 19]]); - expect(findView.findEditor.element).toHaveFocus(); - }); - - it("doesn't scroll to the first match if the settings scrollToResultOnLiveSearch is false", () => { - editorView.style.height = "3px"; - editor.update({autoHeight: false}) - - editorView.component.measureDimensions(); - editor.moveToTop(); - atom.config.set("find-and-replace.scrollToResultOnLiveSearch", false); - findView.findEditor.setText("Array"); - advance(); - expect(editorView.getScrollTop()).toBe(0); - expect(editor.getSelectedBufferRange()).toEqual([]); - expect(findView.findEditor.element).toHaveFocus(); - }); - - it("updates the search results", () => { - expect(findView.refs.descriptionLabel.textContent).toContain("6 results"); - - findView.findEditor.setText( - "why do I need these 2 lines? The editor does not trigger contents-modified without them" - ); - - advance(); - findView.findEditor.setText(""); - advance(); - expect(findView.refs.descriptionLabel.textContent).toContain("Find in Current Buffer"); - expect(findView.element).toHaveFocus(); - - findView.findEditor.setText("sort"); - advance(); - expect(findView.refs.descriptionLabel.textContent).toContain("5 results"); - expect(findView.element).toHaveFocus(); - - findView.findEditor.setText("items"); - advance(); - expect(findView.refs.descriptionLabel.textContent).toContain("6 results"); - expect(findView.element).toHaveFocus(); - }); - - it("respects the `liveSearchMinimumCharacters` setting", () => { - expect(findView.refs.descriptionLabel.textContent).toContain("6 results"); - atom.config.set("find-and-replace.liveSearchMinimumCharacters", 3); - - findView.findEditor.setText( - "why do I need these 2 lines? The editor does not trigger contents-modified without them" - ); - - advance(); - findView.findEditor.setText(""); - advance(); - expect(findView.refs.descriptionLabel.textContent).toContain("Find in Current Buffer"); - expect(findView.element).toHaveFocus(); - - findView.findEditor.setText("ite"); - advance(); - expect(findView.refs.descriptionLabel.textContent).toContain("6 results"); - expect(findView.element).toHaveFocus(); - - findView.findEditor.setText("i"); - advance(); - expect(findView.refs.descriptionLabel.textContent).toContain("6 results"); - expect(findView.element).toHaveFocus(); - - findView.findEditor.setText(""); - advance(); - expect(findView.refs.descriptionLabel.textContent).toContain("Find in Current Buffer"); - expect(findView.element).toHaveFocus(); - - atom.config.set("find-and-replace.liveSearchMinimumCharacters", 0); - findView.findEditor.setText("i"); - advance(); - expect(findView.refs.descriptionLabel.textContent).toContain("20 results"); - expect(findView.element).toHaveFocus(); - }); - - it("doesn't live search on a regex that matches empty string", () => { - expect(findView.refs.descriptionLabel.textContent).toContain("6 results"); - - atom.commands.dispatch(findView.findEditor.element, "find-and-replace:toggle-regex-option"); - findView.findEditor.setText("asdf|"); - advance(); - expect(findView.refs.descriptionLabel.textContent).toContain("6 results"); - }); - - it("doesn't live search on a invalid regex", () => { - expect(findView.refs.descriptionLabel.textContent).toContain("6 results"); - - atom.commands.dispatch(findView.findEditor.element, "find-and-replace:toggle-regex-option"); - findView.findEditor.setText("\\(.*)"); - advance(); - expect(findView.refs.descriptionLabel).toHaveClass("text-error"); - expect(findView.refs.descriptionLabel.textContent).toContain("Invalid regular expression"); - }); - }); - - describe("when another find is called", () => { - it("clears existing markers for another search", () => { - findView.findEditor.setText("notinthefile"); - atom.commands.dispatch(findView.findEditor.element, "core:confirm"); - expect(getResultDecorations(editor, "find-result")).toHaveLength(0); - }); - - it("clears existing markers for an empty search", () => { - findView.findEditor.setText(""); - atom.commands.dispatch(findView.findEditor.element, "core:confirm"); - expect(getResultDecorations(editor, "find-result")).toHaveLength(0); - }); - }); - }); - - it("doesn't throw an exception when toggling the regex option with an invalid pattern before performing any other search (regression)", async () => { - atom.commands.dispatch(editorView, 'find-and-replace:show'); - await activationPromise; - - findView.findEditor.setText('('); - atom.commands.dispatch(findView.findEditor.element, 'find-and-replace:toggle-regex-option'); - - editor.insertText('hi'); - advanceClock(editor.getBuffer().stoppedChangingDelay); - }); - - describe("replacing", () => { - beforeEach(async () => { - editor.setCursorBufferPosition([2, 0]); - atom.commands.dispatch(editorView, "find-and-replace:show-replace"); - - await activationPromise; - - findView.findEditor.setText("items"); - findView.replaceEditor.setText("cats"); - }); - - describe("when the find string is empty", () => { - it("beeps", () => { - findView.findEditor.setText(""); - atom.commands.dispatch(findView.replaceEditor.element, "core:confirm"); - expect(atom.beep).toHaveBeenCalled(); - }); - }); - - describe("when the replacement string contains an escaped char", () => { - describe("when the regex option is chosen", () => { - beforeEach(() => { - atom.commands.dispatch(findView.findEditor.element, "find-and-replace:toggle-regex-option"); - }); - - it("inserts newlines and tabs", () => { - findView.replaceEditor.setText("\\n\\t"); - atom.commands.dispatch(findView.replaceEditor.element, "core:confirm"); - expect(editor.getText()).toMatch(/\n\t/); - }); - - it("doesn't insert a escaped char if there are multiple backslashes in front of the char", () => { - findView.replaceEditor.setText("\\\\t\\\t"); - atom.commands.dispatch(findView.replaceEditor.element, "core:confirm"); - expect(editor.getText()).toMatch(/\\t\\\t/); - }); - }); - - describe("when in normal mode", () => { - it("inserts backslash n and t", () => { - findView.replaceEditor.setText("\\t\\n"); - atom.commands.dispatch(findView.replaceEditor.element, "core:confirm"); - expect(editor.getText()).toMatch(/\\t\\n/); - }); - - it("inserts carriage returns", () => { - const textWithCarriageReturns = editor.getText().replace(/\n/g, "\r"); - editor.setText(textWithCarriageReturns); - findView.replaceEditor.setText("\\t\\r"); - atom.commands.dispatch(findView.replaceEditor.element, "core:confirm"); - expect(editor.getText()).toMatch(/\\t\\r/); - }); - }); - }); - - describe("replace next", () => { - describe("when core:confirm is triggered", () => { - it("replaces the match after the cursor and selects the next match", () => { - atom.commands.dispatch(findView.replaceEditor.element, "core:confirm"); - expect(findView.refs.resultCounter.textContent).toEqual("2 of 5"); - expect(editor.lineTextForBufferRow(2)).toBe(" if (cats.length <= 1) return items;"); - expect(editor.getSelectedBufferRange()).toEqual([[2, 33], [2, 38]]); - }); - - it("replaceEditor maintains focus after core:confirm is run", () => { - findView.replaceEditor.element.focus(); - atom.commands.dispatch(findView.replaceEditor.element, "core:confirm"); - expect(findView.replaceEditor.element).toHaveFocus(); - }); - - it("replaces the _current_ match and selects the next match", () => { - atom.commands.dispatch(findView.findEditor.element, "core:confirm"); - editor.setSelectedBufferRange([[2, 8], [2, 13]]); - expect(findView.refs.resultCounter.textContent).toEqual("2 of 6"); - - atom.commands.dispatch(findView.replaceEditor.element, "core:confirm"); - expect(findView.refs.resultCounter.textContent).toEqual("2 of 5"); - expect(editor.lineTextForBufferRow(2)).toBe(" if (cats.length <= 1) return items;"); - expect(editor.getSelectedBufferRange()).toEqual([[2, 33], [2, 38]]); - - atom.commands.dispatch(findView.replaceEditor.element, "core:confirm"); - expect(findView.refs.resultCounter.textContent).toEqual("2 of 4"); - expect(editor.lineTextForBufferRow(2)).toBe(" if (cats.length <= 1) return cats;"); - expect(editor.getSelectedBufferRange()).toEqual([[3, 16], [3, 21]]); - }); - - it("replaces the _current_ match and selects the next match", () => { - editor.setText( - "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s" - ); - - editor.setSelectedBufferRange([[0, 0], [0, 5]]); - findView.findEditor.setText("Lorem"); - findView.replaceEditor.setText("replacement"); - atom.commands.dispatch(findView.replaceEditor.element, "core:confirm"); - - expect(editor.lineTextForBufferRow(0)).toBe( - "replacement Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s" - ); - - expect(editor.getSelectedBufferRange()).toEqual([[0, 81], [0, 86]]); - }); - }); - - describe("when the replace next button is pressed", () => { - it("replaces the match after the cursor and selects the next match", () => { - findView.refs.replaceNextButton.click(); - expect(findView.refs.resultCounter.textContent).toEqual("2 of 5"); - expect(editor.lineTextForBufferRow(2)).toBe(" if (cats.length <= 1) return items;"); - expect(editor.getSelectedBufferRange()).toEqual([[2, 33], [2, 38]]); - expect(findView.replaceEditor.element).toHaveFocus(); - }); - }); - - describe("when the 'find-and-replace:replace-next' event is triggered", () => { - it("replaces the match after the cursor and selects the next match", () => { - atom.commands.dispatch(editorView, "find-and-replace:replace-next"); - expect(findView.refs.resultCounter.textContent).toEqual("2 of 5"); - expect(editor.lineTextForBufferRow(2)).toBe(" if (cats.length <= 1) return items;"); - expect(editor.getSelectedBufferRange()).toEqual([[2, 33], [2, 38]]); - }); - }); - }); - - describe("replace previous", () => { - describe("when command is triggered", () => { - it("replaces the match after the cursor and selects the previous match", () => { - atom.commands.dispatch(findView.findEditor.element, "core:confirm"); - atom.commands.dispatch(findView.element, "find-and-replace:replace-previous"); - expect(findView.refs.resultCounter.textContent).toEqual("1 of 5"); - expect(editor.lineTextForBufferRow(2)).toBe(" if (cats.length <= 1) return items;"); - expect(editor.getSelectedBufferRange()).toEqual([[1, 22], [1, 27]]); - }); - }); - }); - - describe("replace all", () => { - describe("when the replace all button is pressed", () => { - it("replaces all matched text", () => { - findView.refs.replaceAllButton.click(); - expect(findView.refs.resultCounter.textContent).toEqual("no results"); - expect(editor.getText()).not.toMatch(/items/); - expect(editor.getText().match(/\bcats\b/g)).toHaveLength(6); - expect(editor.getSelectedBufferRange()).toEqual([[2, 0], [2, 0]]); - }); - - it("all changes are undoable in one transaction", () => { - findView.refs.replaceAllButton.click(); - editor.undo(); - expect(editor.getText()).not.toMatch(/\bcats\b/g); - }); - }); - - describe("when the 'find-and-replace:replace-all' event is triggered", () => { - it("replaces all matched text", () => { - atom.commands.dispatch(editorView, "find-and-replace:replace-all"); - expect(findView.refs.resultCounter.textContent).toEqual("no results"); - expect(editor.getText()).not.toMatch(/items/); - expect(editor.getText().match(/\bcats\b/g)).toHaveLength(6); - expect(editor.getSelectedBufferRange()).toEqual([[2, 0], [2, 0]]); - }); - }); - }); - - describe("replacement patterns", () => { - describe("when the regex option is true", () => { - it("replaces $1, $2, etc... with substring matches", () => { - atom.commands.dispatch(findView.findEditor.element, "find-and-replace:toggle-regex-option"); - findView.findEditor.setText("(items)([\\.;])"); - findView.replaceEditor.setText("$2$1"); - atom.commands.dispatch(editorView, "find-and-replace:replace-all"); - expect(editor.getText()).toMatch(/;items/); - expect(editor.getText()).toMatch(/\.items/); - }); - }); - - describe("when the regex option is false", () => { - it("replaces the matches with without any regex subsitions", () => { - findView.findEditor.setText("items"); - findView.replaceEditor.setText("$&cats"); - atom.commands.dispatch(editorView, "find-and-replace:replace-all"); - expect(editor.getText()).not.toMatch(/items/); - expect(editor.getText().match(/\$&cats\b/g)).toHaveLength(6); - }); - }); - }); - }); - - describe("history", () => { - beforeEach(async () => { - atom.commands.dispatch(editorView, "find-and-replace:show"); - await activationPromise; - }); - - describe("when there is no history", () => { - it("retains unsearched text", () => { - const text = "something I want to search for but havent yet"; - findView.findEditor.setText(text); - atom.commands.dispatch(findView.findEditor.element, "core:move-up"); - expect(findView.findEditor.getText()).toEqual(""); - - atom.commands.dispatch(findView.findEditor.element, "core:move-down"); - expect(findView.findEditor.getText()).toEqual(text); - }); - }); - - describe("when there is history", () => { - const [oneRange, twoRange, threeRange] = []; - - beforeEach(() => { - atom.commands.dispatch(editorView, "find-and-replace:show"); - editor.setText("zero\none\ntwo\nthree\n"); - findView.findEditor.setText("one"); - atom.commands.dispatch(findView.findEditor.element, "core:confirm"); - findView.findEditor.setText("two"); - atom.commands.dispatch(findView.findEditor.element, "core:confirm"); - findView.findEditor.setText("three"); - atom.commands.dispatch(findView.findEditor.element, "core:confirm"); - }); - - it("can navigate the entire history stack", () => { - expect(findView.findEditor.getText()).toEqual("three"); - - atom.commands.dispatch(findView.findEditor.element, "core:move-down"); - expect(findView.findEditor.getText()).toEqual(""); - - atom.commands.dispatch(findView.findEditor.element, "core:move-down"); - expect(findView.findEditor.getText()).toEqual(""); - - atom.commands.dispatch(findView.findEditor.element, "core:move-up"); - expect(findView.findEditor.getText()).toEqual("three"); - - atom.commands.dispatch(findView.findEditor.element, "core:move-up"); - expect(findView.findEditor.getText()).toEqual("two"); - - atom.commands.dispatch(findView.findEditor.element, "core:move-up"); - expect(findView.findEditor.getText()).toEqual("one"); - - atom.commands.dispatch(findView.findEditor.element, "core:move-up"); - expect(findView.findEditor.getText()).toEqual("one"); - - atom.commands.dispatch(findView.findEditor.element, "core:move-down"); - expect(findView.findEditor.getText()).toEqual("two"); - }); - - it("retains the current unsearched text", () => { - const text = "something I want to search for but havent yet"; - findView.findEditor.setText(text); - atom.commands.dispatch(findView.findEditor.element, "core:move-up"); - expect(findView.findEditor.getText()).toEqual("three"); - - atom.commands.dispatch(findView.findEditor.element, "core:move-down"); - expect(findView.findEditor.getText()).toEqual(text); - - atom.commands.dispatch(findView.findEditor.element, "core:move-up"); - expect(findView.findEditor.getText()).toEqual("three"); - - atom.commands.dispatch(findView.findEditor.element, "core:move-down"); - atom.commands.dispatch(findView.findEditor.element, "core:confirm"); - atom.commands.dispatch(findView.findEditor.element, "core:move-down"); - expect(findView.findEditor.getText()).toEqual(""); - }); - - it("adds confirmed patterns to the history", () => { - findView.findEditor.setText("cool stuff"); - atom.commands.dispatch(findView.findEditor.element, "core:confirm"); - findView.findEditor.setText("cooler stuff"); - atom.commands.dispatch(findView.findEditor.element, "core:move-up"); - expect(findView.findEditor.getText()).toEqual("cool stuff"); - - atom.commands.dispatch(findView.findEditor.element, "core:move-up"); - expect(findView.findEditor.getText()).toEqual("three"); - }); - - describe("when user types in the find editor", () => { - function advance() { - advanceClock(findView.findEditor.getBuffer().stoppedChangingDelay + 1); - } - - beforeEach(() => { - findView.findEditor.element.focus(); - }); - - it("does not add live searches to the history", () => { - expect(findView.refs.descriptionLabel.textContent).toContain("1 result"); - - findView.findEditor.setText("FIXME: necessary search for some reason??"); - advance(); - findView.findEditor.setText("nope"); - advance(); - expect(findView.refs.descriptionLabel.textContent).toContain("nope"); - - findView.findEditor.setText("zero"); - advance(); - expect(findView.refs.descriptionLabel.textContent).toContain("zero"); - - atom.commands.dispatch(findView.findEditor.element, "core:move-up"); - expect(findView.findEditor.getText()).toEqual("three"); - }); - }); - }); - }); - - describe("panel focus", () => { - beforeEach(async () => { - atom.commands.dispatch(editorView, "find-and-replace:show"); - await activationPromise; - }); - - it("focuses the find editor when the panel gets focus", () => { - findView.replaceEditor.element.focus(); - expect(findView.replaceEditor.element).toHaveFocus(); - findView.element.focus(); - expect(findView.findEditor.element).toHaveFocus(); - }); - - it("moves focus between editors with find-and-replace:focus-next", () => { - findView.findEditor.element.focus(); - expect(findView.findEditor.element).toHaveClass("is-focused"); - expect(findView.replaceEditor).not.toHaveClass("is-focused"); - - atom.commands.dispatch(findView.findEditor.element, "find-and-replace:focus-next"); - expect(findView.findEditor.element).not.toHaveClass("is-focused"); - expect(findView.replaceEditor.element).toHaveClass("is-focused"); - - atom.commands.dispatch(findView.replaceEditor.element, "find-and-replace:focus-next"); - expect(findView.findEditor.element).toHaveClass("is-focused"); - expect(findView.replaceEditor.element).not.toHaveClass("is-focused"); - }); - }); - - describe("when language-javascript is active", () => { - beforeEach(async () => { - await atom.packages.activatePackage("language-javascript"); - }); - - it("uses the regexp grammar when regex-mode is loaded from configuration", async () => { - atom.config.set("find-and-replace.useRegex", true); - atom.commands.dispatch(editorView, "find-and-replace:show"); - await activationPromise; - - expect(findView.model.getFindOptions().useRegex).toBe(true); - expect(findView.findEditor.getGrammar().scopeName).toBe("source.js.regexp"); - expect(findView.replaceEditor.getGrammar().scopeName).toBe("source.js.regexp.replacement"); - }); - - describe("when panel is active", () => { - beforeEach(async () => { - atom.commands.dispatch(editorView, "find-and-replace:show"); - await activationPromise; - }); - - it("does not use regexp grammar when in non-regex mode", () => { - expect(findView.model.getFindOptions().useRegex).not.toBe(true); - expect(findView.findEditor.getGrammar().scopeName).toBe("text.plain.null-grammar"); - expect(findView.replaceEditor.getGrammar().scopeName).toBe("text.plain.null-grammar"); - }); - - it("uses regexp grammar when in regex mode and clears the regexp grammar when regex is disabled", () => { - atom.commands.dispatch(findView.findEditor.element, "find-and-replace:toggle-regex-option"); - expect(findView.model.getFindOptions().useRegex).toBe(true); - expect(findView.findEditor.getGrammar().scopeName).toBe("source.js.regexp"); - expect(findView.replaceEditor.getGrammar().scopeName).toBe("source.js.regexp.replacement"); - - atom.commands.dispatch(findView.findEditor.element, "find-and-replace:toggle-regex-option"); - expect(findView.model.getFindOptions().useRegex).not.toBe(true); - expect(findView.findEditor.getGrammar().scopeName).toBe("text.plain.null-grammar"); - expect(findView.replaceEditor.getGrammar().scopeName).toBe("text.plain.null-grammar"); - }); - }); - }); - - describe("when no buffer is open", () => { - it("toggles regex via an event and finds text matching the pattern", async () => { - atom.commands.dispatch(editorView, "find-and-replace:show"); - editor.destroy(); - await activationPromise; - - findView.findEditor.setText("items"); - atom.commands.dispatch(findView.findEditor.element, "find-and-replace:toggle-regex-option"); - expect(findView.model.getFindOptions().useRegex).toBe(true); - expect(findView.refs.descriptionLabel.textContent).toContain("No results"); - }); - - it("toggles selection via an event and finds text matching the pattern", async () => { - atom.commands.dispatch(editorView, "find-and-replace:show"); - editor.destroy(); - await activationPromise; - - findView.findEditor.setText("items"); - atom.commands.dispatch(findView.findEditor.element, "find-and-replace:toggle-selection-option"); - expect(findView.model.getFindOptions().inCurrentSelection).toBe(true); - expect(findView.refs.descriptionLabel.textContent).toContain("No results"); - }); - }); -}); +// /** @babel */ +// +// const path = require("path"); +// +// describe("FindView", () => { +// let workspaceElement, editorView, editor, findView, activationPromise; +// +// function getFindAtomPanel() { +// return workspaceElement.querySelector(".find-and-replace").parentNode; +// } +// +// function getResultDecorations(editor, clazz) { +// const result = []; +// const decorations = editor.decorationsStateForScreenRowRange(0, editor.getLineCount()) +// for (let id in decorations) { +// const decoration = decorations[id] +// if (decoration.properties.class === clazz) { +// result.push(decoration); +// } +// } +// return result; +// } +// +// beforeEach(async () => { +// spyOn(atom, "beep"); +// workspaceElement = atom.views.getView(atom.workspace); +// workspaceElement.style.height = '800px' +// atom.project.setPaths([path.join(__dirname, "fixtures")]); +// +// await atom.workspace.open("sample.js"); +// +// jasmine.attachToDOM(workspaceElement); +// editor = atom.workspace.getCenter().getActiveTextEditor(); +// editorView = editor.element; +// +// activationPromise = atom.packages.activatePackage("find-and-replace").then(function({mainModule}) { +// mainModule.createViews(); +// ({findView} = mainModule); +// }); +// }); +// +// describe("when find-and-replace:show is triggered", () => { +// it("attaches FindView to the root view", async () => { +// atom.commands.dispatch(editorView, "find-and-replace:show"); +// await activationPromise; +// +// expect(workspaceElement.querySelector(".find-and-replace")).toBeDefined(); +// }); +// +// it("populates the findEditor with selection when there is a selection", async () => { +// editor.setSelectedBufferRange([[2, 8], [2, 13]]); +// +// atom.commands.dispatch(editorView, "find-and-replace:show"); +// await activationPromise; +// +// expect(getFindAtomPanel()).toBeVisible(); +// expect(findView.findEditor.getText()).toBe("items"); +// +// findView.findEditor.setText(""); +// editor.setSelectedBufferRange([[2, 14], [2, 20]]); +// atom.commands.dispatch(editorView, "find-and-replace:show"); +// expect(getFindAtomPanel()).toBeVisible(); +// expect(findView.findEditor.getText()).toBe("length"); +// }); +// +// it("does not change the findEditor text when there is no selection", async () => { +// editor.setSelectedBufferRange([[2, 8], [2, 8]]); +// +// atom.commands.dispatch(editorView, "find-and-replace:show"); +// await activationPromise; +// +// findView.findEditor.setText("kitten"); +// atom.commands.dispatch(editorView, "find-and-replace:show"); +// expect(findView.findEditor.getText()).toBe("kitten"); +// }); +// +// it("does not change the findEditor text when there is a multiline selection", async () => { +// editor.setSelectedBufferRange([[2, 8], [3, 12]]); +// +// atom.commands.dispatch(editorView, "find-and-replace:show"); +// await activationPromise; +// +// expect(getFindAtomPanel()).toBeVisible(); +// expect(findView.findEditor.getText()).toBe(""); +// }); +// +// it("honors config settings for find options", async () => { +// atom.config.set("find-and-replace.useRegex", true); +// atom.config.set("find-and-replace.caseSensitive", true); +// atom.config.set("find-and-replace.inCurrentSelection", true); +// +// atom.commands.dispatch(editorView, "find-and-replace:show"); +// await activationPromise; +// +// expect(findView.refs.caseOptionButton).toHaveClass("selected"); +// expect(findView.refs.regexOptionButton).toHaveClass("selected"); +// expect(findView.refs.selectionOptionButton).toHaveClass("selected"); +// }); +// +// it("places selected text into the find editor and escapes it when Regex is enabled", async () => { +// atom.config.set("find-and-replace.useRegex", true); +// editor.setSelectedBufferRange([[6, 6], [6, 65]]); +// +// atom.commands.dispatch(editorView, "find-and-replace:show"); +// await activationPromise; +// +// expect(findView.findEditor.getText()).toBe( +// "current < pivot \\? left\\.push\\(current\\) : right\\.push\\(current\\);" +// ); +// }); +// +// it('selects the text to find when the panel is re-shown', async () => { +// atom.commands.dispatch(editorView, "find-and-replace:show"); +// await activationPromise; +// +// const stringToSearch = "not found"; +// const findEditor = findView.findEditor; +// +// findEditor.setText(stringToSearch); +// +// atom.commands.dispatch(findEditor.element, "core:confirm"); +// atom.commands.dispatch(document.activeElement, "core:cancel"); +// atom.commands.dispatch(editorView, "find-and-replace:show"); +// +// expect(findEditor.getSelectedBufferRange()).toEqual([[0, 0], [0, stringToSearch.length]]); +// +// const selectionElement = findEditor.getElement().querySelector('.highlight.selection .selection'); +// +// expect(selectionElement.getBoundingClientRect().width).toBeGreaterThan(0); +// }); +// }); +// +// describe("when find-and-replace:toggle is triggered", () => { +// it("toggles the visibility of the FindView", async () => { +// atom.commands.dispatch(workspaceElement, "find-and-replace:toggle"); +// await activationPromise; +// +// expect(getFindAtomPanel()).toBeVisible(); +// atom.commands.dispatch(workspaceElement, "find-and-replace:toggle"); +// expect(getFindAtomPanel()).not.toBeVisible(); +// }); +// }); +// +// describe("when the find-view is focused and window:focus-next-pane is triggered", () => { +// it("attaches FindView to the root view", async () => { +// atom.commands.dispatch(editorView, "find-and-replace:show"); +// await activationPromise; +// +// expect(workspaceElement.querySelector(".find-and-replace")).toHaveFocus(); +// atom.commands.dispatch(findView.findEditor.element, "window:focus-next-pane"); +// expect(workspaceElement.querySelector(".find-and-replace")).not.toHaveFocus(); +// }); +// }); +// +// describe("find-and-replace:show-replace", () => { +// it("focuses the replace editor", async () => { +// atom.commands.dispatch(editorView, "find-and-replace:show-replace"); +// await activationPromise; +// +// expect(findView.replaceEditor.element).toHaveFocus(); +// }); +// +// it("places the current selection in the replace editor", async () => { +// editor.setSelectedBufferRange([[0, 16], [0, 27]]); +// +// atom.commands.dispatch(editorView, "find-and-replace:show-replace"); +// await activationPromise; +// +// expect(findView.replaceEditor.getText()).toBe("function ()"); +// }); +// +// it("does not escape the text when the regex option is enabled", async () => { +// editor.setSelectedBufferRange([[0, 16], [0, 27]]); +// +// atom.commands.dispatch(editorView, "find-and-replace:show"); +// atom.commands.dispatch(editorView, "find-and-replace:toggle-regex-option"); +// atom.commands.dispatch(editorView, "find-and-replace:show-replace"); +// await activationPromise; +// +// expect(findView.replaceEditor.getText()).toBe("function ()"); +// }); +// }); +// +// describe("when find-and-replace:clear-history is triggered", () => { +// it("clears the find and replace histories", async () => { +// atom.commands.dispatch(editorView, "find-and-replace:show"); +// await activationPromise; +// +// findView.findEditor.setText("items"); +// findView.replaceEditor.setText("cat"); +// findView.replaceAll(); +// findView.findEditor.setText("sort"); +// findView.replaceEditor.setText("dog"); +// findView.replaceNext(); +// atom.commands.dispatch(editorView, "find-and-replace:clear-history"); +// atom.commands.dispatch(findView.findEditor.element, "core:move-up"); +// expect(findView.findEditor.getText()).toBe(""); +// +// atom.commands.dispatch(findView.replaceEditor.element, "core:move-up"); +// expect(findView.replaceEditor.getText()).toBe(""); +// }); +// }); +// +// describe("core:cancel", () => { +// beforeEach(async () => { +// atom.commands.dispatch(editorView, "find-and-replace:show"); +// await activationPromise; +// +// findView.findEditor.setText("items"); +// atom.commands.dispatch(findView.findEditor.element, "core:confirm"); +// findView.element.focus(); +// }); +// +// describe("when core:cancel is triggered on the find view", () => { +// it("detaches from the workspace view", () => { +// atom.commands.dispatch(document.activeElement, "core:cancel"); +// expect(getFindAtomPanel()).not.toBeVisible(); +// }); +// +// it("removes highlighted matches", () => { +// expect(workspaceElement).toHaveClass("find-visible"); +// atom.commands.dispatch(document.activeElement, "core:cancel"); +// expect(workspaceElement).not.toHaveClass("find-visible"); +// }); +// }); +// +// describe("when core:cancel is triggered on an empty pane", () => { +// it("hides the find panel", () => { +// const paneElement = atom.views.getView(atom.workspace.getCenter().getActivePane()); +// paneElement.focus(); +// atom.commands.dispatch(paneElement, "core:cancel"); +// expect(getFindAtomPanel()).not.toBeVisible(); +// }); +// }); +// +// describe("when core:cancel is triggered on an editor", () => { +// it("detaches from the workspace view", async () => { +// atom.workspace.open(); +// atom.commands.dispatch(editorView, "core:cancel"); +// expect(getFindAtomPanel()).not.toBeVisible(); +// }); +// }); +// +// describe("when core:cancel is triggered on a mini editor", () => { +// it("leaves the find view attached", () => { +// const miniEditor = document.createElement("atom-text-editor"); +// miniEditor.setAttribute("mini", ""); +// +// atom.workspace.addTopPanel({ +// item: miniEditor +// }); +// +// miniEditor.focus(); +// atom.commands.dispatch(miniEditor, "core:cancel"); +// expect(getFindAtomPanel()).toBeVisible(); +// }); +// }); +// }); +// +// describe("serialization", () => { +// it("serializes find and replace history", async () => { +// atom.commands.dispatch(editorView, "find-and-replace:show"); +// await activationPromise; +// +// findView.findEditor.setText("items"); +// findView.replaceEditor.setText("cat"); +// findView.replaceAll(); +// findView.findEditor.setText("sort"); +// findView.replaceEditor.setText("dog"); +// findView.replaceNext(); +// findView.findEditor.setText("shift"); +// findView.replaceEditor.setText("ok"); +// findView.findNext(false); +// +// await atom.packages.deactivatePackage("find-and-replace"); +// activationPromise = atom.packages.activatePackage("find-and-replace").then(function({mainModule}) { +// mainModule.createViews(); +// ({findView} = mainModule); +// }); +// atom.commands.dispatch(editorView, "find-and-replace:show"); +// await activationPromise; +// +// atom.commands.dispatch(findView.findEditor.element, "core:move-up"); +// expect(findView.findEditor.getText()).toBe("shift"); +// atom.commands.dispatch(findView.findEditor.element, "core:move-up"); +// expect(findView.findEditor.getText()).toBe("sort"); +// atom.commands.dispatch(findView.findEditor.element, "core:move-up"); +// expect(findView.findEditor.getText()).toBe("items"); +// atom.commands.dispatch(findView.replaceEditor.element, "core:move-up"); +// expect(findView.replaceEditor.getText()).toBe("dog"); +// atom.commands.dispatch(findView.replaceEditor.element, "core:move-up"); +// expect(findView.replaceEditor.getText()).toBe("cat"); +// }); +// +// it("serializes find options ", async () => { +// atom.commands.dispatch(editorView, "find-and-replace:show"); +// await activationPromise; +// +// expect(findView.refs.caseOptionButton).not.toHaveClass("selected"); +// expect(findView.refs.regexOptionButton).not.toHaveClass("selected"); +// expect(findView.refs.selectionOptionButton).not.toHaveClass("selected"); +// expect(findView.refs.wholeWordOptionButton).not.toHaveClass("selected"); +// +// findView.refs.caseOptionButton.click(); +// findView.refs.regexOptionButton.click(); +// findView.refs.selectionOptionButton.click(); +// findView.refs.wholeWordOptionButton.click(); +// expect(findView.refs.caseOptionButton).toHaveClass("selected"); +// expect(findView.refs.regexOptionButton).toHaveClass("selected"); +// expect(findView.refs.selectionOptionButton).toHaveClass("selected"); +// expect(findView.refs.wholeWordOptionButton).toHaveClass("selected"); +// +// await atom.packages.deactivatePackage("find-and-replace"); +// activationPromise = atom.packages.activatePackage("find-and-replace").then(function({mainModule}) { +// mainModule.createViews(); +// ({findView} = mainModule); +// }); +// atom.commands.dispatch(editorView, "find-and-replace:show"); +// await activationPromise; +// +// expect(findView.refs.caseOptionButton).toHaveClass("selected"); +// expect(findView.refs.regexOptionButton).toHaveClass("selected"); +// expect(findView.refs.selectionOptionButton).toHaveClass("selected"); +// expect(findView.refs.wholeWordOptionButton).toHaveClass("selected"); +// }); +// }); +// +// describe("finding", () => { +// beforeEach(async () => { +// atom.config.set("find-and-replace.focusEditorAfterSearch", false); +// editor.setCursorBufferPosition([2, 0]); +// +// atom.commands.dispatch(editorView, "find-and-replace:show"); +// await activationPromise; +// +// findView.findEditor.setText("items"); +// atom.commands.dispatch(findView.findEditor.element, "core:confirm"); +// }); +// +// describe("when find-and-replace:confirm is triggered", () => { +// it("runs a search", () => { +// findView.findEditor.setText("notinthefile"); +// atom.commands.dispatch(findView.findEditor.element, "find-and-replace:confirm"); +// expect(getResultDecorations(editor, "find-result")).toHaveLength(0); +// +// findView.findEditor.setText("items"); +// atom.commands.dispatch(findView.findEditor.element, "find-and-replace:confirm"); +// expect(getResultDecorations(editor, "find-result")).toHaveLength(5); +// }); +// }); +// +// describe("when no results are found", () => { +// it("adds a .has-no-results class", () => { +// findView.findEditor.setText("notinthefile"); +// atom.commands.dispatch(findView.findEditor.element, "find-and-replace:confirm"); +// expect(findView.element).toHaveClass("has-no-results"); +// }); +// }); +// +// describe("when results are found", () => { +// it("adds a .has-results class", () => { +// findView.findEditor.setText("items"); +// atom.commands.dispatch(findView.findEditor.element, "find-and-replace:confirm"); +// expect(findView.element).toHaveClass("has-results"); +// }); +// }); +// +// describe("when the find string contains an escaped char", () => { +// beforeEach(() => { +// editor.setText("\t\n\\t\\\\"); +// editor.setCursorBufferPosition([0, 0]); +// }); +// +// describe("when regex search is enabled", () => { +// beforeEach(() => { +// atom.commands.dispatch(findView.findEditor.element, "find-and-replace:toggle-regex-option"); +// }); +// +// it("finds a backslash", () => { +// findView.findEditor.setText("\\\\"); +// atom.commands.dispatch(findView.findEditor.element, "core:confirm"); +// expect(editor.getSelectedBufferRange()).toEqual([[1, 0], [1, 1]]); +// }); +// +// it("finds a newline", () => { +// findView.findEditor.setText("\\n"); +// atom.commands.dispatch(findView.findEditor.element, "core:confirm"); +// expect(editor.getSelectedBufferRange()).toEqual([[0, 1], [1, 0]]); +// }); +// +// it("finds a tab character", () => { +// findView.findEditor.setText("\\t"); +// atom.commands.dispatch(findView.findEditor.element, "core:confirm"); +// expect(editor.getSelectedBufferRange()).toEqual([[0, 0], [0, 1]]); +// }); +// }); +// +// describe("when regex search is disabled", () => { +// it("finds the literal backslash t", () => { +// findView.findEditor.setText("\\t"); +// atom.commands.dispatch(findView.findEditor.element, "core:confirm"); +// expect(editor.getSelectedBufferRange()).toEqual([[1, 0], [1, 2]]); +// }); +// +// it("finds a backslash", () => { +// findView.findEditor.setText("\\"); +// atom.commands.dispatch(findView.findEditor.element, "core:confirm"); +// expect(editor.getSelectedBufferRange()).toEqual([[1, 0], [1, 1]]); +// }); +// +// it("finds two backslashes", () => { +// findView.findEditor.setText('\\\\'); +// atom.commands.dispatch(findView.findEditor.element, "core:confirm"); +// expect(editor.getSelectedBufferRange()).toEqual([[1, 2], [1, 4]]); +// }); +// +// it("doesn't find when escaped", () => { +// findView.findEditor.setText("\\\\t"); +// atom.commands.dispatch(findView.findEditor.element, "core:confirm"); +// expect(editor.getSelectedBufferRange()).toEqual([[0, 0], [0, 0]]); +// }); +// }); +// }); +// +// describe("when focusEditorAfterSearch is set", () => { +// beforeEach(() => { +// atom.config.set("find-and-replace.focusEditorAfterSearch", true); +// atom.commands.dispatch(findView.findEditor.element, "core:confirm"); +// }); +// +// it("selects the first match following the cursor and correctly focuses the editor", () => { +// expect(findView.refs.resultCounter.textContent).toEqual("3 of 6"); +// expect(editor.getSelectedBufferRange()).toEqual([[2, 34], [2, 39]]); +// expect(editorView).toHaveFocus(); +// }); +// }); +// +// describe("when whole-word search is enabled", () => { +// beforeEach(() => { +// editor.setText("-----\nswhole-wordy\nwhole-word\nword\nwhole-swords"); +// editor.setCursorBufferPosition([0, 0]); +// atom.commands.dispatch(findView.findEditor.element, "find-and-replace:toggle-whole-word-option"); +// }); +// +// it("finds the whole words", () => { +// findView.findEditor.setText("word"); +// atom.commands.dispatch(findView.findEditor.element, "core:confirm"); +// expect(editor.getSelectedBufferRange()).toEqual([[2, 6], [2, 10]]); +// }); +// +// it("doesn't highlight the search inside words", () => { +// findView.findEditor.setText("word"); +// atom.commands.dispatch(findView.findEditor.element, "core:confirm"); +// expect(getResultDecorations(editor, "find-result")).toHaveLength(1); +// expect(getResultDecorations(editor, "current-result")).toHaveLength(1); +// }); +// }); +// +// it("doesn't change the selection, beeps if there are no matches and keeps focus on the find view", () => { +// editor.setCursorBufferPosition([2, 0]); +// findView.findEditor.setText("notinthefilebro"); +// findView.findEditor.element.focus(); +// atom.commands.dispatch(findView.findEditor.element, "core:confirm"); +// expect(editor.getCursorBufferPosition()).toEqual([2, 0]); +// expect(atom.beep).toHaveBeenCalled(); +// expect(findView.element).toHaveFocus(); +// expect(findView.refs.descriptionLabel.textContent).toEqual("No results found for 'notinthefilebro'"); +// }); +// +// describe("updating the replace button enablement", () => { +// it("enables the replace buttons when are search results", () => { +// findView.findEditor.setText("item"); +// atom.commands.dispatch(findView.findEditor.element, "core:confirm"); +// expect(findView.refs.replaceAllButton).not.toHaveClass("disabled"); +// expect(findView.refs.replaceNextButton).not.toHaveClass("disabled"); +// +// const disposable = findView.replaceTooltipSubscriptions; +// spyOn(disposable, "dispose"); +// findView.findEditor.setText("it"); +// atom.commands.dispatch(findView.findEditor.element, "core:confirm"); +// expect(findView.refs.replaceAllButton).not.toHaveClass("disabled"); +// expect(findView.refs.replaceNextButton).not.toHaveClass("disabled"); +// expect(disposable.dispose).not.toHaveBeenCalled(); +// +// findView.findEditor.setText("nopenotinthefile"); +// atom.commands.dispatch(findView.findEditor.element, "core:confirm"); +// expect(findView.refs.replaceAllButton).toHaveClass("disabled"); +// expect(findView.refs.replaceNextButton).toHaveClass("disabled"); +// expect(disposable.dispose).toHaveBeenCalled(); +// +// findView.findEditor.setText("i"); +// atom.commands.dispatch(findView.findEditor.element, "core:confirm"); +// expect(findView.refs.replaceAllButton).not.toHaveClass("disabled"); +// expect(findView.refs.replaceNextButton).not.toHaveClass("disabled"); +// +// findView.findEditor.setText(""); +// atom.commands.dispatch(findView.findEditor.element, "core:confirm"); +// expect(findView.refs.replaceAllButton).toHaveClass("disabled"); +// expect(findView.refs.replaceNextButton).toHaveClass("disabled"); +// }); +// }); +// +// describe("updating the descriptionLabel", () => { +// it("properly updates the info message", () => { +// findView.findEditor.setText("item"); +// atom.commands.dispatch(findView.findEditor.element, "core:confirm"); +// expect(findView.refs.descriptionLabel.textContent).toEqual("6 results found for 'item'"); +// +// findView.findEditor.setText("notinthefilenope"); +// atom.commands.dispatch(findView.findEditor.element, "core:confirm"); +// expect(findView.refs.descriptionLabel.textContent).toEqual("No results found for 'notinthefilenope'"); +// +// findView.findEditor.setText("item"); +// atom.commands.dispatch(findView.findEditor.element, "core:confirm"); +// expect(findView.refs.descriptionLabel.textContent).toEqual("6 results found for 'item'"); +// +// findView.findEditor.setText(""); +// atom.commands.dispatch(findView.findEditor.element, "core:confirm"); +// expect(findView.refs.descriptionLabel.textContent).toContain("Find in Current Buffer"); +// }); +// +// describe("when there is an error", () => { +// describe("when the regex search string is invalid", () => { +// beforeEach(() => { +// atom.commands.dispatch(findView.findEditor.element, "find-and-replace:toggle-regex-option"); +// findView.findEditor.setText("i[t"); +// atom.commands.dispatch(findView.findEditor.element, "core:confirm"); +// }); +// +// it("displays the error", () => { +// expect(findView.refs.descriptionLabel).toHaveClass("text-error"); +// expect(findView.refs.descriptionLabel.textContent).toContain("Invalid regular expression"); +// }); +// +// it("will be reset when there is no longer an error", () => { +// expect(findView.refs.descriptionLabel).toHaveClass("text-error"); +// +// findView.findEditor.setText(""); +// atom.commands.dispatch(findView.findEditor.element, "core:confirm"); +// expect(findView.refs.descriptionLabel).not.toHaveClass("text-error"); +// expect(findView.refs.descriptionLabel.textContent).toContain("Find in Current Buffer"); +// +// findView.findEditor.setText("item"); +// atom.commands.dispatch(findView.findEditor.element, "core:confirm"); +// expect(findView.refs.descriptionLabel).not.toHaveClass("text-error"); +// expect(findView.refs.descriptionLabel.textContent).toContain("6 results"); +// }); +// }); +// +// describe("when the search string is too large", () => { +// beforeEach(() => { +// findView.findEditor.setText("x".repeat(50000)); +// atom.commands.dispatch(findView.findEditor.element, "core:confirm"); +// }); +// +// it("displays the error", () => { +// expect(findView.refs.descriptionLabel).toHaveClass("text-error"); +// expect(findView.refs.descriptionLabel.textContent).toBe("regular expression is too large"); +// }); +// +// it("will be reset when there is no longer an error", () => { +// findView.findEditor.setText(""); +// atom.commands.dispatch(findView.findEditor.element, "core:confirm"); +// expect(findView.refs.descriptionLabel).not.toHaveClass("text-error"); +// expect(findView.refs.descriptionLabel.textContent).toContain("Find in Current Buffer"); +// +// findView.findEditor.setText("item"); +// atom.commands.dispatch(findView.findEditor.element, "core:confirm"); +// expect(findView.refs.descriptionLabel).not.toHaveClass("text-error"); +// expect(findView.refs.descriptionLabel.textContent).toContain("6 results"); +// }); +// }); +// }); +// }); +// +// it("selects the first match following the cursor", () => { +// expect(findView.refs.resultCounter.textContent).toEqual("2 of 6"); +// expect(editor.getSelectedBufferRange()).toEqual([[2, 8], [2, 13]]); +// +// atom.commands.dispatch(findView.findEditor.element, "core:confirm"); +// expect(findView.refs.resultCounter.textContent).toEqual("3 of 6"); +// expect(editor.getSelectedBufferRange()).toEqual([[2, 34], [2, 39]]); +// expect(findView.findEditor.element).toHaveFocus(); +// }); +// +// it("selects the next match when the next match button is pressed", () => { +// findView.refs.nextButton.click(); +// expect(findView.refs.resultCounter.textContent).toEqual("3 of 6"); +// expect(editor.getSelectedBufferRange()).toEqual([[2, 34], [2, 39]]); +// }); +// +// it("selects the previous match when the next match button is pressed while holding shift", () => { +// findView.refs.nextButton.dispatchEvent(new MouseEvent("click", { +// shiftKey: true +// })); +// +// expect(findView.refs.resultCounter.textContent).toEqual("1 of 6"); +// expect(editor.getSelectedBufferRange()).toEqual([[1, 22], [1, 27]]); +// }); +// +// it("selects the next match when the 'find-and-replace:find-next' event is triggered and correctly focuses the editor", () => { +// expect(findView.element).toHaveFocus(); +// atom.commands.dispatch(editorView, "find-and-replace:find-next"); +// expect(findView.refs.resultCounter.textContent).toEqual("3 of 6"); +// expect(editor.getSelectedBufferRange()).toEqual([[2, 34], [2, 39]]); +// expect(editorView).toHaveFocus(); +// }); +// +// it("selects the previous match before the cursor when the 'find-and-replace:show-previous' event is triggered", () => { +// expect(findView.refs.resultCounter.textContent).toEqual("2 of 6"); +// expect(editor.getSelectedBufferRange()).toEqual([[2, 8], [2, 13]]); +// atom.commands.dispatch(findView.findEditor.element, "find-and-replace:show-previous"); +// expect(findView.refs.resultCounter.textContent).toEqual("1 of 6"); +// expect(editor.getSelectedBufferRange()).toEqual([[1, 22], [1, 27]]); +// expect(findView.findEditor.element).toHaveFocus(); +// }); +// +// describe("when the match is folded", () => { +// it("unfolds the match", () => { +// editor.foldAll(); +// atom.commands.dispatch(findView.findEditor.element, "core:confirm"); +// expect(editor.getSelectedBufferRange()).toEqual([[2, 34], [2, 39]]); +// expect(editor.isFoldedAtBufferRow(2)).toBe(false); +// expect(editor.getCursorBufferPosition()).toEqual([2, 39]); +// }) +// }) +// +// it("will re-run search if 'find-and-replace:find-next' is triggered after changing the findEditor's text", () => { +// findView.findEditor.setText("sort"); +// atom.commands.dispatch(findView.findEditor.element, "find-and-replace:find-next"); +// expect(findView.refs.resultCounter.textContent).toEqual("3 of 5"); +// expect(editor.getSelectedBufferRange()).toEqual([[8, 11], [8, 15]]); +// }); +// +// it("'find-and-replace:find-next' adds to the findEditor's history", () => { +// findView.findEditor.setText("sort"); +// atom.commands.dispatch(findView.findEditor.element, "find-and-replace:find-next"); +// expect(findView.refs.resultCounter.textContent).toEqual("3 of 5"); +// +// findView.findEditor.setText("nope"); +// atom.commands.dispatch(findView.findEditor.element, "core:move-up"); +// expect(findView.findEditor.getText()).toEqual("sort"); +// }); +// +// it("selects the previous match when the 'find-and-replace:find-previous' event is triggered and correctly focuses the editor", () => { +// expect(findView.element).toHaveFocus(); +// +// atom.commands.dispatch(editorView, "find-and-replace:find-previous"); +// expect(findView.refs.resultCounter.textContent).toEqual("1 of 6"); +// expect(editor.getSelectedBufferRange()).toEqual([[1, 27], [1, 22]]); +// expect(editorView).toHaveFocus(); +// }); +// +// it("will re-run search if 'find-and-replace:find-previous' is triggered after changing the findEditor's text", () => { +// findView.findEditor.setText("sort"); +// atom.commands.dispatch(findView.findEditor.element, "find-and-replace:find-previous"); +// expect(findView.refs.resultCounter.textContent).toEqual("2 of 5"); +// expect(editor.getSelectedBufferRange()).toEqual([[1, 6], [1, 10]]); +// }); +// +// it("selects all matches when 'find-and-replace:find-all' is triggered and correctly focuses the editor", () => { +// expect(findView.element).toHaveFocus(); +// atom.commands.dispatch(findView.findEditor.element, "find-and-replace:find-all"); +// +// expect(editor.getSelectedBufferRanges()).toEqual([ +// [[1, 27], [1, 22]], +// [[2, 8], [2, 13]], +// [[2, 34], [2, 39]], +// [[3, 16], [3, 21]], +// [[4, 10], [4, 15]], +// [[5, 16], [5, 21]] +// ]); +// expect(editorView).toHaveFocus(); +// }); +// +// it("will re-run search if 'find-and-replace:find-all' is triggered after changing the findEditor's text", () => { +// findView.findEditor.setText("sort"); +// atom.commands.dispatch(findView.findEditor.element, "find-and-replace:find-all"); +// +// expect(editor.getSelectedBufferRanges()).toEqual([ +// [[0, 9], [0, 13]], +// [[1, 6], [1, 10]], +// [[8, 11], [8, 15]], +// [[8, 43], [8, 47]], +// [[11, 9], [11, 13]] +// ]); +// }); +// +// it("replaces results counter with number of results found when user moves the cursor", () => { +// editor.moveDown(); +// expect(findView.refs.resultCounter.textContent).toBe("6 found"); +// }); +// +// it("replaces results counter x of y text when user selects a marked range", () => { +// editor.moveDown(); +// editor.setSelectedBufferRange([[2, 34], [2, 39]]); +// expect(findView.refs.resultCounter.textContent).toEqual("3 of 6"); +// }); +// +// it("shows an icon when search wraps around and the editor scrolls", () => { +// editorView.style.height = "80px"; +// +// editorView.component.measureDimensions(); +// expect(editor.getLastVisibleScreenRow()).toBe(3); +// expect(findView.refs.resultCounter.textContent).toEqual("2 of 6"); +// expect(findView.wrapIcon).not.toBeVisible(); +// +// atom.commands.dispatch(editorView, "find-and-replace:find-previous"); +// expect(findView.refs.resultCounter.textContent).toEqual("1 of 6"); +// expect(editor.getLastVisibleScreenRow()).toBe(3); +// expect(findView.wrapIcon).not.toBeVisible(); +// +// atom.commands.dispatch(editorView, "find-and-replace:find-previous"); +// expect(findView.refs.resultCounter.textContent).toEqual("6 of 6"); +// expect(editor.getLastVisibleScreenRow()).toBe(7); +// expect(findView.wrapIcon).toBeVisible(); +// expect(findView.wrapIcon).toHaveClass("icon-move-down"); +// +// atom.commands.dispatch(editorView, "find-and-replace:find-next"); +// expect(findView.refs.resultCounter.textContent).toEqual("1 of 6"); +// expect(editor.getLastVisibleScreenRow()).toBe(3); +// expect(findView.wrapIcon).toBeVisible(); +// expect(findView.wrapIcon).toHaveClass("icon-move-up"); +// }); +// +// it("does not show the wrap icon when the editor does not scroll", () => { +// editorView.style.height = "400px"; +// editor.update({autoHeight: false}) +// +// editorView.component.measureDimensions(); +// expect(editor.getVisibleRowRange()).toEqual([0, 12]); +// +// atom.commands.dispatch(editorView, "find-and-replace:find-previous"); +// expect(findView.refs.resultCounter.textContent).toEqual("1 of 6"); +// +// atom.commands.dispatch(editorView, "find-and-replace:find-previous"); +// expect(findView.refs.resultCounter.textContent).toEqual("6 of 6"); +// expect(editor.getVisibleRowRange()).toEqual([0, 12]); +// expect(findView.wrapIcon).not.toBeVisible(); +// +// atom.commands.dispatch(editorView, "find-and-replace:find-next"); +// expect(findView.refs.resultCounter.textContent).toEqual("1 of 6"); +// expect(editor.getVisibleRowRange()).toEqual([0, 12]); +// expect(findView.wrapIcon).not.toBeVisible(); +// }); +// +// it("allows searching for dashes in combination with non-ascii characters (regression)", () => { +// editor.setText("123-Âbc"); +// findView.findEditor.setText("3-â"); +// atom.commands.dispatch(findView.findEditor.element, "find-and-replace:find-next"); +// expect(findView.refs.descriptionLabel).not.toHaveClass("text-error"); +// expect(editor.getSelectedBufferRange()).toEqual([[0, 2], [0, 5]]); +// }); +// +// describe("when find-and-replace:use-selection-as-find-pattern is triggered", () => { +// it("places the selected text into the find editor", () => { +// editor.setSelectedBufferRange([[1, 6], [1, 10]]); +// atom.commands.dispatch(workspaceElement, "find-and-replace:use-selection-as-find-pattern"); +// expect(findView.findEditor.getText()).toBe("sort"); +// expect(editor.getSelectedBufferRange()).toEqual([[1, 6], [1, 10]]); +// +// atom.commands.dispatch(workspaceElement, "find-and-replace:find-next"); +// expect(editor.getSelectedBufferRange()).toEqual([[8, 11], [8, 15]]); +// +// atom.workspace.destroyActivePane(); +// atom.commands.dispatch(workspaceElement, "find-and-replace:use-selection-as-find-pattern"); +// expect(findView.findEditor.getText()).toBe("sort"); +// }); +// +// it("places the word under the cursor into the find editor", () => { +// editor.setSelectedBufferRange([[1, 8], [1, 8]]); +// atom.commands.dispatch(workspaceElement, "find-and-replace:use-selection-as-find-pattern"); +// expect(findView.findEditor.getText()).toBe("sort"); +// expect(editor.getSelectedBufferRange()).toEqual([[1, 8], [1, 8]]); +// +// atom.commands.dispatch(workspaceElement, "find-and-replace:find-next"); +// expect(editor.getSelectedBufferRange()).toEqual([[8, 11], [8, 15]]); +// }); +// +// it("places the previously selected text into the find editor if no selection", () => { +// editor.setSelectedBufferRange([[1, 6], [1, 10]]); +// atom.commands.dispatch(workspaceElement, "find-and-replace:use-selection-as-find-pattern"); +// expect(findView.findEditor.getText()).toBe("sort"); +// +// editor.setSelectedBufferRange([[1, 1], [1, 1]]); +// atom.commands.dispatch(workspaceElement, "find-and-replace:use-selection-as-find-pattern"); +// expect(findView.findEditor.getText()).toBe("sort"); +// }); +// +// it("places selected text into the find editor and escapes it when Regex is enabled", () => { +// atom.commands.dispatch(findView.findEditor.element, "find-and-replace:toggle-regex-option"); +// editor.setSelectedBufferRange([[6, 6], [6, 65]]); +// atom.commands.dispatch(workspaceElement, "find-and-replace:use-selection-as-find-pattern"); +// +// expect(findView.findEditor.getText()).toBe( +// "current < pivot \\? left\\.push\\(current\\) : right\\.push\\(current\\);" +// ); +// }); +// +// it("searches for the amount of results", () => { +// spyOn(findView, 'liveSearch') // ignore live search - we're interested in the explicit search call +// +// editor.setSelectedBufferRange([[1, 8], [1, 8]]); +// atom.commands.dispatch(workspaceElement, "find-and-replace:use-selection-as-find-pattern"); +// expect(findView.refs.resultCounter.textContent).toEqual("5 found"); +// }) +// }); +// +// describe("when find-and-replace:use-selection-as-replace-pattern is triggered", () => { +// it("places the selected text into the replace editor", () => { +// editor.setSelectedBufferRange([[3, 8], [3, 13]]); +// atom.commands.dispatch(workspaceElement, 'find-and-replace:use-selection-as-replace-pattern'); +// expect(findView.replaceEditor.getText()).toBe('pivot'); +// expect(editor.getSelectedBufferRange()).toEqual([[3, 8], [3, 13]]); +// +// findView.findEditor.setText('sort'); +// atom.commands.dispatch(workspaceElement, 'find-and-replace:find-next'); +// expect(editor.getSelectedBufferRange()).toEqual([[8, 11], [8, 15]]); +// expect(editor.getTextInBufferRange(editor.getSelectedBufferRange())).toEqual('sort'); +// atom.commands.dispatch(workspaceElement, 'find-and-replace:replace-next'); +// expect(editor.getTextInBufferRange([[8, 11], [8, 16]])).toEqual('pivot'); +// expect(editor.getSelectedBufferRange()).toEqual([[8, 44], [8, 48]]); +// expect(editor.getTextInBufferRange(editor.getSelectedBufferRange())).toEqual('sort'); +// }); +// +// it("places the word under the cursor into the replace editor", () => { +// editor.setSelectedBufferRange([[3, 8], [3, 8]]); +// atom.commands.dispatch(workspaceElement, 'find-and-replace:use-selection-as-replace-pattern'); +// expect(findView.replaceEditor.getText()).toBe('pivot'); +// expect(editor.getSelectedBufferRange()).toEqual([[3, 8], [3, 8]]); +// +// findView.findEditor.setText('sort'); +// atom.commands.dispatch(workspaceElement, 'find-and-replace:find-next'); +// expect(editor.getSelectedBufferRange()).toEqual([[8, 11], [8, 15]]); +// expect(editor.getTextInBufferRange(editor.getSelectedBufferRange())).toEqual('sort'); +// atom.commands.dispatch(workspaceElement, 'find-and-replace:replace-next'); +// expect(editor.getTextInBufferRange([[8, 11], [8, 16]])).toEqual('pivot'); +// expect(editor.getSelectedBufferRange()).toEqual([[8, 44], [8, 48]]); +// expect(editor.getTextInBufferRange(editor.getSelectedBufferRange())).toEqual('sort'); +// }); +// +// it("places the previously selected text into the replace editor if no selection", () => { +// editor.setSelectedBufferRange([[1, 6], [1, 10]]); +// atom.commands.dispatch(workspaceElement, 'find-and-replace:use-selection-as-replace-pattern'); +// expect(findView.replaceEditor.getText()).toBe('sort'); +// +// editor.setSelectedBufferRange([[1, 1], [1, 1]]); +// atom.commands.dispatch(workspaceElement, 'find-and-replace:use-selection-as-replace-pattern'); +// expect(findView.replaceEditor.getText()).toBe('sort'); +// }); +// +// it("places selected text into the replace editor and escapes it when Regex is enabled", () => { +// atom.commands.dispatch(findView.replaceEditor.element, 'find-and-replace:toggle-regex-option'); +// editor.setSelectedBufferRange([[6, 6], [6, 65]]); +// atom.commands.dispatch(workspaceElement, 'find-and-replace:use-selection-as-replace-pattern'); +// expect(findView.replaceEditor.getText()).toBe('current < pivot \\? left\\.push\\(current\\) : right\\.push\\(current\\);'); +// }); +// }); +// +// describe("when find-and-replace:find-next-selected is triggered", () => { +// it("places the selected text into the find editor and finds the next occurrence", () => { +// editor.setSelectedBufferRange([[0, 9], [0, 13]]); +// atom.commands.dispatch(workspaceElement, "find-and-replace:find-next-selected"); +// expect(findView.findEditor.getText()).toBe("sort"); +// expect(editor.getSelectedBufferRange()).toEqual([[1, 6], [1, 10]]); +// }); +// +// it("places the word under the cursor into the find editor and finds the next occurrence", () => { +// editor.setSelectedBufferRange([[1, 8], [1, 8]]); +// atom.commands.dispatch(workspaceElement, "find-and-replace:find-next-selected"); +// expect(findView.findEditor.getText()).toBe("sort"); +// expect(editor.getSelectedBufferRange()).toEqual([[8, 11], [8, 15]]); +// }); +// }); +// +// describe("when find-and-replace:find-previous-selected is triggered", () => { +// it("places the selected text into the find editor and finds the previous occurrence ", () => { +// editor.setSelectedBufferRange([[0, 9], [0, 13]]); +// atom.commands.dispatch(workspaceElement, "find-and-replace:find-previous-selected"); +// expect(findView.findEditor.getText()).toBe("sort"); +// expect(editor.getSelectedBufferRange()).toEqual([[11, 9], [11, 13]]); +// }); +// +// it("places the word under the cursor into the find editor and finds the previous occurrence", () => { +// editor.setSelectedBufferRange([[8, 13], [8, 13]]); +// atom.commands.dispatch(workspaceElement, "find-and-replace:find-previous-selected"); +// expect(findView.findEditor.getText()).toBe("sort"); +// expect(editor.getSelectedBufferRange()).toEqual([[1, 6], [1, 10]]); +// }); +// }); +// +// it("does not highlight the found text when the find view is hidden", () => { +// atom.commands.dispatch(findView.findEditor.element, "core:cancel"); +// atom.commands.dispatch(findView.findEditor.element, "find-and-replace:find-next"); +// }); +// +// describe("when the active pane item changes", () => { +// beforeEach(() => { +// editor.setSelectedBufferRange([[0, 0], [0, 0]]); +// }); +// +// describe("when a new editor is activated", () => { +// it("reruns the search on the new editor", async () => { +// await atom.workspace.open("sample.coffee"); +// editor = atom.workspace.getCenter().getActivePaneItem(); +// expect(findView.refs.resultCounter.textContent).toEqual("7 found"); +// expect(editor.getSelectedBufferRange()).toEqual([[0, 0], [0, 0]]); +// }); +// +// it("initially highlights the found text in the new editor", async () => { +// expect(getResultDecorations(editor, "find-result")).toHaveLength(6); +// +// await atom.workspace.open("sample.coffee"); +// expect(getResultDecorations(editor, "find-result")).toHaveLength(0); +// +// const newEditor = atom.workspace.getCenter().getActiveTextEditor(); +// expect(getResultDecorations(newEditor, "find-result")).toHaveLength(7); +// }); +// +// it("highlights the found text in the new editor when find next is triggered", async () => { +// await atom.workspace.open("sample.coffee"); +// +// atom.commands.dispatch(findView.findEditor.element, "find-and-replace:find-next"); +// const newEditor = atom.workspace.getCenter().getActiveTextEditor(); +// expect(getResultDecorations(newEditor, "find-result")).toHaveLength(6); +// expect(getResultDecorations(newEditor, "current-result")).toHaveLength(1); +// }); +// }); +// +// describe("when all active pane items are closed", () => { +// it("updates the result count", () => { +// atom.commands.dispatch(editorView, "core:close"); +// expect(findView.refs.resultCounter.textContent).toEqual("no results"); +// }); +// }); +// +// describe("when the active pane item is not an editor", () => { +// let openerDisposable; +// +// beforeEach(() => { +// openerDisposable = atom.workspace.addOpener(function(pathToOpen, options) { +// return document.createElement("div"); +// }); +// }); +// +// afterEach(() => { +// openerDisposable.dispose(); +// }); +// +// it("updates the result view", async () => { +// await atom.workspace.open("another"); +// expect(findView.refs.resultCounter.textContent).toEqual("no results"); +// }); +// }); +// +// describe("when the active pane is in a dock", () => { +// it("does nothing", async () => { +// const dock = atom.workspace.getLeftDock() +// dock.show() +// dock.getActivePane().activateItem(document.createElement('div')) +// dock.getActivePane().activate() +// expect(findView.refs.resultCounter.textContent).not.toEqual("no results"); +// }); +// }); +// +// describe("when a new editor is activated on a different pane", () => { +// it("initially highlights all the sample.js results", () => { +// expect(getResultDecorations(editor, "find-result")).toHaveLength(6); +// }); +// +// it("reruns the search on the new editor", async () => { +// let newEditor +// if (atom.workspace.createItemForURI) { +// newEditor = await atom.workspace.createItemForURI("sample.coffee"); +// } else { +// newEditor = await atom.workspace.open("sample.coffee", {activateItem: false}) +// } +// +// newEditor = atom.workspace.paneForItem(editor).splitRight({ +// items: [newEditor] +// }).getActiveItem(); +// +// expect(getResultDecorations(newEditor, "find-result")).toHaveLength(7); +// expect(findView.refs.resultCounter.textContent).toEqual("7 found"); +// expect(newEditor.getSelectedBufferRange()).toEqual([[0, 0], [0, 0]]); +// +// atom.commands.dispatch(findView.findEditor.element, "find-and-replace:find-next"); +// expect(findView.refs.resultCounter.textContent).toEqual("1 of 7"); +// expect(newEditor.getSelectedBufferRange()).toEqual([[1, 9], [1, 14]]); +// }); +// +// it("highlights the found text in the new editor (and removes the highlights from the other)", async () => { +// const newEditor = await atom.workspace.open("sample.coffee") +// expect(getResultDecorations(editor, "find-result")).toHaveLength(0); +// expect(getResultDecorations(newEditor, "find-result")).toHaveLength(7); +// }); +// +// it("will still highlight results after the split pane has been destroyed", async () => { +// const newEditor = await atom.workspace.open("sample.coffee") +// const originalPane = atom.workspace.paneForItem(editor); +// const splitPane = atom.workspace.paneForItem(editor).splitRight(); +// originalPane.moveItemToPane(newEditor, splitPane, 0); +// expect(getResultDecorations(newEditor, "find-result")).toHaveLength(7); +// +// atom.commands.dispatch(editor.element, "core:close"); +// editorView.focus(); +// expect(atom.workspace.getCenter().getActiveTextEditor()).toBe(editor); +// expect(getResultDecorations(editor, "find-result")).toHaveLength(6); +// }); +// }); +// }); +// +// describe("when the buffer contents change", () => { +// it("re-runs the search", () => { +// editor.setSelectedBufferRange([[1, 26], [1, 27]]); +// editor.insertText(""); +// window.advanceClock(1000); +// expect(findView.refs.resultCounter.textContent).toEqual("5 found"); +// +// editor.insertText("s"); +// window.advanceClock(1000); +// expect(findView.refs.resultCounter.textContent).toEqual("6 found"); +// }); +// +// it("does not beep if no matches were found", () => { +// editor.setCursorBufferPosition([2, 0]); +// findView.findEditor.setText("notinthefilebro"); +// atom.commands.dispatch(findView.findEditor.element, "core:confirm"); +// atom.beep.reset(); +// editor.insertText("blah blah"); +// expect(atom.beep).not.toHaveBeenCalled(); +// }); +// }); +// +// describe("when in current selection is toggled", () => { +// beforeEach(() => { +// editor.setSelectedBufferRange([[2, 0], [4, 0]]); +// }); +// +// it("toggles find within a selection via an event and only finds matches within the selection", () => { +// findView.findEditor.setText("items"); +// atom.commands.dispatch(findView.findEditor.element, "find-and-replace:toggle-selection-option"); +// expect(editor.getSelectedBufferRange()).toEqual([[2, 0], [4, 0]]); +// expect(findView.refs.resultCounter.textContent).toEqual("3 found"); +// }); +// +// it("toggles find within a selection via button and only finds matches within the selection", () => { +// findView.findEditor.setText("items"); +// findView.refs.selectionOptionButton.click(); +// expect(editor.getSelectedBufferRange()).toEqual([[2, 0], [4, 0]]); +// expect(findView.refs.resultCounter.textContent).toEqual("3 found"); +// }); +// +// describe("when there is no selection", () => { +// beforeEach(() => { +// editor.setSelectedBufferRange([[0, 0], [0, 0]]); +// }); +// +// it("toggles find within a selection via an event", () => { +// findView.findEditor.setText("items"); +// atom.commands.dispatch(findView.findEditor.element, "find-and-replace:toggle-selection-option"); +// expect(editor.getSelectedBufferRange()).toEqual([[1, 22], [1, 27]]); +// expect(findView.refs.resultCounter.textContent).toEqual("1 of 6"); +// }); +// }); +// }); +// +// describe("when regex is toggled", () => { +// it("toggles regex via an event and finds text matching the pattern", () => { +// editor.setCursorBufferPosition([2, 0]); +// atom.commands.dispatch(findView.findEditor.element, "find-and-replace:toggle-regex-option"); +// findView.findEditor.setText("i[t]em+s"); +// expect(editor.getSelectedBufferRange()).toEqual([[2, 8], [2, 13]]); +// }); +// +// it("toggles regex via a button and finds text matching the pattern", () => { +// editor.setCursorBufferPosition([2, 0]); +// findView.refs.regexOptionButton.click(); +// findView.findEditor.setText("i[t]em+s"); +// expect(editor.getSelectedBufferRange()).toEqual([[2, 8], [2, 13]]); +// }); +// +// it("re-runs the search using the new find text when toggled", () => { +// editor.setCursorBufferPosition([1, 0]); +// findView.findEditor.setText("s(o)rt"); +// atom.commands.dispatch(findView.findEditor.element, "find-and-replace:toggle-regex-option"); +// expect(editor.getSelectedBufferRange()).toEqual([[1, 6], [1, 10]]); +// }); +// +// describe("when an invalid regex is entered", () => { +// it("displays an error", () => { +// editor.setCursorBufferPosition([2, 0]); +// atom.commands.dispatch(findView.findEditor.element, "find-and-replace:toggle-regex-option"); +// findView.findEditor.setText("i[t"); +// atom.commands.dispatch(findView.findEditor.element, "core:confirm"); +// expect(findView.refs.descriptionLabel).toHaveClass("text-error"); +// }); +// }); +// +// describe("when there are existing selections", () => { +// it("does not jump to the next match when any selections match the pattern", () => { +// findView.model.setFindOptions({ +// useRegex: false +// }); +// +// findView.findEditor.setText("items.length"); +// editor.setSelectedBufferRange([[2, 8], [2, 20]]); +// findView.refs.regexOptionButton.click(); +// expect(editor.getSelectedBufferRange()).toEqual([[2, 8], [2, 20]]); +// +// findView.refs.regexOptionButton.click(); +// expect(editor.getSelectedBufferRange()).toEqual([[2, 8], [2, 20]]); +// }); +// +// it("jumps to the next match when no selections match the pattern", () => { +// findView.model.setFindOptions({ +// useRegex: false +// }); +// +// findView.findEditor.setText("pivot ?"); +// editor.setSelectedBufferRange([[6, 16], [6, 23]]); +// findView.refs.regexOptionButton.click(); +// expect(editor.getSelectedBufferRange()).toEqual([[8, 29], [8, 34]]); +// +// findView.refs.regexOptionButton.click(); +// expect(editor.getSelectedBufferRange()).toEqual([[6, 16], [6, 23]]); +// }); +// }); +// +// it("matches astral-plane unicode characters with .", () => { +// if (!editor.getBuffer().hasAstral) { +// console.log('Skipping astral-plane test case') +// return +// } +// +// editor.setText("\n\nbefore😄after\n\n"); +// atom.commands.dispatch(findView.findEditor.element, "find-and-replace:toggle-regex-option"); +// findView.findEditor.setText("before.after"); +// atom.commands.dispatch(findView.findEditor.element, "core:confirm"); +// expect(editor.getSelectedBufferRange()).toEqual([[2, 0], [2, 13]]) +// }); +// }); +// +// describe("when whole-word is toggled", () => { +// it("toggles whole-word via an event and finds text matching the pattern", () => { +// editor.setCursorBufferPosition([0, 0]); +// findView.findEditor.setText("sort"); +// atom.commands.dispatch(findView.findEditor.element, "core:confirm"); +// expect(editor.getSelectedBufferRange()).toEqual([[0, 9], [0, 13]]); +// +// atom.commands.dispatch(findView.findEditor.element, "find-and-replace:toggle-whole-word-option"); +// expect(editor.getSelectedBufferRange()).toEqual([[1, 6], [1, 10]]); +// }); +// +// it("toggles whole-word via a button and finds text matching the pattern", () => { +// editor.setCursorBufferPosition([0, 0]); +// findView.findEditor.setText("sort"); +// atom.commands.dispatch(findView.findEditor.element, "core:confirm"); +// expect(editor.getSelectedBufferRange()).toEqual([[0, 9], [0, 13]]); +// +// findView.refs.wholeWordOptionButton.click(); +// expect(editor.getSelectedBufferRange()).toEqual([[1, 6], [1, 10]]); +// }); +// +// it("re-runs the search using the new find text when toggled", () => { +// editor.setCursorBufferPosition([8, 0]); +// findView.findEditor.setText("apply"); +// atom.commands.dispatch(findView.findEditor.element, "find-and-replace:toggle-whole-word-option"); +// expect(editor.getSelectedBufferRange()).toEqual([[11, 20], [11, 25]]); +// }); +// +// describe("when there are existing selections", () => { +// it("does not jump to the next match when any selections match the pattern", () => { +// findView.model.setFindOptions({ +// wholeWord: false +// }); +// +// findView.findEditor.setText("sort"); +// editor.setSelectedBufferRange([[1, 6], [1, 10]]); +// findView.refs.wholeWordOptionButton.click(); +// expect(editor.getSelectedBufferRange()).toEqual([[1, 6], [1, 10]]); +// +// findView.refs.wholeWordOptionButton.click(); +// expect(editor.getSelectedBufferRange()).toEqual([[1, 6], [1, 10]]); +// }); +// +// it("jumps to the next match when no selections match the pattern", () => { +// findView.model.setFindOptions({ +// wholeWord: false +// }); +// +// findView.findEditor.setText("sort"); +// editor.setSelectedBufferRange([[0, 9], [0, 13]]); +// findView.refs.wholeWordOptionButton.click(); +// expect(editor.getSelectedBufferRange()).toEqual([[1, 6], [1, 10]]); +// +// editor.setSelectedBufferRange([[0, 0], [0, 5]]); +// findView.refs.wholeWordOptionButton.click(); +// expect(editor.getSelectedBufferRange()).toEqual([[0, 9], [0, 13]]); +// }); +// }); +// }); +// +// describe("when case sensitivity is toggled", () => { +// beforeEach(() => { +// editor.setText("-----\nwords\nWORDs\n"); +// editor.setCursorBufferPosition([0, 0]); +// }); +// +// it("toggles case sensitivity via an event and finds text matching the pattern", () => { +// findView.findEditor.setText("WORDs"); +// atom.commands.dispatch(findView.findEditor.element, "core:confirm"); +// expect(editor.getSelectedBufferRange()).toEqual([[1, 0], [1, 5]]); +// +// editor.setCursorBufferPosition([0, 0]); +// atom.commands.dispatch(findView.findEditor.element, "find-and-replace:toggle-case-option"); +// expect(editor.getSelectedBufferRange()).toEqual([[2, 0], [2, 5]]); +// }); +// +// it("toggles case sensitivity via a button and finds text matching the pattern", () => { +// findView.findEditor.setText("WORDs"); +// atom.commands.dispatch(findView.findEditor.element, "core:confirm"); +// expect(editor.getSelectedBufferRange()).toEqual([[1, 0], [1, 5]]); +// +// editor.setCursorBufferPosition([0, 0]); +// findView.refs.caseOptionButton.click(); +// expect(editor.getSelectedBufferRange()).toEqual([[2, 0], [2, 5]]); +// }); +// +// describe("when there are existing selections", () => { +// it("does not jump to the next match when any selections match the pattern", () => { +// findView.model.setFindOptions({ +// caseSensitive: false +// }); +// +// findView.findEditor.setText("WORDs"); +// editor.setSelectedBufferRange([[2, 0], [2, 5]]); +// findView.refs.caseOptionButton.click(); +// expect(editor.getSelectedBufferRange()).toEqual([[2, 0], [2, 5]]); +// +// findView.refs.caseOptionButton.click(); +// expect(editor.getSelectedBufferRange()).toEqual([[2, 0], [2, 5]]); +// }); +// +// it("jumps to the next match when no selections match the pattern", () => { +// findView.model.setFindOptions({ +// caseSensitive: false +// }); +// +// findView.findEditor.setText("WORDs"); +// editor.setSelectedBufferRange([[1, 0], [1, 5]]); +// findView.refs.caseOptionButton.click(); +// expect(editor.getSelectedBufferRange()).toEqual([[2, 0], [2, 5]]); +// +// editor.setSelectedBufferRange([[0, 0], [0, 5]]); +// findView.refs.caseOptionButton.click(); +// expect(editor.getSelectedBufferRange()).toEqual([[1, 0], [1, 5]]); +// }); +// }); +// +// it("finds unicode characters with case folding", () => { +// if (!editor.getBuffer().hasAstral) { +// console.log('Skipping unicode test case') +// return +// } +// +// editor.setText("---\n> április\n---\n") +// findView.findEditor.setText("Április") +// atom.commands.dispatch(findView.findEditor.element, "core:confirm") +// expect(editor.getSelectedBufferRange()).toEqual([[1, 2], [1, 9]]) +// }); +// }); +// +// describe("highlighting search results", () => { +// function getResultDecoration(clazz) { +// return getResultDecorations(editor, clazz)[0]; +// } +// +// it("only highlights matches", () => { +// expect(getResultDecorations(editor, "find-result")).toHaveLength(5); +// findView.findEditor.setText("notinthefilebro"); +// atom.commands.dispatch(findView.findEditor.element, "core:confirm"); +// expect(getResultDecorations(editor, "find-result")).toHaveLength(0); +// }); +// +// it("adds a class to the current match indicating it is the current match", () => { +// const firstResultMarker = getResultDecoration("current-result"); +// expect(getResultDecorations(editor, "find-result")).toHaveLength(5); +// +// atom.commands.dispatch(findView.findEditor.element, "core:confirm"); +// atom.commands.dispatch(findView.findEditor.element, "core:confirm"); +// const nextResultMarker = getResultDecoration("current-result"); +// expect(nextResultMarker).not.toEqual(firstResultMarker); +// +// atom.commands.dispatch(findView.findEditor.element, "find-and-replace:find-previous"); +// atom.commands.dispatch(findView.findEditor.element, "find-and-replace:find-previous"); +// const originalResultMarker = getResultDecoration("current-result"); +// expect(originalResultMarker).toEqual(firstResultMarker); +// }); +// +// it("adds a class to the result when the current selection equals the result's range", () => { +// const originalResultMarker = getResultDecoration("current-result"); +// expect(originalResultMarker).toBeDefined(); +// +// editor.setSelectedBufferRange([[5, 16], [5, 20]]); +// expect(getResultDecoration("current-result")).toBeUndefined(); +// +// editor.setSelectedBufferRange([[5, 16], [5, 21]]); +// const newResultMarker = getResultDecoration("current-result"); +// expect(newResultMarker).toBeDefined(); +// expect(newResultMarker).not.toBe(originalResultMarker); +// }); +// }); +// +// describe("when user types in the find editor", () => { +// function advance() { +// advanceClock(findView.findEditor.getBuffer().stoppedChangingDelay + 1); +// } +// +// beforeEach(() => { +// findView.findEditor.element.focus(); +// }); +// +// it("scrolls to the first match if the settings scrollToResultOnLiveSearch is true", () => { +// editorView.style.height = "3px"; +// editor.update({autoHeight: false}) +// +// editorView.component.measureDimensions(); +// editor.moveToTop(); +// atom.config.set("find-and-replace.scrollToResultOnLiveSearch", true); +// findView.findEditor.setText("Array"); +// advance(); +// expect(editorView.getScrollTop()).toBeGreaterThan(0); +// expect(editor.getSelectedBufferRange()).toEqual([[11, 14], [11, 19]]); +// expect(findView.findEditor.element).toHaveFocus(); +// }); +// +// it("doesn't scroll to the first match if the settings scrollToResultOnLiveSearch is false", () => { +// editorView.style.height = "3px"; +// editor.update({autoHeight: false}) +// +// editorView.component.measureDimensions(); +// editor.moveToTop(); +// atom.config.set("find-and-replace.scrollToResultOnLiveSearch", false); +// findView.findEditor.setText("Array"); +// advance(); +// expect(editorView.getScrollTop()).toBe(0); +// expect(editor.getSelectedBufferRange()).toEqual([]); +// expect(findView.findEditor.element).toHaveFocus(); +// }); +// +// it("updates the search results", () => { +// expect(findView.refs.descriptionLabel.textContent).toContain("6 results"); +// +// findView.findEditor.setText( +// "why do I need these 2 lines? The editor does not trigger contents-modified without them" +// ); +// +// advance(); +// findView.findEditor.setText(""); +// advance(); +// expect(findView.refs.descriptionLabel.textContent).toContain("Find in Current Buffer"); +// expect(findView.element).toHaveFocus(); +// +// findView.findEditor.setText("sort"); +// advance(); +// expect(findView.refs.descriptionLabel.textContent).toContain("5 results"); +// expect(findView.element).toHaveFocus(); +// +// findView.findEditor.setText("items"); +// advance(); +// expect(findView.refs.descriptionLabel.textContent).toContain("6 results"); +// expect(findView.element).toHaveFocus(); +// }); +// +// it("respects the `liveSearchMinimumCharacters` setting", () => { +// expect(findView.refs.descriptionLabel.textContent).toContain("6 results"); +// atom.config.set("find-and-replace.liveSearchMinimumCharacters", 3); +// +// findView.findEditor.setText( +// "why do I need these 2 lines? The editor does not trigger contents-modified without them" +// ); +// +// advance(); +// findView.findEditor.setText(""); +// advance(); +// expect(findView.refs.descriptionLabel.textContent).toContain("Find in Current Buffer"); +// expect(findView.element).toHaveFocus(); +// +// findView.findEditor.setText("ite"); +// advance(); +// expect(findView.refs.descriptionLabel.textContent).toContain("6 results"); +// expect(findView.element).toHaveFocus(); +// +// findView.findEditor.setText("i"); +// advance(); +// expect(findView.refs.descriptionLabel.textContent).toContain("6 results"); +// expect(findView.element).toHaveFocus(); +// +// findView.findEditor.setText(""); +// advance(); +// expect(findView.refs.descriptionLabel.textContent).toContain("Find in Current Buffer"); +// expect(findView.element).toHaveFocus(); +// +// atom.config.set("find-and-replace.liveSearchMinimumCharacters", 0); +// findView.findEditor.setText("i"); +// advance(); +// expect(findView.refs.descriptionLabel.textContent).toContain("20 results"); +// expect(findView.element).toHaveFocus(); +// }); +// +// it("doesn't live search on a regex that matches empty string", () => { +// expect(findView.refs.descriptionLabel.textContent).toContain("6 results"); +// +// atom.commands.dispatch(findView.findEditor.element, "find-and-replace:toggle-regex-option"); +// findView.findEditor.setText("asdf|"); +// advance(); +// expect(findView.refs.descriptionLabel.textContent).toContain("6 results"); +// }); +// +// it("doesn't live search on a invalid regex", () => { +// expect(findView.refs.descriptionLabel.textContent).toContain("6 results"); +// +// atom.commands.dispatch(findView.findEditor.element, "find-and-replace:toggle-regex-option"); +// findView.findEditor.setText("\\(.*)"); +// advance(); +// expect(findView.refs.descriptionLabel).toHaveClass("text-error"); +// expect(findView.refs.descriptionLabel.textContent).toContain("Invalid regular expression"); +// }); +// }); +// +// describe("when another find is called", () => { +// it("clears existing markers for another search", () => { +// findView.findEditor.setText("notinthefile"); +// atom.commands.dispatch(findView.findEditor.element, "core:confirm"); +// expect(getResultDecorations(editor, "find-result")).toHaveLength(0); +// }); +// +// it("clears existing markers for an empty search", () => { +// findView.findEditor.setText(""); +// atom.commands.dispatch(findView.findEditor.element, "core:confirm"); +// expect(getResultDecorations(editor, "find-result")).toHaveLength(0); +// }); +// }); +// }); +// +// it("doesn't throw an exception when toggling the regex option with an invalid pattern before performing any other search (regression)", async () => { +// atom.commands.dispatch(editorView, 'find-and-replace:show'); +// await activationPromise; +// +// findView.findEditor.setText('('); +// atom.commands.dispatch(findView.findEditor.element, 'find-and-replace:toggle-regex-option'); +// +// editor.insertText('hi'); +// advanceClock(editor.getBuffer().stoppedChangingDelay); +// }); +// +// describe("replacing", () => { +// beforeEach(async () => { +// editor.setCursorBufferPosition([2, 0]); +// atom.commands.dispatch(editorView, "find-and-replace:show-replace"); +// +// await activationPromise; +// +// findView.findEditor.setText("items"); +// findView.replaceEditor.setText("cats"); +// }); +// +// describe("when the find string is empty", () => { +// it("beeps", () => { +// findView.findEditor.setText(""); +// atom.commands.dispatch(findView.replaceEditor.element, "core:confirm"); +// expect(atom.beep).toHaveBeenCalled(); +// }); +// }); +// +// describe("when the replacement string contains an escaped char", () => { +// describe("when the regex option is chosen", () => { +// beforeEach(() => { +// atom.commands.dispatch(findView.findEditor.element, "find-and-replace:toggle-regex-option"); +// }); +// +// it("inserts newlines and tabs", () => { +// findView.replaceEditor.setText("\\n\\t"); +// atom.commands.dispatch(findView.replaceEditor.element, "core:confirm"); +// expect(editor.getText()).toMatch(/\n\t/); +// }); +// +// it("doesn't insert a escaped char if there are multiple backslashes in front of the char", () => { +// findView.replaceEditor.setText("\\\\t\\\t"); +// atom.commands.dispatch(findView.replaceEditor.element, "core:confirm"); +// expect(editor.getText()).toMatch(/\\t\\\t/); +// }); +// }); +// +// describe("when in normal mode", () => { +// it("inserts backslash n and t", () => { +// findView.replaceEditor.setText("\\t\\n"); +// atom.commands.dispatch(findView.replaceEditor.element, "core:confirm"); +// expect(editor.getText()).toMatch(/\\t\\n/); +// }); +// +// it("inserts carriage returns", () => { +// const textWithCarriageReturns = editor.getText().replace(/\n/g, "\r"); +// editor.setText(textWithCarriageReturns); +// findView.replaceEditor.setText("\\t\\r"); +// atom.commands.dispatch(findView.replaceEditor.element, "core:confirm"); +// expect(editor.getText()).toMatch(/\\t\\r/); +// }); +// }); +// }); +// +// describe("replace next", () => { +// describe("when core:confirm is triggered", () => { +// it("replaces the match after the cursor and selects the next match", () => { +// atom.commands.dispatch(findView.replaceEditor.element, "core:confirm"); +// expect(findView.refs.resultCounter.textContent).toEqual("2 of 5"); +// expect(editor.lineTextForBufferRow(2)).toBe(" if (cats.length <= 1) return items;"); +// expect(editor.getSelectedBufferRange()).toEqual([[2, 33], [2, 38]]); +// }); +// +// it("replaceEditor maintains focus after core:confirm is run", () => { +// findView.replaceEditor.element.focus(); +// atom.commands.dispatch(findView.replaceEditor.element, "core:confirm"); +// expect(findView.replaceEditor.element).toHaveFocus(); +// }); +// +// it("replaces the _current_ match and selects the next match", () => { +// atom.commands.dispatch(findView.findEditor.element, "core:confirm"); +// editor.setSelectedBufferRange([[2, 8], [2, 13]]); +// expect(findView.refs.resultCounter.textContent).toEqual("2 of 6"); +// +// atom.commands.dispatch(findView.replaceEditor.element, "core:confirm"); +// expect(findView.refs.resultCounter.textContent).toEqual("2 of 5"); +// expect(editor.lineTextForBufferRow(2)).toBe(" if (cats.length <= 1) return items;"); +// expect(editor.getSelectedBufferRange()).toEqual([[2, 33], [2, 38]]); +// +// atom.commands.dispatch(findView.replaceEditor.element, "core:confirm"); +// expect(findView.refs.resultCounter.textContent).toEqual("2 of 4"); +// expect(editor.lineTextForBufferRow(2)).toBe(" if (cats.length <= 1) return cats;"); +// expect(editor.getSelectedBufferRange()).toEqual([[3, 16], [3, 21]]); +// }); +// +// it("replaces the _current_ match and selects the next match", () => { +// editor.setText( +// "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s" +// ); +// +// editor.setSelectedBufferRange([[0, 0], [0, 5]]); +// findView.findEditor.setText("Lorem"); +// findView.replaceEditor.setText("replacement"); +// atom.commands.dispatch(findView.replaceEditor.element, "core:confirm"); +// +// expect(editor.lineTextForBufferRow(0)).toBe( +// "replacement Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s" +// ); +// +// expect(editor.getSelectedBufferRange()).toEqual([[0, 81], [0, 86]]); +// }); +// }); +// +// describe("when the replace next button is pressed", () => { +// it("replaces the match after the cursor and selects the next match", () => { +// findView.refs.replaceNextButton.click(); +// expect(findView.refs.resultCounter.textContent).toEqual("2 of 5"); +// expect(editor.lineTextForBufferRow(2)).toBe(" if (cats.length <= 1) return items;"); +// expect(editor.getSelectedBufferRange()).toEqual([[2, 33], [2, 38]]); +// expect(findView.replaceEditor.element).toHaveFocus(); +// }); +// }); +// +// describe("when the 'find-and-replace:replace-next' event is triggered", () => { +// it("replaces the match after the cursor and selects the next match", () => { +// atom.commands.dispatch(editorView, "find-and-replace:replace-next"); +// expect(findView.refs.resultCounter.textContent).toEqual("2 of 5"); +// expect(editor.lineTextForBufferRow(2)).toBe(" if (cats.length <= 1) return items;"); +// expect(editor.getSelectedBufferRange()).toEqual([[2, 33], [2, 38]]); +// }); +// }); +// }); +// +// describe("replace previous", () => { +// describe("when command is triggered", () => { +// it("replaces the match after the cursor and selects the previous match", () => { +// atom.commands.dispatch(findView.findEditor.element, "core:confirm"); +// atom.commands.dispatch(findView.element, "find-and-replace:replace-previous"); +// expect(findView.refs.resultCounter.textContent).toEqual("1 of 5"); +// expect(editor.lineTextForBufferRow(2)).toBe(" if (cats.length <= 1) return items;"); +// expect(editor.getSelectedBufferRange()).toEqual([[1, 22], [1, 27]]); +// }); +// }); +// }); +// +// describe("replace all", () => { +// describe("when the replace all button is pressed", () => { +// it("replaces all matched text", () => { +// findView.refs.replaceAllButton.click(); +// expect(findView.refs.resultCounter.textContent).toEqual("no results"); +// expect(editor.getText()).not.toMatch(/items/); +// expect(editor.getText().match(/\bcats\b/g)).toHaveLength(6); +// expect(editor.getSelectedBufferRange()).toEqual([[2, 0], [2, 0]]); +// }); +// +// it("all changes are undoable in one transaction", () => { +// findView.refs.replaceAllButton.click(); +// editor.undo(); +// expect(editor.getText()).not.toMatch(/\bcats\b/g); +// }); +// }); +// +// describe("when the 'find-and-replace:replace-all' event is triggered", () => { +// it("replaces all matched text", () => { +// atom.commands.dispatch(editorView, "find-and-replace:replace-all"); +// expect(findView.refs.resultCounter.textContent).toEqual("no results"); +// expect(editor.getText()).not.toMatch(/items/); +// expect(editor.getText().match(/\bcats\b/g)).toHaveLength(6); +// expect(editor.getSelectedBufferRange()).toEqual([[2, 0], [2, 0]]); +// }); +// }); +// }); +// +// describe("replacement patterns", () => { +// describe("when the regex option is true", () => { +// it("replaces $1, $2, etc... with substring matches", () => { +// atom.commands.dispatch(findView.findEditor.element, "find-and-replace:toggle-regex-option"); +// findView.findEditor.setText("(items)([\\.;])"); +// findView.replaceEditor.setText("$2$1"); +// atom.commands.dispatch(editorView, "find-and-replace:replace-all"); +// expect(editor.getText()).toMatch(/;items/); +// expect(editor.getText()).toMatch(/\.items/); +// }); +// }); +// +// describe("when the regex option is false", () => { +// it("replaces the matches with without any regex subsitions", () => { +// findView.findEditor.setText("items"); +// findView.replaceEditor.setText("$&cats"); +// atom.commands.dispatch(editorView, "find-and-replace:replace-all"); +// expect(editor.getText()).not.toMatch(/items/); +// expect(editor.getText().match(/\$&cats\b/g)).toHaveLength(6); +// }); +// }); +// }); +// }); +// +// describe("history", () => { +// beforeEach(async () => { +// atom.commands.dispatch(editorView, "find-and-replace:show"); +// await activationPromise; +// }); +// +// describe("when there is no history", () => { +// it("retains unsearched text", () => { +// const text = "something I want to search for but havent yet"; +// findView.findEditor.setText(text); +// atom.commands.dispatch(findView.findEditor.element, "core:move-up"); +// expect(findView.findEditor.getText()).toEqual(""); +// +// atom.commands.dispatch(findView.findEditor.element, "core:move-down"); +// expect(findView.findEditor.getText()).toEqual(text); +// }); +// }); +// +// describe("when there is history", () => { +// const [oneRange, twoRange, threeRange] = []; +// +// beforeEach(() => { +// atom.commands.dispatch(editorView, "find-and-replace:show"); +// editor.setText("zero\none\ntwo\nthree\n"); +// findView.findEditor.setText("one"); +// atom.commands.dispatch(findView.findEditor.element, "core:confirm"); +// findView.findEditor.setText("two"); +// atom.commands.dispatch(findView.findEditor.element, "core:confirm"); +// findView.findEditor.setText("three"); +// atom.commands.dispatch(findView.findEditor.element, "core:confirm"); +// }); +// +// it("can navigate the entire history stack", () => { +// expect(findView.findEditor.getText()).toEqual("three"); +// +// atom.commands.dispatch(findView.findEditor.element, "core:move-down"); +// expect(findView.findEditor.getText()).toEqual(""); +// +// atom.commands.dispatch(findView.findEditor.element, "core:move-down"); +// expect(findView.findEditor.getText()).toEqual(""); +// +// atom.commands.dispatch(findView.findEditor.element, "core:move-up"); +// expect(findView.findEditor.getText()).toEqual("three"); +// +// atom.commands.dispatch(findView.findEditor.element, "core:move-up"); +// expect(findView.findEditor.getText()).toEqual("two"); +// +// atom.commands.dispatch(findView.findEditor.element, "core:move-up"); +// expect(findView.findEditor.getText()).toEqual("one"); +// +// atom.commands.dispatch(findView.findEditor.element, "core:move-up"); +// expect(findView.findEditor.getText()).toEqual("one"); +// +// atom.commands.dispatch(findView.findEditor.element, "core:move-down"); +// expect(findView.findEditor.getText()).toEqual("two"); +// }); +// +// it("retains the current unsearched text", () => { +// const text = "something I want to search for but havent yet"; +// findView.findEditor.setText(text); +// atom.commands.dispatch(findView.findEditor.element, "core:move-up"); +// expect(findView.findEditor.getText()).toEqual("three"); +// +// atom.commands.dispatch(findView.findEditor.element, "core:move-down"); +// expect(findView.findEditor.getText()).toEqual(text); +// +// atom.commands.dispatch(findView.findEditor.element, "core:move-up"); +// expect(findView.findEditor.getText()).toEqual("three"); +// +// atom.commands.dispatch(findView.findEditor.element, "core:move-down"); +// atom.commands.dispatch(findView.findEditor.element, "core:confirm"); +// atom.commands.dispatch(findView.findEditor.element, "core:move-down"); +// expect(findView.findEditor.getText()).toEqual(""); +// }); +// +// it("adds confirmed patterns to the history", () => { +// findView.findEditor.setText("cool stuff"); +// atom.commands.dispatch(findView.findEditor.element, "core:confirm"); +// findView.findEditor.setText("cooler stuff"); +// atom.commands.dispatch(findView.findEditor.element, "core:move-up"); +// expect(findView.findEditor.getText()).toEqual("cool stuff"); +// +// atom.commands.dispatch(findView.findEditor.element, "core:move-up"); +// expect(findView.findEditor.getText()).toEqual("three"); +// }); +// +// describe("when user types in the find editor", () => { +// function advance() { +// advanceClock(findView.findEditor.getBuffer().stoppedChangingDelay + 1); +// } +// +// beforeEach(() => { +// findView.findEditor.element.focus(); +// }); +// +// it("does not add live searches to the history", () => { +// expect(findView.refs.descriptionLabel.textContent).toContain("1 result"); +// +// findView.findEditor.setText("FIXME: necessary search for some reason??"); +// advance(); +// findView.findEditor.setText("nope"); +// advance(); +// expect(findView.refs.descriptionLabel.textContent).toContain("nope"); +// +// findView.findEditor.setText("zero"); +// advance(); +// expect(findView.refs.descriptionLabel.textContent).toContain("zero"); +// +// atom.commands.dispatch(findView.findEditor.element, "core:move-up"); +// expect(findView.findEditor.getText()).toEqual("three"); +// }); +// }); +// }); +// }); +// +// describe("panel focus", () => { +// beforeEach(async () => { +// atom.commands.dispatch(editorView, "find-and-replace:show"); +// await activationPromise; +// }); +// +// it("focuses the find editor when the panel gets focus", () => { +// findView.replaceEditor.element.focus(); +// expect(findView.replaceEditor.element).toHaveFocus(); +// findView.element.focus(); +// expect(findView.findEditor.element).toHaveFocus(); +// }); +// +// it("moves focus between editors with find-and-replace:focus-next", () => { +// findView.findEditor.element.focus(); +// expect(findView.findEditor.element).toHaveClass("is-focused"); +// expect(findView.replaceEditor).not.toHaveClass("is-focused"); +// +// atom.commands.dispatch(findView.findEditor.element, "find-and-replace:focus-next"); +// expect(findView.findEditor.element).not.toHaveClass("is-focused"); +// expect(findView.replaceEditor.element).toHaveClass("is-focused"); +// +// atom.commands.dispatch(findView.replaceEditor.element, "find-and-replace:focus-next"); +// expect(findView.findEditor.element).toHaveClass("is-focused"); +// expect(findView.replaceEditor.element).not.toHaveClass("is-focused"); +// }); +// }); +// +// describe("when language-javascript is active", () => { +// beforeEach(async () => { +// await atom.packages.activatePackage("language-javascript"); +// }); +// +// it("uses the regexp grammar when regex-mode is loaded from configuration", async () => { +// atom.config.set("find-and-replace.useRegex", true); +// atom.commands.dispatch(editorView, "find-and-replace:show"); +// await activationPromise; +// +// expect(findView.model.getFindOptions().useRegex).toBe(true); +// expect(findView.findEditor.getGrammar().scopeName).toBe("source.js.regexp"); +// expect(findView.replaceEditor.getGrammar().scopeName).toBe("source.js.regexp.replacement"); +// }); +// +// describe("when panel is active", () => { +// beforeEach(async () => { +// atom.commands.dispatch(editorView, "find-and-replace:show"); +// await activationPromise; +// }); +// +// it("does not use regexp grammar when in non-regex mode", () => { +// expect(findView.model.getFindOptions().useRegex).not.toBe(true); +// expect(findView.findEditor.getGrammar().scopeName).toBe("text.plain.null-grammar"); +// expect(findView.replaceEditor.getGrammar().scopeName).toBe("text.plain.null-grammar"); +// }); +// +// it("uses regexp grammar when in regex mode and clears the regexp grammar when regex is disabled", () => { +// atom.commands.dispatch(findView.findEditor.element, "find-and-replace:toggle-regex-option"); +// expect(findView.model.getFindOptions().useRegex).toBe(true); +// expect(findView.findEditor.getGrammar().scopeName).toBe("source.js.regexp"); +// expect(findView.replaceEditor.getGrammar().scopeName).toBe("source.js.regexp.replacement"); +// +// atom.commands.dispatch(findView.findEditor.element, "find-and-replace:toggle-regex-option"); +// expect(findView.model.getFindOptions().useRegex).not.toBe(true); +// expect(findView.findEditor.getGrammar().scopeName).toBe("text.plain.null-grammar"); +// expect(findView.replaceEditor.getGrammar().scopeName).toBe("text.plain.null-grammar"); +// }); +// }); +// }); +// +// describe("when no buffer is open", () => { +// it("toggles regex via an event and finds text matching the pattern", async () => { +// atom.commands.dispatch(editorView, "find-and-replace:show"); +// editor.destroy(); +// await activationPromise; +// +// findView.findEditor.setText("items"); +// atom.commands.dispatch(findView.findEditor.element, "find-and-replace:toggle-regex-option"); +// expect(findView.model.getFindOptions().useRegex).toBe(true); +// expect(findView.refs.descriptionLabel.textContent).toContain("No results"); +// }); +// +// it("toggles selection via an event and finds text matching the pattern", async () => { +// atom.commands.dispatch(editorView, "find-and-replace:show"); +// editor.destroy(); +// await activationPromise; +// +// findView.findEditor.setText("items"); +// atom.commands.dispatch(findView.findEditor.element, "find-and-replace:toggle-selection-option"); +// expect(findView.model.getFindOptions().inCurrentSelection).toBe(true); +// expect(findView.refs.descriptionLabel.textContent).toContain("No results"); +// }); +// }); +// }); diff --git a/spec/project-find-view-spec.js b/spec/project-find-view-spec.js index 01d8c7f4..72691832 100644 --- a/spec/project-find-view-spec.js +++ b/spec/project-find-view-spec.js @@ -1,1673 +1,1673 @@ -/** @babel */ - -const path = require('path'); -const temp = require('temp').track(); -const fs = require('fs-plus'); -const dedent = require('dedent'); -const {TextBuffer} = require('atom'); -const ResultsPaneView = require('../lib/project/results-pane'); -const etch = require('etch'); -const {conditionPromise} = require('./async-spec-helpers'); - -for (const ripgrep of [false, true]) { -describe(`ProjectFindView (ripgrep=${ripgrep})`, () => { - const {stoppedChangingDelay} = TextBuffer.prototype; - let activationPromise, searchPromise, editor, editorElement, findView, - projectFindView, workspaceElement; - - function getAtomPanel() { - return workspaceElement.querySelector('.project-find').parentNode; - } - - function getExistingResultsPane() { - const pane = atom.workspace.paneForURI(ResultsPaneView.URI); - if (pane) { - return pane.itemForURI(ResultsPaneView.URI); - } - } - - function getResultsView() { - return getExistingResultsPane().refs.resultsView; - } - - function waitForSearchResults() { - return conditionPromise( - () => projectFindView.refs.descriptionLabel.textContent.includes('results found') - ) - } - - beforeEach(() => { - atom.config.set('find-and-replace.useRipgrep', ripgrep) - workspaceElement = atom.views.getView(atom.workspace); - atom.config.set('core.excludeVcsIgnoredPaths', false); - atom.project.setPaths([path.join(__dirname, 'fixtures')]); - jasmine.attachToDOM(workspaceElement); - - activationPromise = atom.packages.activatePackage("find-and-replace").then(function({mainModule}) { - mainModule.createViews(); - ({findView, projectFindView} = mainModule); - const spy = spyOn(projectFindView, 'search').andCallFake((options) => { - return searchPromise = spy.originalValue.call(projectFindView, options); - }); - }); - }); - - describe("when project-find:show is triggered", () => { - it("attaches ProjectFindView to the root view", async () => { - atom.commands.dispatch(workspaceElement, 'project-find:show'); - await activationPromise; - - projectFindView.findEditor.setText('items'); - expect(getAtomPanel()).toBeVisible(); - expect(projectFindView.findEditor.getSelectedBufferRange()).toEqual([[0, 0], [0, 5]]); - }); - - describe("with an open buffer", () => { - beforeEach(async () => { - atom.commands.dispatch(workspaceElement, 'project-find:show'); - await activationPromise; - projectFindView.findEditor.setText(''); - editor = await atom.workspace.open('project/sample.js'); - }); - - it("populates the findEditor with selection when there is a selection", () => { - editor.setSelectedBufferRange([[2, 8], [2, 13]]); - atom.commands.dispatch(workspaceElement, 'project-find:show'); - expect(getAtomPanel()).toBeVisible(); - expect(projectFindView.findEditor.getText()).toBe('items'); - - editor.setSelectedBufferRange([[2, 14], [2, 20]]); - atom.commands.dispatch(workspaceElement, 'project-find:show'); - expect(getAtomPanel()).toBeVisible(); - expect(projectFindView.findEditor.getText()).toBe('length'); - }); - - it("populates the findEditor with the previous selection when there is no selection", () => { - editor.setSelectedBufferRange([[2, 14], [2, 20]]); - atom.commands.dispatch(workspaceElement, 'project-find:show'); - expect(getAtomPanel()).toBeVisible(); - expect(projectFindView.findEditor.getText()).toBe('length'); - - editor.setSelectedBufferRange([[2, 30], [2, 30]]); - atom.commands.dispatch(workspaceElement, 'project-find:show'); - expect(getAtomPanel()).toBeVisible(); - expect(projectFindView.findEditor.getText()).toBe('length'); - }); - - it("places selected text into the find editor and escapes it when Regex is enabled", () => { - atom.commands.dispatch(projectFindView.element, 'project-find:toggle-regex-option'); - editor.setSelectedBufferRange([[6, 6], [6, 65]]); - atom.commands.dispatch(workspaceElement, 'project-find:show'); - expect(projectFindView.findEditor.getText()).toBe('current < pivot \\? left\\.push\\(current\\) : right\\.push\\(current\\);'); - }); - }); - - describe("when the ProjectFindView is already attached", () => { - beforeEach(async () => { - atom.commands.dispatch(workspaceElement, 'project-find:show'); - await activationPromise; - - projectFindView.findEditor.setText('items'); - projectFindView.findEditor.setSelectedBufferRange([[0, 0], [0, 0]]); - }); - - it("focuses the find editor and selects all the text", () => { - atom.commands.dispatch(workspaceElement, 'project-find:show'); - expect(projectFindView.findEditor.getElement()).toHaveFocus(); - expect(projectFindView.findEditor.getSelectedText()).toBe("items"); - }); - }); - - it("honors config settings for find options", async () => { - atom.config.set('find-and-replace.useRegex', true); - atom.config.set('find-and-replace.caseSensitive', true); - atom.config.set('find-and-replace.wholeWord', true); - - atom.commands.dispatch(workspaceElement, 'project-find:show'); - await activationPromise; - - expect(projectFindView.refs.caseOptionButton).toHaveClass('selected'); - expect(projectFindView.refs.regexOptionButton).toHaveClass('selected'); - expect(projectFindView.refs.wholeWordOptionButton).toHaveClass('selected'); - }); - }); - - describe("when project-find:show-in-current-directory is triggered with an open buffer", () => { - beforeEach(async () => { - atom.project.setPaths([__dirname]); - - atom.commands.dispatch(workspaceElement, 'project-find:show'); - await activationPromise; - - projectFindView.findEditor.setText(''); - projectFindView.pathsEditor.setText(''); - editor = await atom.workspace.open('fixtures/sample.js'); - }); - - it("calls project-find:show, and populates both findEditor and pathsEditor when there is a selection", () => { - editor.setSelectedBufferRange([[3, 8], [3, 13]]); - atom.commands.dispatch(workspaceElement, 'project-find:show-in-current-directory'); - expect(getAtomPanel()).toBeVisible(); - expect(projectFindView.findEditor.getText()).toBe('pivot'); - expect(projectFindView.pathsEditor.getText()).toBe('fixtures'); - - editor.setSelectedBufferRange([[2, 14], [2, 20]]); - atom.commands.dispatch(workspaceElement, 'project-find:show-in-current-directory'); - expect(getAtomPanel()).toBeVisible(); - expect(projectFindView.findEditor.getText()).toBe('length'); - expect(projectFindView.pathsEditor.getText()).toBe('fixtures'); - }); - - it("calls project-find:show, and populates only pathsEditor when there is no selection", () => { - atom.commands.dispatch(workspaceElement, 'project-find:show-in-current-directory'); - expect(getAtomPanel()).toBeVisible(); - expect(projectFindView.findEditor.getText()).toBe(''); - expect(projectFindView.pathsEditor.getText()).toBe('fixtures'); - }); - }); - - describe("when project-find:toggle is triggered", () => { - it("toggles the visibility of the ProjectFindView", async () => { - atom.commands.dispatch(workspaceElement, 'project-find:toggle'); - await activationPromise; - - expect(getAtomPanel()).toBeVisible(); - atom.commands.dispatch(workspaceElement, 'project-find:toggle'); - expect(getAtomPanel()).not.toBeVisible(); - }); - }); - - describe("when project-find:show-in-current-directory is triggered", () => { - let nested, tree, projectPath; - - beforeEach(() => { - projectPath = temp.mkdirSync("atom"); - atom.project.setPaths([projectPath]); - - tree = document.createElement('div'); - tree.className = 'directory'; - tree.innerHTML = dedent` -
- ${projectPath} -
    -
  • - one.js -
  • -
  • - two.js -
  • -
    -
    - nested -
      -
    • - three.js -
    • -
    -
    -
    -
-
- `; - - nested = tree.querySelector('.directory'); - - workspaceElement.appendChild(tree); - }); - - function escapePath(filePath) { - return filePath.replace(/\\/g, '\'); - } - - it("populates the pathsEditor when triggered with a directory", async () => { - atom.commands.dispatch(nested.querySelector('.name'), 'project-find:show-in-current-directory'); - await activationPromise; - - expect(getAtomPanel()).toBeVisible(); - expect(projectFindView.pathsEditor.getText()).toBe('nested'); - expect(projectFindView.findEditor.getElement()).toHaveFocus(); - - atom.commands.dispatch(tree.querySelector('.name'), 'project-find:show-in-current-directory'); - expect(projectFindView.pathsEditor.getText()).toBe(''); - }); - - it("populates the pathsEditor when triggered on a directory's name", async () => { - atom.commands.dispatch(nested, 'project-find:show-in-current-directory'); - await activationPromise; - - expect(getAtomPanel()).toBeVisible(); - expect(projectFindView.pathsEditor.getText()).toBe('nested'); - expect(projectFindView.findEditor.getElement()).toHaveFocus(); - - atom.commands.dispatch(tree.querySelector('.name'), 'project-find:show-in-current-directory'); - expect(projectFindView.pathsEditor.getText()).toBe(''); - }); - - it("populates the pathsEditor when triggered on a file", async () => { - atom.commands.dispatch(nested.querySelector('.file .name'), 'project-find:show-in-current-directory'); - await activationPromise; - - expect(getAtomPanel()).toBeVisible(); - expect(projectFindView.pathsEditor.getText()).toBe('nested'); - expect(projectFindView.findEditor.getElement()).toHaveFocus(); - - atom.commands.dispatch(tree.querySelector('.file .name'), 'project-find:show-in-current-directory'); - expect(projectFindView.pathsEditor.getText()).toBe(''); - }); - - describe("when there are multiple root directories", async () => { - beforeEach(() => { - atom.project.addPath(temp.mkdirSync("another-path-")) - }); - - it("includes the basename of the containing root directory in the paths-editor", async () => { - atom.commands.dispatch(nested.querySelector('.file .name'), 'project-find:show-in-current-directory'); - await activationPromise; - - expect(getAtomPanel()).toBeVisible(); - expect(projectFindView.pathsEditor.getText()).toBe(path.join(path.basename(projectPath), 'nested')); - }); - }); - }); - - describe("finding", () => { - beforeEach(async () => { - atom.project.setPaths([path.join(__dirname, 'fixtures/project')]); - editor = await atom.workspace.open('sample.js'); - editorElement = atom.views.getView(editor); - atom.commands.dispatch(workspaceElement, 'project-find:show'); - await activationPromise; - workspaceElement.style.height = '800px' - }); - - describe("when the find string contains an escaped char", () => { - beforeEach(() => { - jasmine.useRealClock() - - let projectPath = temp.mkdirSync("atom"); - fs.writeFileSync(path.join(projectPath, "tabs.txt"), "\t\n\\\t\n\\\\t"); - atom.project.setPaths([projectPath]); - atom.commands.dispatch(workspaceElement, 'project-find:show'); - }); - - describe("when regex search is enabled", () => { - it("finds a literal tab character", async () => { - atom.commands.dispatch(projectFindView.element, 'project-find:toggle-regex-option'); - projectFindView.findEditor.setText('\\t'); - - atom.commands.dispatch(projectFindView.element, 'core:confirm'); - await searchPromise; - - const resultsView = getResultsView(); - expect(resultsView.element).toBeVisible(); - expect(resultsView.refs.listView.element.querySelectorAll(".match-row")).toHaveLength(2); - }) - }); - - describe("when regex search is disabled", () => { - it("finds the escape char", async () => { - projectFindView.findEditor.setText('\\t'); - - atom.commands.dispatch(projectFindView.element, 'core:confirm'); - await searchPromise; - - const resultsView = getResultsView(); - expect(resultsView.element).toBeVisible(); - expect(resultsView.refs.listView.element.querySelectorAll(".match-row")).toHaveLength(1); - }); - - it("finds a backslash", async () => { - projectFindView.findEditor.setText('\\'); - - atom.commands.dispatch(projectFindView.element, 'core:confirm'); - await searchPromise; - - const resultsView = getResultsView(); - expect(resultsView.element).toBeVisible(); - expect(resultsView.refs.listView.element.querySelectorAll(".match-row")).toHaveLength(2); - expect(resultsView.refs.listView.element.querySelectorAll(".match.highlight-info")).toHaveLength(3); - }); - - it("doesn't insert a escaped char if there are multiple backslashs in front of the char", async () => { - projectFindView.findEditor.setText('\\\\t'); - - atom.commands.dispatch(projectFindView.element, 'core:confirm'); - await searchPromise; - - const resultsView = getResultsView(); - expect(resultsView.element).toBeVisible(); - expect(resultsView.refs.listView.element.querySelectorAll(".match-row")).toHaveLength(1); - }); - }); - }); - - describe("when core:cancel is triggered", () => { - it("detaches from the root view", () => { - atom.commands.dispatch(workspaceElement, 'project-find:show'); - projectFindView.element.focus(); - atom.commands.dispatch(document.activeElement, 'core:cancel'); - expect(getAtomPanel()).not.toBeVisible(); - }); - }); - - describe("when close option is true", () => { - beforeEach(() => { - atom.config.set('find-and-replace.closeFindPanelAfterSearch', true); - }) - - it("closes the panel after search", async () => { - projectFindView.findEditor.setText('something'); - atom.commands.dispatch(projectFindView.element, 'core:confirm'); - await searchPromise; - - expect(getAtomPanel()).not.toBeVisible(); - }); - - it("leaves the panel open after an empty search", async () => { - projectFindView.findEditor.setText(''); - atom.commands.dispatch(projectFindView.element, 'core:confirm'); - await searchPromise; - - expect(getAtomPanel()).toBeVisible(); - }); - - it("closes the panel after a no-op search", async () => { - projectFindView.findEditor.setText('something'); - atom.commands.dispatch(projectFindView.element, 'core:confirm'); - await searchPromise; - - atom.commands.dispatch(workspaceElement, 'project-find:show'); - await activationPromise; - - expect(getAtomPanel()).toBeVisible(); - - atom.commands.dispatch(projectFindView.element, 'core:confirm'); - await searchPromise; - - expect(getAtomPanel()).not.toBeVisible(); - }); - - it("does not close the panel after the replacement text is altered", async () => { - projectFindView.replaceEditor.setText('something else'); - - expect(getAtomPanel()).toBeVisible(); - }); - }); - - describe("splitting into a second pane", () => { - beforeEach(() => { - workspaceElement.style.height = '1000px'; - atom.commands.dispatch(editorElement, 'project-find:show'); - jasmine.useRealClock() - }); - - it("splits when option is right", async () => { - const initialPane = atom.workspace.getCenter().getActivePane(); - atom.config.set('find-and-replace.projectSearchResultsPaneSplitDirection', 'right'); - projectFindView.findEditor.setText('items'); - - atom.commands.dispatch(projectFindView.element, 'core:confirm'); - await searchPromise; - - expect(atom.workspace.getCenter().getActivePane()).not.toBe(initialPane); - }); - - it("splits when option is bottom", async () => { - const initialPane = atom.workspace.getCenter().getActivePane(); - atom.config.set('find-and-replace.projectSearchResultsPaneSplitDirection', 'down'); - projectFindView.findEditor.setText('items'); - - atom.commands.dispatch(projectFindView.element, 'core:confirm'); - await searchPromise; - - expect(atom.workspace.getCenter().getActivePane()).not.toBe(initialPane); - }); - - it("does not split when option is false", async () => { - const initialPane = atom.workspace.getCenter().getActivePane(); - projectFindView.findEditor.setText('items'); - - atom.commands.dispatch(projectFindView.element, 'core:confirm'); - await searchPromise; - - expect(atom.workspace.getCenter().getActivePane()).toBe(initialPane); - }); - - it("can be duplicated on the right", async () => { - atom.config.set('find-and-replace.projectSearchResultsPaneSplitDirection', 'right'); - projectFindView.findEditor.setText('items'); - - atom.commands.dispatch(projectFindView.element, 'core:confirm'); - await searchPromise; - - const resultsPaneView1 = atom.views.getView(getExistingResultsPane()); - const pane1 = atom.workspace.getCenter().getActivePane(); - const resultsView1 = pane1.getItems()[0].refs.resultsView - pane1.splitRight({copyActiveItem: true}); - - const pane2 = atom.workspace.getCenter().getActivePane(); - const resultsView2 = pane2.getItems()[0].refs.resultsView - const resultsPaneView2 = atom.views.getView(pane2.itemForURI(ResultsPaneView.URI)); - expect(pane1).not.toBe(pane2); - expect(resultsPaneView1).not.toBe(resultsPaneView2); - simulateResizeEvent(resultsView2.element); - - await etch.update(resultsView1); - await etch.update(resultsView2); - await waitForSearchResults(); - - const resultCount = resultsPaneView1.querySelectorAll('.match-row').length; - expect(resultCount).toBeGreaterThan(0); - expect(resultsPaneView2.querySelectorAll('.match-row')).toHaveLength(resultCount); - expect(resultsPaneView2.querySelector('.preview-count').innerHTML).toEqual(resultsPaneView1.querySelector('.preview-count').innerHTML); - }); - - it("can be duplicated at the bottom", async () => { - atom.config.set('find-and-replace.projectSearchResultsPaneSplitDirection', 'down'); - projectFindView.findEditor.setText('items'); - - atom.commands.dispatch(projectFindView.element, 'core:confirm'); - await searchPromise; - - const resultsPaneView1 = atom.views.getView(getExistingResultsPane()); - const pane1 = atom.workspace.getCenter().getActivePane(); - const resultsView1 = pane1.getItems()[0].refs.resultsView - - pane1.splitDown({copyActiveItem: true}); - const pane2 = atom.workspace.getCenter().getActivePane(); - const resultsView2 = pane2.getItems()[0].refs.resultsView - const resultsPaneView2 = atom.views.getView(pane2.itemForURI(ResultsPaneView.URI)); - expect(pane1).not.toBe(pane2); - expect(resultsPaneView1).not.toBe(resultsPaneView2); - - await etch.update(resultsView1); - await etch.update(resultsView2); - - expect(resultsPaneView2.querySelector('.preview-count').innerHTML).toEqual(resultsPaneView1.querySelector('.preview-count').innerHTML); - }); - }); - - describe("serialization", () => { - it("serializes if the case, regex and whole word options", async () => { - atom.commands.dispatch(editorElement, 'project-find:show'); - expect(projectFindView.refs.caseOptionButton).not.toHaveClass('selected'); - projectFindView.refs.caseOptionButton.click(); - expect(projectFindView.refs.caseOptionButton).toHaveClass('selected'); - - expect(projectFindView.refs.regexOptionButton).not.toHaveClass('selected'); - projectFindView.refs.regexOptionButton.click(); - expect(projectFindView.refs.regexOptionButton).toHaveClass('selected'); - - expect(projectFindView.refs.wholeWordOptionButton).not.toHaveClass('selected'); - projectFindView.refs.wholeWordOptionButton.click(); - expect(projectFindView.refs.wholeWordOptionButton).toHaveClass('selected'); - - await atom.packages.deactivatePackage("find-and-replace"); - - activationPromise = atom.packages.activatePackage("find-and-replace").then(function({mainModule}) { - mainModule.createViews(); - return {projectFindView} = mainModule; - }); - - atom.commands.dispatch(editorElement, 'project-find:show'); - await activationPromise; - - expect(projectFindView.refs.caseOptionButton).toHaveClass('selected'); - expect(projectFindView.refs.regexOptionButton).toHaveClass('selected'); - expect(projectFindView.refs.wholeWordOptionButton).toHaveClass('selected'); - }) - }); - - describe("description label", () => { - beforeEach(() => { - atom.commands.dispatch(editorElement, 'project-find:show'); - }); - - it("indicates that it's searching, then shows the results", async () => { - projectFindView.findEditor.setText('item'); - atom.commands.dispatch(projectFindView.element, 'core:confirm'); - - await projectFindView.showResultPane(); - - expect(projectFindView.refs.descriptionLabel.textContent).toContain('Searching...'); - - await searchPromise; - - expect(projectFindView.refs.descriptionLabel.textContent).toContain('13 results found in 2 files'); - atom.commands.dispatch(projectFindView.element, 'core:confirm'); - expect(projectFindView.refs.descriptionLabel.textContent).toContain('13 results found in 2 files'); - }); - - it("shows an error when the pattern is invalid and clears when no error", async () => { - spyOn(atom.workspace, 'scan').andReturn(Promise.resolve()); - atom.commands.dispatch(projectFindView.element, 'project-find:toggle-regex-option'); - projectFindView.findEditor.setText('['); - atom.commands.dispatch(projectFindView.element, 'core:confirm'); - - await searchPromise; - - expect(projectFindView.refs.descriptionLabel).toHaveClass('text-error'); - expect(projectFindView.refs.descriptionLabel.textContent).toContain('Invalid regular expression'); - - projectFindView.findEditor.setText(''); - atom.commands.dispatch(projectFindView.element, 'core:confirm'); - - expect(projectFindView.refs.descriptionLabel).not.toHaveClass('text-error'); - expect(projectFindView.refs.descriptionLabel.textContent).toContain('Find in Project'); - - projectFindView.findEditor.setText('items'); - atom.commands.dispatch(projectFindView.element, 'core:confirm'); - - await searchPromise; - - expect(projectFindView.refs.descriptionLabel).not.toHaveClass('text-error'); - expect(projectFindView.refs.descriptionLabel.textContent).toContain('items'); - }); - }); - - describe("regex", () => { - beforeEach(() => { - atom.commands.dispatch(editorElement, 'project-find:show'); - projectFindView.findEditor.setText('i(\\w)ems+'); - spyOn(atom.workspace, 'scan').andCallFake(async () => {}); - }); - - it("escapes regex patterns by default", async () => { - atom.commands.dispatch(projectFindView.element, 'core:confirm'); - await searchPromise; - - expect(atom.workspace.scan.argsForCall[0][0]).toEqual(/i\(\\w\)ems\+/gim); - }); - - it("shows an error when the regex pattern is invalid", async () => { - atom.commands.dispatch(projectFindView.element, 'project-find:toggle-regex-option'); - projectFindView.findEditor.setText('['); - - atom.commands.dispatch(projectFindView.element, 'core:confirm'); - await searchPromise; - - expect(projectFindView.refs.descriptionLabel).toHaveClass('text-error'); - }); - - describe("when search has not been run yet", () => { - it("toggles regex option via an event but does not run the search", () => { - expect(projectFindView.refs.regexOptionButton).not.toHaveClass('selected'); - atom.commands.dispatch(projectFindView.element, 'project-find:toggle-regex-option'); - expect(projectFindView.refs.regexOptionButton).toHaveClass('selected'); - expect(atom.workspace.scan).not.toHaveBeenCalled(); - }) - }); - - describe("when search has been run", () => { - beforeEach(async () => { - atom.commands.dispatch(projectFindView.element, 'core:confirm'); - await searchPromise; - }); - - it("toggles regex option via an event and finds files matching the pattern", async () => { - expect(projectFindView.refs.regexOptionButton).not.toHaveClass('selected'); - atom.commands.dispatch(projectFindView.element, 'project-find:toggle-regex-option'); - - await searchPromise; - - expect(projectFindView.refs.regexOptionButton).toHaveClass('selected'); - expect(atom.workspace.scan.mostRecentCall.args[0]).toEqual(/i(\w)ems+/gim); - }); - - it("toggles regex option via a button and finds files matching the pattern", async () => { - expect(projectFindView.refs.regexOptionButton).not.toHaveClass('selected'); - projectFindView.refs.regexOptionButton.click(); - - await searchPromise; - - expect(projectFindView.refs.regexOptionButton).toHaveClass('selected'); - expect(atom.workspace.scan.mostRecentCall.args[0]).toEqual(/i(\w)ems+/gim); - }); - }); - }); - - describe("case sensitivity", () => { - beforeEach(async () => { - atom.commands.dispatch(editorElement, 'project-find:show'); - spyOn(atom.workspace, 'scan').andCallFake(() => Promise.resolve()); - projectFindView.findEditor.setText('ITEMS'); - - atom.commands.dispatch(projectFindView.element, 'core:confirm'); - await searchPromise; - }); - - it("runs a case insensitive search by default", () => expect(atom.workspace.scan.argsForCall[0][0]).toEqual(/ITEMS/gim)); - - it("toggles case sensitive option via an event and finds files matching the pattern", async () => { - expect(projectFindView.refs.caseOptionButton).not.toHaveClass('selected'); - - atom.commands.dispatch(projectFindView.element, 'project-find:toggle-case-option'); - await searchPromise; - - expect(projectFindView.refs.caseOptionButton).toHaveClass('selected'); - expect(atom.workspace.scan.mostRecentCall.args[0]).toEqual(/ITEMS/gm); - }); - - it("toggles case sensitive option via a button and finds files matching the pattern", async () => { - expect(projectFindView.refs.caseOptionButton).not.toHaveClass('selected'); - - projectFindView.refs.caseOptionButton.click(); - await searchPromise; - - expect(projectFindView.refs.caseOptionButton).toHaveClass('selected'); - expect(atom.workspace.scan.mostRecentCall.args[0]).toEqual(/ITEMS/gm); - }); - }); - - describe("whole word", () => { - beforeEach(async () => { - atom.commands.dispatch(editorElement, 'project-find:show'); - spyOn(atom.workspace, 'scan').andCallFake(async () => {}); - projectFindView.findEditor.setText('wholeword'); - - atom.commands.dispatch(projectFindView.element, 'core:confirm'); - await searchPromise; - }); - - it("does not run whole word search by default", () => { - expect(atom.workspace.scan.argsForCall[0][0]).toEqual(/wholeword/gim) - }); - - it("toggles whole word option via an event and finds files matching the pattern", async () => { - expect(projectFindView.refs.wholeWordOptionButton).not.toHaveClass('selected'); - atom.commands.dispatch(projectFindView.element, 'project-find:toggle-whole-word-option'); - - await searchPromise; - expect(projectFindView.refs.wholeWordOptionButton).toHaveClass('selected'); - expect(atom.workspace.scan.mostRecentCall.args[0]).toEqual(/\bwholeword\b/gim); - }); - - it("toggles whole word option via a button and finds files matching the pattern", async () => { - expect(projectFindView.refs.wholeWordOptionButton).not.toHaveClass('selected'); - - projectFindView.refs.wholeWordOptionButton.click(); - await searchPromise; - - expect(projectFindView.refs.wholeWordOptionButton).toHaveClass('selected'); - expect(atom.workspace.scan.mostRecentCall.args[0]).toEqual(/\bwholeword\b/gim); - }); - }); - - describe("when project-find:confirm is triggered", () => { - beforeEach(() => { - jasmine.useRealClock() - }); - - it("displays the results and no errors", async () => { - projectFindView.findEditor.setText('items'); - atom.commands.dispatch(projectFindView.element, 'project-find:confirm'); - - await searchPromise; - await waitForSearchResults(); - - const resultsView = getResultsView(); - expect(resultsView.element).toBeVisible(); - expect(resultsView.refs.listView.element.querySelectorAll(".match-row")).toHaveLength(11); - expect(resultsView.refs.listView.element.querySelectorAll(".match.highlight-info")).toHaveLength(13); - }) - }); - - describe("when core:confirm is triggered", () => { - beforeEach(() => { - atom.commands.dispatch(workspaceElement, 'project-find:show') - jasmine.useRealClock() - }); - - describe("when the there search field is empty", () => { - it("does not run the search but clears the model", () => { - spyOn(atom.workspace, 'scan'); - spyOn(projectFindView.model, 'clear'); - atom.commands.dispatch(projectFindView.element, 'core:confirm'); - expect(atom.workspace.scan).not.toHaveBeenCalled(); - expect(projectFindView.model.clear).toHaveBeenCalled(); - }) - }); - - it("reruns the search when confirmed again after focusing the window", async () => { - projectFindView.findEditor.setText('thisdoesnotmatch'); - atom.commands.dispatch(projectFindView.element, 'core:confirm'); - - await searchPromise; - - spyOn(atom.workspace, 'scan'); - atom.commands.dispatch(projectFindView.element, 'core:confirm'); - - await searchPromise; - - expect(atom.workspace.scan).not.toHaveBeenCalled(); - atom.workspace.scan.reset(); - window.dispatchEvent(new FocusEvent("focus")); - atom.commands.dispatch(projectFindView.element, 'core:confirm'); - - await searchPromise; - - expect(atom.workspace.scan).toHaveBeenCalled(); - atom.workspace.scan.reset(); - atom.commands.dispatch(projectFindView.element, 'core:confirm'); - - await searchPromise; - - expect(atom.workspace.scan).not.toHaveBeenCalled(); - }); - - describe("when results exist", () => { - beforeEach(() => { - projectFindView.findEditor.setText('items') - }); - - it("displays the results and no errors", async () => { - atom.commands.dispatch(projectFindView.element, 'core:confirm'); - await searchPromise; - - const resultsView = getResultsView(); - const resultsPaneView = getExistingResultsPane(); - - expect(resultsView.element).toBeVisible(); - expect(resultsView.refs.listView.element.querySelectorAll(".match-row")).toHaveLength(11); - expect(resultsView.refs.listView.element.querySelectorAll(".match.highlight-info")).toHaveLength(13); - - expect(resultsPaneView.refs.previewCount.textContent).toBe("13 results found in 2 files for items"); - expect(projectFindView.errorMessages).not.toBeVisible(); - }); - - it("only searches paths matching text in the path filter", async () => { - spyOn(atom.workspace, 'scan').andCallFake(async () => {}); - projectFindView.pathsEditor.setText('*.js'); - - atom.commands.dispatch(projectFindView.element, 'core:confirm'); - await searchPromise; - - expect(atom.workspace.scan.argsForCall[0][1].paths).toEqual(['*.js']); - }); - - it("updates the results list when a buffer changes", async () => { - const editor = await atom.workspace.open('sample.js') - - atom.commands.dispatch(projectFindView.element, 'core:confirm'); - await searchPromise; - - const resultsView = getResultsView(); - const listView = resultsView.refs.listView; - const resultsPaneView = getExistingResultsPane(); - - expect(listView.element.querySelectorAll(".match-row")).toHaveLength(11); - expect(listView.element.querySelectorAll(".match.highlight-info")).toHaveLength(13); - expect(resultsPaneView.refs.previewCount.textContent).toBe("13 results found in 2 files for items"); - - resultsView.selectFirstResult(); - for (let i = 0; i < 6; i++) resultsView.moveDown(); - await resultsView.moveDown(); - - expect(listView.element.querySelectorAll(".path-row")[1].parentElement).toHaveClass('selected'); - - editor.setText('there is one "items" in this file'); - await etch.getScheduler().getNextUpdatePromise() - await searchPromise; - - await conditionPromise( - () => resultsPaneView.refs.previewCount.textContent === "8 results found in 2 files for items" - ) - - expect(listView.element.querySelectorAll(".path-row")[1].parentElement).toHaveClass('selected'); - - // Ensure the newly added item can be opened. - await resultsView.moveDown() - atom.commands.dispatch(resultsView.element, 'core:confirm'); - await waitForSearchResults(); - await conditionPromise( - () => editor.getSelectedText() === "items" - ) - - editor.setText('no matches in this file'); - await waitForSearchResults(); - - await conditionPromise( - () => resultsPaneView.refs.previewCount.textContent === "7 results found in 1 file for items" - ) - }); - - it("doesn't update the results list when a buffer outside the project changes", async () => { - const editor = await atom.workspace.open('../sample.js') - - atom.commands.dispatch(projectFindView.element, 'core:confirm'); - await searchPromise; - - const resultsView = getResultsView(); - const resultsPaneView = getExistingResultsPane(); - - expect(resultsView.refs.listView.element.querySelectorAll(".list-item")).toHaveLength(13); - expect(resultsPaneView.refs.previewCount.textContent).toBe("13 results found in 2 files for items"); - - resultsView.selectFirstResult(); - for (let i = 0; i < 7; i++) await resultsView.moveDown() - expect(resultsView.refs.listView.element.querySelectorAll(".list-nested-item")[1]).toHaveClass('selected'); - - editor.setText('there is one "items" in this file'); - advanceClock(editor.getBuffer().stoppedChangingDelay); - await etch.getScheduler().getNextUpdatePromise() - expect(resultsPaneView.refs.previewCount.textContent).toBe("13 results found in 2 files for items"); - expect(resultsView.refs.listView.element.querySelectorAll(".list-nested-item")[1]).toHaveClass('selected'); - }); - }); - - describe("when no results exist", () => { - beforeEach(() => { - projectFindView.findEditor.setText('notintheprojectbro'); - spyOn(atom.workspace, 'scan').andCallFake(async () => {}); - }); - - it("displays no errors and no results", async () => { - atom.commands.dispatch(projectFindView.element, 'core:confirm'); - await searchPromise; - - const resultsView = getResultsView(); - expect(projectFindView.refs.errorMessages).not.toBeVisible(); - expect(resultsView.element).toBeVisible(); - expect(resultsView.refs.listView.element.querySelectorAll(".match-row")).toHaveLength(0); - }); - }); - }); - - describe("history", () => { - beforeEach(() => { - atom.commands.dispatch(workspaceElement, 'project-find:show'); - spyOn(atom.workspace, 'scan').andCallFake(() => { - let promise = Promise.resolve(); - promise.cancel = () => {}; - return promise; - }); - - projectFindView.findEditor.setText('sort'); - projectFindView.replaceEditor.setText('bort'); - projectFindView.pathsEditor.setText('abc'); - atom.commands.dispatch(projectFindView.findEditor.getElement(), 'core:confirm'); - - projectFindView.findEditor.setText('items'); - projectFindView.replaceEditor.setText('eyetims'); - projectFindView.pathsEditor.setText('def'); - atom.commands.dispatch(projectFindView.findEditor.getElement(), 'core:confirm'); - }); - - it("can navigate the entire history stack", () => { - expect(projectFindView.findEditor.getText()).toEqual('items'); - - atom.commands.dispatch(projectFindView.findEditor.getElement(), 'core:move-up'); - expect(projectFindView.findEditor.getText()).toEqual('sort'); - - atom.commands.dispatch(projectFindView.findEditor.getElement(), 'core:move-down'); - expect(projectFindView.findEditor.getText()).toEqual('items'); - - atom.commands.dispatch(projectFindView.findEditor.getElement(), 'core:move-down'); - expect(projectFindView.findEditor.getText()).toEqual(''); - - expect(projectFindView.pathsEditor.getText()).toEqual('def'); - - atom.commands.dispatch(projectFindView.pathsEditor.element, 'core:move-up'); - expect(projectFindView.pathsEditor.getText()).toEqual('abc'); - - atom.commands.dispatch(projectFindView.pathsEditor.element, 'core:move-down'); - expect(projectFindView.pathsEditor.getText()).toEqual('def'); - - atom.commands.dispatch(projectFindView.pathsEditor.element, 'core:move-down'); - expect(projectFindView.pathsEditor.getText()).toEqual(''); - - expect(projectFindView.replaceEditor.getText()).toEqual('eyetims'); - - atom.commands.dispatch(projectFindView.replaceEditor.element, 'core:move-up'); - expect(projectFindView.replaceEditor.getText()).toEqual('bort'); - - atom.commands.dispatch(projectFindView.replaceEditor.element, 'core:move-down'); - expect(projectFindView.replaceEditor.getText()).toEqual('eyetims'); - - atom.commands.dispatch(projectFindView.replaceEditor.element, 'core:move-down'); - expect(projectFindView.replaceEditor.getText()).toEqual(''); - }); - }); - - describe("when find-and-replace:use-selection-as-find-pattern is triggered", () => { - it("places the selected text into the find editor", () => { - editor.setSelectedBufferRange([[1, 6], [1, 10]]); - atom.commands.dispatch(workspaceElement, 'find-and-replace:use-selection-as-find-pattern'); - expect(projectFindView.findEditor.getText()).toBe('sort'); - - editor.setSelectedBufferRange([[1, 13], [1, 21]]); - atom.commands.dispatch(workspaceElement, 'find-and-replace:use-selection-as-find-pattern'); - expect(projectFindView.findEditor.getText()).toBe('function'); - }); - - it("places the word under the cursor into the find editor", () => { - editor.setSelectedBufferRange([[1, 8], [1, 8]]); - atom.commands.dispatch(workspaceElement, 'find-and-replace:use-selection-as-find-pattern'); - expect(projectFindView.findEditor.getText()).toBe('sort'); - - editor.setSelectedBufferRange([[1, 15], [1, 15]]); - atom.commands.dispatch(workspaceElement, 'find-and-replace:use-selection-as-find-pattern'); - expect(projectFindView.findEditor.getText()).toBe('function'); - }); - - it("places the previously selected text into the find editor if no selection and no word under cursor", () => { - editor.setSelectedBufferRange([[1, 13], [1, 21]]); - atom.commands.dispatch(workspaceElement, 'find-and-replace:use-selection-as-find-pattern'); - expect(projectFindView.findEditor.getText()).toBe('function'); - - editor.setSelectedBufferRange([[1, 1], [1, 1]]); - atom.commands.dispatch(workspaceElement, 'find-and-replace:use-selection-as-find-pattern'); - expect(projectFindView.findEditor.getText()).toBe('function'); - }); - - it("places selected text into the find editor and escapes it when Regex is enabled", () => { - atom.commands.dispatch(projectFindView.element, 'project-find:toggle-regex-option'); - editor.setSelectedBufferRange([[6, 6], [6, 65]]); - atom.commands.dispatch(workspaceElement, 'find-and-replace:use-selection-as-find-pattern'); - expect(projectFindView.findEditor.getText()).toBe('current < pivot \\? left\\.push\\(current\\) : right\\.push\\(current\\);'); - }); - }); - - describe("when find-and-replace:use-selection-as-replace-pattern is triggered", () => { - it("places the selected text into the replace editor", () => { - editor.setSelectedBufferRange([[1, 6], [1, 10]]); - atom.commands.dispatch(workspaceElement, 'find-and-replace:use-selection-as-replace-pattern'); - expect(projectFindView.replaceEditor.getText()).toBe('sort'); - - editor.setSelectedBufferRange([[1, 13], [1, 21]]); - atom.commands.dispatch(workspaceElement, 'find-and-replace:use-selection-as-replace-pattern'); - expect(projectFindView.replaceEditor.getText()).toBe('function'); - }); - - it("places the word under the cursor into the replace editor", () => { - editor.setSelectedBufferRange([[1, 8], [1, 8]]); - atom.commands.dispatch(workspaceElement, 'find-and-replace:use-selection-as-replace-pattern'); - expect(projectFindView.replaceEditor.getText()).toBe('sort'); - - editor.setSelectedBufferRange([[1, 15], [1, 15]]); - atom.commands.dispatch(workspaceElement, 'find-and-replace:use-selection-as-replace-pattern'); - expect(projectFindView.replaceEditor.getText()).toBe('function'); - }); - - it("places the previously selected text into the replace editor if no selection and no word under cursor", () => { - editor.setSelectedBufferRange([[1, 13], [1, 21]]); - atom.commands.dispatch(workspaceElement, 'find-and-replace:use-selection-as-replace-pattern'); - expect(projectFindView.replaceEditor.getText()).toBe('function'); - - editor.setSelectedBufferRange([[1, 1], [1, 1]]); - atom.commands.dispatch(workspaceElement, 'find-and-replace:use-selection-as-replace-pattern'); - expect(projectFindView.replaceEditor.getText()).toBe('function'); - }); - - it("places selected text into the replace editor and escapes it when Regex is enabled", () => { - atom.commands.dispatch(projectFindView.element, 'project-find:toggle-regex-option') - editor.setSelectedBufferRange([[6, 6], [6, 65]]); - atom.commands.dispatch(workspaceElement, 'find-and-replace:use-selection-as-replace-pattern'); - expect(projectFindView.replaceEditor.getText()).toBe('current < pivot \\? left\\.push\\(current\\) : right\\.push\\(current\\);'); - }); - }); - - describe("when there is an error searching", () => { - it("displays the errors in the results pane", async () => { - projectFindView.findEditor.setText('items'); - - let errorList; - spyOn(atom.workspace, 'scan').andCallFake(async (regex, options, callback) => { - const resultsPaneView = getExistingResultsPane(); - ({errorList} = resultsPaneView.refs); - expect(errorList.querySelectorAll("li")).toHaveLength(0); - - callback(null, {path: '/some/path.js', code: 'ENOENT', message: 'Nope'}); - await etch.update(resultsPaneView); - expect(errorList).toBeVisible(); - expect(errorList.querySelectorAll("li")).toHaveLength(1); - - callback(null, {path: '/some/path.js', code: 'ENOENT', message: 'Broken'}); - await etch.update(resultsPaneView); - expect(errorList.querySelectorAll("li")).toHaveLength(2); - }); - - atom.commands.dispatch(projectFindView.element, 'core:confirm'); - - await searchPromise; - - expect(errorList).toBeVisible(); - expect(errorList.querySelectorAll("li")).toHaveLength(2); - expect(errorList.querySelectorAll("li")[0].textContent).toBe('Nope'); - expect(errorList.querySelectorAll("li")[1].textContent).toBe('Broken'); - }) - }); - - describe("buffer search sharing of the find options", () => { - function getResultDecorations(clazz) { - const result = []; - const decorations = editor.decorationsStateForScreenRowRange(0, editor.getLineCount()); - for (let id in decorations) { - const decoration = decorations[id]; - if (decoration.properties.class === clazz) { - result.push(decoration); - } - } - return result; - } - - it("setting the find text does not interfere with the project replace state", async () => { - // Not sure why I need to advance the clock before setting the text. If - // this advanceClock doesnt happen, the text will be ''. wtf. - advanceClock(projectFindView.findEditor.getBuffer().stoppedChangingDelay + 1); - spyOn(atom.workspace, 'scan'); - - projectFindView.findEditor.setText('findme'); - advanceClock(projectFindView.findEditor.getBuffer().stoppedChangingDelay + 1); - - await projectFindView.search({onlyRunIfActive: false, onlyRunIfChanged: true}); - expect(atom.workspace.scan).toHaveBeenCalled(); - }); - - it("shares the buffers and history cyclers between both buffer and project views", () => { - projectFindView.findEditor.setText('findme'); - projectFindView.replaceEditor.setText('replaceme'); - - atom.commands.dispatch(editorElement, 'find-and-replace:show'); - expect(findView.findEditor.getText()).toBe('findme'); - expect(findView.replaceEditor.getText()).toBe('replaceme'); - - // add some things to the history - atom.commands.dispatch(findView.findEditor.element, 'core:confirm'); - findView.findEditor.setText('findme1'); - atom.commands.dispatch(findView.findEditor.element, 'core:confirm'); - findView.findEditor.setText(''); - - atom.commands.dispatch(findView.replaceEditor.element, 'core:confirm'); - findView.replaceEditor.setText('replaceme1'); - atom.commands.dispatch(findView.replaceEditor.element, 'core:confirm'); - findView.replaceEditor.setText(''); - - // Back to the project view to make sure we're using the same cycler - atom.commands.dispatch(editorElement, 'project-find:show'); - - expect(projectFindView.findEditor.getText()).toBe(''); - atom.commands.dispatch(projectFindView.findEditor.element, 'core:move-up'); - expect(projectFindView.findEditor.getText()).toBe('findme1'); - atom.commands.dispatch(projectFindView.findEditor.element, 'core:move-up'); - expect(projectFindView.findEditor.getText()).toBe('findme'); - - expect(projectFindView.replaceEditor.getText()).toBe(''); - atom.commands.dispatch(projectFindView.replaceEditor.element, 'core:move-up'); - expect(projectFindView.replaceEditor.getText()).toBe('replaceme1'); - atom.commands.dispatch(projectFindView.replaceEditor.element, 'core:move-up'); - expect(projectFindView.replaceEditor.getText()).toBe('replaceme'); - }); - - it('highlights the search results in the selected file', async () => { - jasmine.useRealClock(); - // Process here is to - // * open samplejs - // * run a search that has sample js results - // * that should place the pattern in the buffer find - // * focus project/sample.js by clicking on a project/sample.js result - // * when the file has been activated, it's results for the project search should be highlighted - - editor = await atom.workspace.open('sample.js'); - expect(getResultDecorations('find-result')).toHaveLength(0); - - projectFindView.findEditor.setText('item'); - atom.commands.dispatch(projectFindView.element, 'core:confirm'); - await searchPromise; - await waitForSearchResults(); - - const resultsView = getResultsView(); - resultsView.scrollToBottom(); // To load ALL the results - await etch.update(resultsView); - expect(resultsView.element).toBeVisible(); - expect(resultsView.refs.listView.element.querySelectorAll(".match-row")).toHaveLength(11); - expect(resultsView.refs.listView.element.querySelectorAll(".match.highlight-info")).toHaveLength(13); - - resultsView.selectFirstResult(); - for (let i = 0; i < 9; i++) resultsView.moveDown(); - await resultsView.moveDown(); - - atom.commands.dispatch(resultsView.element, 'core:confirm'); - await new Promise(resolve => editor.onDidChangeSelectionRange(resolve)) - - // project/sample.js has 6 results - expect(getResultDecorations('find-result')).toHaveLength(5); - expect(getResultDecorations('current-result')).toHaveLength(1); - expect(workspaceElement).toHaveClass('find-visible'); - - const initialSelectedRange = editor.getSelectedBufferRange(); - - // now we can find next - atom.commands.dispatch(atom.views.getView(editor), 'find-and-replace:find-next'); - expect(editor.getSelectedBufferRange()).not.toEqual(initialSelectedRange); - - // Now we toggle the whole-word option to make sure it is updated in the buffer find - atom.commands.dispatch(projectFindView.element, 'project-find:toggle-whole-word-option'); - await searchPromise; - - // project/sample.js has 0 results for whole word `item` - expect(getResultDecorations('find-result')).toHaveLength(0); - expect(workspaceElement).toHaveClass('find-visible'); - - // Now we toggle the whole-word option to make sure it is updated in the buffer find - atom.commands.dispatch(projectFindView.element, 'project-find:toggle-whole-word-option'); - }); - }); - - describe("when user asked not to override last search results", () => { - beforeEach(async () => { - atom.commands.dispatch(editorElement, 'project-find:show'); - projectFindView.findEditor.setText('items'); - atom.commands.dispatch(projectFindView.element, 'core:confirm'); - await searchPromise; - - }); - it("opens new search results in new panel", async () => { - const result_pane = getExistingResultsPane(); - result_pane.dontOverrideTab(); - projectFindView.findEditor.setText('items2'); - atom.commands.dispatch(projectFindView.element, 'core:confirm'); - await searchPromise; - expect(result_pane).not.toBe(getExistingResultsPane()); - }); - }); - }); - - describe("replacing", () => { - let testDir, sampleJs, sampleCoffee, replacePromise; - - beforeEach(async () => { - testDir = temp.mkdirSync('atom-find-and-replace'); - sampleJs = path.join(testDir, 'project/sample.js'); - sampleCoffee = path.join(testDir, 'sample.coffee'); - - fs.makeTreeSync(testDir); - fs.writeFileSync(sampleCoffee, fs.readFileSync(require.resolve('./fixtures/sample.coffee'))); - fs.writeFileSync(sampleJs, fs.readFileSync(require.resolve('./fixtures/project/sample.js'))); - - atom.commands.dispatch(workspaceElement, 'project-find:show'); - await activationPromise; - - atom.project.setPaths([testDir]); - const spy = spyOn(projectFindView, 'replaceAll').andCallFake(() => { - replacePromise = spy.originalValue.call(projectFindView); - }); - }); - - describe("when the replace string contains an escaped char", () => { - let filePath = null; - - beforeEach(() => { - let projectPath = temp.mkdirSync("atom"); - filePath = path.join(projectPath, "tabs.txt"); - fs.writeFileSync(filePath, "a\nb\na"); - atom.project.setPaths([projectPath]); - atom.commands.dispatch(workspaceElement, 'project-find:show'); - - spyOn(atom, 'confirm').andReturn({response:0}); - }); - - describe("when the regex option is chosen", () => { - beforeEach(async () => { - atom.commands.dispatch(projectFindView.element, 'project-find:toggle-regex-option'); - projectFindView.findEditor.setText('a'); - atom.commands.dispatch(projectFindView.element, 'project-find:confirm'); - await searchPromise; - }); - - it("finds the escape char", async () => { - projectFindView.replaceEditor.setText('\\t'); - - atom.commands.dispatch(projectFindView.element, 'project-find:replace-all'); - await replacePromise; - - expect(fs.readFileSync(filePath, 'utf8')).toBe("\t\nb\n\t"); - }); - - it("doesn't insert a escaped char if there are multiple backslashs in front of the char", async () => { - projectFindView.replaceEditor.setText('\\\\t'); - - atom.commands.dispatch(projectFindView.element, 'project-find:replace-all'); - await replacePromise; - - expect(fs.readFileSync(filePath, 'utf8')).toBe("\\t\nb\n\\t"); - }); - }); - - describe("when regex option is not set", () => { - beforeEach(async () => { - projectFindView.findEditor.setText('a'); - atom.commands.dispatch(projectFindView.element, 'project-find:confirm'); - await searchPromise; - }); - - it("finds the escape char", async () => { - projectFindView.replaceEditor.setText('\\t'); - - atom.commands.dispatch(projectFindView.element, 'project-find:replace-all'); - await replacePromise; - - expect(fs.readFileSync(filePath, 'utf8')).toBe("\\t\nb\n\\t"); - }); - }); - }); - - describe("replace all button enablement", () => { - let disposable = null; - - it("is disabled initially", () => { - expect(projectFindView.refs.replaceAllButton).toHaveClass('disabled') - }); - - it("is disabled when a search returns no results", async () => { - projectFindView.findEditor.setText('items'); - atom.commands.dispatch(projectFindView.element, 'project-find:confirm'); - await searchPromise; - - expect(projectFindView.refs.replaceAllButton).not.toHaveClass('disabled'); - - projectFindView.findEditor.setText('nopenotinthefile'); - atom.commands.dispatch(projectFindView.element, 'project-find:confirm'); - await searchPromise; - - expect(projectFindView.refs.replaceAllButton).toHaveClass('disabled'); - }); - - it("is enabled when a search has results and disabled when there are no results", async () => { - projectFindView.findEditor.setText('items'); - atom.commands.dispatch(projectFindView.element, 'project-find:confirm'); - - await searchPromise; - - disposable = projectFindView.replaceTooltipSubscriptions; - spyOn(disposable, 'dispose'); - - expect(projectFindView.refs.replaceAllButton).not.toHaveClass('disabled'); - - // The replace all button should still be disabled as the text has been changed and a new search has not been run - projectFindView.findEditor.setText('itemss'); - advanceClock(stoppedChangingDelay); - expect(projectFindView.refs.replaceAllButton).toHaveClass('disabled'); - expect(disposable.dispose).toHaveBeenCalled(); - - // The button should still be disabled because the search and search pattern are out of sync - projectFindView.replaceEditor.setText('omgomg'); - advanceClock(stoppedChangingDelay); - expect(projectFindView.refs.replaceAllButton).toHaveClass('disabled'); - - disposable = projectFindView.replaceTooltipSubscriptions; - spyOn(disposable, 'dispose'); - projectFindView.findEditor.setText('items'); - advanceClock(stoppedChangingDelay); - expect(projectFindView.refs.replaceAllButton).not.toHaveClass('disabled'); - - projectFindView.findEditor.setText(''); - atom.commands.dispatch(projectFindView.element, 'project-find:confirm'); - - expect(projectFindView.refs.replaceAllButton).toHaveClass('disabled'); - }); - }); - - describe("when the replace button is pressed", () => { - beforeEach(() => { - spyOn(atom, 'confirm').andReturn({ response: 0 }); - }); - - it("runs the search, and replaces all the matches", async () => { - projectFindView.findEditor.setText('items'); - atom.commands.dispatch(projectFindView.element, 'core:confirm'); - await searchPromise; - - projectFindView.replaceEditor.setText('sunshine'); - projectFindView.refs.replaceAllButton.click(); - await replacePromise; - - expect(projectFindView.errorMessages).not.toBeVisible(); - expect(projectFindView.refs.descriptionLabel.textContent).toContain('Replaced'); - - const sampleJsContent = fs.readFileSync(sampleJs, 'utf8'); - expect(sampleJsContent.match(/items/g)).toBeFalsy(); - expect(sampleJsContent.match(/sunshine/g)).toHaveLength(6); - - const sampleCoffeeContent = fs.readFileSync(sampleCoffee, 'utf8'); - expect(sampleCoffeeContent.match(/items/g)).toBeFalsy(); - expect(sampleCoffeeContent.match(/sunshine/g)).toHaveLength(7); - }); - - describe("when there are search results after a replace", () => { - it("runs the search after the replace", async () => { - projectFindView.findEditor.setText('items'); - atom.commands.dispatch(projectFindView.element, 'core:confirm'); - await searchPromise; - - projectFindView.replaceEditor.setText('items-123'); - projectFindView.refs.replaceAllButton.click(); - await replacePromise; - - await etch.update(getExistingResultsPane()); - - expect(projectFindView.errorMessages).not.toBeVisible(); - expect(getExistingResultsPane().refs.previewCount.textContent).toContain('13 results found in 2 files for items'); - expect(projectFindView.refs.descriptionLabel.textContent).toContain('Replaced items with items-123 13 times in 2 files'); - - projectFindView.replaceEditor.setText('cats'); - advanceClock(projectFindView.replaceEditor.getBuffer().stoppedChangingDelay); - expect(projectFindView.refs.descriptionLabel.textContent).not.toContain('Replaced items'); - expect(projectFindView.refs.descriptionLabel.textContent).toContain("13 results found in 2 files for items"); - }) - }); - }); - - describe("when the project-find:replace-all is triggered", () => { - describe("when no search has been run", () => { - beforeEach(() => { - spyOn(atom, 'confirm').andReturn(0) - }); - - it("does nothing", () => { - projectFindView.findEditor.setText('items'); - projectFindView.replaceEditor.setText('sunshine'); - - spyOn(atom, 'beep'); - atom.commands.dispatch(projectFindView.element, 'project-find:replace-all'); - - expect(replacePromise).toBeUndefined(); - - expect(atom.beep).toHaveBeenCalled(); - expect(projectFindView.refs.descriptionLabel.textContent).toContain("Find in Project"); - }); - }); - - describe("when a search with no results has been run", () => { - beforeEach(async () => { - spyOn(atom, 'confirm').andReturn({ response: 0 }); - projectFindView.findEditor.setText('nopenotinthefile'); - atom.commands.dispatch(projectFindView.element, 'core:confirm'); - - await searchPromise; - }); - - it("doesnt replace anything", () => { - projectFindView.replaceEditor.setText('sunshine'); - - spyOn(atom.workspace, 'scan').andCallThrough(); - spyOn(atom, 'beep'); - atom.commands.dispatch(projectFindView.element, 'project-find:replace-all'); - - // The replacement isnt even run - expect(replacePromise).toBeUndefined(); - - expect(atom.workspace.scan).not.toHaveBeenCalled(); - expect(atom.beep).toHaveBeenCalled(); - expect(projectFindView.refs.descriptionLabel.textContent.replace(/( )/g, ' ')).toContain("No results"); - }); - }); - - describe("when a search with results has been run", () => { - beforeEach(async () => { - projectFindView.findEditor.setText('items'); - atom.commands.dispatch(projectFindView.element, 'core:confirm'); - - await searchPromise; - }); - - it("messages the user when the search text has changed since that last search", () => { - spyOn(atom, 'confirm').andReturn({ response: 0 }); - spyOn(atom.workspace, 'scan').andCallThrough(); - - projectFindView.findEditor.setText('sort'); - projectFindView.replaceEditor.setText('ok'); - - advanceClock(stoppedChangingDelay); - atom.commands.dispatch(projectFindView.element, 'project-find:replace-all'); - - expect(replacePromise).toBeUndefined(); - expect(atom.workspace.scan).not.toHaveBeenCalled(); - expect(atom.confirm).toHaveBeenCalled(); - expect(atom.confirm.mostRecentCall.args[0].message).toContain('was changed to'); - }); - - it("replaces all the matches and updates the results view", async () => { - spyOn(atom, 'confirm').andReturn({ response: 0 }); - projectFindView.replaceEditor.setText('sunshine'); - - expect(projectFindView.errorMessages).not.toBeVisible(); - atom.commands.dispatch(projectFindView.element, 'project-find:replace-all'); - await replacePromise; - - const resultsView = getResultsView(); - expect(resultsView.element).toBeVisible(); - expect(resultsView.refs.listView.element.querySelectorAll(".match-row")).toHaveLength(0); - - expect(projectFindView.refs.descriptionLabel.textContent).toContain("Replaced items with sunshine 13 times in 2 files"); - - let sampleJsContent = fs.readFileSync(sampleJs, 'utf8'); - expect(sampleJsContent.match(/items/g)).toBeFalsy(); - expect(sampleJsContent.match(/sunshine/g)).toHaveLength(6); - - let sampleCoffeeContent = fs.readFileSync(sampleCoffee, 'utf8'); - expect(sampleCoffeeContent.match(/items/g)).toBeFalsy(); - expect(sampleCoffeeContent.match(/sunshine/g)).toHaveLength(7); - }); - - describe("when the confirm box is cancelled", () => { - beforeEach(() => { - spyOn(atom, 'confirm').andReturn(1) - }); - - it("does not replace", async () => { - projectFindView.replaceEditor.setText('sunshine'); - - atom.commands.dispatch(projectFindView.element, 'project-find:replace-all'); - await replacePromise; - - expect(projectFindView.refs.descriptionLabel.textContent).toContain("13 results found"); - }); - }); - }); - - describe("when the find field contains a ^ or a $ and the regex option is enabled", () => { - it("correctly replaces all matches", async () => { - // TODO: Remove version check when Atom 1.21 reaches stable - if (parseFloat(atom.getVersion()) < 1.21) { - return; - } - - atom.commands.dispatch(projectFindView.element, 'project-find:toggle-regex-option'); - projectFindView.findEditor.setText(';$'); - atom.commands.dispatch(projectFindView.element, 'core:confirm'); - await searchPromise; - - spyOn(atom, 'confirm').andReturn({ response: 0 }); - projectFindView.replaceEditor.setText('sunshine'); - - expect(projectFindView.errorMessages).not.toBeVisible(); - atom.commands.dispatch(projectFindView.element, 'project-find:replace-all'); - await replacePromise; - - expect(projectFindView.refs.descriptionLabel.textContent).toContain("Replaced ;$ with sunshine 9 times in 2 files"); - - let sampleJsContent = fs.readFileSync(sampleJs, 'utf8'); - expect(sampleJsContent.match(/;$/gm)).toBeFalsy(); - expect(sampleJsContent.match(/sunshine/g)).toHaveLength(8); - }); - }); - }); - - describe("when there is an error replacing", () => { - beforeEach(async () => { - spyOn(atom, 'confirm').andReturn({ response: 0 }); - projectFindView.findEditor.setText('items'); - atom.commands.dispatch(projectFindView.element, 'project-find:confirm'); - await searchPromise; - }); - - it("displays the errors in the results pane", async () => { - let errorList - spyOn(atom.workspace, 'replace').andCallFake(async (regex, replacement, paths, callback) => { - ({ errorList } = getExistingResultsPane().refs); - expect(errorList.querySelectorAll("li")).toHaveLength(0); - - callback(null, {path: '/some/path.js', code: 'ENOENT', message: 'Nope'}); - await etch.update(getExistingResultsPane()); - expect(errorList).toBeVisible(); - expect(errorList.querySelectorAll("li")).toHaveLength(1); - - callback(null, {path: '/some/path.js', code: 'ENOENT', message: 'Broken'}); - await etch.update(getExistingResultsPane()); - expect(errorList.querySelectorAll("li")).toHaveLength(2); - }); - - projectFindView.replaceEditor.setText('sunshine'); - atom.commands.dispatch(projectFindView.element, 'project-find:replace-all'); - await replacePromise; - - expect(errorList).toBeVisible(); - expect(errorList.querySelectorAll("li")).toHaveLength(2); - expect(errorList.querySelectorAll("li")[0].textContent).toBe('Nope'); - expect(errorList.querySelectorAll("li")[1].textContent).toBe('Broken'); - }); - }); - }); - - describe("panel focus", () => { - beforeEach(async () => { - atom.commands.dispatch(workspaceElement, 'project-find:show'); - await activationPromise; - }); - - it("focuses the find editor when the panel gets focus", () => { - projectFindView.replaceEditor.element.focus(); - expect(projectFindView.replaceEditor.element).toHaveFocus(); - - projectFindView.element.focus(); - expect(projectFindView.findEditor.getElement()).toHaveFocus(); - }); - - it("moves focus between editors with find-and-replace:focus-next", () => { - projectFindView.findEditor.element.focus(); - expect(projectFindView.findEditor.element).toHaveFocus() - - atom.commands.dispatch(projectFindView.findEditor.element, 'find-and-replace:focus-next'); - expect(projectFindView.replaceEditor.element).toHaveFocus() - - atom.commands.dispatch(projectFindView.replaceEditor.element, 'find-and-replace:focus-next'); - expect(projectFindView.pathsEditor.element).toHaveFocus() - - atom.commands.dispatch(projectFindView.replaceEditor.element, 'find-and-replace:focus-next'); - expect(projectFindView.findEditor.element).toHaveFocus() - - atom.commands.dispatch(projectFindView.replaceEditor.element, 'find-and-replace:focus-previous'); - expect(projectFindView.pathsEditor.element).toHaveFocus() - - atom.commands.dispatch(projectFindView.replaceEditor.element, 'find-and-replace:focus-previous'); - expect(projectFindView.replaceEditor.element).toHaveFocus() - }); - }); - - describe("panel opening", () => { - describe("when a panel is already open on the right", () => { - beforeEach(async () => { - atom.config.set('find-and-replace.projectSearchResultsPaneSplitDirection', 'right'); - - editor = await atom.workspace.open('project/sample.js'); - editorElement = atom.views.getView(editor); - - atom.commands.dispatch(workspaceElement, 'project-find:show'); - await activationPromise; - - projectFindView.findEditor.setText('items'); - atom.commands.dispatch(projectFindView.element, 'core:confirm'); - await searchPromise; - }); - - it("doesn't open another panel even if the active pane is vertically split", async () => { - atom.commands.dispatch(editorElement, 'pane:split-down'); - projectFindView.findEditor.setText('items'); - - atom.commands.dispatch(projectFindView.element, 'core:confirm'); - await searchPromise; - - expect(workspaceElement.querySelectorAll('.preview-pane').length).toBe(1); - }); - }); - - describe("when a panel is already open at the bottom", () => { - beforeEach(async () => { - atom.config.set('find-and-replace.projectSearchResultsPaneSplitDirection', 'down'); - - editor = await atom.workspace.open('project/sample.js'); - editorElement = atom.views.getView(editor); - - atom.commands.dispatch(workspaceElement, 'project-find:show'); - await activationPromise; - - projectFindView.findEditor.setText('items'); - atom.commands.dispatch(projectFindView.element, 'core:confirm'); - await searchPromise; - }); - - it("doesn't open another panel even if the active pane is horizontally split", async () => { - atom.commands.dispatch(editorElement, 'pane:split-right'); - projectFindView.findEditor.setText('items'); - - atom.commands.dispatch(projectFindView.element, 'core:confirm'); - await searchPromise; - - expect(workspaceElement.querySelectorAll('.preview-pane').length).toBe(1); - }); - }); - }); - - describe("when language-javascript is active", () => { - beforeEach(async () => { - await atom.packages.activatePackage("language-javascript"); - }); - - it("uses the regexp grammar when regex-mode is loaded from configuration", async () => { - atom.config.set('find-and-replace.useRegex', true); - - atom.commands.dispatch(workspaceElement, 'project-find:show'); - await activationPromise; - - expect(projectFindView.model.getFindOptions().useRegex).toBe(true); - expect(projectFindView.findEditor.getGrammar().scopeName).toBe('source.js.regexp'); - expect(projectFindView.replaceEditor.getGrammar().scopeName).toBe('source.js.regexp.replacement'); - }); - - describe("when panel is active", () => { - beforeEach(async () => { - atom.commands.dispatch(workspaceElement, 'project-find:show'); - await activationPromise; - }); - - it("does not use regexp grammar when in non-regex mode", () => { - expect(projectFindView.model.getFindOptions().useRegex).not.toBe(true); - expect(projectFindView.findEditor.getGrammar().scopeName).toBe('text.plain.null-grammar'); - expect(projectFindView.replaceEditor.getGrammar().scopeName).toBe('text.plain.null-grammar'); - }); - - it("uses regexp grammar when in regex mode and clears the regexp grammar when regex is disabled", () => { - atom.commands.dispatch(projectFindView.element, 'project-find:toggle-regex-option'); - - expect(projectFindView.model.getFindOptions().useRegex).toBe(true); - expect(projectFindView.findEditor.getGrammar().scopeName).toBe('source.js.regexp'); - expect(projectFindView.replaceEditor.getGrammar().scopeName).toBe('source.js.regexp.replacement'); - - atom.commands.dispatch(projectFindView.element, 'project-find:toggle-regex-option'); - - expect(projectFindView.model.getFindOptions().useRegex).not.toBe(true); - expect(projectFindView.findEditor.getGrammar().scopeName).toBe('text.plain.null-grammar'); - expect(projectFindView.replaceEditor.getGrammar().scopeName).toBe('text.plain.null-grammar'); - }); - }); - }); -}); -} - -function simulateResizeEvent(element) { - Array.from(element.children).forEach((child) => { - child.dispatchEvent(new AnimationEvent('animationstart')); - }); - advanceClock(1); -} +// /** @babel */ +// +// const path = require('path'); +// const temp = require('temp').track(); +// const fs = require('fs-plus'); +// const dedent = require('dedent'); +// const {TextBuffer} = require('atom'); +// const ResultsPaneView = require('../lib/project/results-pane'); +// const etch = require('etch'); +// const {conditionPromise} = require('./async-spec-helpers'); +// +// for (const ripgrep of [false, true]) { +// describe(`ProjectFindView (ripgrep=${ripgrep})`, () => { +// const {stoppedChangingDelay} = TextBuffer.prototype; +// let activationPromise, searchPromise, editor, editorElement, findView, +// projectFindView, workspaceElement; +// +// function getAtomPanel() { +// return workspaceElement.querySelector('.project-find').parentNode; +// } +// +// function getExistingResultsPane() { +// const pane = atom.workspace.paneForURI(ResultsPaneView.URI); +// if (pane) { +// return pane.itemForURI(ResultsPaneView.URI); +// } +// } +// +// function getResultsView() { +// return getExistingResultsPane().refs.resultsView; +// } +// +// function waitForSearchResults() { +// return conditionPromise( +// () => projectFindView.refs.descriptionLabel.textContent.includes('results found') +// ) +// } +// +// beforeEach(() => { +// atom.config.set('find-and-replace.useRipgrep', ripgrep) +// workspaceElement = atom.views.getView(atom.workspace); +// atom.config.set('core.excludeVcsIgnoredPaths', false); +// atom.project.setPaths([path.join(__dirname, 'fixtures')]); +// jasmine.attachToDOM(workspaceElement); +// +// activationPromise = atom.packages.activatePackage("find-and-replace").then(function({mainModule}) { +// mainModule.createViews(); +// ({findView, projectFindView} = mainModule); +// const spy = spyOn(projectFindView, 'search').andCallFake((options) => { +// return searchPromise = spy.originalValue.call(projectFindView, options); +// }); +// }); +// }); +// +// describe("when project-find:show is triggered", () => { +// it("attaches ProjectFindView to the root view", async () => { +// atom.commands.dispatch(workspaceElement, 'project-find:show'); +// await activationPromise; +// +// projectFindView.findEditor.setText('items'); +// expect(getAtomPanel()).toBeVisible(); +// expect(projectFindView.findEditor.getSelectedBufferRange()).toEqual([[0, 0], [0, 5]]); +// }); +// +// describe("with an open buffer", () => { +// beforeEach(async () => { +// atom.commands.dispatch(workspaceElement, 'project-find:show'); +// await activationPromise; +// projectFindView.findEditor.setText(''); +// editor = await atom.workspace.open('project/sample.js'); +// }); +// +// it("populates the findEditor with selection when there is a selection", () => { +// editor.setSelectedBufferRange([[2, 8], [2, 13]]); +// atom.commands.dispatch(workspaceElement, 'project-find:show'); +// expect(getAtomPanel()).toBeVisible(); +// expect(projectFindView.findEditor.getText()).toBe('items'); +// +// editor.setSelectedBufferRange([[2, 14], [2, 20]]); +// atom.commands.dispatch(workspaceElement, 'project-find:show'); +// expect(getAtomPanel()).toBeVisible(); +// expect(projectFindView.findEditor.getText()).toBe('length'); +// }); +// +// it("populates the findEditor with the previous selection when there is no selection", () => { +// editor.setSelectedBufferRange([[2, 14], [2, 20]]); +// atom.commands.dispatch(workspaceElement, 'project-find:show'); +// expect(getAtomPanel()).toBeVisible(); +// expect(projectFindView.findEditor.getText()).toBe('length'); +// +// editor.setSelectedBufferRange([[2, 30], [2, 30]]); +// atom.commands.dispatch(workspaceElement, 'project-find:show'); +// expect(getAtomPanel()).toBeVisible(); +// expect(projectFindView.findEditor.getText()).toBe('length'); +// }); +// +// it("places selected text into the find editor and escapes it when Regex is enabled", () => { +// atom.commands.dispatch(projectFindView.element, 'project-find:toggle-regex-option'); +// editor.setSelectedBufferRange([[6, 6], [6, 65]]); +// atom.commands.dispatch(workspaceElement, 'project-find:show'); +// expect(projectFindView.findEditor.getText()).toBe('current < pivot \\? left\\.push\\(current\\) : right\\.push\\(current\\);'); +// }); +// }); +// +// describe("when the ProjectFindView is already attached", () => { +// beforeEach(async () => { +// atom.commands.dispatch(workspaceElement, 'project-find:show'); +// await activationPromise; +// +// projectFindView.findEditor.setText('items'); +// projectFindView.findEditor.setSelectedBufferRange([[0, 0], [0, 0]]); +// }); +// +// it("focuses the find editor and selects all the text", () => { +// atom.commands.dispatch(workspaceElement, 'project-find:show'); +// expect(projectFindView.findEditor.getElement()).toHaveFocus(); +// expect(projectFindView.findEditor.getSelectedText()).toBe("items"); +// }); +// }); +// +// it("honors config settings for find options", async () => { +// atom.config.set('find-and-replace.useRegex', true); +// atom.config.set('find-and-replace.caseSensitive', true); +// atom.config.set('find-and-replace.wholeWord', true); +// +// atom.commands.dispatch(workspaceElement, 'project-find:show'); +// await activationPromise; +// +// expect(projectFindView.refs.caseOptionButton).toHaveClass('selected'); +// expect(projectFindView.refs.regexOptionButton).toHaveClass('selected'); +// expect(projectFindView.refs.wholeWordOptionButton).toHaveClass('selected'); +// }); +// }); +// +// describe("when project-find:show-in-current-directory is triggered with an open buffer", () => { +// beforeEach(async () => { +// atom.project.setPaths([__dirname]); +// +// atom.commands.dispatch(workspaceElement, 'project-find:show'); +// await activationPromise; +// +// projectFindView.findEditor.setText(''); +// projectFindView.pathsEditor.setText(''); +// editor = await atom.workspace.open('fixtures/sample.js'); +// }); +// +// it("calls project-find:show, and populates both findEditor and pathsEditor when there is a selection", () => { +// editor.setSelectedBufferRange([[3, 8], [3, 13]]); +// atom.commands.dispatch(workspaceElement, 'project-find:show-in-current-directory'); +// expect(getAtomPanel()).toBeVisible(); +// expect(projectFindView.findEditor.getText()).toBe('pivot'); +// expect(projectFindView.pathsEditor.getText()).toBe('fixtures'); +// +// editor.setSelectedBufferRange([[2, 14], [2, 20]]); +// atom.commands.dispatch(workspaceElement, 'project-find:show-in-current-directory'); +// expect(getAtomPanel()).toBeVisible(); +// expect(projectFindView.findEditor.getText()).toBe('length'); +// expect(projectFindView.pathsEditor.getText()).toBe('fixtures'); +// }); +// +// it("calls project-find:show, and populates only pathsEditor when there is no selection", () => { +// atom.commands.dispatch(workspaceElement, 'project-find:show-in-current-directory'); +// expect(getAtomPanel()).toBeVisible(); +// expect(projectFindView.findEditor.getText()).toBe(''); +// expect(projectFindView.pathsEditor.getText()).toBe('fixtures'); +// }); +// }); +// +// describe("when project-find:toggle is triggered", () => { +// it("toggles the visibility of the ProjectFindView", async () => { +// atom.commands.dispatch(workspaceElement, 'project-find:toggle'); +// await activationPromise; +// +// expect(getAtomPanel()).toBeVisible(); +// atom.commands.dispatch(workspaceElement, 'project-find:toggle'); +// expect(getAtomPanel()).not.toBeVisible(); +// }); +// }); +// +// describe("when project-find:show-in-current-directory is triggered", () => { +// let nested, tree, projectPath; +// +// beforeEach(() => { +// projectPath = temp.mkdirSync("atom"); +// atom.project.setPaths([projectPath]); +// +// tree = document.createElement('div'); +// tree.className = 'directory'; +// tree.innerHTML = dedent` +//
+// ${projectPath} +//
    +//
  • +// one.js +//
  • +//
  • +// two.js +//
  • +//
    +//
    +// nested +//
      +//
    • +// three.js +//
    • +//
    +//
    +//
    +//
+//
+// `; +// +// nested = tree.querySelector('.directory'); +// +// workspaceElement.appendChild(tree); +// }); +// +// function escapePath(filePath) { +// return filePath.replace(/\\/g, '\'); +// } +// +// it("populates the pathsEditor when triggered with a directory", async () => { +// atom.commands.dispatch(nested.querySelector('.name'), 'project-find:show-in-current-directory'); +// await activationPromise; +// +// expect(getAtomPanel()).toBeVisible(); +// expect(projectFindView.pathsEditor.getText()).toBe('nested'); +// expect(projectFindView.findEditor.getElement()).toHaveFocus(); +// +// atom.commands.dispatch(tree.querySelector('.name'), 'project-find:show-in-current-directory'); +// expect(projectFindView.pathsEditor.getText()).toBe(''); +// }); +// +// it("populates the pathsEditor when triggered on a directory's name", async () => { +// atom.commands.dispatch(nested, 'project-find:show-in-current-directory'); +// await activationPromise; +// +// expect(getAtomPanel()).toBeVisible(); +// expect(projectFindView.pathsEditor.getText()).toBe('nested'); +// expect(projectFindView.findEditor.getElement()).toHaveFocus(); +// +// atom.commands.dispatch(tree.querySelector('.name'), 'project-find:show-in-current-directory'); +// expect(projectFindView.pathsEditor.getText()).toBe(''); +// }); +// +// it("populates the pathsEditor when triggered on a file", async () => { +// atom.commands.dispatch(nested.querySelector('.file .name'), 'project-find:show-in-current-directory'); +// await activationPromise; +// +// expect(getAtomPanel()).toBeVisible(); +// expect(projectFindView.pathsEditor.getText()).toBe('nested'); +// expect(projectFindView.findEditor.getElement()).toHaveFocus(); +// +// atom.commands.dispatch(tree.querySelector('.file .name'), 'project-find:show-in-current-directory'); +// expect(projectFindView.pathsEditor.getText()).toBe(''); +// }); +// +// describe("when there are multiple root directories", async () => { +// beforeEach(() => { +// atom.project.addPath(temp.mkdirSync("another-path-")) +// }); +// +// it("includes the basename of the containing root directory in the paths-editor", async () => { +// atom.commands.dispatch(nested.querySelector('.file .name'), 'project-find:show-in-current-directory'); +// await activationPromise; +// +// expect(getAtomPanel()).toBeVisible(); +// expect(projectFindView.pathsEditor.getText()).toBe(path.join(path.basename(projectPath), 'nested')); +// }); +// }); +// }); +// +// describe("finding", () => { +// beforeEach(async () => { +// atom.project.setPaths([path.join(__dirname, 'fixtures/project')]); +// editor = await atom.workspace.open('sample.js'); +// editorElement = atom.views.getView(editor); +// atom.commands.dispatch(workspaceElement, 'project-find:show'); +// await activationPromise; +// workspaceElement.style.height = '800px' +// }); +// +// describe("when the find string contains an escaped char", () => { +// beforeEach(() => { +// jasmine.useRealClock() +// +// let projectPath = temp.mkdirSync("atom"); +// fs.writeFileSync(path.join(projectPath, "tabs.txt"), "\t\n\\\t\n\\\\t"); +// atom.project.setPaths([projectPath]); +// atom.commands.dispatch(workspaceElement, 'project-find:show'); +// }); +// +// describe("when regex search is enabled", () => { +// it("finds a literal tab character", async () => { +// atom.commands.dispatch(projectFindView.element, 'project-find:toggle-regex-option'); +// projectFindView.findEditor.setText('\\t'); +// +// atom.commands.dispatch(projectFindView.element, 'core:confirm'); +// await searchPromise; +// +// const resultsView = getResultsView(); +// expect(resultsView.element).toBeVisible(); +// expect(resultsView.refs.listView.element.querySelectorAll(".match-row")).toHaveLength(2); +// }) +// }); +// +// describe("when regex search is disabled", () => { +// it("finds the escape char", async () => { +// projectFindView.findEditor.setText('\\t'); +// +// atom.commands.dispatch(projectFindView.element, 'core:confirm'); +// await searchPromise; +// +// const resultsView = getResultsView(); +// expect(resultsView.element).toBeVisible(); +// expect(resultsView.refs.listView.element.querySelectorAll(".match-row")).toHaveLength(1); +// }); +// +// it("finds a backslash", async () => { +// projectFindView.findEditor.setText('\\'); +// +// atom.commands.dispatch(projectFindView.element, 'core:confirm'); +// await searchPromise; +// +// const resultsView = getResultsView(); +// expect(resultsView.element).toBeVisible(); +// expect(resultsView.refs.listView.element.querySelectorAll(".match-row")).toHaveLength(2); +// expect(resultsView.refs.listView.element.querySelectorAll(".match.highlight-info")).toHaveLength(3); +// }); +// +// it("doesn't insert a escaped char if there are multiple backslashs in front of the char", async () => { +// projectFindView.findEditor.setText('\\\\t'); +// +// atom.commands.dispatch(projectFindView.element, 'core:confirm'); +// await searchPromise; +// +// const resultsView = getResultsView(); +// expect(resultsView.element).toBeVisible(); +// expect(resultsView.refs.listView.element.querySelectorAll(".match-row")).toHaveLength(1); +// }); +// }); +// }); +// +// describe("when core:cancel is triggered", () => { +// it("detaches from the root view", () => { +// atom.commands.dispatch(workspaceElement, 'project-find:show'); +// projectFindView.element.focus(); +// atom.commands.dispatch(document.activeElement, 'core:cancel'); +// expect(getAtomPanel()).not.toBeVisible(); +// }); +// }); +// +// describe("when close option is true", () => { +// beforeEach(() => { +// atom.config.set('find-and-replace.closeFindPanelAfterSearch', true); +// }) +// +// it("closes the panel after search", async () => { +// projectFindView.findEditor.setText('something'); +// atom.commands.dispatch(projectFindView.element, 'core:confirm'); +// await searchPromise; +// +// expect(getAtomPanel()).not.toBeVisible(); +// }); +// +// it("leaves the panel open after an empty search", async () => { +// projectFindView.findEditor.setText(''); +// atom.commands.dispatch(projectFindView.element, 'core:confirm'); +// await searchPromise; +// +// expect(getAtomPanel()).toBeVisible(); +// }); +// +// it("closes the panel after a no-op search", async () => { +// projectFindView.findEditor.setText('something'); +// atom.commands.dispatch(projectFindView.element, 'core:confirm'); +// await searchPromise; +// +// atom.commands.dispatch(workspaceElement, 'project-find:show'); +// await activationPromise; +// +// expect(getAtomPanel()).toBeVisible(); +// +// atom.commands.dispatch(projectFindView.element, 'core:confirm'); +// await searchPromise; +// +// expect(getAtomPanel()).not.toBeVisible(); +// }); +// +// it("does not close the panel after the replacement text is altered", async () => { +// projectFindView.replaceEditor.setText('something else'); +// +// expect(getAtomPanel()).toBeVisible(); +// }); +// }); +// +// describe("splitting into a second pane", () => { +// beforeEach(() => { +// workspaceElement.style.height = '1000px'; +// atom.commands.dispatch(editorElement, 'project-find:show'); +// jasmine.useRealClock() +// }); +// +// it("splits when option is right", async () => { +// const initialPane = atom.workspace.getCenter().getActivePane(); +// atom.config.set('find-and-replace.projectSearchResultsPaneSplitDirection', 'right'); +// projectFindView.findEditor.setText('items'); +// +// atom.commands.dispatch(projectFindView.element, 'core:confirm'); +// await searchPromise; +// +// expect(atom.workspace.getCenter().getActivePane()).not.toBe(initialPane); +// }); +// +// it("splits when option is bottom", async () => { +// const initialPane = atom.workspace.getCenter().getActivePane(); +// atom.config.set('find-and-replace.projectSearchResultsPaneSplitDirection', 'down'); +// projectFindView.findEditor.setText('items'); +// +// atom.commands.dispatch(projectFindView.element, 'core:confirm'); +// await searchPromise; +// +// expect(atom.workspace.getCenter().getActivePane()).not.toBe(initialPane); +// }); +// +// it("does not split when option is false", async () => { +// const initialPane = atom.workspace.getCenter().getActivePane(); +// projectFindView.findEditor.setText('items'); +// +// atom.commands.dispatch(projectFindView.element, 'core:confirm'); +// await searchPromise; +// +// expect(atom.workspace.getCenter().getActivePane()).toBe(initialPane); +// }); +// +// it("can be duplicated on the right", async () => { +// atom.config.set('find-and-replace.projectSearchResultsPaneSplitDirection', 'right'); +// projectFindView.findEditor.setText('items'); +// +// atom.commands.dispatch(projectFindView.element, 'core:confirm'); +// await searchPromise; +// +// const resultsPaneView1 = atom.views.getView(getExistingResultsPane()); +// const pane1 = atom.workspace.getCenter().getActivePane(); +// const resultsView1 = pane1.getItems()[0].refs.resultsView +// pane1.splitRight({copyActiveItem: true}); +// +// const pane2 = atom.workspace.getCenter().getActivePane(); +// const resultsView2 = pane2.getItems()[0].refs.resultsView +// const resultsPaneView2 = atom.views.getView(pane2.itemForURI(ResultsPaneView.URI)); +// expect(pane1).not.toBe(pane2); +// expect(resultsPaneView1).not.toBe(resultsPaneView2); +// simulateResizeEvent(resultsView2.element); +// +// await etch.update(resultsView1); +// await etch.update(resultsView2); +// await waitForSearchResults(); +// +// const resultCount = resultsPaneView1.querySelectorAll('.match-row').length; +// expect(resultCount).toBeGreaterThan(0); +// expect(resultsPaneView2.querySelectorAll('.match-row')).toHaveLength(resultCount); +// expect(resultsPaneView2.querySelector('.preview-count').innerHTML).toEqual(resultsPaneView1.querySelector('.preview-count').innerHTML); +// }); +// +// it("can be duplicated at the bottom", async () => { +// atom.config.set('find-and-replace.projectSearchResultsPaneSplitDirection', 'down'); +// projectFindView.findEditor.setText('items'); +// +// atom.commands.dispatch(projectFindView.element, 'core:confirm'); +// await searchPromise; +// +// const resultsPaneView1 = atom.views.getView(getExistingResultsPane()); +// const pane1 = atom.workspace.getCenter().getActivePane(); +// const resultsView1 = pane1.getItems()[0].refs.resultsView +// +// pane1.splitDown({copyActiveItem: true}); +// const pane2 = atom.workspace.getCenter().getActivePane(); +// const resultsView2 = pane2.getItems()[0].refs.resultsView +// const resultsPaneView2 = atom.views.getView(pane2.itemForURI(ResultsPaneView.URI)); +// expect(pane1).not.toBe(pane2); +// expect(resultsPaneView1).not.toBe(resultsPaneView2); +// +// await etch.update(resultsView1); +// await etch.update(resultsView2); +// +// expect(resultsPaneView2.querySelector('.preview-count').innerHTML).toEqual(resultsPaneView1.querySelector('.preview-count').innerHTML); +// }); +// }); +// +// describe("serialization", () => { +// it("serializes if the case, regex and whole word options", async () => { +// atom.commands.dispatch(editorElement, 'project-find:show'); +// expect(projectFindView.refs.caseOptionButton).not.toHaveClass('selected'); +// projectFindView.refs.caseOptionButton.click(); +// expect(projectFindView.refs.caseOptionButton).toHaveClass('selected'); +// +// expect(projectFindView.refs.regexOptionButton).not.toHaveClass('selected'); +// projectFindView.refs.regexOptionButton.click(); +// expect(projectFindView.refs.regexOptionButton).toHaveClass('selected'); +// +// expect(projectFindView.refs.wholeWordOptionButton).not.toHaveClass('selected'); +// projectFindView.refs.wholeWordOptionButton.click(); +// expect(projectFindView.refs.wholeWordOptionButton).toHaveClass('selected'); +// +// await atom.packages.deactivatePackage("find-and-replace"); +// +// activationPromise = atom.packages.activatePackage("find-and-replace").then(function({mainModule}) { +// mainModule.createViews(); +// return {projectFindView} = mainModule; +// }); +// +// atom.commands.dispatch(editorElement, 'project-find:show'); +// await activationPromise; +// +// expect(projectFindView.refs.caseOptionButton).toHaveClass('selected'); +// expect(projectFindView.refs.regexOptionButton).toHaveClass('selected'); +// expect(projectFindView.refs.wholeWordOptionButton).toHaveClass('selected'); +// }) +// }); +// +// describe("description label", () => { +// beforeEach(() => { +// atom.commands.dispatch(editorElement, 'project-find:show'); +// }); +// +// it("indicates that it's searching, then shows the results", async () => { +// projectFindView.findEditor.setText('item'); +// atom.commands.dispatch(projectFindView.element, 'core:confirm'); +// +// await projectFindView.showResultPane(); +// +// expect(projectFindView.refs.descriptionLabel.textContent).toContain('Searching...'); +// +// await searchPromise; +// +// expect(projectFindView.refs.descriptionLabel.textContent).toContain('13 results found in 2 files'); +// atom.commands.dispatch(projectFindView.element, 'core:confirm'); +// expect(projectFindView.refs.descriptionLabel.textContent).toContain('13 results found in 2 files'); +// }); +// +// it("shows an error when the pattern is invalid and clears when no error", async () => { +// spyOn(atom.workspace, 'scan').andReturn(Promise.resolve()); +// atom.commands.dispatch(projectFindView.element, 'project-find:toggle-regex-option'); +// projectFindView.findEditor.setText('['); +// atom.commands.dispatch(projectFindView.element, 'core:confirm'); +// +// await searchPromise; +// +// expect(projectFindView.refs.descriptionLabel).toHaveClass('text-error'); +// expect(projectFindView.refs.descriptionLabel.textContent).toContain('Invalid regular expression'); +// +// projectFindView.findEditor.setText(''); +// atom.commands.dispatch(projectFindView.element, 'core:confirm'); +// +// expect(projectFindView.refs.descriptionLabel).not.toHaveClass('text-error'); +// expect(projectFindView.refs.descriptionLabel.textContent).toContain('Find in Project'); +// +// projectFindView.findEditor.setText('items'); +// atom.commands.dispatch(projectFindView.element, 'core:confirm'); +// +// await searchPromise; +// +// expect(projectFindView.refs.descriptionLabel).not.toHaveClass('text-error'); +// expect(projectFindView.refs.descriptionLabel.textContent).toContain('items'); +// }); +// }); +// +// describe("regex", () => { +// beforeEach(() => { +// atom.commands.dispatch(editorElement, 'project-find:show'); +// projectFindView.findEditor.setText('i(\\w)ems+'); +// spyOn(atom.workspace, 'scan').andCallFake(async () => {}); +// }); +// +// it("escapes regex patterns by default", async () => { +// atom.commands.dispatch(projectFindView.element, 'core:confirm'); +// await searchPromise; +// +// expect(atom.workspace.scan.argsForCall[0][0]).toEqual(/i\(\\w\)ems\+/gim); +// }); +// +// it("shows an error when the regex pattern is invalid", async () => { +// atom.commands.dispatch(projectFindView.element, 'project-find:toggle-regex-option'); +// projectFindView.findEditor.setText('['); +// +// atom.commands.dispatch(projectFindView.element, 'core:confirm'); +// await searchPromise; +// +// expect(projectFindView.refs.descriptionLabel).toHaveClass('text-error'); +// }); +// +// describe("when search has not been run yet", () => { +// it("toggles regex option via an event but does not run the search", () => { +// expect(projectFindView.refs.regexOptionButton).not.toHaveClass('selected'); +// atom.commands.dispatch(projectFindView.element, 'project-find:toggle-regex-option'); +// expect(projectFindView.refs.regexOptionButton).toHaveClass('selected'); +// expect(atom.workspace.scan).not.toHaveBeenCalled(); +// }) +// }); +// +// describe("when search has been run", () => { +// beforeEach(async () => { +// atom.commands.dispatch(projectFindView.element, 'core:confirm'); +// await searchPromise; +// }); +// +// it("toggles regex option via an event and finds files matching the pattern", async () => { +// expect(projectFindView.refs.regexOptionButton).not.toHaveClass('selected'); +// atom.commands.dispatch(projectFindView.element, 'project-find:toggle-regex-option'); +// +// await searchPromise; +// +// expect(projectFindView.refs.regexOptionButton).toHaveClass('selected'); +// expect(atom.workspace.scan.mostRecentCall.args[0]).toEqual(/i(\w)ems+/gim); +// }); +// +// it("toggles regex option via a button and finds files matching the pattern", async () => { +// expect(projectFindView.refs.regexOptionButton).not.toHaveClass('selected'); +// projectFindView.refs.regexOptionButton.click(); +// +// await searchPromise; +// +// expect(projectFindView.refs.regexOptionButton).toHaveClass('selected'); +// expect(atom.workspace.scan.mostRecentCall.args[0]).toEqual(/i(\w)ems+/gim); +// }); +// }); +// }); +// +// describe("case sensitivity", () => { +// beforeEach(async () => { +// atom.commands.dispatch(editorElement, 'project-find:show'); +// spyOn(atom.workspace, 'scan').andCallFake(() => Promise.resolve()); +// projectFindView.findEditor.setText('ITEMS'); +// +// atom.commands.dispatch(projectFindView.element, 'core:confirm'); +// await searchPromise; +// }); +// +// it("runs a case insensitive search by default", () => expect(atom.workspace.scan.argsForCall[0][0]).toEqual(/ITEMS/gim)); +// +// it("toggles case sensitive option via an event and finds files matching the pattern", async () => { +// expect(projectFindView.refs.caseOptionButton).not.toHaveClass('selected'); +// +// atom.commands.dispatch(projectFindView.element, 'project-find:toggle-case-option'); +// await searchPromise; +// +// expect(projectFindView.refs.caseOptionButton).toHaveClass('selected'); +// expect(atom.workspace.scan.mostRecentCall.args[0]).toEqual(/ITEMS/gm); +// }); +// +// it("toggles case sensitive option via a button and finds files matching the pattern", async () => { +// expect(projectFindView.refs.caseOptionButton).not.toHaveClass('selected'); +// +// projectFindView.refs.caseOptionButton.click(); +// await searchPromise; +// +// expect(projectFindView.refs.caseOptionButton).toHaveClass('selected'); +// expect(atom.workspace.scan.mostRecentCall.args[0]).toEqual(/ITEMS/gm); +// }); +// }); +// +// describe("whole word", () => { +// beforeEach(async () => { +// atom.commands.dispatch(editorElement, 'project-find:show'); +// spyOn(atom.workspace, 'scan').andCallFake(async () => {}); +// projectFindView.findEditor.setText('wholeword'); +// +// atom.commands.dispatch(projectFindView.element, 'core:confirm'); +// await searchPromise; +// }); +// +// it("does not run whole word search by default", () => { +// expect(atom.workspace.scan.argsForCall[0][0]).toEqual(/wholeword/gim) +// }); +// +// it("toggles whole word option via an event and finds files matching the pattern", async () => { +// expect(projectFindView.refs.wholeWordOptionButton).not.toHaveClass('selected'); +// atom.commands.dispatch(projectFindView.element, 'project-find:toggle-whole-word-option'); +// +// await searchPromise; +// expect(projectFindView.refs.wholeWordOptionButton).toHaveClass('selected'); +// expect(atom.workspace.scan.mostRecentCall.args[0]).toEqual(/\bwholeword\b/gim); +// }); +// +// it("toggles whole word option via a button and finds files matching the pattern", async () => { +// expect(projectFindView.refs.wholeWordOptionButton).not.toHaveClass('selected'); +// +// projectFindView.refs.wholeWordOptionButton.click(); +// await searchPromise; +// +// expect(projectFindView.refs.wholeWordOptionButton).toHaveClass('selected'); +// expect(atom.workspace.scan.mostRecentCall.args[0]).toEqual(/\bwholeword\b/gim); +// }); +// }); +// +// describe("when project-find:confirm is triggered", () => { +// beforeEach(() => { +// jasmine.useRealClock() +// }); +// +// it("displays the results and no errors", async () => { +// projectFindView.findEditor.setText('items'); +// atom.commands.dispatch(projectFindView.element, 'project-find:confirm'); +// +// await searchPromise; +// await waitForSearchResults(); +// +// const resultsView = getResultsView(); +// expect(resultsView.element).toBeVisible(); +// expect(resultsView.refs.listView.element.querySelectorAll(".match-row")).toHaveLength(11); +// expect(resultsView.refs.listView.element.querySelectorAll(".match.highlight-info")).toHaveLength(13); +// }) +// }); +// +// describe("when core:confirm is triggered", () => { +// beforeEach(() => { +// atom.commands.dispatch(workspaceElement, 'project-find:show') +// jasmine.useRealClock() +// }); +// +// describe("when the there search field is empty", () => { +// it("does not run the search but clears the model", () => { +// spyOn(atom.workspace, 'scan'); +// spyOn(projectFindView.model, 'clear'); +// atom.commands.dispatch(projectFindView.element, 'core:confirm'); +// expect(atom.workspace.scan).not.toHaveBeenCalled(); +// expect(projectFindView.model.clear).toHaveBeenCalled(); +// }) +// }); +// +// it("reruns the search when confirmed again after focusing the window", async () => { +// projectFindView.findEditor.setText('thisdoesnotmatch'); +// atom.commands.dispatch(projectFindView.element, 'core:confirm'); +// +// await searchPromise; +// +// spyOn(atom.workspace, 'scan'); +// atom.commands.dispatch(projectFindView.element, 'core:confirm'); +// +// await searchPromise; +// +// expect(atom.workspace.scan).not.toHaveBeenCalled(); +// atom.workspace.scan.reset(); +// window.dispatchEvent(new FocusEvent("focus")); +// atom.commands.dispatch(projectFindView.element, 'core:confirm'); +// +// await searchPromise; +// +// expect(atom.workspace.scan).toHaveBeenCalled(); +// atom.workspace.scan.reset(); +// atom.commands.dispatch(projectFindView.element, 'core:confirm'); +// +// await searchPromise; +// +// expect(atom.workspace.scan).not.toHaveBeenCalled(); +// }); +// +// describe("when results exist", () => { +// beforeEach(() => { +// projectFindView.findEditor.setText('items') +// }); +// +// it("displays the results and no errors", async () => { +// atom.commands.dispatch(projectFindView.element, 'core:confirm'); +// await searchPromise; +// +// const resultsView = getResultsView(); +// const resultsPaneView = getExistingResultsPane(); +// +// expect(resultsView.element).toBeVisible(); +// expect(resultsView.refs.listView.element.querySelectorAll(".match-row")).toHaveLength(11); +// expect(resultsView.refs.listView.element.querySelectorAll(".match.highlight-info")).toHaveLength(13); +// +// expect(resultsPaneView.refs.previewCount.textContent).toBe("13 results found in 2 files for items"); +// expect(projectFindView.errorMessages).not.toBeVisible(); +// }); +// +// it("only searches paths matching text in the path filter", async () => { +// spyOn(atom.workspace, 'scan').andCallFake(async () => {}); +// projectFindView.pathsEditor.setText('*.js'); +// +// atom.commands.dispatch(projectFindView.element, 'core:confirm'); +// await searchPromise; +// +// expect(atom.workspace.scan.argsForCall[0][1].paths).toEqual(['*.js']); +// }); +// +// it("updates the results list when a buffer changes", async () => { +// const editor = await atom.workspace.open('sample.js') +// +// atom.commands.dispatch(projectFindView.element, 'core:confirm'); +// await searchPromise; +// +// const resultsView = getResultsView(); +// const listView = resultsView.refs.listView; +// const resultsPaneView = getExistingResultsPane(); +// +// expect(listView.element.querySelectorAll(".match-row")).toHaveLength(11); +// expect(listView.element.querySelectorAll(".match.highlight-info")).toHaveLength(13); +// expect(resultsPaneView.refs.previewCount.textContent).toBe("13 results found in 2 files for items"); +// +// resultsView.selectFirstResult(); +// for (let i = 0; i < 6; i++) resultsView.moveDown(); +// await resultsView.moveDown(); +// +// expect(listView.element.querySelectorAll(".path-row")[1].parentElement).toHaveClass('selected'); +// +// editor.setText('there is one "items" in this file'); +// await etch.getScheduler().getNextUpdatePromise() +// await searchPromise; +// +// await conditionPromise( +// () => resultsPaneView.refs.previewCount.textContent === "8 results found in 2 files for items" +// ) +// +// expect(listView.element.querySelectorAll(".path-row")[1].parentElement).toHaveClass('selected'); +// +// // Ensure the newly added item can be opened. +// await resultsView.moveDown() +// atom.commands.dispatch(resultsView.element, 'core:confirm'); +// await waitForSearchResults(); +// await conditionPromise( +// () => editor.getSelectedText() === "items" +// ) +// +// editor.setText('no matches in this file'); +// await waitForSearchResults(); +// +// await conditionPromise( +// () => resultsPaneView.refs.previewCount.textContent === "7 results found in 1 file for items" +// ) +// }); +// +// it("doesn't update the results list when a buffer outside the project changes", async () => { +// const editor = await atom.workspace.open('../sample.js') +// +// atom.commands.dispatch(projectFindView.element, 'core:confirm'); +// await searchPromise; +// +// const resultsView = getResultsView(); +// const resultsPaneView = getExistingResultsPane(); +// +// expect(resultsView.refs.listView.element.querySelectorAll(".list-item")).toHaveLength(13); +// expect(resultsPaneView.refs.previewCount.textContent).toBe("13 results found in 2 files for items"); +// +// resultsView.selectFirstResult(); +// for (let i = 0; i < 7; i++) await resultsView.moveDown() +// expect(resultsView.refs.listView.element.querySelectorAll(".list-nested-item")[1]).toHaveClass('selected'); +// +// editor.setText('there is one "items" in this file'); +// advanceClock(editor.getBuffer().stoppedChangingDelay); +// await etch.getScheduler().getNextUpdatePromise() +// expect(resultsPaneView.refs.previewCount.textContent).toBe("13 results found in 2 files for items"); +// expect(resultsView.refs.listView.element.querySelectorAll(".list-nested-item")[1]).toHaveClass('selected'); +// }); +// }); +// +// describe("when no results exist", () => { +// beforeEach(() => { +// projectFindView.findEditor.setText('notintheprojectbro'); +// spyOn(atom.workspace, 'scan').andCallFake(async () => {}); +// }); +// +// it("displays no errors and no results", async () => { +// atom.commands.dispatch(projectFindView.element, 'core:confirm'); +// await searchPromise; +// +// const resultsView = getResultsView(); +// expect(projectFindView.refs.errorMessages).not.toBeVisible(); +// expect(resultsView.element).toBeVisible(); +// expect(resultsView.refs.listView.element.querySelectorAll(".match-row")).toHaveLength(0); +// }); +// }); +// }); +// +// describe("history", () => { +// beforeEach(() => { +// atom.commands.dispatch(workspaceElement, 'project-find:show'); +// spyOn(atom.workspace, 'scan').andCallFake(() => { +// let promise = Promise.resolve(); +// promise.cancel = () => {}; +// return promise; +// }); +// +// projectFindView.findEditor.setText('sort'); +// projectFindView.replaceEditor.setText('bort'); +// projectFindView.pathsEditor.setText('abc'); +// atom.commands.dispatch(projectFindView.findEditor.getElement(), 'core:confirm'); +// +// projectFindView.findEditor.setText('items'); +// projectFindView.replaceEditor.setText('eyetims'); +// projectFindView.pathsEditor.setText('def'); +// atom.commands.dispatch(projectFindView.findEditor.getElement(), 'core:confirm'); +// }); +// +// it("can navigate the entire history stack", () => { +// expect(projectFindView.findEditor.getText()).toEqual('items'); +// +// atom.commands.dispatch(projectFindView.findEditor.getElement(), 'core:move-up'); +// expect(projectFindView.findEditor.getText()).toEqual('sort'); +// +// atom.commands.dispatch(projectFindView.findEditor.getElement(), 'core:move-down'); +// expect(projectFindView.findEditor.getText()).toEqual('items'); +// +// atom.commands.dispatch(projectFindView.findEditor.getElement(), 'core:move-down'); +// expect(projectFindView.findEditor.getText()).toEqual(''); +// +// expect(projectFindView.pathsEditor.getText()).toEqual('def'); +// +// atom.commands.dispatch(projectFindView.pathsEditor.element, 'core:move-up'); +// expect(projectFindView.pathsEditor.getText()).toEqual('abc'); +// +// atom.commands.dispatch(projectFindView.pathsEditor.element, 'core:move-down'); +// expect(projectFindView.pathsEditor.getText()).toEqual('def'); +// +// atom.commands.dispatch(projectFindView.pathsEditor.element, 'core:move-down'); +// expect(projectFindView.pathsEditor.getText()).toEqual(''); +// +// expect(projectFindView.replaceEditor.getText()).toEqual('eyetims'); +// +// atom.commands.dispatch(projectFindView.replaceEditor.element, 'core:move-up'); +// expect(projectFindView.replaceEditor.getText()).toEqual('bort'); +// +// atom.commands.dispatch(projectFindView.replaceEditor.element, 'core:move-down'); +// expect(projectFindView.replaceEditor.getText()).toEqual('eyetims'); +// +// atom.commands.dispatch(projectFindView.replaceEditor.element, 'core:move-down'); +// expect(projectFindView.replaceEditor.getText()).toEqual(''); +// }); +// }); +// +// describe("when find-and-replace:use-selection-as-find-pattern is triggered", () => { +// it("places the selected text into the find editor", () => { +// editor.setSelectedBufferRange([[1, 6], [1, 10]]); +// atom.commands.dispatch(workspaceElement, 'find-and-replace:use-selection-as-find-pattern'); +// expect(projectFindView.findEditor.getText()).toBe('sort'); +// +// editor.setSelectedBufferRange([[1, 13], [1, 21]]); +// atom.commands.dispatch(workspaceElement, 'find-and-replace:use-selection-as-find-pattern'); +// expect(projectFindView.findEditor.getText()).toBe('function'); +// }); +// +// it("places the word under the cursor into the find editor", () => { +// editor.setSelectedBufferRange([[1, 8], [1, 8]]); +// atom.commands.dispatch(workspaceElement, 'find-and-replace:use-selection-as-find-pattern'); +// expect(projectFindView.findEditor.getText()).toBe('sort'); +// +// editor.setSelectedBufferRange([[1, 15], [1, 15]]); +// atom.commands.dispatch(workspaceElement, 'find-and-replace:use-selection-as-find-pattern'); +// expect(projectFindView.findEditor.getText()).toBe('function'); +// }); +// +// it("places the previously selected text into the find editor if no selection and no word under cursor", () => { +// editor.setSelectedBufferRange([[1, 13], [1, 21]]); +// atom.commands.dispatch(workspaceElement, 'find-and-replace:use-selection-as-find-pattern'); +// expect(projectFindView.findEditor.getText()).toBe('function'); +// +// editor.setSelectedBufferRange([[1, 1], [1, 1]]); +// atom.commands.dispatch(workspaceElement, 'find-and-replace:use-selection-as-find-pattern'); +// expect(projectFindView.findEditor.getText()).toBe('function'); +// }); +// +// it("places selected text into the find editor and escapes it when Regex is enabled", () => { +// atom.commands.dispatch(projectFindView.element, 'project-find:toggle-regex-option'); +// editor.setSelectedBufferRange([[6, 6], [6, 65]]); +// atom.commands.dispatch(workspaceElement, 'find-and-replace:use-selection-as-find-pattern'); +// expect(projectFindView.findEditor.getText()).toBe('current < pivot \\? left\\.push\\(current\\) : right\\.push\\(current\\);'); +// }); +// }); +// +// describe("when find-and-replace:use-selection-as-replace-pattern is triggered", () => { +// it("places the selected text into the replace editor", () => { +// editor.setSelectedBufferRange([[1, 6], [1, 10]]); +// atom.commands.dispatch(workspaceElement, 'find-and-replace:use-selection-as-replace-pattern'); +// expect(projectFindView.replaceEditor.getText()).toBe('sort'); +// +// editor.setSelectedBufferRange([[1, 13], [1, 21]]); +// atom.commands.dispatch(workspaceElement, 'find-and-replace:use-selection-as-replace-pattern'); +// expect(projectFindView.replaceEditor.getText()).toBe('function'); +// }); +// +// it("places the word under the cursor into the replace editor", () => { +// editor.setSelectedBufferRange([[1, 8], [1, 8]]); +// atom.commands.dispatch(workspaceElement, 'find-and-replace:use-selection-as-replace-pattern'); +// expect(projectFindView.replaceEditor.getText()).toBe('sort'); +// +// editor.setSelectedBufferRange([[1, 15], [1, 15]]); +// atom.commands.dispatch(workspaceElement, 'find-and-replace:use-selection-as-replace-pattern'); +// expect(projectFindView.replaceEditor.getText()).toBe('function'); +// }); +// +// it("places the previously selected text into the replace editor if no selection and no word under cursor", () => { +// editor.setSelectedBufferRange([[1, 13], [1, 21]]); +// atom.commands.dispatch(workspaceElement, 'find-and-replace:use-selection-as-replace-pattern'); +// expect(projectFindView.replaceEditor.getText()).toBe('function'); +// +// editor.setSelectedBufferRange([[1, 1], [1, 1]]); +// atom.commands.dispatch(workspaceElement, 'find-and-replace:use-selection-as-replace-pattern'); +// expect(projectFindView.replaceEditor.getText()).toBe('function'); +// }); +// +// it("places selected text into the replace editor and escapes it when Regex is enabled", () => { +// atom.commands.dispatch(projectFindView.element, 'project-find:toggle-regex-option') +// editor.setSelectedBufferRange([[6, 6], [6, 65]]); +// atom.commands.dispatch(workspaceElement, 'find-and-replace:use-selection-as-replace-pattern'); +// expect(projectFindView.replaceEditor.getText()).toBe('current < pivot \\? left\\.push\\(current\\) : right\\.push\\(current\\);'); +// }); +// }); +// +// describe("when there is an error searching", () => { +// it("displays the errors in the results pane", async () => { +// projectFindView.findEditor.setText('items'); +// +// let errorList; +// spyOn(atom.workspace, 'scan').andCallFake(async (regex, options, callback) => { +// const resultsPaneView = getExistingResultsPane(); +// ({errorList} = resultsPaneView.refs); +// expect(errorList.querySelectorAll("li")).toHaveLength(0); +// +// callback(null, {path: '/some/path.js', code: 'ENOENT', message: 'Nope'}); +// await etch.update(resultsPaneView); +// expect(errorList).toBeVisible(); +// expect(errorList.querySelectorAll("li")).toHaveLength(1); +// +// callback(null, {path: '/some/path.js', code: 'ENOENT', message: 'Broken'}); +// await etch.update(resultsPaneView); +// expect(errorList.querySelectorAll("li")).toHaveLength(2); +// }); +// +// atom.commands.dispatch(projectFindView.element, 'core:confirm'); +// +// await searchPromise; +// +// expect(errorList).toBeVisible(); +// expect(errorList.querySelectorAll("li")).toHaveLength(2); +// expect(errorList.querySelectorAll("li")[0].textContent).toBe('Nope'); +// expect(errorList.querySelectorAll("li")[1].textContent).toBe('Broken'); +// }) +// }); +// +// describe("buffer search sharing of the find options", () => { +// function getResultDecorations(clazz) { +// const result = []; +// const decorations = editor.decorationsStateForScreenRowRange(0, editor.getLineCount()); +// for (let id in decorations) { +// const decoration = decorations[id]; +// if (decoration.properties.class === clazz) { +// result.push(decoration); +// } +// } +// return result; +// } +// +// it("setting the find text does not interfere with the project replace state", async () => { +// // Not sure why I need to advance the clock before setting the text. If +// // this advanceClock doesnt happen, the text will be ''. wtf. +// advanceClock(projectFindView.findEditor.getBuffer().stoppedChangingDelay + 1); +// spyOn(atom.workspace, 'scan'); +// +// projectFindView.findEditor.setText('findme'); +// advanceClock(projectFindView.findEditor.getBuffer().stoppedChangingDelay + 1); +// +// await projectFindView.search({onlyRunIfActive: false, onlyRunIfChanged: true}); +// expect(atom.workspace.scan).toHaveBeenCalled(); +// }); +// +// it("shares the buffers and history cyclers between both buffer and project views", () => { +// projectFindView.findEditor.setText('findme'); +// projectFindView.replaceEditor.setText('replaceme'); +// +// atom.commands.dispatch(editorElement, 'find-and-replace:show'); +// expect(findView.findEditor.getText()).toBe('findme'); +// expect(findView.replaceEditor.getText()).toBe('replaceme'); +// +// // add some things to the history +// atom.commands.dispatch(findView.findEditor.element, 'core:confirm'); +// findView.findEditor.setText('findme1'); +// atom.commands.dispatch(findView.findEditor.element, 'core:confirm'); +// findView.findEditor.setText(''); +// +// atom.commands.dispatch(findView.replaceEditor.element, 'core:confirm'); +// findView.replaceEditor.setText('replaceme1'); +// atom.commands.dispatch(findView.replaceEditor.element, 'core:confirm'); +// findView.replaceEditor.setText(''); +// +// // Back to the project view to make sure we're using the same cycler +// atom.commands.dispatch(editorElement, 'project-find:show'); +// +// expect(projectFindView.findEditor.getText()).toBe(''); +// atom.commands.dispatch(projectFindView.findEditor.element, 'core:move-up'); +// expect(projectFindView.findEditor.getText()).toBe('findme1'); +// atom.commands.dispatch(projectFindView.findEditor.element, 'core:move-up'); +// expect(projectFindView.findEditor.getText()).toBe('findme'); +// +// expect(projectFindView.replaceEditor.getText()).toBe(''); +// atom.commands.dispatch(projectFindView.replaceEditor.element, 'core:move-up'); +// expect(projectFindView.replaceEditor.getText()).toBe('replaceme1'); +// atom.commands.dispatch(projectFindView.replaceEditor.element, 'core:move-up'); +// expect(projectFindView.replaceEditor.getText()).toBe('replaceme'); +// }); +// +// it('highlights the search results in the selected file', async () => { +// jasmine.useRealClock(); +// // Process here is to +// // * open samplejs +// // * run a search that has sample js results +// // * that should place the pattern in the buffer find +// // * focus project/sample.js by clicking on a project/sample.js result +// // * when the file has been activated, it's results for the project search should be highlighted +// +// editor = await atom.workspace.open('sample.js'); +// expect(getResultDecorations('find-result')).toHaveLength(0); +// +// projectFindView.findEditor.setText('item'); +// atom.commands.dispatch(projectFindView.element, 'core:confirm'); +// await searchPromise; +// await waitForSearchResults(); +// +// const resultsView = getResultsView(); +// resultsView.scrollToBottom(); // To load ALL the results +// await etch.update(resultsView); +// expect(resultsView.element).toBeVisible(); +// expect(resultsView.refs.listView.element.querySelectorAll(".match-row")).toHaveLength(11); +// expect(resultsView.refs.listView.element.querySelectorAll(".match.highlight-info")).toHaveLength(13); +// +// resultsView.selectFirstResult(); +// for (let i = 0; i < 9; i++) resultsView.moveDown(); +// await resultsView.moveDown(); +// +// atom.commands.dispatch(resultsView.element, 'core:confirm'); +// await new Promise(resolve => editor.onDidChangeSelectionRange(resolve)) +// +// // project/sample.js has 6 results +// expect(getResultDecorations('find-result')).toHaveLength(5); +// expect(getResultDecorations('current-result')).toHaveLength(1); +// expect(workspaceElement).toHaveClass('find-visible'); +// +// const initialSelectedRange = editor.getSelectedBufferRange(); +// +// // now we can find next +// atom.commands.dispatch(atom.views.getView(editor), 'find-and-replace:find-next'); +// expect(editor.getSelectedBufferRange()).not.toEqual(initialSelectedRange); +// +// // Now we toggle the whole-word option to make sure it is updated in the buffer find +// atom.commands.dispatch(projectFindView.element, 'project-find:toggle-whole-word-option'); +// await searchPromise; +// +// // project/sample.js has 0 results for whole word `item` +// expect(getResultDecorations('find-result')).toHaveLength(0); +// expect(workspaceElement).toHaveClass('find-visible'); +// +// // Now we toggle the whole-word option to make sure it is updated in the buffer find +// atom.commands.dispatch(projectFindView.element, 'project-find:toggle-whole-word-option'); +// }); +// }); +// +// describe("when user asked not to override last search results", () => { +// beforeEach(async () => { +// atom.commands.dispatch(editorElement, 'project-find:show'); +// projectFindView.findEditor.setText('items'); +// atom.commands.dispatch(projectFindView.element, 'core:confirm'); +// await searchPromise; +// +// }); +// it("opens new search results in new panel", async () => { +// const result_pane = getExistingResultsPane(); +// result_pane.dontOverrideTab(); +// projectFindView.findEditor.setText('items2'); +// atom.commands.dispatch(projectFindView.element, 'core:confirm'); +// await searchPromise; +// expect(result_pane).not.toBe(getExistingResultsPane()); +// }); +// }); +// }); +// +// describe("replacing", () => { +// let testDir, sampleJs, sampleCoffee, replacePromise; +// +// beforeEach(async () => { +// testDir = temp.mkdirSync('atom-find-and-replace'); +// sampleJs = path.join(testDir, 'project/sample.js'); +// sampleCoffee = path.join(testDir, 'sample.coffee'); +// +// fs.makeTreeSync(testDir); +// fs.writeFileSync(sampleCoffee, fs.readFileSync(require.resolve('./fixtures/sample.coffee'))); +// fs.writeFileSync(sampleJs, fs.readFileSync(require.resolve('./fixtures/project/sample.js'))); +// +// atom.commands.dispatch(workspaceElement, 'project-find:show'); +// await activationPromise; +// +// atom.project.setPaths([testDir]); +// const spy = spyOn(projectFindView, 'replaceAll').andCallFake(() => { +// replacePromise = spy.originalValue.call(projectFindView); +// }); +// }); +// +// describe("when the replace string contains an escaped char", () => { +// let filePath = null; +// +// beforeEach(() => { +// let projectPath = temp.mkdirSync("atom"); +// filePath = path.join(projectPath, "tabs.txt"); +// fs.writeFileSync(filePath, "a\nb\na"); +// atom.project.setPaths([projectPath]); +// atom.commands.dispatch(workspaceElement, 'project-find:show'); +// +// spyOn(atom, 'confirm').andReturn({response:0}); +// }); +// +// describe("when the regex option is chosen", () => { +// beforeEach(async () => { +// atom.commands.dispatch(projectFindView.element, 'project-find:toggle-regex-option'); +// projectFindView.findEditor.setText('a'); +// atom.commands.dispatch(projectFindView.element, 'project-find:confirm'); +// await searchPromise; +// }); +// +// it("finds the escape char", async () => { +// projectFindView.replaceEditor.setText('\\t'); +// +// atom.commands.dispatch(projectFindView.element, 'project-find:replace-all'); +// await replacePromise; +// +// expect(fs.readFileSync(filePath, 'utf8')).toBe("\t\nb\n\t"); +// }); +// +// it("doesn't insert a escaped char if there are multiple backslashs in front of the char", async () => { +// projectFindView.replaceEditor.setText('\\\\t'); +// +// atom.commands.dispatch(projectFindView.element, 'project-find:replace-all'); +// await replacePromise; +// +// expect(fs.readFileSync(filePath, 'utf8')).toBe("\\t\nb\n\\t"); +// }); +// }); +// +// describe("when regex option is not set", () => { +// beforeEach(async () => { +// projectFindView.findEditor.setText('a'); +// atom.commands.dispatch(projectFindView.element, 'project-find:confirm'); +// await searchPromise; +// }); +// +// it("finds the escape char", async () => { +// projectFindView.replaceEditor.setText('\\t'); +// +// atom.commands.dispatch(projectFindView.element, 'project-find:replace-all'); +// await replacePromise; +// +// expect(fs.readFileSync(filePath, 'utf8')).toBe("\\t\nb\n\\t"); +// }); +// }); +// }); +// +// describe("replace all button enablement", () => { +// let disposable = null; +// +// it("is disabled initially", () => { +// expect(projectFindView.refs.replaceAllButton).toHaveClass('disabled') +// }); +// +// it("is disabled when a search returns no results", async () => { +// projectFindView.findEditor.setText('items'); +// atom.commands.dispatch(projectFindView.element, 'project-find:confirm'); +// await searchPromise; +// +// expect(projectFindView.refs.replaceAllButton).not.toHaveClass('disabled'); +// +// projectFindView.findEditor.setText('nopenotinthefile'); +// atom.commands.dispatch(projectFindView.element, 'project-find:confirm'); +// await searchPromise; +// +// expect(projectFindView.refs.replaceAllButton).toHaveClass('disabled'); +// }); +// +// it("is enabled when a search has results and disabled when there are no results", async () => { +// projectFindView.findEditor.setText('items'); +// atom.commands.dispatch(projectFindView.element, 'project-find:confirm'); +// +// await searchPromise; +// +// disposable = projectFindView.replaceTooltipSubscriptions; +// spyOn(disposable, 'dispose'); +// +// expect(projectFindView.refs.replaceAllButton).not.toHaveClass('disabled'); +// +// // The replace all button should still be disabled as the text has been changed and a new search has not been run +// projectFindView.findEditor.setText('itemss'); +// advanceClock(stoppedChangingDelay); +// expect(projectFindView.refs.replaceAllButton).toHaveClass('disabled'); +// expect(disposable.dispose).toHaveBeenCalled(); +// +// // The button should still be disabled because the search and search pattern are out of sync +// projectFindView.replaceEditor.setText('omgomg'); +// advanceClock(stoppedChangingDelay); +// expect(projectFindView.refs.replaceAllButton).toHaveClass('disabled'); +// +// disposable = projectFindView.replaceTooltipSubscriptions; +// spyOn(disposable, 'dispose'); +// projectFindView.findEditor.setText('items'); +// advanceClock(stoppedChangingDelay); +// expect(projectFindView.refs.replaceAllButton).not.toHaveClass('disabled'); +// +// projectFindView.findEditor.setText(''); +// atom.commands.dispatch(projectFindView.element, 'project-find:confirm'); +// +// expect(projectFindView.refs.replaceAllButton).toHaveClass('disabled'); +// }); +// }); +// +// describe("when the replace button is pressed", () => { +// beforeEach(() => { +// spyOn(atom, 'confirm').andReturn({ response: 0 }); +// }); +// +// it("runs the search, and replaces all the matches", async () => { +// projectFindView.findEditor.setText('items'); +// atom.commands.dispatch(projectFindView.element, 'core:confirm'); +// await searchPromise; +// +// projectFindView.replaceEditor.setText('sunshine'); +// projectFindView.refs.replaceAllButton.click(); +// await replacePromise; +// +// expect(projectFindView.errorMessages).not.toBeVisible(); +// expect(projectFindView.refs.descriptionLabel.textContent).toContain('Replaced'); +// +// const sampleJsContent = fs.readFileSync(sampleJs, 'utf8'); +// expect(sampleJsContent.match(/items/g)).toBeFalsy(); +// expect(sampleJsContent.match(/sunshine/g)).toHaveLength(6); +// +// const sampleCoffeeContent = fs.readFileSync(sampleCoffee, 'utf8'); +// expect(sampleCoffeeContent.match(/items/g)).toBeFalsy(); +// expect(sampleCoffeeContent.match(/sunshine/g)).toHaveLength(7); +// }); +// +// describe("when there are search results after a replace", () => { +// it("runs the search after the replace", async () => { +// projectFindView.findEditor.setText('items'); +// atom.commands.dispatch(projectFindView.element, 'core:confirm'); +// await searchPromise; +// +// projectFindView.replaceEditor.setText('items-123'); +// projectFindView.refs.replaceAllButton.click(); +// await replacePromise; +// +// await etch.update(getExistingResultsPane()); +// +// expect(projectFindView.errorMessages).not.toBeVisible(); +// expect(getExistingResultsPane().refs.previewCount.textContent).toContain('13 results found in 2 files for items'); +// expect(projectFindView.refs.descriptionLabel.textContent).toContain('Replaced items with items-123 13 times in 2 files'); +// +// projectFindView.replaceEditor.setText('cats'); +// advanceClock(projectFindView.replaceEditor.getBuffer().stoppedChangingDelay); +// expect(projectFindView.refs.descriptionLabel.textContent).not.toContain('Replaced items'); +// expect(projectFindView.refs.descriptionLabel.textContent).toContain("13 results found in 2 files for items"); +// }) +// }); +// }); +// +// describe("when the project-find:replace-all is triggered", () => { +// describe("when no search has been run", () => { +// beforeEach(() => { +// spyOn(atom, 'confirm').andReturn(0) +// }); +// +// it("does nothing", () => { +// projectFindView.findEditor.setText('items'); +// projectFindView.replaceEditor.setText('sunshine'); +// +// spyOn(atom, 'beep'); +// atom.commands.dispatch(projectFindView.element, 'project-find:replace-all'); +// +// expect(replacePromise).toBeUndefined(); +// +// expect(atom.beep).toHaveBeenCalled(); +// expect(projectFindView.refs.descriptionLabel.textContent).toContain("Find in Project"); +// }); +// }); +// +// describe("when a search with no results has been run", () => { +// beforeEach(async () => { +// spyOn(atom, 'confirm').andReturn({ response: 0 }); +// projectFindView.findEditor.setText('nopenotinthefile'); +// atom.commands.dispatch(projectFindView.element, 'core:confirm'); +// +// await searchPromise; +// }); +// +// it("doesnt replace anything", () => { +// projectFindView.replaceEditor.setText('sunshine'); +// +// spyOn(atom.workspace, 'scan').andCallThrough(); +// spyOn(atom, 'beep'); +// atom.commands.dispatch(projectFindView.element, 'project-find:replace-all'); +// +// // The replacement isnt even run +// expect(replacePromise).toBeUndefined(); +// +// expect(atom.workspace.scan).not.toHaveBeenCalled(); +// expect(atom.beep).toHaveBeenCalled(); +// expect(projectFindView.refs.descriptionLabel.textContent.replace(/( )/g, ' ')).toContain("No results"); +// }); +// }); +// +// describe("when a search with results has been run", () => { +// beforeEach(async () => { +// projectFindView.findEditor.setText('items'); +// atom.commands.dispatch(projectFindView.element, 'core:confirm'); +// +// await searchPromise; +// }); +// +// it("messages the user when the search text has changed since that last search", () => { +// spyOn(atom, 'confirm').andReturn({ response: 0 }); +// spyOn(atom.workspace, 'scan').andCallThrough(); +// +// projectFindView.findEditor.setText('sort'); +// projectFindView.replaceEditor.setText('ok'); +// +// advanceClock(stoppedChangingDelay); +// atom.commands.dispatch(projectFindView.element, 'project-find:replace-all'); +// +// expect(replacePromise).toBeUndefined(); +// expect(atom.workspace.scan).not.toHaveBeenCalled(); +// expect(atom.confirm).toHaveBeenCalled(); +// expect(atom.confirm.mostRecentCall.args[0].message).toContain('was changed to'); +// }); +// +// it("replaces all the matches and updates the results view", async () => { +// spyOn(atom, 'confirm').andReturn({ response: 0 }); +// projectFindView.replaceEditor.setText('sunshine'); +// +// expect(projectFindView.errorMessages).not.toBeVisible(); +// atom.commands.dispatch(projectFindView.element, 'project-find:replace-all'); +// await replacePromise; +// +// const resultsView = getResultsView(); +// expect(resultsView.element).toBeVisible(); +// expect(resultsView.refs.listView.element.querySelectorAll(".match-row")).toHaveLength(0); +// +// expect(projectFindView.refs.descriptionLabel.textContent).toContain("Replaced items with sunshine 13 times in 2 files"); +// +// let sampleJsContent = fs.readFileSync(sampleJs, 'utf8'); +// expect(sampleJsContent.match(/items/g)).toBeFalsy(); +// expect(sampleJsContent.match(/sunshine/g)).toHaveLength(6); +// +// let sampleCoffeeContent = fs.readFileSync(sampleCoffee, 'utf8'); +// expect(sampleCoffeeContent.match(/items/g)).toBeFalsy(); +// expect(sampleCoffeeContent.match(/sunshine/g)).toHaveLength(7); +// }); +// +// describe("when the confirm box is cancelled", () => { +// beforeEach(() => { +// spyOn(atom, 'confirm').andReturn(1) +// }); +// +// it("does not replace", async () => { +// projectFindView.replaceEditor.setText('sunshine'); +// +// atom.commands.dispatch(projectFindView.element, 'project-find:replace-all'); +// await replacePromise; +// +// expect(projectFindView.refs.descriptionLabel.textContent).toContain("13 results found"); +// }); +// }); +// }); +// +// describe("when the find field contains a ^ or a $ and the regex option is enabled", () => { +// it("correctly replaces all matches", async () => { +// // TODO: Remove version check when Atom 1.21 reaches stable +// if (parseFloat(atom.getVersion()) < 1.21) { +// return; +// } +// +// atom.commands.dispatch(projectFindView.element, 'project-find:toggle-regex-option'); +// projectFindView.findEditor.setText(';$'); +// atom.commands.dispatch(projectFindView.element, 'core:confirm'); +// await searchPromise; +// +// spyOn(atom, 'confirm').andReturn({ response: 0 }); +// projectFindView.replaceEditor.setText('sunshine'); +// +// expect(projectFindView.errorMessages).not.toBeVisible(); +// atom.commands.dispatch(projectFindView.element, 'project-find:replace-all'); +// await replacePromise; +// +// expect(projectFindView.refs.descriptionLabel.textContent).toContain("Replaced ;$ with sunshine 9 times in 2 files"); +// +// let sampleJsContent = fs.readFileSync(sampleJs, 'utf8'); +// expect(sampleJsContent.match(/;$/gm)).toBeFalsy(); +// expect(sampleJsContent.match(/sunshine/g)).toHaveLength(8); +// }); +// }); +// }); +// +// describe("when there is an error replacing", () => { +// beforeEach(async () => { +// spyOn(atom, 'confirm').andReturn({ response: 0 }); +// projectFindView.findEditor.setText('items'); +// atom.commands.dispatch(projectFindView.element, 'project-find:confirm'); +// await searchPromise; +// }); +// +// it("displays the errors in the results pane", async () => { +// let errorList +// spyOn(atom.workspace, 'replace').andCallFake(async (regex, replacement, paths, callback) => { +// ({ errorList } = getExistingResultsPane().refs); +// expect(errorList.querySelectorAll("li")).toHaveLength(0); +// +// callback(null, {path: '/some/path.js', code: 'ENOENT', message: 'Nope'}); +// await etch.update(getExistingResultsPane()); +// expect(errorList).toBeVisible(); +// expect(errorList.querySelectorAll("li")).toHaveLength(1); +// +// callback(null, {path: '/some/path.js', code: 'ENOENT', message: 'Broken'}); +// await etch.update(getExistingResultsPane()); +// expect(errorList.querySelectorAll("li")).toHaveLength(2); +// }); +// +// projectFindView.replaceEditor.setText('sunshine'); +// atom.commands.dispatch(projectFindView.element, 'project-find:replace-all'); +// await replacePromise; +// +// expect(errorList).toBeVisible(); +// expect(errorList.querySelectorAll("li")).toHaveLength(2); +// expect(errorList.querySelectorAll("li")[0].textContent).toBe('Nope'); +// expect(errorList.querySelectorAll("li")[1].textContent).toBe('Broken'); +// }); +// }); +// }); +// +// describe("panel focus", () => { +// beforeEach(async () => { +// atom.commands.dispatch(workspaceElement, 'project-find:show'); +// await activationPromise; +// }); +// +// it("focuses the find editor when the panel gets focus", () => { +// projectFindView.replaceEditor.element.focus(); +// expect(projectFindView.replaceEditor.element).toHaveFocus(); +// +// projectFindView.element.focus(); +// expect(projectFindView.findEditor.getElement()).toHaveFocus(); +// }); +// +// it("moves focus between editors with find-and-replace:focus-next", () => { +// projectFindView.findEditor.element.focus(); +// expect(projectFindView.findEditor.element).toHaveFocus() +// +// atom.commands.dispatch(projectFindView.findEditor.element, 'find-and-replace:focus-next'); +// expect(projectFindView.replaceEditor.element).toHaveFocus() +// +// atom.commands.dispatch(projectFindView.replaceEditor.element, 'find-and-replace:focus-next'); +// expect(projectFindView.pathsEditor.element).toHaveFocus() +// +// atom.commands.dispatch(projectFindView.replaceEditor.element, 'find-and-replace:focus-next'); +// expect(projectFindView.findEditor.element).toHaveFocus() +// +// atom.commands.dispatch(projectFindView.replaceEditor.element, 'find-and-replace:focus-previous'); +// expect(projectFindView.pathsEditor.element).toHaveFocus() +// +// atom.commands.dispatch(projectFindView.replaceEditor.element, 'find-and-replace:focus-previous'); +// expect(projectFindView.replaceEditor.element).toHaveFocus() +// }); +// }); +// +// describe("panel opening", () => { +// describe("when a panel is already open on the right", () => { +// beforeEach(async () => { +// atom.config.set('find-and-replace.projectSearchResultsPaneSplitDirection', 'right'); +// +// editor = await atom.workspace.open('project/sample.js'); +// editorElement = atom.views.getView(editor); +// +// atom.commands.dispatch(workspaceElement, 'project-find:show'); +// await activationPromise; +// +// projectFindView.findEditor.setText('items'); +// atom.commands.dispatch(projectFindView.element, 'core:confirm'); +// await searchPromise; +// }); +// +// it("doesn't open another panel even if the active pane is vertically split", async () => { +// atom.commands.dispatch(editorElement, 'pane:split-down'); +// projectFindView.findEditor.setText('items'); +// +// atom.commands.dispatch(projectFindView.element, 'core:confirm'); +// await searchPromise; +// +// expect(workspaceElement.querySelectorAll('.preview-pane').length).toBe(1); +// }); +// }); +// +// describe("when a panel is already open at the bottom", () => { +// beforeEach(async () => { +// atom.config.set('find-and-replace.projectSearchResultsPaneSplitDirection', 'down'); +// +// editor = await atom.workspace.open('project/sample.js'); +// editorElement = atom.views.getView(editor); +// +// atom.commands.dispatch(workspaceElement, 'project-find:show'); +// await activationPromise; +// +// projectFindView.findEditor.setText('items'); +// atom.commands.dispatch(projectFindView.element, 'core:confirm'); +// await searchPromise; +// }); +// +// it("doesn't open another panel even if the active pane is horizontally split", async () => { +// atom.commands.dispatch(editorElement, 'pane:split-right'); +// projectFindView.findEditor.setText('items'); +// +// atom.commands.dispatch(projectFindView.element, 'core:confirm'); +// await searchPromise; +// +// expect(workspaceElement.querySelectorAll('.preview-pane').length).toBe(1); +// }); +// }); +// }); +// +// describe("when language-javascript is active", () => { +// beforeEach(async () => { +// await atom.packages.activatePackage("language-javascript"); +// }); +// +// it("uses the regexp grammar when regex-mode is loaded from configuration", async () => { +// atom.config.set('find-and-replace.useRegex', true); +// +// atom.commands.dispatch(workspaceElement, 'project-find:show'); +// await activationPromise; +// +// expect(projectFindView.model.getFindOptions().useRegex).toBe(true); +// expect(projectFindView.findEditor.getGrammar().scopeName).toBe('source.js.regexp'); +// expect(projectFindView.replaceEditor.getGrammar().scopeName).toBe('source.js.regexp.replacement'); +// }); +// +// describe("when panel is active", () => { +// beforeEach(async () => { +// atom.commands.dispatch(workspaceElement, 'project-find:show'); +// await activationPromise; +// }); +// +// it("does not use regexp grammar when in non-regex mode", () => { +// expect(projectFindView.model.getFindOptions().useRegex).not.toBe(true); +// expect(projectFindView.findEditor.getGrammar().scopeName).toBe('text.plain.null-grammar'); +// expect(projectFindView.replaceEditor.getGrammar().scopeName).toBe('text.plain.null-grammar'); +// }); +// +// it("uses regexp grammar when in regex mode and clears the regexp grammar when regex is disabled", () => { +// atom.commands.dispatch(projectFindView.element, 'project-find:toggle-regex-option'); +// +// expect(projectFindView.model.getFindOptions().useRegex).toBe(true); +// expect(projectFindView.findEditor.getGrammar().scopeName).toBe('source.js.regexp'); +// expect(projectFindView.replaceEditor.getGrammar().scopeName).toBe('source.js.regexp.replacement'); +// +// atom.commands.dispatch(projectFindView.element, 'project-find:toggle-regex-option'); +// +// expect(projectFindView.model.getFindOptions().useRegex).not.toBe(true); +// expect(projectFindView.findEditor.getGrammar().scopeName).toBe('text.plain.null-grammar'); +// expect(projectFindView.replaceEditor.getGrammar().scopeName).toBe('text.plain.null-grammar'); +// }); +// }); +// }); +// }); +// } +// +// function simulateResizeEvent(element) { +// Array.from(element.children).forEach((child) => { +// child.dispatchEvent(new AnimationEvent('animationstart')); +// }); +// advanceClock(1); +// } diff --git a/spec/result-row-spec.js b/spec/result-row-spec.js index eb2ce5fd..b4e86c72 100644 --- a/spec/result-row-spec.js +++ b/spec/result-row-spec.js @@ -1,98 +1,98 @@ -/** @babel */ - -const { - LeadingContextRow, - TrailingContextRow, - ResultPathRow, - MatchRow, - ResultRowGroup -} = require("../lib/project/result-row"); - -describe("ResultRowGroup", () => { - const lines = (new Array(18)).fill().map((x, i) => `line-${i}`) - const rg = (i) => [[i, 0], [i, lines[i].length]] - const testedRowIndices = [0, 7, 13, 16, 17] - - const result = { - filePath: 'fake-file-path', - matches: testedRowIndices.map(lineNb => ({ - range: rg(lineNb), - leadingContextLines: lines.slice(Math.max(lineNb - 3, 0), lineNb), - trailingContextLines: lines.slice(lineNb + 1, lineNb + 4), - lineTextOffset: 0, - lineText: lines[lineNb], - matchText: 'fake-match-text' - })) - } - - describe("generateRows", () => { - it("generates a path row and several match rows", () => { - const rowGroup = new ResultRowGroup( - result, - { leadingContextLineCount: 0, trailingContextLineCount: 0 } - ) - - const expectedRows = [ - new ResultPathRow(rowGroup), - new MatchRow(rowGroup, false, 0, [ result.matches[0] ]), - new MatchRow(rowGroup, true, 7, [ result.matches[1] ]), - new MatchRow(rowGroup, true, 13, [ result.matches[2] ]), - new MatchRow(rowGroup, true, 16, [ result.matches[3] ]), - new MatchRow(rowGroup, false, 17, [ result.matches[4] ]) - ] - - for (let i = 0; i < rowGroup.rows.length; ++i) { - expect(rowGroup.rows[i].data).toEqual(expectedRows[i].data) - } - }) - - it("generates context rows between matches", () => { - const rowGroup = new ResultRowGroup( - result, - { leadingContextLineCount: 3, trailingContextLineCount: 2 } - ) - - const expectedRows = [ - new ResultPathRow(rowGroup), - - new MatchRow(rowGroup, false, 0, [ result.matches[0] ]), - new TrailingContextRow(rowGroup, lines[1], false, 0, 1), - new TrailingContextRow(rowGroup, lines[2], false, 0, 2), - - new LeadingContextRow(rowGroup, lines[4], true, 7, 3), - new LeadingContextRow(rowGroup, lines[5], false, 7, 2), - new LeadingContextRow(rowGroup, lines[6], false, 7, 1), - new MatchRow(rowGroup, false, 7, [ result.matches[1] ]), - new TrailingContextRow(rowGroup, lines[8], false, 7, 1), - new TrailingContextRow(rowGroup, lines[9], false, 7, 2), - - new LeadingContextRow(rowGroup, lines[10], false, 13, 3), - new LeadingContextRow(rowGroup, lines[11], false, 13, 2), - new LeadingContextRow(rowGroup, lines[12], false, 13, 1), - new MatchRow(rowGroup, false, 13, [ result.matches[2] ]), - new TrailingContextRow(rowGroup, lines[14], false, 13, 1), - new TrailingContextRow(rowGroup, lines[15], false, 13, 2), - - new MatchRow(rowGroup, false, 16, [ result.matches[3] ]), - new MatchRow(rowGroup, false, 17, [ result.matches[4] ]) - ] - - for (let i = 0; i < rowGroup.rows.length; ++i) { - expect(rowGroup.rows[i].data).toEqual(expectedRows[i].data) - } - }) - }) - - describe("getLineNumber", () => { - it("generates correct line numbers", () => { - const rowGroup = new ResultRowGroup( - result, - { leadingContextLineCount: 1, trailingContextLineCount: 1 } - ) - - expect(rowGroup.rows.slice(1).map(row => row.data.lineNumber)).toEqual( - [0, 1, 6, 7, 8, 12, 13, 14, 15, 16, 17] - ) - }) - }) -}) +// /** @babel */ +// +// const { +// LeadingContextRow, +// TrailingContextRow, +// ResultPathRow, +// MatchRow, +// ResultRowGroup +// } = require("../lib/project/result-row"); +// +// describe("ResultRowGroup", () => { +// const lines = (new Array(18)).fill().map((x, i) => `line-${i}`) +// const rg = (i) => [[i, 0], [i, lines[i].length]] +// const testedRowIndices = [0, 7, 13, 16, 17] +// +// const result = { +// filePath: 'fake-file-path', +// matches: testedRowIndices.map(lineNb => ({ +// range: rg(lineNb), +// leadingContextLines: lines.slice(Math.max(lineNb - 3, 0), lineNb), +// trailingContextLines: lines.slice(lineNb + 1, lineNb + 4), +// lineTextOffset: 0, +// lineText: lines[lineNb], +// matchText: 'fake-match-text' +// })) +// } +// +// describe("generateRows", () => { +// it("generates a path row and several match rows", () => { +// const rowGroup = new ResultRowGroup( +// result, +// { leadingContextLineCount: 0, trailingContextLineCount: 0 } +// ) +// +// const expectedRows = [ +// new ResultPathRow(rowGroup), +// new MatchRow(rowGroup, false, 0, [ result.matches[0] ]), +// new MatchRow(rowGroup, true, 7, [ result.matches[1] ]), +// new MatchRow(rowGroup, true, 13, [ result.matches[2] ]), +// new MatchRow(rowGroup, true, 16, [ result.matches[3] ]), +// new MatchRow(rowGroup, false, 17, [ result.matches[4] ]) +// ] +// +// for (let i = 0; i < rowGroup.rows.length; ++i) { +// expect(rowGroup.rows[i].data).toEqual(expectedRows[i].data) +// } +// }) +// +// it("generates context rows between matches", () => { +// const rowGroup = new ResultRowGroup( +// result, +// { leadingContextLineCount: 3, trailingContextLineCount: 2 } +// ) +// +// const expectedRows = [ +// new ResultPathRow(rowGroup), +// +// new MatchRow(rowGroup, false, 0, [ result.matches[0] ]), +// new TrailingContextRow(rowGroup, lines[1], false, 0, 1), +// new TrailingContextRow(rowGroup, lines[2], false, 0, 2), +// +// new LeadingContextRow(rowGroup, lines[4], true, 7, 3), +// new LeadingContextRow(rowGroup, lines[5], false, 7, 2), +// new LeadingContextRow(rowGroup, lines[6], false, 7, 1), +// new MatchRow(rowGroup, false, 7, [ result.matches[1] ]), +// new TrailingContextRow(rowGroup, lines[8], false, 7, 1), +// new TrailingContextRow(rowGroup, lines[9], false, 7, 2), +// +// new LeadingContextRow(rowGroup, lines[10], false, 13, 3), +// new LeadingContextRow(rowGroup, lines[11], false, 13, 2), +// new LeadingContextRow(rowGroup, lines[12], false, 13, 1), +// new MatchRow(rowGroup, false, 13, [ result.matches[2] ]), +// new TrailingContextRow(rowGroup, lines[14], false, 13, 1), +// new TrailingContextRow(rowGroup, lines[15], false, 13, 2), +// +// new MatchRow(rowGroup, false, 16, [ result.matches[3] ]), +// new MatchRow(rowGroup, false, 17, [ result.matches[4] ]) +// ] +// +// for (let i = 0; i < rowGroup.rows.length; ++i) { +// expect(rowGroup.rows[i].data).toEqual(expectedRows[i].data) +// } +// }) +// }) +// +// describe("getLineNumber", () => { +// it("generates correct line numbers", () => { +// const rowGroup = new ResultRowGroup( +// result, +// { leadingContextLineCount: 1, trailingContextLineCount: 1 } +// ) +// +// expect(rowGroup.rows.slice(1).map(row => row.data.lineNumber)).toEqual( +// [0, 1, 6, 7, 8, 12, 13, 14, 15, 16, 17] +// ) +// }) +// }) +// }) diff --git a/spec/results-model-spec.js b/spec/results-model-spec.js index 2e12af7f..df4fe1bf 100644 --- a/spec/results-model-spec.js +++ b/spec/results-model-spec.js @@ -1,146 +1,146 @@ -/** @babel */ - -const path = require("path"); -const ResultsModel = require("../lib/project/results-model"); -const FindOptions = require("../lib/find-options"); - -describe("ResultsModel", () => { - let editor, resultsModel, reporterSpy; - - beforeEach(async () => { - atom.config.set("core.excludeVcsIgnoredPaths", false); - atom.config.set("find-and-replace.searchContextLineCountBefore", 2); - atom.config.set("find-and-replace.searchContextLineCountAfter", 3); - atom.project.setPaths([path.join(__dirname, "fixtures/project")]); - - editor = await atom.workspace.open("sample.js"); - reporterSpy = { - sendSearchEvent: jasmine.createSpy() - } - resultsModel = new ResultsModel(new FindOptions(), reporterSpy); - }); - - describe("searching for a pattern", () => { - it("populates the model with all the results, and updates in response to changes in the buffer", async () => { - const resultAddedSpy = jasmine.createSpy(); - const resultSetSpy = jasmine.createSpy(); - const resultRemovedSpy = jasmine.createSpy(); - - resultsModel.onDidAddResult(resultAddedSpy); - resultsModel.onDidSetResult(resultSetSpy); - resultsModel.onDidRemoveResult(resultRemovedSpy); - await resultsModel.search("items", "*.js", ""); - - expect(resultAddedSpy).toHaveBeenCalled(); - expect(resultAddedSpy.callCount).toBe(1); - - let result = resultsModel.getResult(editor.getPath()); - expect(result.matches.length).toBe(6); - expect(resultsModel.getPathCount()).toBe(1); - expect(resultsModel.getMatchCount()).toBe(6); - expect(resultsModel.getPaths()).toEqual([editor.getPath()]); - expect(result.matches[0].leadingContextLines.length).toBe(1); - expect(result.matches[0].leadingContextLines[0]).toBe("var quicksort = function () {"); - expect(result.matches[0].trailingContextLines.length).toBe(3); - expect(result.matches[0].trailingContextLines[0]).toBe(" if (items.length <= 1) return items;"); - expect(result.matches[0].trailingContextLines[1]).toBe(" var pivot = items.shift(), current, left = [], right = [];"); - expect(result.matches[0].trailingContextLines[2]).toBe(" while(items.length > 0) {"); - expect(result.matches[5].leadingContextLines.length).toBe(2); - expect(result.matches[5].trailingContextLines.length).toBe(3); - - editor.setText("there are some items in here"); - advanceClock(editor.buffer.stoppedChangingDelay); - expect(resultAddedSpy.callCount).toBe(1); - expect(resultSetSpy.callCount).toBe(1); - - result = resultsModel.getResult(editor.getPath()); - expect(result.matches.length).toBe(1); - expect(resultsModel.getPathCount()).toBe(1); - expect(resultsModel.getMatchCount()).toBe(1); - expect(resultsModel.getPaths()).toEqual([editor.getPath()]); - expect(result.matches[0].lineText).toBe("there are some items in here"); - expect(result.matches[0].leadingContextLines.length).toBe(0); - expect(result.matches[0].trailingContextLines.length).toBe(0); - - editor.setText("no matches in here"); - advanceClock(editor.buffer.stoppedChangingDelay); - expect(resultAddedSpy.callCount).toBe(1); - expect(resultSetSpy.callCount).toBe(1); - expect(resultRemovedSpy.callCount).toBe(1); - - result = resultsModel.getResult(editor.getPath()); - expect(result).not.toBeDefined(); - expect(resultsModel.getPathCount()).toBe(0); - expect(resultsModel.getMatchCount()).toBe(0); - - resultsModel.clear(); - spyOn(editor, "scan").andCallThrough(); - editor.setText("no matches in here"); - advanceClock(editor.buffer.stoppedChangingDelay); - expect(editor.scan).not.toHaveBeenCalled(); - expect(resultsModel.getPathCount()).toBe(0); - expect(resultsModel.getMatchCount()).toBe(0); - }); - - it("ignores changes in untitled buffers", async () => { - await atom.workspace.open(); - await resultsModel.search("items", "*.js", ""); - - editor = atom.workspace.getCenter().getActiveTextEditor(); - editor.setText("items\nitems"); - spyOn(editor, "scan").andCallThrough(); - advanceClock(editor.buffer.stoppedChangingDelay); - expect(editor.scan).not.toHaveBeenCalled(); - }); - - it("contains valid match objects after destroying a buffer (regression)", async () => { - await resultsModel.search('items', '*.js', ''); - - advanceClock(editor.buffer.stoppedChangingDelay) - editor.getBuffer().destroy() - result = resultsModel.getResult(editor.getPath()) - expect(result.matches[0].lineText).toBe(" var sort = function(items) {") - }); - }); - - describe("cancelling a search", () => { - let cancelledSpy; - - beforeEach(() => { - cancelledSpy = jasmine.createSpy(); - resultsModel.onDidCancelSearching(cancelledSpy); - }); - - it("populates the model with all the results, and updates in response to changes in the buffer", async () => { - const searchPromise = resultsModel.search("items", "*.js", ""); - expect(resultsModel.inProgressSearchPromise).toBeTruthy(); - resultsModel.clear(); - expect(resultsModel.inProgressSearchPromise).toBeFalsy(); - - await searchPromise; - expect(cancelledSpy).toHaveBeenCalled(); - }); - - it("populates the model with all the results, and updates in response to changes in the buffer", async () => { - resultsModel.search("items", "*.js", ""); - await resultsModel.search("sort", "*.js", ""); - - expect(cancelledSpy).toHaveBeenCalled(); - expect(resultsModel.getPathCount()).toBe(1); - expect(resultsModel.getMatchCount()).toBe(5); - }); - }); - - describe("logging metrics", () => { - it("logs the elapsed time and the number of results", async () => { - await resultsModel.search('items', '*.js', ''); - - advanceClock(editor.buffer.stoppedChangingDelay) - editor.getBuffer().destroy() - result = resultsModel.getResult(editor.getPath()) - - expect(Number.isInteger(reporterSpy.sendSearchEvent.calls[0].args[0])).toBeTruthy() - expect(reporterSpy.sendSearchEvent.calls[0].args[1]).toBe(6) - }); - }); -}); +// /** @babel */ +// +// const path = require("path"); +// const ResultsModel = require("../lib/project/results-model"); +// const FindOptions = require("../lib/find-options"); +// +// describe("ResultsModel", () => { +// let editor, resultsModel, reporterSpy; +// +// beforeEach(async () => { +// atom.config.set("core.excludeVcsIgnoredPaths", false); +// atom.config.set("find-and-replace.searchContextLineCountBefore", 2); +// atom.config.set("find-and-replace.searchContextLineCountAfter", 3); +// atom.project.setPaths([path.join(__dirname, "fixtures/project")]); +// +// editor = await atom.workspace.open("sample.js"); +// reporterSpy = { +// sendSearchEvent: jasmine.createSpy() +// } +// resultsModel = new ResultsModel(new FindOptions(), reporterSpy); +// }); +// +// describe("searching for a pattern", () => { +// it("populates the model with all the results, and updates in response to changes in the buffer", async () => { +// const resultAddedSpy = jasmine.createSpy(); +// const resultSetSpy = jasmine.createSpy(); +// const resultRemovedSpy = jasmine.createSpy(); +// +// resultsModel.onDidAddResult(resultAddedSpy); +// resultsModel.onDidSetResult(resultSetSpy); +// resultsModel.onDidRemoveResult(resultRemovedSpy); +// await resultsModel.search("items", "*.js", ""); +// +// expect(resultAddedSpy).toHaveBeenCalled(); +// expect(resultAddedSpy.callCount).toBe(1); +// +// let result = resultsModel.getResult(editor.getPath()); +// expect(result.matches.length).toBe(6); +// expect(resultsModel.getPathCount()).toBe(1); +// expect(resultsModel.getMatchCount()).toBe(6); +// expect(resultsModel.getPaths()).toEqual([editor.getPath()]); +// expect(result.matches[0].leadingContextLines.length).toBe(1); +// expect(result.matches[0].leadingContextLines[0]).toBe("var quicksort = function () {"); +// expect(result.matches[0].trailingContextLines.length).toBe(3); +// expect(result.matches[0].trailingContextLines[0]).toBe(" if (items.length <= 1) return items;"); +// expect(result.matches[0].trailingContextLines[1]).toBe(" var pivot = items.shift(), current, left = [], right = [];"); +// expect(result.matches[0].trailingContextLines[2]).toBe(" while(items.length > 0) {"); +// expect(result.matches[5].leadingContextLines.length).toBe(2); +// expect(result.matches[5].trailingContextLines.length).toBe(3); +// +// editor.setText("there are some items in here"); +// advanceClock(editor.buffer.stoppedChangingDelay); +// expect(resultAddedSpy.callCount).toBe(1); +// expect(resultSetSpy.callCount).toBe(1); +// +// result = resultsModel.getResult(editor.getPath()); +// expect(result.matches.length).toBe(1); +// expect(resultsModel.getPathCount()).toBe(1); +// expect(resultsModel.getMatchCount()).toBe(1); +// expect(resultsModel.getPaths()).toEqual([editor.getPath()]); +// expect(result.matches[0].lineText).toBe("there are some items in here"); +// expect(result.matches[0].leadingContextLines.length).toBe(0); +// expect(result.matches[0].trailingContextLines.length).toBe(0); +// +// editor.setText("no matches in here"); +// advanceClock(editor.buffer.stoppedChangingDelay); +// expect(resultAddedSpy.callCount).toBe(1); +// expect(resultSetSpy.callCount).toBe(1); +// expect(resultRemovedSpy.callCount).toBe(1); +// +// result = resultsModel.getResult(editor.getPath()); +// expect(result).not.toBeDefined(); +// expect(resultsModel.getPathCount()).toBe(0); +// expect(resultsModel.getMatchCount()).toBe(0); +// +// resultsModel.clear(); +// spyOn(editor, "scan").andCallThrough(); +// editor.setText("no matches in here"); +// advanceClock(editor.buffer.stoppedChangingDelay); +// expect(editor.scan).not.toHaveBeenCalled(); +// expect(resultsModel.getPathCount()).toBe(0); +// expect(resultsModel.getMatchCount()).toBe(0); +// }); +// +// it("ignores changes in untitled buffers", async () => { +// await atom.workspace.open(); +// await resultsModel.search("items", "*.js", ""); +// +// editor = atom.workspace.getCenter().getActiveTextEditor(); +// editor.setText("items\nitems"); +// spyOn(editor, "scan").andCallThrough(); +// advanceClock(editor.buffer.stoppedChangingDelay); +// expect(editor.scan).not.toHaveBeenCalled(); +// }); +// +// it("contains valid match objects after destroying a buffer (regression)", async () => { +// await resultsModel.search('items', '*.js', ''); +// +// advanceClock(editor.buffer.stoppedChangingDelay) +// editor.getBuffer().destroy() +// result = resultsModel.getResult(editor.getPath()) +// expect(result.matches[0].lineText).toBe(" var sort = function(items) {") +// }); +// }); +// +// describe("cancelling a search", () => { +// let cancelledSpy; +// +// beforeEach(() => { +// cancelledSpy = jasmine.createSpy(); +// resultsModel.onDidCancelSearching(cancelledSpy); +// }); +// +// it("populates the model with all the results, and updates in response to changes in the buffer", async () => { +// const searchPromise = resultsModel.search("items", "*.js", ""); +// expect(resultsModel.inProgressSearchPromise).toBeTruthy(); +// resultsModel.clear(); +// expect(resultsModel.inProgressSearchPromise).toBeFalsy(); +// +// await searchPromise; +// expect(cancelledSpy).toHaveBeenCalled(); +// }); +// +// it("populates the model with all the results, and updates in response to changes in the buffer", async () => { +// resultsModel.search("items", "*.js", ""); +// await resultsModel.search("sort", "*.js", ""); +// +// expect(cancelledSpy).toHaveBeenCalled(); +// expect(resultsModel.getPathCount()).toBe(1); +// expect(resultsModel.getMatchCount()).toBe(5); +// }); +// }); +// +// describe("logging metrics", () => { +// it("logs the elapsed time and the number of results", async () => { +// await resultsModel.search('items', '*.js', ''); +// +// advanceClock(editor.buffer.stoppedChangingDelay) +// editor.getBuffer().destroy() +// result = resultsModel.getResult(editor.getPath()) +// +// expect(Number.isInteger(reporterSpy.sendSearchEvent.calls[0].args[0])).toBeTruthy() +// expect(reporterSpy.sendSearchEvent.calls[0].args[1]).toBe(6) +// }); +// }); +// }); diff --git a/spec/results-view-spec.js b/spec/results-view-spec.js index c15c3707..05de0443 100644 --- a/spec/results-view-spec.js +++ b/spec/results-view-spec.js @@ -90,205 +90,205 @@ describe('ResultsView', () => { await activationPromise; }); - describe("when the result is for a long line", () => { - it("renders the context around the match", async () => { - projectFindView.findEditor.setText('ghijkl'); - atom.commands.dispatch(projectFindView.element, 'core:confirm'); - await searchPromise; - - resultsView = getResultsView(); - expect(resultsView.refs.listView.element.querySelector('.path-name').textContent).toBe("one-long-line.coffee"); - expect(resultsView.refs.listView.element.querySelectorAll('.preview').length).toBe(1); - expect(resultsView.refs.listView.element.querySelector('.preview').textContent).toBe('test test test test test test test test test test test a b c d e f g h i j k l abcdefghijklmnopqrstuvwxyz'); - expect(resultsView.refs.listView.element.querySelector('.match').textContent).toBe('ghijkl'); - }) - }); - - describe("when there are multiple project paths", () => { - beforeEach(() => { - atom.project.addPath(temp.mkdirSync("another-project-path")) - }); - - it("includes the basename of the project path that contains the match", async () => { - projectFindView.findEditor.setText('ghijkl'); - atom.commands.dispatch(projectFindView.element, 'core:confirm'); - await searchPromise; - - resultsView = getResultsView(); - expect(resultsView.refs.listView.element.querySelector('.path-name').textContent).toBe(path.join("project", "one-long-line.coffee")); - }); - }); - - describe("rendering replacement text", () => { - let modifiedDelay = null; - - beforeEach(() => { - projectFindView.findEditor.setText('ghijkl'); - modifiedDelay = projectFindView.replaceEditor.getBuffer().stoppedChangingDelay; - }); - - it("renders the replacement when doing a search and there is a replacement pattern", async () => { - projectFindView.replaceEditor.setText('cats'); - atom.commands.dispatch(projectFindView.element, 'core:confirm'); - await searchPromise; - - resultsView = getResultsView(); - expect(resultsView.refs.listView.element.querySelector('.path-name').textContent).toBe("one-long-line.coffee"); - expect(resultsView.refs.listView.element.querySelectorAll('.preview').length).toBe(1); - expect(resultsView.refs.listView.element.querySelector('.match').textContent).toBe('ghijkl'); - expect(resultsView.refs.listView.element.querySelector('.replacement').textContent).toBe('cats'); - }); - - it("renders the replacement when changing the text in the replacement field", async () => { - atom.commands.dispatch(projectFindView.element, 'core:confirm'); - await searchPromise; - - resultsView = getResultsView(); - expect(resultsView.refs.listView.element.querySelector('.match').textContent).toBe('ghijkl'); - expect(resultsView.refs.listView.element.querySelector('.match')).toHaveClass('highlight-info'); - expect(resultsView.refs.listView.element.querySelector('.replacement').textContent).toBe(''); - expect(resultsView.refs.listView.element.querySelector('.replacement')).toBeHidden(); - - projectFindView.replaceEditor.setText('cats'); - advanceClock(modifiedDelay); - await etch.update(resultsView); - - expect(resultsView.refs.listView.element.querySelector('.match').textContent).toBe('ghijkl'); - expect(resultsView.refs.listView.element.querySelector('.match')).toHaveClass('highlight-error'); - expect(resultsView.refs.listView.element.querySelector('.replacement').textContent).toBe('cats'); - expect(resultsView.refs.listView.element.querySelector('.replacement')).toBeVisible(); - - projectFindView.replaceEditor.setText(''); - advanceClock(modifiedDelay); - await etch.update(resultsView); - - expect(resultsView.refs.listView.element.querySelector('.match').textContent).toBe('ghijkl'); - expect(resultsView.refs.listView.element.querySelector('.match')).toHaveClass('highlight-info'); - expect(resultsView.refs.listView.element.querySelector('.replacement')).toBeHidden(); - }); - - it('renders the captured text when the replace pattern uses captures', async () => { - projectFindView.refs.regexOptionButton.click(); - projectFindView.findEditor.setText('function ?(\\([^)]*\\))'); - projectFindView.replaceEditor.setText('$1 =>') - atom.commands.dispatch(projectFindView.element, 'core:confirm'); - await searchPromise; - - resultsView = getResultsView(); - const listElement = resultsView.refs.listView.element; - expect(listElement.querySelectorAll('.match')[0].textContent).toBe('function ()'); - expect(listElement.querySelectorAll('.replacement')[0].textContent).toBe('() =>'); - expect(listElement.querySelectorAll('.match')[1].textContent).toBe('function(items)'); - expect(listElement.querySelectorAll('.replacement')[1].textContent).toBe('(items) =>'); - }) - }); - - describe("core:page-up and core:page-down", () => { - beforeEach(async () => { - workspaceElement.style.height = '300px'; - workspaceElement.style.width = '1024px'; - projectFindView.findEditor.setText(' '); - projectFindView.confirm(); - - await searchPromise; - - resultsView = getResultsView(); - const {listView} = resultsView.refs; - expect(listView.element.scrollTop).toBe(0); - expect(listView.element.scrollHeight).toBeGreaterThan(listView.element.offsetHeight); - }); - - function getSelectedItem() { - return resultsView.refs.listView.element.querySelector('.selected'); - } - - function getRecursivePosition(element, substract_scroll) { - let x = 0; - let y = 0; - while (element && !isNaN(element.offsetLeft) && !isNaN(element.offsetTop)) { - x += element.offsetLeft; - y += element.offsetTop; - if (substract_scroll) { - x -= element.scrollLeft; - y -= element.scrollTop; - } - element = element.offsetParent; - } - return { top: y, left: x }; - } - - function getSelectedOffset() { - return getRecursivePosition(getSelectedItem(), true).top; - } - - function getSelectedPosition() { - return getRecursivePosition(getSelectedItem(), false).top; - } - - it("selects the first result on the next page when core:page-down is triggered", async () => { - const {listView} = resultsView.refs; - expect(listView.element.querySelectorAll('.path-row').length).not.toBeGreaterThan(resultsView.model.getPathCount()); - expect(listView.element.querySelectorAll('.match-row').length).not.toBeGreaterThan(resultsView.model.getMatchCount()); - expect(listView.element.querySelector('.path-row').parentElement).toHaveClass('selected'); - - let initiallySelectedItem = getSelectedItem(); - let initiallySelectedOffset = getSelectedOffset(); - let initiallySelectedPosition = getSelectedPosition(); - - await resultsView.pageDown(); - - expect(getSelectedItem()).not.toBe(initiallySelectedItem); - expect(getSelectedPosition()).toBeGreaterThan(initiallySelectedPosition); - - initiallySelectedItem = getSelectedItem(); - initiallySelectedOffset = getSelectedOffset(); - initiallySelectedPosition = getSelectedPosition(); - - await resultsView.pageDown(); - - expect(getSelectedItem()).not.toBe(initiallySelectedItem); - expect(getSelectedPosition()).toBeGreaterThan(initiallySelectedPosition); - - initiallySelectedPosition = getSelectedPosition(); - - for (let i = 0; i < 100; i++) resultsView.pageDown(); - await resultsView.pageDown(); - expect(_.last(resultsView.element.querySelectorAll('.match-row'))).toHaveClass('selected'); - expect(getSelectedPosition()).toBeGreaterThan(initiallySelectedPosition); - }); - - it("selects the first result on the previous page when core:page-up is triggered", async () => { - await resultsView.moveToBottom(); - expect(_.last(resultsView.element.querySelectorAll('.match-row'))).toHaveClass('selected'); - - const {listView} = resultsView.refs; - - let initiallySelectedItem = getSelectedItem(); - let initiallySelectedOffset = getSelectedOffset(); - let initiallySelectedPosition = getSelectedPosition(); - - await resultsView.pageUp(); - - expect(getSelectedItem()).not.toBe(initiallySelectedItem); - expect(getSelectedPosition()).toBeLessThan(initiallySelectedPosition); - - initiallySelectedItem = getSelectedItem(); - initiallySelectedOffset = getSelectedOffset(); - initiallySelectedPosition = getSelectedPosition(); - - await resultsView.pageUp(); - - expect(getSelectedItem()).not.toBe(initiallySelectedItem); - expect(getSelectedPosition()).toBeLessThan(initiallySelectedPosition); - - initiallySelectedPosition = getSelectedPosition(); - - for (let i = 0; i < 100; i++) resultsView.pageUp(); - await resultsView.pageUp(); - expect(listView.element.querySelector('.path-row').parentElement).toHaveClass('selected'); - expect(getSelectedPosition()).toBeLessThan(initiallySelectedPosition); - }); - }); + // describe("when the result is for a long line", () => { + // it("renders the context around the match", async () => { + // projectFindView.findEditor.setText('ghijkl'); + // atom.commands.dispatch(projectFindView.element, 'core:confirm'); + // await searchPromise; + // + // resultsView = getResultsView(); + // expect(resultsView.refs.listView.element.querySelector('.path-name').textContent).toBe("one-long-line.coffee"); + // expect(resultsView.refs.listView.element.querySelectorAll('.preview').length).toBe(1); + // expect(resultsView.refs.listView.element.querySelector('.preview').textContent).toBe('test test test test test test test test test test test a b c d e f g h i j k l abcdefghijklmnopqrstuvwxyz'); + // expect(resultsView.refs.listView.element.querySelector('.match').textContent).toBe('ghijkl'); + // }) + // }); + // + // describe("when there are multiple project paths", () => { + // beforeEach(() => { + // atom.project.addPath(temp.mkdirSync("another-project-path")) + // }); + // + // it("includes the basename of the project path that contains the match", async () => { + // projectFindView.findEditor.setText('ghijkl'); + // atom.commands.dispatch(projectFindView.element, 'core:confirm'); + // await searchPromise; + // + // resultsView = getResultsView(); + // expect(resultsView.refs.listView.element.querySelector('.path-name').textContent).toBe(path.join("project", "one-long-line.coffee")); + // }); + // }); + // + // describe("rendering replacement text", () => { + // let modifiedDelay = null; + // + // beforeEach(() => { + // projectFindView.findEditor.setText('ghijkl'); + // modifiedDelay = projectFindView.replaceEditor.getBuffer().stoppedChangingDelay; + // }); + // + // it("renders the replacement when doing a search and there is a replacement pattern", async () => { + // projectFindView.replaceEditor.setText('cats'); + // atom.commands.dispatch(projectFindView.element, 'core:confirm'); + // await searchPromise; + // + // resultsView = getResultsView(); + // expect(resultsView.refs.listView.element.querySelector('.path-name').textContent).toBe("one-long-line.coffee"); + // expect(resultsView.refs.listView.element.querySelectorAll('.preview').length).toBe(1); + // expect(resultsView.refs.listView.element.querySelector('.match').textContent).toBe('ghijkl'); + // expect(resultsView.refs.listView.element.querySelector('.replacement').textContent).toBe('cats'); + // }); + // + // it("renders the replacement when changing the text in the replacement field", async () => { + // atom.commands.dispatch(projectFindView.element, 'core:confirm'); + // await searchPromise; + // + // resultsView = getResultsView(); + // expect(resultsView.refs.listView.element.querySelector('.match').textContent).toBe('ghijkl'); + // expect(resultsView.refs.listView.element.querySelector('.match')).toHaveClass('highlight-info'); + // expect(resultsView.refs.listView.element.querySelector('.replacement').textContent).toBe(''); + // expect(resultsView.refs.listView.element.querySelector('.replacement')).toBeHidden(); + // + // projectFindView.replaceEditor.setText('cats'); + // advanceClock(modifiedDelay); + // await etch.update(resultsView); + // + // expect(resultsView.refs.listView.element.querySelector('.match').textContent).toBe('ghijkl'); + // expect(resultsView.refs.listView.element.querySelector('.match')).toHaveClass('highlight-error'); + // expect(resultsView.refs.listView.element.querySelector('.replacement').textContent).toBe('cats'); + // expect(resultsView.refs.listView.element.querySelector('.replacement')).toBeVisible(); + // + // projectFindView.replaceEditor.setText(''); + // advanceClock(modifiedDelay); + // await etch.update(resultsView); + // + // expect(resultsView.refs.listView.element.querySelector('.match').textContent).toBe('ghijkl'); + // expect(resultsView.refs.listView.element.querySelector('.match')).toHaveClass('highlight-info'); + // expect(resultsView.refs.listView.element.querySelector('.replacement')).toBeHidden(); + // }); + // + // it('renders the captured text when the replace pattern uses captures', async () => { + // projectFindView.refs.regexOptionButton.click(); + // projectFindView.findEditor.setText('function ?(\\([^)]*\\))'); + // projectFindView.replaceEditor.setText('$1 =>') + // atom.commands.dispatch(projectFindView.element, 'core:confirm'); + // await searchPromise; + // + // resultsView = getResultsView(); + // const listElement = resultsView.refs.listView.element; + // expect(listElement.querySelectorAll('.match')[0].textContent).toBe('function ()'); + // expect(listElement.querySelectorAll('.replacement')[0].textContent).toBe('() =>'); + // expect(listElement.querySelectorAll('.match')[1].textContent).toBe('function(items)'); + // expect(listElement.querySelectorAll('.replacement')[1].textContent).toBe('(items) =>'); + // }) + // }); + // + // describe("core:page-up and core:page-down", () => { + // beforeEach(async () => { + // workspaceElement.style.height = '300px'; + // workspaceElement.style.width = '1024px'; + // projectFindView.findEditor.setText(' '); + // projectFindView.confirm(); + // + // await searchPromise; + // + // resultsView = getResultsView(); + // const {listView} = resultsView.refs; + // expect(listView.element.scrollTop).toBe(0); + // expect(listView.element.scrollHeight).toBeGreaterThan(listView.element.offsetHeight); + // }); + // + // function getSelectedItem() { + // return resultsView.refs.listView.element.querySelector('.selected'); + // } + // + // function getRecursivePosition(element, substract_scroll) { + // let x = 0; + // let y = 0; + // while (element && !isNaN(element.offsetLeft) && !isNaN(element.offsetTop)) { + // x += element.offsetLeft; + // y += element.offsetTop; + // if (substract_scroll) { + // x -= element.scrollLeft; + // y -= element.scrollTop; + // } + // element = element.offsetParent; + // } + // return { top: y, left: x }; + // } + // + // function getSelectedOffset() { + // return getRecursivePosition(getSelectedItem(), true).top; + // } + // + // function getSelectedPosition() { + // return getRecursivePosition(getSelectedItem(), false).top; + // } + // + // it("selects the first result on the next page when core:page-down is triggered", async () => { + // const {listView} = resultsView.refs; + // expect(listView.element.querySelectorAll('.path-row').length).not.toBeGreaterThan(resultsView.model.getPathCount()); + // expect(listView.element.querySelectorAll('.match-row').length).not.toBeGreaterThan(resultsView.model.getMatchCount()); + // expect(listView.element.querySelector('.path-row').parentElement).toHaveClass('selected'); + // + // let initiallySelectedItem = getSelectedItem(); + // let initiallySelectedOffset = getSelectedOffset(); + // let initiallySelectedPosition = getSelectedPosition(); + // + // await resultsView.pageDown(); + // + // expect(getSelectedItem()).not.toBe(initiallySelectedItem); + // expect(getSelectedPosition()).toBeGreaterThan(initiallySelectedPosition); + // + // initiallySelectedItem = getSelectedItem(); + // initiallySelectedOffset = getSelectedOffset(); + // initiallySelectedPosition = getSelectedPosition(); + // + // await resultsView.pageDown(); + // + // expect(getSelectedItem()).not.toBe(initiallySelectedItem); + // expect(getSelectedPosition()).toBeGreaterThan(initiallySelectedPosition); + // + // initiallySelectedPosition = getSelectedPosition(); + // + // for (let i = 0; i < 100; i++) resultsView.pageDown(); + // await resultsView.pageDown(); + // expect(_.last(resultsView.element.querySelectorAll('.match-row'))).toHaveClass('selected'); + // expect(getSelectedPosition()).toBeGreaterThan(initiallySelectedPosition); + // }); + // + // it("selects the first result on the previous page when core:page-up is triggered", async () => { + // await resultsView.moveToBottom(); + // expect(_.last(resultsView.element.querySelectorAll('.match-row'))).toHaveClass('selected'); + // + // const {listView} = resultsView.refs; + // + // let initiallySelectedItem = getSelectedItem(); + // let initiallySelectedOffset = getSelectedOffset(); + // let initiallySelectedPosition = getSelectedPosition(); + // + // await resultsView.pageUp(); + // + // expect(getSelectedItem()).not.toBe(initiallySelectedItem); + // expect(getSelectedPosition()).toBeLessThan(initiallySelectedPosition); + // + // initiallySelectedItem = getSelectedItem(); + // initiallySelectedOffset = getSelectedOffset(); + // initiallySelectedPosition = getSelectedPosition(); + // + // await resultsView.pageUp(); + // + // expect(getSelectedItem()).not.toBe(initiallySelectedItem); + // expect(getSelectedPosition()).toBeLessThan(initiallySelectedPosition); + // + // initiallySelectedPosition = getSelectedPosition(); + // + // for (let i = 0; i < 100; i++) resultsView.pageUp(); + // await resultsView.pageUp(); + // expect(listView.element.querySelector('.path-row').parentElement).toHaveClass('selected'); + // expect(getSelectedPosition()).toBeLessThan(initiallySelectedPosition); + // }); + // }); describe("core:move-to-top and core:move-to-bottom", () => { beforeEach(async () => { @@ -335,658 +335,658 @@ describe('ResultsView', () => { }); }); - describe("expanding and collapsing results", () => { - it('preserves the selected file when collapsing all results', async () => { - projectFindView.findEditor.setText('items'); - atom.commands.dispatch(projectFindView.element, 'core:confirm'); - await searchPromise; - - resultsView = getResultsView(); - - resultsView.moveDown(); - resultsView.moveDown(); - await resultsView.moveDown(); - const selectedMatch = resultsView.element.querySelector('.selected'); - expect(selectedMatch).toHaveClass('match-row'); - - await resultsView.collapseAllResults(); - const selectedPath = resultsView.element.querySelector('.selected'); - expect(selectedPath.firstChild).toHaveClass('path-row'); - expect(selectedPath.firstChild.dataset.filePath).toContain('sample.coffee'); - - // Moving down while the path is collapsed moves to the next path, - // as opposed to selecting the next match within the collapsed path. - resultsView.moveDown(); - await resultsView.expandAllResults(); - const newSelectedPath = resultsView.element.querySelector('.selected'); - expect(newSelectedPath.firstChild.dataset.filePath).toContain('sample.js'); - - resultsView.moveDown(); - resultsView.moveDown(); - await resultsView.moveDown(); - expect(resultsView.element.querySelector('.selected')).toHaveClass('match-row'); - - // Moving up while the path is collapsed moves to the previous path, - // as opposed to moving up to the next match within the collapsed path. - resultsView.collapseAllResults(); - resultsView.moveUp(); - await resultsView.expandAllResults(); - expect(resultsView.element.querySelector('.selected')).toBe(selectedPath); - }); - - it('re-expands all results when running a new search', async () => { - projectFindView.findEditor.setText('items'); - atom.commands.dispatch(projectFindView.element, 'core:confirm'); - await searchPromise; - - resultsView = getResultsView(); - - await resultsView.collapseResult(); - expect(resultsView.element.querySelector('.collapsed')).not.toBe(null); - - projectFindView.findEditor.setText('sort'); - atom.commands.dispatch(projectFindView.element, 'core:confirm'); - await searchPromise; - - expect(resultsView.element.querySelector('.collapsed')).toBe(null); - }) - - it('preserves the collapsed state of the right files when results are removed', async () => { - projectFindView.findEditor.setText('push'); - atom.commands.dispatch(projectFindView.element, 'core:confirm'); - await searchPromise; - resultsView = getResultsView(); - - // collapse the first result - resultsView.selectFirstResult(); - resultsView.collapseResult(); - - // remove the first result - const firstPath = resultsView.model.getPaths()[0]; - const firstResult = resultsView.model.getResult(firstPath); - resultsView.model.removeResult(firstPath); - - // Check that the first result is not collapsed - const matchedPaths = resultsView.refs.listView.element.querySelectorAll('.path.list-nested-item'); - expect(matchedPaths[0]).not.toHaveClass('collapsed') - }); - - it('preserves the collapsed state of the right files when results are added', async () => { - projectFindView.findEditor.setText('push'); - atom.commands.dispatch(projectFindView.element, 'core:confirm'); - await searchPromise; - resultsView = getResultsView(); - - // remove the first result - const firstPath = resultsView.model.getPaths()[0]; - const firstResult = resultsView.model.getResult(firstPath); - resultsView.model.removeResult(firstPath); - - // collapse the new first result - resultsView.selectFirstResult(); - resultsView.collapseResult(); - - // re-add the old first result - resultsView.model.addResult(firstPath, firstResult); - - await etch.update(resultsView); - - // Check that the first result is not collapsed while the second one still is - const matchedPaths = resultsView.refs.listView.element.querySelectorAll('.path-row'); - expect(matchedPaths[0].parentElement).not.toHaveClass('collapsed') - expect(matchedPaths[1].parentElement).toHaveClass('collapsed') - }); - }); - - describe("opening results", () => { - beforeEach(async () => { - await atom.workspace.open('sample.js'); - - projectFindView.findEditor.setText('items'); - atom.commands.dispatch(projectFindView.element, 'core:confirm'); - await searchPromise; - - resultsView = getResultsView(); - resultsView.selectFirstResult(); - }); - - function paneItemOpening(pending = null) { - return new Promise(resolve => { - const subscription = atom.workspace.onDidOpen(({pane, item}) => { - if (pending === null || (pane.getPendingItem() === item) === pending) { - resolve() - subscription.dispose() - } - }) - }) - } - - it("opens the file containing the result when 'core:confirm' is called", async () => { - // open something in sample.coffee - resultsView.element.focus(); - _.times(3, () => atom.commands.dispatch(resultsView.element, 'core:move-down')); - atom.commands.dispatch(resultsView.element, 'core:confirm'); - await paneItemOpening() - expect(atom.workspace.getCenter().getActivePaneItem().getPath()).toContain('sample.'); - - // open something in sample.js - resultsView.element.focus(); - _.times(6, () => atom.commands.dispatch(resultsView.element, 'core:move-down')); - atom.commands.dispatch(resultsView.element, 'core:confirm'); - await paneItemOpening() - expect(atom.workspace.getCenter().getActivePaneItem().getPath()).toContain('sample.'); - }); - - it("opens the file containing the result in a non-pending state when the search result is double-clicked", async () => { - const pathNode = resultsView.refs.listView.element.querySelectorAll(".match-row")[0]; - const click1 = buildMouseEvent('mousedown', {target: pathNode, detail: 1}); - const click2 = buildMouseEvent('mousedown', {target: pathNode, detail: 2}); - pathNode.dispatchEvent(click1); - pathNode.dispatchEvent(click2); - - // Otherwise, the double click will transfer focus back to the results view - expect(click2.defaultPrevented).toBe(true); - - await paneItemOpening(false) - const editor = atom.workspace.getCenter().getActiveTextEditor(); - expect(atom.workspace.getCenter().getActivePane().getPendingItem()).toBe(null); - expect(atom.views.getView(editor)).toHaveFocus(); - }); - - it("opens the file containing the result in a pending state when the search result is single-clicked", async () => { - const pathNode = resultsView.refs.listView.element.querySelectorAll(".match-row")[0]; - pathNode.dispatchEvent(buildMouseEvent('mousedown', {target: pathNode, which: 1})); - await paneItemOpening() - const editor = atom.workspace.getCenter().getActiveTextEditor(); - expect(atom.workspace.getCenter().getActivePane().getPendingItem()).toBe(editor); - expect(atom.views.getView(editor)).toHaveFocus(); - }) - - it("Result view should maintain scroll position", async () => { - spyOn(resultsView,'setScrollTop').andCallThrough(); - - projectFindView.findEditor.setText('1'); - atom.commands.dispatch(projectFindView.element, 'core:confirm'); - await searchPromise; - - resultsView.moveToBottom(); - - const pathNode = resultsView.element.querySelector('.selected'); - pathNode.dispatchEvent(buildMouseEvent('mousedown', {target: pathNode, which: 1})); - await paneItemOpening(); - - expect(resultsView.setScrollTop).toHaveBeenCalledWith(resultsView.currentScrollTop); - }); - - describe("the `projectSearchResultsPaneSplitDirection` option", () => { - beforeEach(() => { - spyOn(atom.workspace, 'open').andCallThrough() - }); - - it("does not create a split when the option is 'none'", async () => { - atom.config.set('find-and-replace.projectSearchResultsPaneSplitDirection', 'none'); - atom.commands.dispatch(resultsView.element, 'core:move-down'); - atom.commands.dispatch(resultsView.element, 'core:confirm'); - await paneItemOpening() - expect(atom.workspace.open.mostRecentCall.args[1].split).toBeUndefined(); - }); - - it("always opens the file in the left pane when the option is 'right'", async () => { - atom.config.set('find-and-replace.projectSearchResultsPaneSplitDirection', 'right'); - atom.commands.dispatch(resultsView.element, 'core:move-down'); - atom.commands.dispatch(resultsView.element, 'core:confirm'); - await paneItemOpening() - expect(atom.workspace.open.mostRecentCall.args[1].split).toBe('left'); - }); - - it("always opens the file in the pane above when the options is 'down'", async () => { - atom.config.set('find-and-replace.projectSearchResultsPaneSplitDirection', 'down') - atom.commands.dispatch(resultsView.element, 'core:move-down'); - atom.commands.dispatch(resultsView.element, 'core:confirm'); - await paneItemOpening() - expect(atom.workspace.open.mostRecentCall.args[1].split).toBe('up'); - }); - }); - }); - - describe("arrowing through the list", () => { - it("arrows through the entire list without selecting paths and overshooting the boundaries", async () => { - await atom.workspace.open('sample.js'); - - projectFindView.findEditor.setText('items'); - atom.commands.dispatch(projectFindView.element, 'core:confirm'); - await searchPromise; - - resultsView = getResultsView(); - - let {length: resultCount} = resultsView.refs.listView.element.querySelectorAll(".match-row"); - expect(resultCount).toBe(11); - - resultsView.selectFirstResult(); - - // moves down for 11 results + 2 files - for (let i = 0; i < resultCount; ++i) { - resultsView.moveDown(); - } - await resultsView.moveDown(); - await resultsView.moveDown(); - let selectedItem = resultsView.element.querySelector('.selected'); - expect(selectedItem).toHaveClass('match-row'); - - // stays at the bottom - let lastSelectedItem = selectedItem; - await resultsView.moveDown(); - await resultsView.moveDown(); - selectedItem = resultsView.element.querySelector('.selected'); - expect(selectedItem).toBe(lastSelectedItem); - - // moves up to the top - lastSelectedItem = selectedItem; - for (let i = 0; i < resultCount; ++i) { - resultsView.moveUp(); - } - await resultsView.moveUp(); - await resultsView.moveUp(); - selectedItem = resultsView.element.querySelector('.selected'); - expect(selectedItem.firstChild).toHaveClass('path-row'); - expect(selectedItem).not.toBe(lastSelectedItem); - - // stays at the top - lastSelectedItem = selectedItem; - await resultsView.moveUp(); - await resultsView.moveUp(); - selectedItem = resultsView.element.querySelector('.selected'); - expect(selectedItem).toBe(lastSelectedItem); - }); - - describe("when there are a list of items", () => { - beforeEach(async () => { - projectFindView.findEditor.setText('items'); - atom.commands.dispatch(projectFindView.element, 'core:confirm'); - await searchPromise; - resultsView = getResultsView(); - }); - - it("shows the preview-controls", () => { - expect(getResultsPane().refs.previewControls).toBeVisible(); - expect(getResultsPane().refs.previewControls.style).not.toBe('hidden'); - }); - - it("collapses the selected results view", async () => { - clickOn(resultsView.refs.listView.element.querySelector('.match-row')); - - await resultsView.collapseResult(); - - let selectedItem = resultsView.element.querySelector('.selected'); - expect(selectedItem).toHaveClass('collapsed'); - expect(selectedItem).toBe(resultsView.refs.listView.element.querySelector('.path-row').parentElement); - }); - - it("collapses all results if collapse All button is pressed", async () => { - await resultsView.collapseAllResults(); - for (let item of Array.from(resultsView.refs.listView.element.querySelectorAll('.path-row'))) { - expect(item.parentElement).toHaveClass('collapsed'); - } - }); - - it("expands the selected results view", async () => { - clickOn(resultsView.refs.listView.element.querySelector('.path-row').parentElement); - - await resultsView.expandResult(); - - let selectedItem = resultsView.element.querySelector('.selected'); - expect(selectedItem).toHaveClass('match-row'); - expect(selectedItem).toBe(resultsView.refs.listView.element.querySelector('.match-row')); - }); - - it("expands all results if 'Expand All' button is pressed", async () => { - await resultsView.expandAllResults(); - await etch.update(resultsView.refs.listView); - for (let item of Array.from(resultsView.refs.listView.element.querySelectorAll('.path-row'))) { - expect(item.parentElement).not.toHaveClass('collapsed'); - } - }); - - describe("when there are collapsed results", () => { - it("moves to the correct prev/next result when a path is selected", async () => { - resultsView.selectRow(0); - resultsView.collapseResult(); - await resultsView.selectRow(2); - - expect(resultsView.refs.listView.element.querySelectorAll('.match-row')[0]).toHaveClass('selected'); - - await resultsView.moveUp(); - expect(resultsView.refs.listView.element.querySelectorAll('.path-row')[1].parentElement).toHaveClass('selected'); - - await resultsView.moveUp(); - expect(resultsView.refs.listView.element.querySelectorAll('.path-row')[0].parentElement).toHaveClass('selected'); - - await resultsView.moveDown(); - expect(resultsView.refs.listView.element.querySelectorAll('.path-row')[1].parentElement).toHaveClass('selected'); - }); - }); - }); - }); - - describe("when the results view is empty", () => { - it("ignores core:confirm and other commands for selecting results", async () => { - const resultsView = buildResultsView({ empty: true }); - atom.commands.dispatch(resultsView.element, 'core:confirm'); - atom.commands.dispatch(resultsView.element, 'core:move-down'); - atom.commands.dispatch(resultsView.element, 'core:move-up'); - atom.commands.dispatch(resultsView.element, 'core:move-to-top'); - atom.commands.dispatch(resultsView.element, 'core:move-to-bottom'); - atom.commands.dispatch(resultsView.element, 'core:page-down'); - atom.commands.dispatch(resultsView.element, 'core:page-up'); - }); - - it("won't show the preview-controls", async () => { - const resultsPane = new ResultsPaneView(); - expect(resultsPane.refs.previewControls.style.display).toBe('none'); - }); - }); - - describe("copying items with core:copy", () => { - it("copies the selected line onto the clipboard", () => { - const resultsView = buildResultsView(); - - resultsView.selectFirstResult(); - _.times(3, () => atom.commands.dispatch(resultsView.element, 'core:move-down')); - atom.commands.dispatch(resultsView.element, 'core:copy'); - expect(atom.clipboard.read()).toBe('goodnight moon'); - }); - }); - - describe("copying path with find-and-replace:copy-path", () => { - it("copies the selected file path to clipboard", () => { - const resultsView = buildResultsView(); - - resultsView.selectFirstResult(); - // await resultsView.collapseResult(); - atom.commands.dispatch(resultsView.element, 'find-and-replace:copy-path'); - expect(atom.clipboard.read()).toBe('/a/b.txt'); - - atom.commands.dispatch(resultsView.element, 'core:move-down'); - atom.commands.dispatch(resultsView.element, 'core:move-down'); - atom.commands.dispatch(resultsView.element, 'find-and-replace:copy-path'); - expect(atom.clipboard.read()).toBe('/c/d.txt'); - - atom.commands.dispatch(resultsView.element, 'core:move-up'); - atom.commands.dispatch(resultsView.element, 'find-and-replace:copy-path'); - expect(atom.clipboard.read()).toBe('/a/b.txt'); - }); - }); - - describe("fonts", () => { - it('respect the editor.fontFamily setting', async () => { - atom.config.set('editor.fontFamily', 'Courier'); - const resultsView = buildResultsView(); - - await etch.update(resultsView); - expect(resultsView.element.style.fontFamily).toBe('Courier'); - - atom.config.set('editor.fontFamily', 'Helvetica'); - await etch.update(resultsView); - expect(resultsView.element.style.fontFamily).toBe('Helvetica'); - }) - }); - - describe('icon services', () => { - describe('atom.file-icons', () => { - it('has a default handler', () => { - expect(getIconServices().fileIcons).toBe(DefaultFileIcons) - }) - - it('displays icons for common filetypes', () => { - expect(DefaultFileIcons.iconClassForPath('README.md')).toBe('icon-book') - expect(DefaultFileIcons.iconClassForPath('zip.zip')).toBe('icon-file-zip') - expect(DefaultFileIcons.iconClassForPath('a.gif')).toBe('icon-file-media') - expect(DefaultFileIcons.iconClassForPath('a.pdf')).toBe('icon-file-pdf') - expect(DefaultFileIcons.iconClassForPath('an.exe')).toBe('icon-file-binary') - expect(DefaultFileIcons.iconClassForPath('jg.js')).toBe('icon-file-text') - }) - - it('allows a service provider to change the handler', async () => { - const provider = { - iconClassForPath(path, context) { - expect(context).toBe('find-and-replace') - return (path.endsWith('one-long-line.coffee')) - ? 'first-icon-class second-icon-class' - : ['third-icon-class', 'fourth-icon-class'] - } - } - const disposable = atom.packages.serviceHub.provide('atom.file-icons', '1.0.0', provider); - expect(getIconServices().fileIcons).toBe(provider) - - projectFindView.findEditor.setText('i'); - atom.commands.dispatch(projectFindView.element, 'core:confirm'); - await searchPromise; - - resultsView = getResultsView(); - let fileIconClasses = Array.from(resultsView.refs.listView.element.querySelectorAll('.path-row .icon')).map(el => el.className); - expect(fileIconClasses).toContain('first-icon-class second-icon-class icon'); - expect(fileIconClasses).toContain('third-icon-class fourth-icon-class icon'); - expect(fileIconClasses).not.toContain('icon-file-text icon'); - - disposable.dispose(); - projectFindView.findEditor.setText('e'); - atom.commands.dispatch(projectFindView.element, 'core:confirm'); - - await searchPromise; - resultsView = getResultsView(); - fileIconClasses = Array.from(resultsView.refs.listView.element.querySelectorAll('.path-row .icon')).map(el => el.className); - expect(fileIconClasses).not.toContain('first-icon-class second-icon-class icon'); - expect(fileIconClasses).not.toContain('third-icon-class fourth-icon-class icon'); - expect(fileIconClasses).toContain('icon-file-text icon'); - }) - }) - - describe('file-icons.element-icons', () => { - beforeEach(() => jasmine.useRealClock()) - - it('has no default handler', () => { - expect(getIconServices().elementIcons).toBe(null) - }) - - it('uses the element-icon service if available', () => { - const iconSelector = '.path-row .icon:not([data-name="fake-file-path"])' - const provider = (element, path) => { - expect(element).toBeInstanceOf(HTMLElement) - expect(typeof path === "string").toBe(true) - expect(path.length).toBeGreaterThan(0) - const classes = path.endsWith('one-long-line.coffee') - ? ['foo', 'bar'] - : ['baz', 'qlux'] - element.classList.add(...classes) - return new Disposable(() => { - element.classList.remove(...classes) - }) - } - let disposable - - waitsForPromise(() => { - disposable = atom.packages.serviceHub.provide('file-icons.element-icons', '1.0.0', provider) - expect(getIconServices().elementIcons).toBe(provider) - projectFindView.findEditor.setText('i'); - atom.commands.dispatch(projectFindView.element, 'core:confirm'); - return searchPromise - }) - - waitsForPromise(() => delayFor(35)) - - runs(() => { - resultsView = getResultsView() - const iconElements = resultsView.element.querySelectorAll(iconSelector) - expect(iconElements[0].className.trim()).toBe('icon foo bar') - expect(iconElements[1].className.trim()).toBe('icon baz qlux') - expect(resultsView.element.querySelector('.icon-file-text')).toBe(null) - - disposable.dispose() - projectFindView.findEditor.setText('e') - atom.commands.dispatch(projectFindView.element, 'core:confirm') - }) - - waitsForPromise(() => searchPromise) - - waitsForPromise(() => delayFor(35)) - - runs(() => { - resultsView = getResultsView() - const iconElements = resultsView.element.querySelectorAll(iconSelector) - expect(iconElements[0].className.trim()).toBe('icon-file-text icon') - expect(iconElements[1].className.trim()).toBe('icon-file-text icon') - expect(resultsView.element.querySelector('.foo, .bar, .baz, .qlux')).toBe(null) - }) - }) - }) - }) - - describe('updating the search while viewing results', () => { - it('resets the results message', async () => { - projectFindView.findEditor.setText('a'); - atom.commands.dispatch(projectFindView.element, 'core:confirm'); - await searchPromise; - - resultsPane = getResultsPane(); - await etch.update(resultsPane); - expect(resultsPane.refs.previewCount.textContent).toContain('3 files'); - - projectFindView.findEditor.setText(''); - atom.commands.dispatch(projectFindView.element, 'core:confirm'); - await etch.update(resultsPane); - expect(resultsPane.refs.previewCount.textContent).toContain('Project search results'); - }) - }); - - describe('search result context lines', () => { - beforeEach(async () => { - atom.config.set('find-and-replace.searchContextLineCountBefore', 4); - atom.config.set('find-and-replace.searchContextLineCountAfter', 3); - atom.config.set('find-and-replace.leadingContextLineCount', 0); - atom.config.set('find-and-replace.trailingContextLineCount', 0); - - projectFindView.findEditor.setText('items.'); - atom.commands.dispatch(projectFindView.element, 'core:confirm'); - await searchPromise; - - resultsView = getResultsView(); - }); - - function getFirstMatchRows(resultsView) { - const {element} = resultsView.refs.listView - const rowNodes = Array.from(element.querySelectorAll('.list-item')); - const rowCount = resultsView.resultRowGroups[0].rows.filter(row => - row.data.matchLineNumber === resultsView.resultRows[1].data.matchLineNumber - ).length - return rowNodes.slice(1, 1 + rowCount); - } - - it('shows no context lines', async () => { - expect(resultsView.model.getFindOptions().leadingContextLineCount).toBe(0); - expect(resultsView.model.getFindOptions().trailingContextLineCount).toBe(0); - - const lineNodes = getFirstMatchRows(resultsView); - expect(lineNodes.length).toBe(1); - expect(lineNodes[0]).toHaveClass('match-row'); - expect(lineNodes[0].querySelector('.preview').textContent).toBe(' return items if items.length <= 1'); - }); - - it('shows 1 leading context line, 1 trailing context line', async () => { - resultsView.incrementLeadingContextLines(); - await resultsView.incrementTrailingContextLines(); - expect(resultsView.model.getFindOptions().leadingContextLineCount).toBe(1); - expect(resultsView.model.getFindOptions().trailingContextLineCount).toBe(1); - - const lineNodes = getFirstMatchRows(resultsView); - expect(lineNodes.length).toBe(3); - expect(lineNodes[0]).toHaveClass('context-row'); - /* - FIXME: I suspect this test fails because of a bug in atom's scan - See issue #16948 - expect(lineNodes[0].querySelector('.preview').textContent).toBe(' sort: (items) ->'); - */ - expect(lineNodes[1]).toHaveClass('match-row'); - expect(lineNodes[1].querySelector('.preview').textContent).toBe(' return items if items.length <= 1'); - expect(lineNodes[2]).toHaveClass('context-row'); - expect(lineNodes[2].querySelector('.preview').textContent).toBe(''); - }); - - it('shows all leading context lines, 2 trailing context lines', async () => { - resultsView.toggleLeadingContextLines(); - resultsView.incrementTrailingContextLines(); - await resultsView.incrementTrailingContextLines(); - expect(resultsView.model.getFindOptions().leadingContextLineCount).toBe(4); - expect(resultsView.model.getFindOptions().trailingContextLineCount).toBe(2); - - const lineNodes = getFirstMatchRows(resultsView); - - // There are two leading context lines after the start of the document - // There are two trailing context lines before the next match - expect(lineNodes.length).toBe(4); - - expect(lineNodes[0]).toHaveClass('context-row'); - expect(lineNodes[0].querySelector('.preview').textContent).toBe('class quicksort'); - expect(lineNodes[1]).toHaveClass('context-row'); - expect(lineNodes[1].querySelector('.preview').textContent).toBe(' sort: (items) ->'); - expect(lineNodes[2]).toHaveClass('match-row'); - expect(lineNodes[2].querySelector('.preview').textContent).toBe(' return items if items.length <= 1'); - expect(lineNodes[3]).toHaveClass('context-row'); - expect(lineNodes[3].querySelector('.preview').textContent).toBe(''); - }); - }); - - describe('selected result and match index', () => { - beforeEach(async () => { - projectFindView.findEditor.setText('push'); - atom.commands.dispatch(projectFindView.element, 'core:confirm'); - await searchPromise; - - resultsView = getResultsView(); - }); - - it('maintains selected result when adding and removing results', async () => { - { - const matchRows = resultsView.refs.listView.element.querySelectorAll('.match-row'); - expect(matchRows.length).toBe(3); - - resultsView.moveDown(); - resultsView.moveDown(); - resultsView.moveDown(); - await resultsView.moveDown(); - expect(matchRows[2]).toHaveClass('selected'); - expect(matchRows[2].querySelector('.preview').textContent).toBe(' current < pivot ? left.push(current) : right.push(current);'); - expect(resultsView.selectedRowIndex).toBe(4); - } - - // remove the first result - const firstPath = resultsView.model.getPaths()[0]; - const firstResult = resultsView.model.getResult(firstPath); - resultsView.model.removeResult(firstPath); - await etch.update(resultsView); - - // check that the same match is still selected - { - const matchRows = resultsView.refs.listView.element.querySelectorAll('.match-row'); - expect(matchRows.length).toBe(1); - expect(matchRows[0]).toHaveClass('selected'); - expect(matchRows[0].querySelector('.preview').textContent).toBe(' current < pivot ? left.push(current) : right.push(current);'); - expect(resultsView.selectedRowIndex).toBe(1); - } - - // re-add the first result - resultsView.model.addResult(firstPath, firstResult); - await etch.update(resultsView); - - // check that the same match is still selected - { - const matchRows = resultsView.refs.listView.element.querySelectorAll('.match-row'); - expect(matchRows.length).toBe(3); - expect(matchRows[2]).toHaveClass('selected'); - expect(matchRows[2].querySelector('.preview').textContent).toBe(' current < pivot ? left.push(current) : right.push(current);'); - expect(resultsView.selectedRowIndex).toBe(4); - } - }); - }) + // describe("expanding and collapsing results", () => { + // it('preserves the selected file when collapsing all results', async () => { + // projectFindView.findEditor.setText('items'); + // atom.commands.dispatch(projectFindView.element, 'core:confirm'); + // await searchPromise; + // + // resultsView = getResultsView(); + // + // resultsView.moveDown(); + // resultsView.moveDown(); + // await resultsView.moveDown(); + // const selectedMatch = resultsView.element.querySelector('.selected'); + // expect(selectedMatch).toHaveClass('match-row'); + // + // await resultsView.collapseAllResults(); + // const selectedPath = resultsView.element.querySelector('.selected'); + // expect(selectedPath.firstChild).toHaveClass('path-row'); + // expect(selectedPath.firstChild.dataset.filePath).toContain('sample.coffee'); + // + // // Moving down while the path is collapsed moves to the next path, + // // as opposed to selecting the next match within the collapsed path. + // resultsView.moveDown(); + // await resultsView.expandAllResults(); + // const newSelectedPath = resultsView.element.querySelector('.selected'); + // expect(newSelectedPath.firstChild.dataset.filePath).toContain('sample.js'); + // + // resultsView.moveDown(); + // resultsView.moveDown(); + // await resultsView.moveDown(); + // expect(resultsView.element.querySelector('.selected')).toHaveClass('match-row'); + // + // // Moving up while the path is collapsed moves to the previous path, + // // as opposed to moving up to the next match within the collapsed path. + // resultsView.collapseAllResults(); + // resultsView.moveUp(); + // await resultsView.expandAllResults(); + // expect(resultsView.element.querySelector('.selected')).toBe(selectedPath); + // }); + // + // it('re-expands all results when running a new search', async () => { + // projectFindView.findEditor.setText('items'); + // atom.commands.dispatch(projectFindView.element, 'core:confirm'); + // await searchPromise; + // + // resultsView = getResultsView(); + // + // await resultsView.collapseResult(); + // expect(resultsView.element.querySelector('.collapsed')).not.toBe(null); + // + // projectFindView.findEditor.setText('sort'); + // atom.commands.dispatch(projectFindView.element, 'core:confirm'); + // await searchPromise; + // + // expect(resultsView.element.querySelector('.collapsed')).toBe(null); + // }) + // + // it('preserves the collapsed state of the right files when results are removed', async () => { + // projectFindView.findEditor.setText('push'); + // atom.commands.dispatch(projectFindView.element, 'core:confirm'); + // await searchPromise; + // resultsView = getResultsView(); + // + // // collapse the first result + // resultsView.selectFirstResult(); + // resultsView.collapseResult(); + // + // // remove the first result + // const firstPath = resultsView.model.getPaths()[0]; + // const firstResult = resultsView.model.getResult(firstPath); + // resultsView.model.removeResult(firstPath); + // + // // Check that the first result is not collapsed + // const matchedPaths = resultsView.refs.listView.element.querySelectorAll('.path.list-nested-item'); + // expect(matchedPaths[0]).not.toHaveClass('collapsed') + // }); + // + // it('preserves the collapsed state of the right files when results are added', async () => { + // projectFindView.findEditor.setText('push'); + // atom.commands.dispatch(projectFindView.element, 'core:confirm'); + // await searchPromise; + // resultsView = getResultsView(); + // + // // remove the first result + // const firstPath = resultsView.model.getPaths()[0]; + // const firstResult = resultsView.model.getResult(firstPath); + // resultsView.model.removeResult(firstPath); + // + // // collapse the new first result + // resultsView.selectFirstResult(); + // resultsView.collapseResult(); + // + // // re-add the old first result + // resultsView.model.addResult(firstPath, firstResult); + // + // await etch.update(resultsView); + // + // // Check that the first result is not collapsed while the second one still is + // const matchedPaths = resultsView.refs.listView.element.querySelectorAll('.path-row'); + // expect(matchedPaths[0].parentElement).not.toHaveClass('collapsed') + // expect(matchedPaths[1].parentElement).toHaveClass('collapsed') + // }); + // }); + // + // describe("opening results", () => { + // beforeEach(async () => { + // await atom.workspace.open('sample.js'); + // + // projectFindView.findEditor.setText('items'); + // atom.commands.dispatch(projectFindView.element, 'core:confirm'); + // await searchPromise; + // + // resultsView = getResultsView(); + // resultsView.selectFirstResult(); + // }); + // + // function paneItemOpening(pending = null) { + // return new Promise(resolve => { + // const subscription = atom.workspace.onDidOpen(({pane, item}) => { + // if (pending === null || (pane.getPendingItem() === item) === pending) { + // resolve() + // subscription.dispose() + // } + // }) + // }) + // } + // + // it("opens the file containing the result when 'core:confirm' is called", async () => { + // // open something in sample.coffee + // resultsView.element.focus(); + // _.times(3, () => atom.commands.dispatch(resultsView.element, 'core:move-down')); + // atom.commands.dispatch(resultsView.element, 'core:confirm'); + // await paneItemOpening() + // expect(atom.workspace.getCenter().getActivePaneItem().getPath()).toContain('sample.'); + // + // // open something in sample.js + // resultsView.element.focus(); + // _.times(6, () => atom.commands.dispatch(resultsView.element, 'core:move-down')); + // atom.commands.dispatch(resultsView.element, 'core:confirm'); + // await paneItemOpening() + // expect(atom.workspace.getCenter().getActivePaneItem().getPath()).toContain('sample.'); + // }); + // + // it("opens the file containing the result in a non-pending state when the search result is double-clicked", async () => { + // const pathNode = resultsView.refs.listView.element.querySelectorAll(".match-row")[0]; + // const click1 = buildMouseEvent('mousedown', {target: pathNode, detail: 1}); + // const click2 = buildMouseEvent('mousedown', {target: pathNode, detail: 2}); + // pathNode.dispatchEvent(click1); + // pathNode.dispatchEvent(click2); + // + // // Otherwise, the double click will transfer focus back to the results view + // expect(click2.defaultPrevented).toBe(true); + // + // await paneItemOpening(false) + // const editor = atom.workspace.getCenter().getActiveTextEditor(); + // expect(atom.workspace.getCenter().getActivePane().getPendingItem()).toBe(null); + // expect(atom.views.getView(editor)).toHaveFocus(); + // }); + // + // it("opens the file containing the result in a pending state when the search result is single-clicked", async () => { + // const pathNode = resultsView.refs.listView.element.querySelectorAll(".match-row")[0]; + // pathNode.dispatchEvent(buildMouseEvent('mousedown', {target: pathNode, which: 1})); + // await paneItemOpening() + // const editor = atom.workspace.getCenter().getActiveTextEditor(); + // expect(atom.workspace.getCenter().getActivePane().getPendingItem()).toBe(editor); + // expect(atom.views.getView(editor)).toHaveFocus(); + // }) + // + // it("Result view should maintain scroll position", async () => { + // spyOn(resultsView,'setScrollTop').andCallThrough(); + // + // projectFindView.findEditor.setText('1'); + // atom.commands.dispatch(projectFindView.element, 'core:confirm'); + // await searchPromise; + // + // resultsView.moveToBottom(); + // + // const pathNode = resultsView.element.querySelector('.selected'); + // pathNode.dispatchEvent(buildMouseEvent('mousedown', {target: pathNode, which: 1})); + // await paneItemOpening(); + // + // expect(resultsView.setScrollTop).toHaveBeenCalledWith(resultsView.currentScrollTop); + // }); + // + // describe("the `projectSearchResultsPaneSplitDirection` option", () => { + // beforeEach(() => { + // spyOn(atom.workspace, 'open').andCallThrough() + // }); + // + // it("does not create a split when the option is 'none'", async () => { + // atom.config.set('find-and-replace.projectSearchResultsPaneSplitDirection', 'none'); + // atom.commands.dispatch(resultsView.element, 'core:move-down'); + // atom.commands.dispatch(resultsView.element, 'core:confirm'); + // await paneItemOpening() + // expect(atom.workspace.open.mostRecentCall.args[1].split).toBeUndefined(); + // }); + // + // it("always opens the file in the left pane when the option is 'right'", async () => { + // atom.config.set('find-and-replace.projectSearchResultsPaneSplitDirection', 'right'); + // atom.commands.dispatch(resultsView.element, 'core:move-down'); + // atom.commands.dispatch(resultsView.element, 'core:confirm'); + // await paneItemOpening() + // expect(atom.workspace.open.mostRecentCall.args[1].split).toBe('left'); + // }); + // + // it("always opens the file in the pane above when the options is 'down'", async () => { + // atom.config.set('find-and-replace.projectSearchResultsPaneSplitDirection', 'down') + // atom.commands.dispatch(resultsView.element, 'core:move-down'); + // atom.commands.dispatch(resultsView.element, 'core:confirm'); + // await paneItemOpening() + // expect(atom.workspace.open.mostRecentCall.args[1].split).toBe('up'); + // }); + // }); + // }); + // + // describe("arrowing through the list", () => { + // it("arrows through the entire list without selecting paths and overshooting the boundaries", async () => { + // await atom.workspace.open('sample.js'); + // + // projectFindView.findEditor.setText('items'); + // atom.commands.dispatch(projectFindView.element, 'core:confirm'); + // await searchPromise; + // + // resultsView = getResultsView(); + // + // let {length: resultCount} = resultsView.refs.listView.element.querySelectorAll(".match-row"); + // expect(resultCount).toBe(11); + // + // resultsView.selectFirstResult(); + // + // // moves down for 11 results + 2 files + // for (let i = 0; i < resultCount; ++i) { + // resultsView.moveDown(); + // } + // await resultsView.moveDown(); + // await resultsView.moveDown(); + // let selectedItem = resultsView.element.querySelector('.selected'); + // expect(selectedItem).toHaveClass('match-row'); + // + // // stays at the bottom + // let lastSelectedItem = selectedItem; + // await resultsView.moveDown(); + // await resultsView.moveDown(); + // selectedItem = resultsView.element.querySelector('.selected'); + // expect(selectedItem).toBe(lastSelectedItem); + // + // // moves up to the top + // lastSelectedItem = selectedItem; + // for (let i = 0; i < resultCount; ++i) { + // resultsView.moveUp(); + // } + // await resultsView.moveUp(); + // await resultsView.moveUp(); + // selectedItem = resultsView.element.querySelector('.selected'); + // expect(selectedItem.firstChild).toHaveClass('path-row'); + // expect(selectedItem).not.toBe(lastSelectedItem); + // + // // stays at the top + // lastSelectedItem = selectedItem; + // await resultsView.moveUp(); + // await resultsView.moveUp(); + // selectedItem = resultsView.element.querySelector('.selected'); + // expect(selectedItem).toBe(lastSelectedItem); + // }); + // + // describe("when there are a list of items", () => { + // beforeEach(async () => { + // projectFindView.findEditor.setText('items'); + // atom.commands.dispatch(projectFindView.element, 'core:confirm'); + // await searchPromise; + // resultsView = getResultsView(); + // }); + // + // it("shows the preview-controls", () => { + // expect(getResultsPane().refs.previewControls).toBeVisible(); + // expect(getResultsPane().refs.previewControls.style).not.toBe('hidden'); + // }); + // + // it("collapses the selected results view", async () => { + // clickOn(resultsView.refs.listView.element.querySelector('.match-row')); + // + // await resultsView.collapseResult(); + // + // let selectedItem = resultsView.element.querySelector('.selected'); + // expect(selectedItem).toHaveClass('collapsed'); + // expect(selectedItem).toBe(resultsView.refs.listView.element.querySelector('.path-row').parentElement); + // }); + // + // it("collapses all results if collapse All button is pressed", async () => { + // await resultsView.collapseAllResults(); + // for (let item of Array.from(resultsView.refs.listView.element.querySelectorAll('.path-row'))) { + // expect(item.parentElement).toHaveClass('collapsed'); + // } + // }); + // + // it("expands the selected results view", async () => { + // clickOn(resultsView.refs.listView.element.querySelector('.path-row').parentElement); + // + // await resultsView.expandResult(); + // + // let selectedItem = resultsView.element.querySelector('.selected'); + // expect(selectedItem).toHaveClass('match-row'); + // expect(selectedItem).toBe(resultsView.refs.listView.element.querySelector('.match-row')); + // }); + // + // it("expands all results if 'Expand All' button is pressed", async () => { + // await resultsView.expandAllResults(); + // await etch.update(resultsView.refs.listView); + // for (let item of Array.from(resultsView.refs.listView.element.querySelectorAll('.path-row'))) { + // expect(item.parentElement).not.toHaveClass('collapsed'); + // } + // }); + // + // describe("when there are collapsed results", () => { + // it("moves to the correct prev/next result when a path is selected", async () => { + // resultsView.selectRow(0); + // resultsView.collapseResult(); + // await resultsView.selectRow(2); + // + // expect(resultsView.refs.listView.element.querySelectorAll('.match-row')[0]).toHaveClass('selected'); + // + // await resultsView.moveUp(); + // expect(resultsView.refs.listView.element.querySelectorAll('.path-row')[1].parentElement).toHaveClass('selected'); + // + // await resultsView.moveUp(); + // expect(resultsView.refs.listView.element.querySelectorAll('.path-row')[0].parentElement).toHaveClass('selected'); + // + // await resultsView.moveDown(); + // expect(resultsView.refs.listView.element.querySelectorAll('.path-row')[1].parentElement).toHaveClass('selected'); + // }); + // }); + // }); + // }); + // + // describe("when the results view is empty", () => { + // it("ignores core:confirm and other commands for selecting results", async () => { + // const resultsView = buildResultsView({ empty: true }); + // atom.commands.dispatch(resultsView.element, 'core:confirm'); + // atom.commands.dispatch(resultsView.element, 'core:move-down'); + // atom.commands.dispatch(resultsView.element, 'core:move-up'); + // atom.commands.dispatch(resultsView.element, 'core:move-to-top'); + // atom.commands.dispatch(resultsView.element, 'core:move-to-bottom'); + // atom.commands.dispatch(resultsView.element, 'core:page-down'); + // atom.commands.dispatch(resultsView.element, 'core:page-up'); + // }); + // + // it("won't show the preview-controls", async () => { + // const resultsPane = new ResultsPaneView(); + // expect(resultsPane.refs.previewControls.style.display).toBe('none'); + // }); + // }); + // + // describe("copying items with core:copy", () => { + // it("copies the selected line onto the clipboard", () => { + // const resultsView = buildResultsView(); + // + // resultsView.selectFirstResult(); + // _.times(3, () => atom.commands.dispatch(resultsView.element, 'core:move-down')); + // atom.commands.dispatch(resultsView.element, 'core:copy'); + // expect(atom.clipboard.read()).toBe('goodnight moon'); + // }); + // }); + // + // describe("copying path with find-and-replace:copy-path", () => { + // it("copies the selected file path to clipboard", () => { + // const resultsView = buildResultsView(); + // + // resultsView.selectFirstResult(); + // // await resultsView.collapseResult(); + // atom.commands.dispatch(resultsView.element, 'find-and-replace:copy-path'); + // expect(atom.clipboard.read()).toBe('/a/b.txt'); + // + // atom.commands.dispatch(resultsView.element, 'core:move-down'); + // atom.commands.dispatch(resultsView.element, 'core:move-down'); + // atom.commands.dispatch(resultsView.element, 'find-and-replace:copy-path'); + // expect(atom.clipboard.read()).toBe('/c/d.txt'); + // + // atom.commands.dispatch(resultsView.element, 'core:move-up'); + // atom.commands.dispatch(resultsView.element, 'find-and-replace:copy-path'); + // expect(atom.clipboard.read()).toBe('/a/b.txt'); + // }); + // }); + // + // describe("fonts", () => { + // it('respect the editor.fontFamily setting', async () => { + // atom.config.set('editor.fontFamily', 'Courier'); + // const resultsView = buildResultsView(); + // + // await etch.update(resultsView); + // expect(resultsView.element.style.fontFamily).toBe('Courier'); + // + // atom.config.set('editor.fontFamily', 'Helvetica'); + // await etch.update(resultsView); + // expect(resultsView.element.style.fontFamily).toBe('Helvetica'); + // }) + // }); + // + // describe('icon services', () => { + // describe('atom.file-icons', () => { + // it('has a default handler', () => { + // expect(getIconServices().fileIcons).toBe(DefaultFileIcons) + // }) + // + // it('displays icons for common filetypes', () => { + // expect(DefaultFileIcons.iconClassForPath('README.md')).toBe('icon-book') + // expect(DefaultFileIcons.iconClassForPath('zip.zip')).toBe('icon-file-zip') + // expect(DefaultFileIcons.iconClassForPath('a.gif')).toBe('icon-file-media') + // expect(DefaultFileIcons.iconClassForPath('a.pdf')).toBe('icon-file-pdf') + // expect(DefaultFileIcons.iconClassForPath('an.exe')).toBe('icon-file-binary') + // expect(DefaultFileIcons.iconClassForPath('jg.js')).toBe('icon-file-text') + // }) + // + // it('allows a service provider to change the handler', async () => { + // const provider = { + // iconClassForPath(path, context) { + // expect(context).toBe('find-and-replace') + // return (path.endsWith('one-long-line.coffee')) + // ? 'first-icon-class second-icon-class' + // : ['third-icon-class', 'fourth-icon-class'] + // } + // } + // const disposable = atom.packages.serviceHub.provide('atom.file-icons', '1.0.0', provider); + // expect(getIconServices().fileIcons).toBe(provider) + // + // projectFindView.findEditor.setText('i'); + // atom.commands.dispatch(projectFindView.element, 'core:confirm'); + // await searchPromise; + // + // resultsView = getResultsView(); + // let fileIconClasses = Array.from(resultsView.refs.listView.element.querySelectorAll('.path-row .icon')).map(el => el.className); + // expect(fileIconClasses).toContain('first-icon-class second-icon-class icon'); + // expect(fileIconClasses).toContain('third-icon-class fourth-icon-class icon'); + // expect(fileIconClasses).not.toContain('icon-file-text icon'); + // + // disposable.dispose(); + // projectFindView.findEditor.setText('e'); + // atom.commands.dispatch(projectFindView.element, 'core:confirm'); + // + // await searchPromise; + // resultsView = getResultsView(); + // fileIconClasses = Array.from(resultsView.refs.listView.element.querySelectorAll('.path-row .icon')).map(el => el.className); + // expect(fileIconClasses).not.toContain('first-icon-class second-icon-class icon'); + // expect(fileIconClasses).not.toContain('third-icon-class fourth-icon-class icon'); + // expect(fileIconClasses).toContain('icon-file-text icon'); + // }) + // }) + // + // describe('file-icons.element-icons', () => { + // beforeEach(() => jasmine.useRealClock()) + // + // it('has no default handler', () => { + // expect(getIconServices().elementIcons).toBe(null) + // }) + // + // it('uses the element-icon service if available', () => { + // const iconSelector = '.path-row .icon:not([data-name="fake-file-path"])' + // const provider = (element, path) => { + // expect(element).toBeInstanceOf(HTMLElement) + // expect(typeof path === "string").toBe(true) + // expect(path.length).toBeGreaterThan(0) + // const classes = path.endsWith('one-long-line.coffee') + // ? ['foo', 'bar'] + // : ['baz', 'qlux'] + // element.classList.add(...classes) + // return new Disposable(() => { + // element.classList.remove(...classes) + // }) + // } + // let disposable + // + // waitsForPromise(() => { + // disposable = atom.packages.serviceHub.provide('file-icons.element-icons', '1.0.0', provider) + // expect(getIconServices().elementIcons).toBe(provider) + // projectFindView.findEditor.setText('i'); + // atom.commands.dispatch(projectFindView.element, 'core:confirm'); + // return searchPromise + // }) + // + // waitsForPromise(() => delayFor(35)) + // + // runs(() => { + // resultsView = getResultsView() + // const iconElements = resultsView.element.querySelectorAll(iconSelector) + // expect(iconElements[0].className.trim()).toBe('icon foo bar') + // expect(iconElements[1].className.trim()).toBe('icon baz qlux') + // expect(resultsView.element.querySelector('.icon-file-text')).toBe(null) + // + // disposable.dispose() + // projectFindView.findEditor.setText('e') + // atom.commands.dispatch(projectFindView.element, 'core:confirm') + // }) + // + // waitsForPromise(() => searchPromise) + // + // waitsForPromise(() => delayFor(35)) + // + // runs(() => { + // resultsView = getResultsView() + // const iconElements = resultsView.element.querySelectorAll(iconSelector) + // expect(iconElements[0].className.trim()).toBe('icon-file-text icon') + // expect(iconElements[1].className.trim()).toBe('icon-file-text icon') + // expect(resultsView.element.querySelector('.foo, .bar, .baz, .qlux')).toBe(null) + // }) + // }) + // }) + // }) + // + // describe('updating the search while viewing results', () => { + // it('resets the results message', async () => { + // projectFindView.findEditor.setText('a'); + // atom.commands.dispatch(projectFindView.element, 'core:confirm'); + // await searchPromise; + // + // resultsPane = getResultsPane(); + // await etch.update(resultsPane); + // expect(resultsPane.refs.previewCount.textContent).toContain('3 files'); + // + // projectFindView.findEditor.setText(''); + // atom.commands.dispatch(projectFindView.element, 'core:confirm'); + // await etch.update(resultsPane); + // expect(resultsPane.refs.previewCount.textContent).toContain('Project search results'); + // }) + // }); + // + // describe('search result context lines', () => { + // beforeEach(async () => { + // atom.config.set('find-and-replace.searchContextLineCountBefore', 4); + // atom.config.set('find-and-replace.searchContextLineCountAfter', 3); + // atom.config.set('find-and-replace.leadingContextLineCount', 0); + // atom.config.set('find-and-replace.trailingContextLineCount', 0); + // + // projectFindView.findEditor.setText('items.'); + // atom.commands.dispatch(projectFindView.element, 'core:confirm'); + // await searchPromise; + // + // resultsView = getResultsView(); + // }); + // + // function getFirstMatchRows(resultsView) { + // const {element} = resultsView.refs.listView + // const rowNodes = Array.from(element.querySelectorAll('.list-item')); + // const rowCount = resultsView.resultRowGroups[0].rows.filter(row => + // row.data.matchLineNumber === resultsView.resultRows[1].data.matchLineNumber + // ).length + // return rowNodes.slice(1, 1 + rowCount); + // } + // + // it('shows no context lines', async () => { + // expect(resultsView.model.getFindOptions().leadingContextLineCount).toBe(0); + // expect(resultsView.model.getFindOptions().trailingContextLineCount).toBe(0); + // + // const lineNodes = getFirstMatchRows(resultsView); + // expect(lineNodes.length).toBe(1); + // expect(lineNodes[0]).toHaveClass('match-row'); + // expect(lineNodes[0].querySelector('.preview').textContent).toBe(' return items if items.length <= 1'); + // }); + // + // it('shows 1 leading context line, 1 trailing context line', async () => { + // resultsView.incrementLeadingContextLines(); + // await resultsView.incrementTrailingContextLines(); + // expect(resultsView.model.getFindOptions().leadingContextLineCount).toBe(1); + // expect(resultsView.model.getFindOptions().trailingContextLineCount).toBe(1); + // + // const lineNodes = getFirstMatchRows(resultsView); + // expect(lineNodes.length).toBe(3); + // expect(lineNodes[0]).toHaveClass('context-row'); + // /* + // FIXME: I suspect this test fails because of a bug in atom's scan + // See issue #16948 + // expect(lineNodes[0].querySelector('.preview').textContent).toBe(' sort: (items) ->'); + // */ + // expect(lineNodes[1]).toHaveClass('match-row'); + // expect(lineNodes[1].querySelector('.preview').textContent).toBe(' return items if items.length <= 1'); + // expect(lineNodes[2]).toHaveClass('context-row'); + // expect(lineNodes[2].querySelector('.preview').textContent).toBe(''); + // }); + // + // it('shows all leading context lines, 2 trailing context lines', async () => { + // resultsView.toggleLeadingContextLines(); + // resultsView.incrementTrailingContextLines(); + // await resultsView.incrementTrailingContextLines(); + // expect(resultsView.model.getFindOptions().leadingContextLineCount).toBe(4); + // expect(resultsView.model.getFindOptions().trailingContextLineCount).toBe(2); + // + // const lineNodes = getFirstMatchRows(resultsView); + // + // // There are two leading context lines after the start of the document + // // There are two trailing context lines before the next match + // expect(lineNodes.length).toBe(4); + // + // expect(lineNodes[0]).toHaveClass('context-row'); + // expect(lineNodes[0].querySelector('.preview').textContent).toBe('class quicksort'); + // expect(lineNodes[1]).toHaveClass('context-row'); + // expect(lineNodes[1].querySelector('.preview').textContent).toBe(' sort: (items) ->'); + // expect(lineNodes[2]).toHaveClass('match-row'); + // expect(lineNodes[2].querySelector('.preview').textContent).toBe(' return items if items.length <= 1'); + // expect(lineNodes[3]).toHaveClass('context-row'); + // expect(lineNodes[3].querySelector('.preview').textContent).toBe(''); + // }); + // }); + // + // describe('selected result and match index', () => { + // beforeEach(async () => { + // projectFindView.findEditor.setText('push'); + // atom.commands.dispatch(projectFindView.element, 'core:confirm'); + // await searchPromise; + // + // resultsView = getResultsView(); + // }); + // + // it('maintains selected result when adding and removing results', async () => { + // { + // const matchRows = resultsView.refs.listView.element.querySelectorAll('.match-row'); + // expect(matchRows.length).toBe(3); + // + // resultsView.moveDown(); + // resultsView.moveDown(); + // resultsView.moveDown(); + // await resultsView.moveDown(); + // expect(matchRows[2]).toHaveClass('selected'); + // expect(matchRows[2].querySelector('.preview').textContent).toBe(' current < pivot ? left.push(current) : right.push(current);'); + // expect(resultsView.selectedRowIndex).toBe(4); + // } + // + // // remove the first result + // const firstPath = resultsView.model.getPaths()[0]; + // const firstResult = resultsView.model.getResult(firstPath); + // resultsView.model.removeResult(firstPath); + // await etch.update(resultsView); + // + // // check that the same match is still selected + // { + // const matchRows = resultsView.refs.listView.element.querySelectorAll('.match-row'); + // expect(matchRows.length).toBe(1); + // expect(matchRows[0]).toHaveClass('selected'); + // expect(matchRows[0].querySelector('.preview').textContent).toBe(' current < pivot ? left.push(current) : right.push(current);'); + // expect(resultsView.selectedRowIndex).toBe(1); + // } + // + // // re-add the first result + // resultsView.model.addResult(firstPath, firstResult); + // await etch.update(resultsView); + // + // // check that the same match is still selected + // { + // const matchRows = resultsView.refs.listView.element.querySelectorAll('.match-row'); + // expect(matchRows.length).toBe(3); + // expect(matchRows[2]).toHaveClass('selected'); + // expect(matchRows[2].querySelector('.preview').textContent).toBe(' current < pivot ? left.push(current) : right.push(current);'); + // expect(resultsView.selectedRowIndex).toBe(4); + // } + // }); + // }) }); function buildMouseEvent(type, properties) { diff --git a/spec/select-next-spec.js b/spec/select-next-spec.js index 6b13f45d..14236db5 100644 --- a/spec/select-next-spec.js +++ b/spec/select-next-spec.js @@ -1,636 +1,636 @@ -/** @babel */ - -const path = require('path'); -const SelectNext = require('../lib/select-next'); -const dedent = require('dedent'); - -describe("SelectNext", () => { - let workspaceElement, editorElement, editor; - - beforeEach(async () => { - workspaceElement = atom.views.getView(atom.workspace); - atom.project.setPaths([path.join(__dirname, 'fixtures')]); - - editor = await atom.workspace.open('sample.js'); - editorElement = atom.views.getView(editor); - - jasmine.attachToDOM(workspaceElement); - const activationPromise = atom.packages.activatePackage("find-and-replace"); - atom.commands.dispatch(editorElement, 'find-and-replace:show'); - await activationPromise; - }); - - describe("find-and-replace:select-next", () => { - describe("when nothing is selected", () => { - it("selects the word under the cursor", () => { - editor.setCursorBufferPosition([1, 3]); - atom.commands.dispatch(editorElement, 'find-and-replace:select-next'); - expect(editor.getSelectedBufferRanges()).toEqual([[[1, 2], [1, 5]]]); - }); - }); - - describe("when a word is selected", () => { - describe("when the selection was created using select-next", () => { - beforeEach(() => {}); - - it("selects the next occurrence of the selected word skipping any non-word matches", () => { - editor.setText(dedent` - for - information - format - another for - fork - a 3rd for is here - `); - - editor.setCursorBufferPosition([0, 0]); - atom.commands.dispatch(editorElement, 'find-and-replace:select-next'); - expect(editor.getSelectedBufferRanges()).toEqual([ - [[0, 0], [0, 3]] - ]); - - atom.commands.dispatch(editorElement, 'find-and-replace:select-next'); - expect(editor.getSelectedBufferRanges()).toEqual([ - [[0, 0], [0, 3]], - [[3, 8], [3, 11]] - ]); - - atom.commands.dispatch(editorElement, 'find-and-replace:select-next'); - expect(editor.getSelectedBufferRanges()).toEqual([ - [[0, 0], [0, 3]], - [[3, 8], [3, 11]], - [[5, 6], [5, 9]] - ]); - - atom.commands.dispatch(editorElement, 'find-and-replace:select-next'); - expect(editor.getSelectedBufferRanges()).toEqual([ - [[0, 0], [0, 3]], - [[3, 8], [3, 11]], - [[5, 6], [5, 9]] - ]); - - editor.setText("Testing reallyTesting"); - editor.setCursorBufferPosition([0, 0]); - - atom.commands.dispatch(editorElement, 'find-and-replace:select-next'); - expect(editor.getSelectedBufferRanges()).toEqual([ - [[0, 0], [0, 7]] - ]); - - atom.commands.dispatch(editorElement, 'find-and-replace:select-next'); - expect(editor.getSelectedBufferRanges()).toEqual([ - [[0, 0], [0, 7]] - ]);});}); - - describe("when the selection was not created using select-next", () => { - it("selects the next occurrence of the selected characters including non-word matches", () => { - editor.setText(dedent` - for - information - format - another for - fork - a 3rd for is here - `); - - editor.setSelectedBufferRange([[0, 0], [0, 3]]); - - atom.commands.dispatch(editorElement, 'find-and-replace:select-next'); - expect(editor.getSelectedBufferRanges()).toEqual([ - [[0, 0], [0, 3]], - [[1, 2], [1, 5]] - ]); - - atom.commands.dispatch(editorElement, 'find-and-replace:select-next'); - expect(editor.getSelectedBufferRanges()).toEqual([ - [[0, 0], [0, 3]], - [[1, 2], [1, 5]], - [[2, 0], [2, 3]] - ]); - - atom.commands.dispatch(editorElement, 'find-and-replace:select-next'); - expect(editor.getSelectedBufferRanges()).toEqual([ - [[0, 0], [0, 3]], - [[1, 2], [1, 5]], - [[2, 0], [2, 3]], - [[3, 8], [3, 11]] - ]); - - editor.setText("Testing reallyTesting"); - editor.setSelectedBufferRange([[0, 0], [0, 7]]); - - atom.commands.dispatch(editorElement, 'find-and-replace:select-next'); - expect(editor.getSelectedBufferRanges()).toEqual([ - [[0, 0], [0, 7]], - [[0, 14], [0, 21]] - ]); - }); - }); - }); - - describe("when part of a word is selected", () => { - it("selects the next occurrence of the selected text", () => { - editor.setText(dedent` - for - information - format - another for - fork - a 3rd for is here - `); - - editor.setSelectedBufferRange([[1, 2], [1, 5]]); - - atom.commands.dispatch(editorElement, 'find-and-replace:select-next'); - expect(editor.getSelectedBufferRanges()).toEqual([ - [[1, 2], [1, 5]], - [[2, 0], [2, 3]] - ]); - - atom.commands.dispatch(editorElement, 'find-and-replace:select-next'); - expect(editor.getSelectedBufferRanges()).toEqual([ - [[1, 2], [1, 5]], - [[2, 0], [2, 3]], - [[3, 8], [3, 11]] - ]); - - atom.commands.dispatch(editorElement, 'find-and-replace:select-next'); - expect(editor.getSelectedBufferRanges()).toEqual([ - [[1, 2], [1, 5]], - [[2, 0], [2, 3]], - [[3, 8], [3, 11]], - [[4, 0], [4, 3]] - ]); - - atom.commands.dispatch(editorElement, 'find-and-replace:select-next'); - expect(editor.getSelectedBufferRanges()).toEqual([ - [[1, 2], [1, 5]], - [[2, 0], [2, 3]], - [[3, 8], [3, 11]], - [[4, 0], [4, 3]], - [[5, 6], [5, 9]] - ]); - - atom.commands.dispatch(editorElement, 'find-and-replace:select-next'); - expect(editor.getSelectedBufferRanges()).toEqual([ - [[1, 2], [1, 5]], - [[2, 0], [2, 3]], - [[3, 8], [3, 11]], - [[4, 0], [4, 3]], - [[5, 6], [5, 9]], - [[0, 0], [0, 3]] - ]); - }); - }); - - describe("when a non-word is selected", () => { - it("selects the next occurrence of the selected text", () => { - editor.setText(dedent` - { - it("does not select the newlines", () => { - editor.setText(dedent` - a - - a - `); - - atom.commands.dispatch(editorElement, 'find-and-replace:select-next'); - expect(editor.getSelectedBufferRanges()).toEqual([ - [[0, 0], [0, 1]] - ]); - - atom.commands.dispatch(editorElement, 'find-and-replace:select-next'); - expect(editor.getSelectedBufferRanges()).toEqual([ - [[0, 0], [0, 1]], - [[2, 0], [2, 1]] - ]); - - atom.commands.dispatch(editorElement, 'find-and-replace:select-next'); - expect(editor.getSelectedBufferRanges()).toEqual([ - [[0, 0], [0, 1]], - [[2, 0], [2, 1]] - ]); - }); - }); - - it('honors the reversed orientation of previous selections', () => { - editor.setText('ab ab ab ab') - editor.setSelectedBufferRange([[0, 0], [0, 2]], {reversed: true}) - - atom.commands.dispatch(editorElement, 'find-and-replace:select-next') - expect(editor.getSelections().length).toBe(2) - expect(editor.getSelections().every(s => s.isReversed())).toBe(true) - - atom.commands.dispatch(editorElement, 'find-and-replace:select-next') - expect(editor.getSelections().length).toBe(3) - expect(editor.getSelections().every(s => s.isReversed())).toBe(true) - - editor.setSelectedBufferRange([[0, 0], [0, 2]], {reversed: false}) - - atom.commands.dispatch(editorElement, 'find-and-replace:select-next') - expect(editor.getSelections().length).toBe(2) - expect(editor.getSelections().every(s => !s.isReversed())).toBe(true) - - atom.commands.dispatch(editorElement, 'find-and-replace:select-next') - expect(editor.getSelections().length).toBe(3) - expect(editor.getSelections().every(s => !s.isReversed())).toBe(true) - }) - }); - - describe("find-and-replace:select-all", () => { - describe("when there is no selection", () => { - it("find and selects all occurrences of the word under the cursor", () => { - editor.setText(dedent` - for - information - format - another for - fork - a 3rd for is here - `); - - atom.commands.dispatch(editorElement, 'find-and-replace:select-all'); - expect(editor.getSelectedBufferRanges()).toEqual([ - [[0, 0], [0, 3]], - [[3, 8], [3, 11]], - [[5, 6], [5, 9]] - ]); - - atom.commands.dispatch(editorElement, 'find-and-replace:select-all'); - expect(editor.getSelectedBufferRanges()).toEqual([ - [[0, 0], [0, 3]], - [[3, 8], [3, 11]], - [[5, 6], [5, 9]] - ]); - }) - }); - - describe("when a word is selected", () => { - describe("when the word was selected using select-next", () => { - it("find and selects all occurrences of the word", () => { - editor.setText(dedent` - for - information - format - another for - fork - a 3rd for is here - `); - - atom.commands.dispatch(editorElement, 'find-and-replace:select-all'); - expect(editor.getSelectedBufferRanges()).toEqual([ - [[0, 0], [0, 3]], - [[3, 8], [3, 11]], - [[5, 6], [5, 9]] - ]); - - atom.commands.dispatch(editorElement, 'find-and-replace:select-all'); - expect(editor.getSelectedBufferRanges()).toEqual([ - [[0, 0], [0, 3]], - [[3, 8], [3, 11]], - [[5, 6], [5, 9]] - ]); - }); - }); - - describe("when the word was not selected using select-next", () => { - it("find and selects all occurrences including non-words", () => { - editor.setText(dedent` - for - information - format - another for - fork - a 3rd for is here - `); - - editor.setSelectedBufferRange([[3, 8], [3, 11]]); - - atom.commands.dispatch(editorElement, 'find-and-replace:select-all'); - expect(editor.getSelectedBufferRanges()).toEqual([ - [[3, 8], [3, 11]], - [[0, 0], [0, 3]], - [[1, 2], [1, 5]], - [[2, 0], [2, 3]], - [[4, 0], [4, 3]], - [[5, 6], [5, 9]] - ]); - }); - }); - }); - - describe("when a non-word is selected", () => { - it("selects the next occurrence of the selected text", () => { - editor.setText(dedent` - { - editor.setText('ab ab ab ab') - editor.setSelectedBufferRange([[0, 0], [0, 2]], {reversed: true}) - - atom.commands.dispatch(editorElement, 'find-and-replace:select-all') - expect(editor.getSelections().length).toBe(4) - expect(editor.getSelections().every(s => s.isReversed())).toBe(true) - - editor.setSelectedBufferRange([[0, 0], [0, 2]], {reversed: false}) - - atom.commands.dispatch(editorElement, 'find-and-replace:select-all') - expect(editor.getSelections().length).toBe(4) - expect(editor.getSelections().every(s => !s.isReversed())).toBe(true) - }) - }); - - describe("find-and-replace:select-undo", () => { - describe("when there is no selection", () => { - it("does nothing", () => { - editor.setText(dedent` - for - information - format - another for - fork - a 3rd for is here - `); - - atom.commands.dispatch(editorElement, 'find-and-replace:select-undo'); - expect(editor.getSelectedBufferRanges()).toEqual([ - [[0, 0], [0, 0]] - ]); - }) - }); - - describe("when a word is selected", () => { - it("unselects current word", () => { - editor.setText(dedent` - for - information - format - another for - fork - a 3rd for is here - `); - - editor.setSelectedBufferRange([[3, 8], [3, 11]]); - - atom.commands.dispatch(editorElement, 'find-and-replace:select-undo'); - expect(editor.getSelectedBufferRanges()).toEqual([ - [[3, 11], [3, 11]] - ]); - }) - }); - - describe("when two words are selected", () => { - it("unselects words in order", () => { - editor.setText(dedent` - for - information - format - another for - fork - a 3rd for is here - `); - - editor.setSelectedBufferRange([[3, 8], [3, 11]]); - - atom.commands.dispatch(editorElement, 'find-and-replace:select-next'); - atom.commands.dispatch(editorElement, 'find-and-replace:select-undo'); - expect(editor.getSelectedBufferRanges()).toEqual([ - [[3, 8], [3, 11]] - ]); - - atom.commands.dispatch(editorElement, 'find-and-replace:select-undo'); - expect(editor.getSelectedBufferRanges()).toEqual([ - [[3, 11], [3, 11]] - ]); - }) - }); - - describe("when three words are selected", () => { - it("unselects words in order", () => { - editor.setText(dedent` - for - information - format - another for - fork - a 3rd for is here - `); - - editor.setCursorBufferPosition([0, 0]); - atom.commands.dispatch(editorElement, 'find-and-replace:select-next'); - atom.commands.dispatch(editorElement, 'find-and-replace:select-next'); - atom.commands.dispatch(editorElement, 'find-and-replace:select-next'); - - atom.commands.dispatch(editorElement, 'find-and-replace:select-undo'); - expect(editor.getSelectedBufferRanges()).toEqual([ - [[0, 0], [0, 3]], - [[3, 8], [3, 11]] - ]); - - atom.commands.dispatch(editorElement, 'find-and-replace:select-undo'); - expect(editor.getSelectedBufferRanges()).toEqual([ - [[0, 0], [0, 3]] - ]); - }) - }); - - describe("when starting at the bottom word", () => { - it("unselects words in order", () => { - editor.setText(dedent` - for - information - format - another for - fork - a 3rd for is here - `); - - editor.setCursorBufferPosition([5, 7]); - atom.commands.dispatch(editorElement, 'find-and-replace:select-next'); - expect(editor.getSelectedBufferRanges()).toEqual([ - [[5, 6], [5, 9]] - ]); - atom.commands.dispatch(editorElement, 'find-and-replace:select-next'); - expect(editor.getSelectedBufferRanges()).toEqual([ - [[5, 6], [5, 9]], - [[0, 0], [0, 3]] - ]); - atom.commands.dispatch(editorElement, 'find-and-replace:select-undo'); - expect(editor.getSelectedBufferRanges()).toEqual([ - [[5, 6], [5, 9]] - ]);}); - - it("doesn't stack previously selected", () => { - editor.setText(dedent` - for - information - format - another for - fork - a 3rd for is here - `); - - editor.setCursorBufferPosition([5, 7]); - atom.commands.dispatch(editorElement, 'find-and-replace:select-next'); - expect(editor.getSelectedBufferRanges()).toEqual([ - [[5, 6], [5, 9]] - ]); - atom.commands.dispatch(editorElement, 'find-and-replace:select-next'); - atom.commands.dispatch(editorElement, 'find-and-replace:select-next'); - atom.commands.dispatch(editorElement, 'find-and-replace:select-next'); - atom.commands.dispatch(editorElement, 'find-and-replace:select-undo'); - expect(editor.getSelectedBufferRanges()).toEqual([ - [[5, 6], [5, 9]], - [[0, 0], [0, 3]] - ]); - }); - }); - }); - - describe("find-and-replace:select-skip", () => { - describe("when there is no selection", () => { - it("does nothing", () => { - editor.setText(dedent` - for - information - format - another for - fork - a 3rd for is here - `); - - atom.commands.dispatch(editorElement, 'find-and-replace:select-skip'); - expect(editor.getSelectedBufferRanges()).toEqual([ - [[0, 0], [0, 0]] - ]); - }) - }); - - describe("when a word is selected", () => { - it("unselects current word and selects next match", () => { - editor.setText(dedent` - for - information - format - another for - fork - a 3rd for is here - `); - - editor.setCursorBufferPosition([3, 8]); - atom.commands.dispatch(editorElement, 'find-and-replace:select-next'); - expect(editor.getSelectedBufferRanges()).toEqual([ - [[3, 8], [3, 11]] - ]); - - atom.commands.dispatch(editorElement, 'find-and-replace:select-skip'); - expect(editor.getSelectedBufferRanges()).toEqual([ - [[5, 6], [5, 9]] - ]); - }) - }); - - describe("when two words are selected", () => { - it("unselects second word and selects next match", () => { - editor.setText(dedent` - for - information - format - another for - fork - a 3rd for is here - `); - - editor.setCursorBufferPosition([0, 0]); - atom.commands.dispatch(editorElement, 'find-and-replace:select-next'); - expect(editor.getSelectedBufferRanges()).toEqual([ - [[0, 0], [0, 3]] - ]); - - atom.commands.dispatch(editorElement, 'find-and-replace:select-next'); - atom.commands.dispatch(editorElement, 'find-and-replace:select-skip'); - expect(editor.getSelectedBufferRanges()).toEqual([ - [[0, 0], [0, 3]], - [[5, 6], [5, 9]] - ]); - - atom.commands.dispatch(editorElement, 'find-and-replace:select-skip'); - expect(editor.getSelectedBufferRanges()).toEqual([ - [[0, 0], [0, 3]] - ]); - }); - }); - - describe("when starting at the bottom word", () => { - it("unselects second word and selects next match", () => { - editor.setText(dedent` - for - information - format - another for - fork - a 3rd for is here - `); - - editor.setCursorBufferPosition([5, 7]); - atom.commands.dispatch(editorElement, 'find-and-replace:select-next'); - expect(editor.getSelectedBufferRanges()).toEqual([ - [[5, 6], [5, 9]] - ]); - atom.commands.dispatch(editorElement, 'find-and-replace:select-next'); - atom.commands.dispatch(editorElement, 'find-and-replace:select-skip'); - expect(editor.getSelectedBufferRanges()).toEqual([ - [[5, 6], [5, 9]], - [[3, 8], [3, 11]] - ]); - }); - }); - - it('honors the reversed orientation of previous selections', () => { - editor.setText('ab ab ab ab') - editor.setSelectedBufferRange([[0, 0], [0, 2]], {reversed: true}) - - atom.commands.dispatch(editorElement, 'find-and-replace:select-skip') - expect(editor.getSelections().length).toBe(1) - expect(editor.getSelections().every(s => s.isReversed())).toBe(true) - - atom.commands.dispatch(editorElement, 'find-and-replace:select-next') - atom.commands.dispatch(editorElement, 'find-and-replace:select-skip') - expect(editor.getSelections().length).toBe(2) - expect(editor.getSelections().every(s => s.isReversed())).toBe(true) - - editor.setSelectedBufferRange([[0, 0], [0, 2]], {reversed: false}) - - atom.commands.dispatch(editorElement, 'find-and-replace:select-skip') - expect(editor.getSelections().length).toBe(1) - expect(editor.getSelections().every(s => !s.isReversed())).toBe(true) - - atom.commands.dispatch(editorElement, 'find-and-replace:select-next') - atom.commands.dispatch(editorElement, 'find-and-replace:select-skip') - expect(editor.getSelections().length).toBe(2) - expect(editor.getSelections().every(s => !s.isReversed())).toBe(true) - }) - }); -}); +// /** @babel */ +// +// const path = require('path'); +// const SelectNext = require('../lib/select-next'); +// const dedent = require('dedent'); +// +// describe("SelectNext", () => { +// let workspaceElement, editorElement, editor; +// +// beforeEach(async () => { +// workspaceElement = atom.views.getView(atom.workspace); +// atom.project.setPaths([path.join(__dirname, 'fixtures')]); +// +// editor = await atom.workspace.open('sample.js'); +// editorElement = atom.views.getView(editor); +// +// jasmine.attachToDOM(workspaceElement); +// const activationPromise = atom.packages.activatePackage("find-and-replace"); +// atom.commands.dispatch(editorElement, 'find-and-replace:show'); +// await activationPromise; +// }); +// +// describe("find-and-replace:select-next", () => { +// describe("when nothing is selected", () => { +// it("selects the word under the cursor", () => { +// editor.setCursorBufferPosition([1, 3]); +// atom.commands.dispatch(editorElement, 'find-and-replace:select-next'); +// expect(editor.getSelectedBufferRanges()).toEqual([[[1, 2], [1, 5]]]); +// }); +// }); +// +// describe("when a word is selected", () => { +// describe("when the selection was created using select-next", () => { +// beforeEach(() => {}); +// +// it("selects the next occurrence of the selected word skipping any non-word matches", () => { +// editor.setText(dedent` +// for +// information +// format +// another for +// fork +// a 3rd for is here +// `); +// +// editor.setCursorBufferPosition([0, 0]); +// atom.commands.dispatch(editorElement, 'find-and-replace:select-next'); +// expect(editor.getSelectedBufferRanges()).toEqual([ +// [[0, 0], [0, 3]] +// ]); +// +// atom.commands.dispatch(editorElement, 'find-and-replace:select-next'); +// expect(editor.getSelectedBufferRanges()).toEqual([ +// [[0, 0], [0, 3]], +// [[3, 8], [3, 11]] +// ]); +// +// atom.commands.dispatch(editorElement, 'find-and-replace:select-next'); +// expect(editor.getSelectedBufferRanges()).toEqual([ +// [[0, 0], [0, 3]], +// [[3, 8], [3, 11]], +// [[5, 6], [5, 9]] +// ]); +// +// atom.commands.dispatch(editorElement, 'find-and-replace:select-next'); +// expect(editor.getSelectedBufferRanges()).toEqual([ +// [[0, 0], [0, 3]], +// [[3, 8], [3, 11]], +// [[5, 6], [5, 9]] +// ]); +// +// editor.setText("Testing reallyTesting"); +// editor.setCursorBufferPosition([0, 0]); +// +// atom.commands.dispatch(editorElement, 'find-and-replace:select-next'); +// expect(editor.getSelectedBufferRanges()).toEqual([ +// [[0, 0], [0, 7]] +// ]); +// +// atom.commands.dispatch(editorElement, 'find-and-replace:select-next'); +// expect(editor.getSelectedBufferRanges()).toEqual([ +// [[0, 0], [0, 7]] +// ]);});}); +// +// describe("when the selection was not created using select-next", () => { +// it("selects the next occurrence of the selected characters including non-word matches", () => { +// editor.setText(dedent` +// for +// information +// format +// another for +// fork +// a 3rd for is here +// `); +// +// editor.setSelectedBufferRange([[0, 0], [0, 3]]); +// +// atom.commands.dispatch(editorElement, 'find-and-replace:select-next'); +// expect(editor.getSelectedBufferRanges()).toEqual([ +// [[0, 0], [0, 3]], +// [[1, 2], [1, 5]] +// ]); +// +// atom.commands.dispatch(editorElement, 'find-and-replace:select-next'); +// expect(editor.getSelectedBufferRanges()).toEqual([ +// [[0, 0], [0, 3]], +// [[1, 2], [1, 5]], +// [[2, 0], [2, 3]] +// ]); +// +// atom.commands.dispatch(editorElement, 'find-and-replace:select-next'); +// expect(editor.getSelectedBufferRanges()).toEqual([ +// [[0, 0], [0, 3]], +// [[1, 2], [1, 5]], +// [[2, 0], [2, 3]], +// [[3, 8], [3, 11]] +// ]); +// +// editor.setText("Testing reallyTesting"); +// editor.setSelectedBufferRange([[0, 0], [0, 7]]); +// +// atom.commands.dispatch(editorElement, 'find-and-replace:select-next'); +// expect(editor.getSelectedBufferRanges()).toEqual([ +// [[0, 0], [0, 7]], +// [[0, 14], [0, 21]] +// ]); +// }); +// }); +// }); +// +// describe("when part of a word is selected", () => { +// it("selects the next occurrence of the selected text", () => { +// editor.setText(dedent` +// for +// information +// format +// another for +// fork +// a 3rd for is here +// `); +// +// editor.setSelectedBufferRange([[1, 2], [1, 5]]); +// +// atom.commands.dispatch(editorElement, 'find-and-replace:select-next'); +// expect(editor.getSelectedBufferRanges()).toEqual([ +// [[1, 2], [1, 5]], +// [[2, 0], [2, 3]] +// ]); +// +// atom.commands.dispatch(editorElement, 'find-and-replace:select-next'); +// expect(editor.getSelectedBufferRanges()).toEqual([ +// [[1, 2], [1, 5]], +// [[2, 0], [2, 3]], +// [[3, 8], [3, 11]] +// ]); +// +// atom.commands.dispatch(editorElement, 'find-and-replace:select-next'); +// expect(editor.getSelectedBufferRanges()).toEqual([ +// [[1, 2], [1, 5]], +// [[2, 0], [2, 3]], +// [[3, 8], [3, 11]], +// [[4, 0], [4, 3]] +// ]); +// +// atom.commands.dispatch(editorElement, 'find-and-replace:select-next'); +// expect(editor.getSelectedBufferRanges()).toEqual([ +// [[1, 2], [1, 5]], +// [[2, 0], [2, 3]], +// [[3, 8], [3, 11]], +// [[4, 0], [4, 3]], +// [[5, 6], [5, 9]] +// ]); +// +// atom.commands.dispatch(editorElement, 'find-and-replace:select-next'); +// expect(editor.getSelectedBufferRanges()).toEqual([ +// [[1, 2], [1, 5]], +// [[2, 0], [2, 3]], +// [[3, 8], [3, 11]], +// [[4, 0], [4, 3]], +// [[5, 6], [5, 9]], +// [[0, 0], [0, 3]] +// ]); +// }); +// }); +// +// describe("when a non-word is selected", () => { +// it("selects the next occurrence of the selected text", () => { +// editor.setText(dedent` +// { +// it("does not select the newlines", () => { +// editor.setText(dedent` +// a +// +// a +// `); +// +// atom.commands.dispatch(editorElement, 'find-and-replace:select-next'); +// expect(editor.getSelectedBufferRanges()).toEqual([ +// [[0, 0], [0, 1]] +// ]); +// +// atom.commands.dispatch(editorElement, 'find-and-replace:select-next'); +// expect(editor.getSelectedBufferRanges()).toEqual([ +// [[0, 0], [0, 1]], +// [[2, 0], [2, 1]] +// ]); +// +// atom.commands.dispatch(editorElement, 'find-and-replace:select-next'); +// expect(editor.getSelectedBufferRanges()).toEqual([ +// [[0, 0], [0, 1]], +// [[2, 0], [2, 1]] +// ]); +// }); +// }); +// +// it('honors the reversed orientation of previous selections', () => { +// editor.setText('ab ab ab ab') +// editor.setSelectedBufferRange([[0, 0], [0, 2]], {reversed: true}) +// +// atom.commands.dispatch(editorElement, 'find-and-replace:select-next') +// expect(editor.getSelections().length).toBe(2) +// expect(editor.getSelections().every(s => s.isReversed())).toBe(true) +// +// atom.commands.dispatch(editorElement, 'find-and-replace:select-next') +// expect(editor.getSelections().length).toBe(3) +// expect(editor.getSelections().every(s => s.isReversed())).toBe(true) +// +// editor.setSelectedBufferRange([[0, 0], [0, 2]], {reversed: false}) +// +// atom.commands.dispatch(editorElement, 'find-and-replace:select-next') +// expect(editor.getSelections().length).toBe(2) +// expect(editor.getSelections().every(s => !s.isReversed())).toBe(true) +// +// atom.commands.dispatch(editorElement, 'find-and-replace:select-next') +// expect(editor.getSelections().length).toBe(3) +// expect(editor.getSelections().every(s => !s.isReversed())).toBe(true) +// }) +// }); +// +// describe("find-and-replace:select-all", () => { +// describe("when there is no selection", () => { +// it("find and selects all occurrences of the word under the cursor", () => { +// editor.setText(dedent` +// for +// information +// format +// another for +// fork +// a 3rd for is here +// `); +// +// atom.commands.dispatch(editorElement, 'find-and-replace:select-all'); +// expect(editor.getSelectedBufferRanges()).toEqual([ +// [[0, 0], [0, 3]], +// [[3, 8], [3, 11]], +// [[5, 6], [5, 9]] +// ]); +// +// atom.commands.dispatch(editorElement, 'find-and-replace:select-all'); +// expect(editor.getSelectedBufferRanges()).toEqual([ +// [[0, 0], [0, 3]], +// [[3, 8], [3, 11]], +// [[5, 6], [5, 9]] +// ]); +// }) +// }); +// +// describe("when a word is selected", () => { +// describe("when the word was selected using select-next", () => { +// it("find and selects all occurrences of the word", () => { +// editor.setText(dedent` +// for +// information +// format +// another for +// fork +// a 3rd for is here +// `); +// +// atom.commands.dispatch(editorElement, 'find-and-replace:select-all'); +// expect(editor.getSelectedBufferRanges()).toEqual([ +// [[0, 0], [0, 3]], +// [[3, 8], [3, 11]], +// [[5, 6], [5, 9]] +// ]); +// +// atom.commands.dispatch(editorElement, 'find-and-replace:select-all'); +// expect(editor.getSelectedBufferRanges()).toEqual([ +// [[0, 0], [0, 3]], +// [[3, 8], [3, 11]], +// [[5, 6], [5, 9]] +// ]); +// }); +// }); +// +// describe("when the word was not selected using select-next", () => { +// it("find and selects all occurrences including non-words", () => { +// editor.setText(dedent` +// for +// information +// format +// another for +// fork +// a 3rd for is here +// `); +// +// editor.setSelectedBufferRange([[3, 8], [3, 11]]); +// +// atom.commands.dispatch(editorElement, 'find-and-replace:select-all'); +// expect(editor.getSelectedBufferRanges()).toEqual([ +// [[3, 8], [3, 11]], +// [[0, 0], [0, 3]], +// [[1, 2], [1, 5]], +// [[2, 0], [2, 3]], +// [[4, 0], [4, 3]], +// [[5, 6], [5, 9]] +// ]); +// }); +// }); +// }); +// +// describe("when a non-word is selected", () => { +// it("selects the next occurrence of the selected text", () => { +// editor.setText(dedent` +// { +// editor.setText('ab ab ab ab') +// editor.setSelectedBufferRange([[0, 0], [0, 2]], {reversed: true}) +// +// atom.commands.dispatch(editorElement, 'find-and-replace:select-all') +// expect(editor.getSelections().length).toBe(4) +// expect(editor.getSelections().every(s => s.isReversed())).toBe(true) +// +// editor.setSelectedBufferRange([[0, 0], [0, 2]], {reversed: false}) +// +// atom.commands.dispatch(editorElement, 'find-and-replace:select-all') +// expect(editor.getSelections().length).toBe(4) +// expect(editor.getSelections().every(s => !s.isReversed())).toBe(true) +// }) +// }); +// +// describe("find-and-replace:select-undo", () => { +// describe("when there is no selection", () => { +// it("does nothing", () => { +// editor.setText(dedent` +// for +// information +// format +// another for +// fork +// a 3rd for is here +// `); +// +// atom.commands.dispatch(editorElement, 'find-and-replace:select-undo'); +// expect(editor.getSelectedBufferRanges()).toEqual([ +// [[0, 0], [0, 0]] +// ]); +// }) +// }); +// +// describe("when a word is selected", () => { +// it("unselects current word", () => { +// editor.setText(dedent` +// for +// information +// format +// another for +// fork +// a 3rd for is here +// `); +// +// editor.setSelectedBufferRange([[3, 8], [3, 11]]); +// +// atom.commands.dispatch(editorElement, 'find-and-replace:select-undo'); +// expect(editor.getSelectedBufferRanges()).toEqual([ +// [[3, 11], [3, 11]] +// ]); +// }) +// }); +// +// describe("when two words are selected", () => { +// it("unselects words in order", () => { +// editor.setText(dedent` +// for +// information +// format +// another for +// fork +// a 3rd for is here +// `); +// +// editor.setSelectedBufferRange([[3, 8], [3, 11]]); +// +// atom.commands.dispatch(editorElement, 'find-and-replace:select-next'); +// atom.commands.dispatch(editorElement, 'find-and-replace:select-undo'); +// expect(editor.getSelectedBufferRanges()).toEqual([ +// [[3, 8], [3, 11]] +// ]); +// +// atom.commands.dispatch(editorElement, 'find-and-replace:select-undo'); +// expect(editor.getSelectedBufferRanges()).toEqual([ +// [[3, 11], [3, 11]] +// ]); +// }) +// }); +// +// describe("when three words are selected", () => { +// it("unselects words in order", () => { +// editor.setText(dedent` +// for +// information +// format +// another for +// fork +// a 3rd for is here +// `); +// +// editor.setCursorBufferPosition([0, 0]); +// atom.commands.dispatch(editorElement, 'find-and-replace:select-next'); +// atom.commands.dispatch(editorElement, 'find-and-replace:select-next'); +// atom.commands.dispatch(editorElement, 'find-and-replace:select-next'); +// +// atom.commands.dispatch(editorElement, 'find-and-replace:select-undo'); +// expect(editor.getSelectedBufferRanges()).toEqual([ +// [[0, 0], [0, 3]], +// [[3, 8], [3, 11]] +// ]); +// +// atom.commands.dispatch(editorElement, 'find-and-replace:select-undo'); +// expect(editor.getSelectedBufferRanges()).toEqual([ +// [[0, 0], [0, 3]] +// ]); +// }) +// }); +// +// describe("when starting at the bottom word", () => { +// it("unselects words in order", () => { +// editor.setText(dedent` +// for +// information +// format +// another for +// fork +// a 3rd for is here +// `); +// +// editor.setCursorBufferPosition([5, 7]); +// atom.commands.dispatch(editorElement, 'find-and-replace:select-next'); +// expect(editor.getSelectedBufferRanges()).toEqual([ +// [[5, 6], [5, 9]] +// ]); +// atom.commands.dispatch(editorElement, 'find-and-replace:select-next'); +// expect(editor.getSelectedBufferRanges()).toEqual([ +// [[5, 6], [5, 9]], +// [[0, 0], [0, 3]] +// ]); +// atom.commands.dispatch(editorElement, 'find-and-replace:select-undo'); +// expect(editor.getSelectedBufferRanges()).toEqual([ +// [[5, 6], [5, 9]] +// ]);}); +// +// it("doesn't stack previously selected", () => { +// editor.setText(dedent` +// for +// information +// format +// another for +// fork +// a 3rd for is here +// `); +// +// editor.setCursorBufferPosition([5, 7]); +// atom.commands.dispatch(editorElement, 'find-and-replace:select-next'); +// expect(editor.getSelectedBufferRanges()).toEqual([ +// [[5, 6], [5, 9]] +// ]); +// atom.commands.dispatch(editorElement, 'find-and-replace:select-next'); +// atom.commands.dispatch(editorElement, 'find-and-replace:select-next'); +// atom.commands.dispatch(editorElement, 'find-and-replace:select-next'); +// atom.commands.dispatch(editorElement, 'find-and-replace:select-undo'); +// expect(editor.getSelectedBufferRanges()).toEqual([ +// [[5, 6], [5, 9]], +// [[0, 0], [0, 3]] +// ]); +// }); +// }); +// }); +// +// describe("find-and-replace:select-skip", () => { +// describe("when there is no selection", () => { +// it("does nothing", () => { +// editor.setText(dedent` +// for +// information +// format +// another for +// fork +// a 3rd for is here +// `); +// +// atom.commands.dispatch(editorElement, 'find-and-replace:select-skip'); +// expect(editor.getSelectedBufferRanges()).toEqual([ +// [[0, 0], [0, 0]] +// ]); +// }) +// }); +// +// describe("when a word is selected", () => { +// it("unselects current word and selects next match", () => { +// editor.setText(dedent` +// for +// information +// format +// another for +// fork +// a 3rd for is here +// `); +// +// editor.setCursorBufferPosition([3, 8]); +// atom.commands.dispatch(editorElement, 'find-and-replace:select-next'); +// expect(editor.getSelectedBufferRanges()).toEqual([ +// [[3, 8], [3, 11]] +// ]); +// +// atom.commands.dispatch(editorElement, 'find-and-replace:select-skip'); +// expect(editor.getSelectedBufferRanges()).toEqual([ +// [[5, 6], [5, 9]] +// ]); +// }) +// }); +// +// describe("when two words are selected", () => { +// it("unselects second word and selects next match", () => { +// editor.setText(dedent` +// for +// information +// format +// another for +// fork +// a 3rd for is here +// `); +// +// editor.setCursorBufferPosition([0, 0]); +// atom.commands.dispatch(editorElement, 'find-and-replace:select-next'); +// expect(editor.getSelectedBufferRanges()).toEqual([ +// [[0, 0], [0, 3]] +// ]); +// +// atom.commands.dispatch(editorElement, 'find-and-replace:select-next'); +// atom.commands.dispatch(editorElement, 'find-and-replace:select-skip'); +// expect(editor.getSelectedBufferRanges()).toEqual([ +// [[0, 0], [0, 3]], +// [[5, 6], [5, 9]] +// ]); +// +// atom.commands.dispatch(editorElement, 'find-and-replace:select-skip'); +// expect(editor.getSelectedBufferRanges()).toEqual([ +// [[0, 0], [0, 3]] +// ]); +// }); +// }); +// +// describe("when starting at the bottom word", () => { +// it("unselects second word and selects next match", () => { +// editor.setText(dedent` +// for +// information +// format +// another for +// fork +// a 3rd for is here +// `); +// +// editor.setCursorBufferPosition([5, 7]); +// atom.commands.dispatch(editorElement, 'find-and-replace:select-next'); +// expect(editor.getSelectedBufferRanges()).toEqual([ +// [[5, 6], [5, 9]] +// ]); +// atom.commands.dispatch(editorElement, 'find-and-replace:select-next'); +// atom.commands.dispatch(editorElement, 'find-and-replace:select-skip'); +// expect(editor.getSelectedBufferRanges()).toEqual([ +// [[5, 6], [5, 9]], +// [[3, 8], [3, 11]] +// ]); +// }); +// }); +// +// it('honors the reversed orientation of previous selections', () => { +// editor.setText('ab ab ab ab') +// editor.setSelectedBufferRange([[0, 0], [0, 2]], {reversed: true}) +// +// atom.commands.dispatch(editorElement, 'find-and-replace:select-skip') +// expect(editor.getSelections().length).toBe(1) +// expect(editor.getSelections().every(s => s.isReversed())).toBe(true) +// +// atom.commands.dispatch(editorElement, 'find-and-replace:select-next') +// atom.commands.dispatch(editorElement, 'find-and-replace:select-skip') +// expect(editor.getSelections().length).toBe(2) +// expect(editor.getSelections().every(s => s.isReversed())).toBe(true) +// +// editor.setSelectedBufferRange([[0, 0], [0, 2]], {reversed: false}) +// +// atom.commands.dispatch(editorElement, 'find-and-replace:select-skip') +// expect(editor.getSelections().length).toBe(1) +// expect(editor.getSelections().every(s => !s.isReversed())).toBe(true) +// +// atom.commands.dispatch(editorElement, 'find-and-replace:select-next') +// atom.commands.dispatch(editorElement, 'find-and-replace:select-skip') +// expect(editor.getSelections().length).toBe(2) +// expect(editor.getSelections().every(s => !s.isReversed())).toBe(true) +// }) +// }); +// }); From 7fda43636eaaabeda87a531930ef85eb88ded54b Mon Sep 17 00:00:00 2001 From: Benjamin Gray Date: Fri, 18 Sep 2020 12:14:37 +1000 Subject: [PATCH 09/10] add back earlier tests --- spec/results-view-spec.js | 399 +++++++++++++++++++------------------- spec/setup-spec.js | 1 + 2 files changed, 201 insertions(+), 199 deletions(-) diff --git a/spec/results-view-spec.js b/spec/results-view-spec.js index 05de0443..c818f0ae 100644 --- a/spec/results-view-spec.js +++ b/spec/results-view-spec.js @@ -90,205 +90,205 @@ describe('ResultsView', () => { await activationPromise; }); - // describe("when the result is for a long line", () => { - // it("renders the context around the match", async () => { - // projectFindView.findEditor.setText('ghijkl'); - // atom.commands.dispatch(projectFindView.element, 'core:confirm'); - // await searchPromise; - // - // resultsView = getResultsView(); - // expect(resultsView.refs.listView.element.querySelector('.path-name').textContent).toBe("one-long-line.coffee"); - // expect(resultsView.refs.listView.element.querySelectorAll('.preview').length).toBe(1); - // expect(resultsView.refs.listView.element.querySelector('.preview').textContent).toBe('test test test test test test test test test test test a b c d e f g h i j k l abcdefghijklmnopqrstuvwxyz'); - // expect(resultsView.refs.listView.element.querySelector('.match').textContent).toBe('ghijkl'); - // }) - // }); - // - // describe("when there are multiple project paths", () => { - // beforeEach(() => { - // atom.project.addPath(temp.mkdirSync("another-project-path")) - // }); - // - // it("includes the basename of the project path that contains the match", async () => { - // projectFindView.findEditor.setText('ghijkl'); - // atom.commands.dispatch(projectFindView.element, 'core:confirm'); - // await searchPromise; - // - // resultsView = getResultsView(); - // expect(resultsView.refs.listView.element.querySelector('.path-name').textContent).toBe(path.join("project", "one-long-line.coffee")); - // }); - // }); - // - // describe("rendering replacement text", () => { - // let modifiedDelay = null; - // - // beforeEach(() => { - // projectFindView.findEditor.setText('ghijkl'); - // modifiedDelay = projectFindView.replaceEditor.getBuffer().stoppedChangingDelay; - // }); - // - // it("renders the replacement when doing a search and there is a replacement pattern", async () => { - // projectFindView.replaceEditor.setText('cats'); - // atom.commands.dispatch(projectFindView.element, 'core:confirm'); - // await searchPromise; - // - // resultsView = getResultsView(); - // expect(resultsView.refs.listView.element.querySelector('.path-name').textContent).toBe("one-long-line.coffee"); - // expect(resultsView.refs.listView.element.querySelectorAll('.preview').length).toBe(1); - // expect(resultsView.refs.listView.element.querySelector('.match').textContent).toBe('ghijkl'); - // expect(resultsView.refs.listView.element.querySelector('.replacement').textContent).toBe('cats'); - // }); - // - // it("renders the replacement when changing the text in the replacement field", async () => { - // atom.commands.dispatch(projectFindView.element, 'core:confirm'); - // await searchPromise; - // - // resultsView = getResultsView(); - // expect(resultsView.refs.listView.element.querySelector('.match').textContent).toBe('ghijkl'); - // expect(resultsView.refs.listView.element.querySelector('.match')).toHaveClass('highlight-info'); - // expect(resultsView.refs.listView.element.querySelector('.replacement').textContent).toBe(''); - // expect(resultsView.refs.listView.element.querySelector('.replacement')).toBeHidden(); - // - // projectFindView.replaceEditor.setText('cats'); - // advanceClock(modifiedDelay); - // await etch.update(resultsView); - // - // expect(resultsView.refs.listView.element.querySelector('.match').textContent).toBe('ghijkl'); - // expect(resultsView.refs.listView.element.querySelector('.match')).toHaveClass('highlight-error'); - // expect(resultsView.refs.listView.element.querySelector('.replacement').textContent).toBe('cats'); - // expect(resultsView.refs.listView.element.querySelector('.replacement')).toBeVisible(); - // - // projectFindView.replaceEditor.setText(''); - // advanceClock(modifiedDelay); - // await etch.update(resultsView); - // - // expect(resultsView.refs.listView.element.querySelector('.match').textContent).toBe('ghijkl'); - // expect(resultsView.refs.listView.element.querySelector('.match')).toHaveClass('highlight-info'); - // expect(resultsView.refs.listView.element.querySelector('.replacement')).toBeHidden(); - // }); - // - // it('renders the captured text when the replace pattern uses captures', async () => { - // projectFindView.refs.regexOptionButton.click(); - // projectFindView.findEditor.setText('function ?(\\([^)]*\\))'); - // projectFindView.replaceEditor.setText('$1 =>') - // atom.commands.dispatch(projectFindView.element, 'core:confirm'); - // await searchPromise; - // - // resultsView = getResultsView(); - // const listElement = resultsView.refs.listView.element; - // expect(listElement.querySelectorAll('.match')[0].textContent).toBe('function ()'); - // expect(listElement.querySelectorAll('.replacement')[0].textContent).toBe('() =>'); - // expect(listElement.querySelectorAll('.match')[1].textContent).toBe('function(items)'); - // expect(listElement.querySelectorAll('.replacement')[1].textContent).toBe('(items) =>'); - // }) - // }); - // - // describe("core:page-up and core:page-down", () => { - // beforeEach(async () => { - // workspaceElement.style.height = '300px'; - // workspaceElement.style.width = '1024px'; - // projectFindView.findEditor.setText(' '); - // projectFindView.confirm(); - // - // await searchPromise; - // - // resultsView = getResultsView(); - // const {listView} = resultsView.refs; - // expect(listView.element.scrollTop).toBe(0); - // expect(listView.element.scrollHeight).toBeGreaterThan(listView.element.offsetHeight); - // }); - // - // function getSelectedItem() { - // return resultsView.refs.listView.element.querySelector('.selected'); - // } - // - // function getRecursivePosition(element, substract_scroll) { - // let x = 0; - // let y = 0; - // while (element && !isNaN(element.offsetLeft) && !isNaN(element.offsetTop)) { - // x += element.offsetLeft; - // y += element.offsetTop; - // if (substract_scroll) { - // x -= element.scrollLeft; - // y -= element.scrollTop; - // } - // element = element.offsetParent; - // } - // return { top: y, left: x }; - // } - // - // function getSelectedOffset() { - // return getRecursivePosition(getSelectedItem(), true).top; - // } - // - // function getSelectedPosition() { - // return getRecursivePosition(getSelectedItem(), false).top; - // } - // - // it("selects the first result on the next page when core:page-down is triggered", async () => { - // const {listView} = resultsView.refs; - // expect(listView.element.querySelectorAll('.path-row').length).not.toBeGreaterThan(resultsView.model.getPathCount()); - // expect(listView.element.querySelectorAll('.match-row').length).not.toBeGreaterThan(resultsView.model.getMatchCount()); - // expect(listView.element.querySelector('.path-row').parentElement).toHaveClass('selected'); - // - // let initiallySelectedItem = getSelectedItem(); - // let initiallySelectedOffset = getSelectedOffset(); - // let initiallySelectedPosition = getSelectedPosition(); - // - // await resultsView.pageDown(); - // - // expect(getSelectedItem()).not.toBe(initiallySelectedItem); - // expect(getSelectedPosition()).toBeGreaterThan(initiallySelectedPosition); - // - // initiallySelectedItem = getSelectedItem(); - // initiallySelectedOffset = getSelectedOffset(); - // initiallySelectedPosition = getSelectedPosition(); - // - // await resultsView.pageDown(); - // - // expect(getSelectedItem()).not.toBe(initiallySelectedItem); - // expect(getSelectedPosition()).toBeGreaterThan(initiallySelectedPosition); - // - // initiallySelectedPosition = getSelectedPosition(); - // - // for (let i = 0; i < 100; i++) resultsView.pageDown(); - // await resultsView.pageDown(); - // expect(_.last(resultsView.element.querySelectorAll('.match-row'))).toHaveClass('selected'); - // expect(getSelectedPosition()).toBeGreaterThan(initiallySelectedPosition); - // }); - // - // it("selects the first result on the previous page when core:page-up is triggered", async () => { - // await resultsView.moveToBottom(); - // expect(_.last(resultsView.element.querySelectorAll('.match-row'))).toHaveClass('selected'); - // - // const {listView} = resultsView.refs; - // - // let initiallySelectedItem = getSelectedItem(); - // let initiallySelectedOffset = getSelectedOffset(); - // let initiallySelectedPosition = getSelectedPosition(); - // - // await resultsView.pageUp(); - // - // expect(getSelectedItem()).not.toBe(initiallySelectedItem); - // expect(getSelectedPosition()).toBeLessThan(initiallySelectedPosition); - // - // initiallySelectedItem = getSelectedItem(); - // initiallySelectedOffset = getSelectedOffset(); - // initiallySelectedPosition = getSelectedPosition(); - // - // await resultsView.pageUp(); - // - // expect(getSelectedItem()).not.toBe(initiallySelectedItem); - // expect(getSelectedPosition()).toBeLessThan(initiallySelectedPosition); - // - // initiallySelectedPosition = getSelectedPosition(); - // - // for (let i = 0; i < 100; i++) resultsView.pageUp(); - // await resultsView.pageUp(); - // expect(listView.element.querySelector('.path-row').parentElement).toHaveClass('selected'); - // expect(getSelectedPosition()).toBeLessThan(initiallySelectedPosition); - // }); - // }); + describe("when the result is for a long line", () => { + it("renders the context around the match", async () => { + projectFindView.findEditor.setText('ghijkl'); + atom.commands.dispatch(projectFindView.element, 'core:confirm'); + await searchPromise; + + resultsView = getResultsView(); + expect(resultsView.refs.listView.element.querySelector('.path-name').textContent).toBe("one-long-line.coffee"); + expect(resultsView.refs.listView.element.querySelectorAll('.preview').length).toBe(1); + expect(resultsView.refs.listView.element.querySelector('.preview').textContent).toBe('test test test test test test test test test test test a b c d e f g h i j k l abcdefghijklmnopqrstuvwxyz'); + expect(resultsView.refs.listView.element.querySelector('.match').textContent).toBe('ghijkl'); + }) + }); + + describe("when there are multiple project paths", () => { + beforeEach(() => { + atom.project.addPath(temp.mkdirSync("another-project-path")) + }); + + it("includes the basename of the project path that contains the match", async () => { + projectFindView.findEditor.setText('ghijkl'); + atom.commands.dispatch(projectFindView.element, 'core:confirm'); + await searchPromise; + + resultsView = getResultsView(); + expect(resultsView.refs.listView.element.querySelector('.path-name').textContent).toBe(path.join("project", "one-long-line.coffee")); + }); + }); + + describe("rendering replacement text", () => { + let modifiedDelay = null; + + beforeEach(() => { + projectFindView.findEditor.setText('ghijkl'); + modifiedDelay = projectFindView.replaceEditor.getBuffer().stoppedChangingDelay; + }); + + it("renders the replacement when doing a search and there is a replacement pattern", async () => { + projectFindView.replaceEditor.setText('cats'); + atom.commands.dispatch(projectFindView.element, 'core:confirm'); + await searchPromise; + + resultsView = getResultsView(); + expect(resultsView.refs.listView.element.querySelector('.path-name').textContent).toBe("one-long-line.coffee"); + expect(resultsView.refs.listView.element.querySelectorAll('.preview').length).toBe(1); + expect(resultsView.refs.listView.element.querySelector('.match').textContent).toBe('ghijkl'); + expect(resultsView.refs.listView.element.querySelector('.replacement').textContent).toBe('cats'); + }); + + it("renders the replacement when changing the text in the replacement field", async () => { + atom.commands.dispatch(projectFindView.element, 'core:confirm'); + await searchPromise; + + resultsView = getResultsView(); + expect(resultsView.refs.listView.element.querySelector('.match').textContent).toBe('ghijkl'); + expect(resultsView.refs.listView.element.querySelector('.match')).toHaveClass('highlight-info'); + expect(resultsView.refs.listView.element.querySelector('.replacement').textContent).toBe(''); + expect(resultsView.refs.listView.element.querySelector('.replacement')).toBeHidden(); + + projectFindView.replaceEditor.setText('cats'); + advanceClock(modifiedDelay); + await etch.update(resultsView); + + expect(resultsView.refs.listView.element.querySelector('.match').textContent).toBe('ghijkl'); + expect(resultsView.refs.listView.element.querySelector('.match')).toHaveClass('highlight-error'); + expect(resultsView.refs.listView.element.querySelector('.replacement').textContent).toBe('cats'); + expect(resultsView.refs.listView.element.querySelector('.replacement')).toBeVisible(); + + projectFindView.replaceEditor.setText(''); + advanceClock(modifiedDelay); + await etch.update(resultsView); + + expect(resultsView.refs.listView.element.querySelector('.match').textContent).toBe('ghijkl'); + expect(resultsView.refs.listView.element.querySelector('.match')).toHaveClass('highlight-info'); + expect(resultsView.refs.listView.element.querySelector('.replacement')).toBeHidden(); + }); + + it('renders the captured text when the replace pattern uses captures', async () => { + projectFindView.refs.regexOptionButton.click(); + projectFindView.findEditor.setText('function ?(\\([^)]*\\))'); + projectFindView.replaceEditor.setText('$1 =>') + atom.commands.dispatch(projectFindView.element, 'core:confirm'); + await searchPromise; + + resultsView = getResultsView(); + const listElement = resultsView.refs.listView.element; + expect(listElement.querySelectorAll('.match')[0].textContent).toBe('function ()'); + expect(listElement.querySelectorAll('.replacement')[0].textContent).toBe('() =>'); + expect(listElement.querySelectorAll('.match')[1].textContent).toBe('function(items)'); + expect(listElement.querySelectorAll('.replacement')[1].textContent).toBe('(items) =>'); + }) + }); + + describe("core:page-up and core:page-down", () => { + beforeEach(async () => { + workspaceElement.style.height = '300px'; + workspaceElement.style.width = '1024px'; + projectFindView.findEditor.setText(' '); + projectFindView.confirm(); + + await searchPromise; + + resultsView = getResultsView(); + const {listView} = resultsView.refs; + expect(listView.element.scrollTop).toBe(0); + expect(listView.element.scrollHeight).toBeGreaterThan(listView.element.offsetHeight); + }); + + function getSelectedItem() { + return resultsView.refs.listView.element.querySelector('.selected'); + } + + function getRecursivePosition(element, substract_scroll) { + let x = 0; + let y = 0; + while (element && !isNaN(element.offsetLeft) && !isNaN(element.offsetTop)) { + x += element.offsetLeft; + y += element.offsetTop; + if (substract_scroll) { + x -= element.scrollLeft; + y -= element.scrollTop; + } + element = element.offsetParent; + } + return { top: y, left: x }; + } + + function getSelectedOffset() { + return getRecursivePosition(getSelectedItem(), true).top; + } + + function getSelectedPosition() { + return getRecursivePosition(getSelectedItem(), false).top; + } + + it("selects the first result on the next page when core:page-down is triggered", async () => { + const {listView} = resultsView.refs; + expect(listView.element.querySelectorAll('.path-row').length).not.toBeGreaterThan(resultsView.model.getPathCount()); + expect(listView.element.querySelectorAll('.match-row').length).not.toBeGreaterThan(resultsView.model.getMatchCount()); + expect(listView.element.querySelector('.path-row').parentElement).toHaveClass('selected'); + + let initiallySelectedItem = getSelectedItem(); + let initiallySelectedOffset = getSelectedOffset(); + let initiallySelectedPosition = getSelectedPosition(); + + await resultsView.pageDown(); + + expect(getSelectedItem()).not.toBe(initiallySelectedItem); + expect(getSelectedPosition()).toBeGreaterThan(initiallySelectedPosition); + + initiallySelectedItem = getSelectedItem(); + initiallySelectedOffset = getSelectedOffset(); + initiallySelectedPosition = getSelectedPosition(); + + await resultsView.pageDown(); + + expect(getSelectedItem()).not.toBe(initiallySelectedItem); + expect(getSelectedPosition()).toBeGreaterThan(initiallySelectedPosition); + + initiallySelectedPosition = getSelectedPosition(); + + for (let i = 0; i < 100; i++) resultsView.pageDown(); + await resultsView.pageDown(); + expect(_.last(resultsView.element.querySelectorAll('.match-row'))).toHaveClass('selected'); + expect(getSelectedPosition()).toBeGreaterThan(initiallySelectedPosition); + }); + + it("selects the first result on the previous page when core:page-up is triggered", async () => { + await resultsView.moveToBottom(); + expect(_.last(resultsView.element.querySelectorAll('.match-row'))).toHaveClass('selected'); + + const {listView} = resultsView.refs; + + let initiallySelectedItem = getSelectedItem(); + let initiallySelectedOffset = getSelectedOffset(); + let initiallySelectedPosition = getSelectedPosition(); + + await resultsView.pageUp(); + + expect(getSelectedItem()).not.toBe(initiallySelectedItem); + expect(getSelectedPosition()).toBeLessThan(initiallySelectedPosition); + + initiallySelectedItem = getSelectedItem(); + initiallySelectedOffset = getSelectedOffset(); + initiallySelectedPosition = getSelectedPosition(); + + await resultsView.pageUp(); + + expect(getSelectedItem()).not.toBe(initiallySelectedItem); + expect(getSelectedPosition()).toBeLessThan(initiallySelectedPosition); + + initiallySelectedPosition = getSelectedPosition(); + + for (let i = 0; i < 100; i++) resultsView.pageUp(); + await resultsView.pageUp(); + expect(listView.element.querySelector('.path-row').parentElement).toHaveClass('selected'); + expect(getSelectedPosition()).toBeLessThan(initiallySelectedPosition); + }); + }); describe("core:move-to-top and core:move-to-bottom", () => { beforeEach(async () => { @@ -300,6 +300,7 @@ describe('ResultsView', () => { }); it("selects the first/last item when core:move-to-top/move-to-bottom is triggered", async () => { + console.log("Running bad test"); const {listView} = resultsView.refs; expect(listView.element.querySelectorAll('li').length).toBeLessThan(resultsView.model.getPathCount() + resultsView.model.getMatchCount()); diff --git a/spec/setup-spec.js b/spec/setup-spec.js index f517817b..9a91ea54 100644 --- a/spec/setup-spec.js +++ b/spec/setup-spec.js @@ -1,3 +1,4 @@ +console.log("Set scehduler"); require('etch').setScheduler({ updateDocument(callback) { callback(); }, getNextUpdatePromise() { return Promise.resolve(); } From c830c91573e7ceffc8cfc82c5d8adb408c6c6f5d Mon Sep 17 00:00:00 2001 From: Benjamin Gray Date: Sat, 19 Sep 2020 11:04:39 +1000 Subject: [PATCH 10/10] enable more --- spec/project-find-view-spec.js | 3346 ++++++++++++++++---------------- spec/results-view-spec.js | 3 + 2 files changed, 1676 insertions(+), 1673 deletions(-) diff --git a/spec/project-find-view-spec.js b/spec/project-find-view-spec.js index 72691832..01d8c7f4 100644 --- a/spec/project-find-view-spec.js +++ b/spec/project-find-view-spec.js @@ -1,1673 +1,1673 @@ -// /** @babel */ -// -// const path = require('path'); -// const temp = require('temp').track(); -// const fs = require('fs-plus'); -// const dedent = require('dedent'); -// const {TextBuffer} = require('atom'); -// const ResultsPaneView = require('../lib/project/results-pane'); -// const etch = require('etch'); -// const {conditionPromise} = require('./async-spec-helpers'); -// -// for (const ripgrep of [false, true]) { -// describe(`ProjectFindView (ripgrep=${ripgrep})`, () => { -// const {stoppedChangingDelay} = TextBuffer.prototype; -// let activationPromise, searchPromise, editor, editorElement, findView, -// projectFindView, workspaceElement; -// -// function getAtomPanel() { -// return workspaceElement.querySelector('.project-find').parentNode; -// } -// -// function getExistingResultsPane() { -// const pane = atom.workspace.paneForURI(ResultsPaneView.URI); -// if (pane) { -// return pane.itemForURI(ResultsPaneView.URI); -// } -// } -// -// function getResultsView() { -// return getExistingResultsPane().refs.resultsView; -// } -// -// function waitForSearchResults() { -// return conditionPromise( -// () => projectFindView.refs.descriptionLabel.textContent.includes('results found') -// ) -// } -// -// beforeEach(() => { -// atom.config.set('find-and-replace.useRipgrep', ripgrep) -// workspaceElement = atom.views.getView(atom.workspace); -// atom.config.set('core.excludeVcsIgnoredPaths', false); -// atom.project.setPaths([path.join(__dirname, 'fixtures')]); -// jasmine.attachToDOM(workspaceElement); -// -// activationPromise = atom.packages.activatePackage("find-and-replace").then(function({mainModule}) { -// mainModule.createViews(); -// ({findView, projectFindView} = mainModule); -// const spy = spyOn(projectFindView, 'search').andCallFake((options) => { -// return searchPromise = spy.originalValue.call(projectFindView, options); -// }); -// }); -// }); -// -// describe("when project-find:show is triggered", () => { -// it("attaches ProjectFindView to the root view", async () => { -// atom.commands.dispatch(workspaceElement, 'project-find:show'); -// await activationPromise; -// -// projectFindView.findEditor.setText('items'); -// expect(getAtomPanel()).toBeVisible(); -// expect(projectFindView.findEditor.getSelectedBufferRange()).toEqual([[0, 0], [0, 5]]); -// }); -// -// describe("with an open buffer", () => { -// beforeEach(async () => { -// atom.commands.dispatch(workspaceElement, 'project-find:show'); -// await activationPromise; -// projectFindView.findEditor.setText(''); -// editor = await atom.workspace.open('project/sample.js'); -// }); -// -// it("populates the findEditor with selection when there is a selection", () => { -// editor.setSelectedBufferRange([[2, 8], [2, 13]]); -// atom.commands.dispatch(workspaceElement, 'project-find:show'); -// expect(getAtomPanel()).toBeVisible(); -// expect(projectFindView.findEditor.getText()).toBe('items'); -// -// editor.setSelectedBufferRange([[2, 14], [2, 20]]); -// atom.commands.dispatch(workspaceElement, 'project-find:show'); -// expect(getAtomPanel()).toBeVisible(); -// expect(projectFindView.findEditor.getText()).toBe('length'); -// }); -// -// it("populates the findEditor with the previous selection when there is no selection", () => { -// editor.setSelectedBufferRange([[2, 14], [2, 20]]); -// atom.commands.dispatch(workspaceElement, 'project-find:show'); -// expect(getAtomPanel()).toBeVisible(); -// expect(projectFindView.findEditor.getText()).toBe('length'); -// -// editor.setSelectedBufferRange([[2, 30], [2, 30]]); -// atom.commands.dispatch(workspaceElement, 'project-find:show'); -// expect(getAtomPanel()).toBeVisible(); -// expect(projectFindView.findEditor.getText()).toBe('length'); -// }); -// -// it("places selected text into the find editor and escapes it when Regex is enabled", () => { -// atom.commands.dispatch(projectFindView.element, 'project-find:toggle-regex-option'); -// editor.setSelectedBufferRange([[6, 6], [6, 65]]); -// atom.commands.dispatch(workspaceElement, 'project-find:show'); -// expect(projectFindView.findEditor.getText()).toBe('current < pivot \\? left\\.push\\(current\\) : right\\.push\\(current\\);'); -// }); -// }); -// -// describe("when the ProjectFindView is already attached", () => { -// beforeEach(async () => { -// atom.commands.dispatch(workspaceElement, 'project-find:show'); -// await activationPromise; -// -// projectFindView.findEditor.setText('items'); -// projectFindView.findEditor.setSelectedBufferRange([[0, 0], [0, 0]]); -// }); -// -// it("focuses the find editor and selects all the text", () => { -// atom.commands.dispatch(workspaceElement, 'project-find:show'); -// expect(projectFindView.findEditor.getElement()).toHaveFocus(); -// expect(projectFindView.findEditor.getSelectedText()).toBe("items"); -// }); -// }); -// -// it("honors config settings for find options", async () => { -// atom.config.set('find-and-replace.useRegex', true); -// atom.config.set('find-and-replace.caseSensitive', true); -// atom.config.set('find-and-replace.wholeWord', true); -// -// atom.commands.dispatch(workspaceElement, 'project-find:show'); -// await activationPromise; -// -// expect(projectFindView.refs.caseOptionButton).toHaveClass('selected'); -// expect(projectFindView.refs.regexOptionButton).toHaveClass('selected'); -// expect(projectFindView.refs.wholeWordOptionButton).toHaveClass('selected'); -// }); -// }); -// -// describe("when project-find:show-in-current-directory is triggered with an open buffer", () => { -// beforeEach(async () => { -// atom.project.setPaths([__dirname]); -// -// atom.commands.dispatch(workspaceElement, 'project-find:show'); -// await activationPromise; -// -// projectFindView.findEditor.setText(''); -// projectFindView.pathsEditor.setText(''); -// editor = await atom.workspace.open('fixtures/sample.js'); -// }); -// -// it("calls project-find:show, and populates both findEditor and pathsEditor when there is a selection", () => { -// editor.setSelectedBufferRange([[3, 8], [3, 13]]); -// atom.commands.dispatch(workspaceElement, 'project-find:show-in-current-directory'); -// expect(getAtomPanel()).toBeVisible(); -// expect(projectFindView.findEditor.getText()).toBe('pivot'); -// expect(projectFindView.pathsEditor.getText()).toBe('fixtures'); -// -// editor.setSelectedBufferRange([[2, 14], [2, 20]]); -// atom.commands.dispatch(workspaceElement, 'project-find:show-in-current-directory'); -// expect(getAtomPanel()).toBeVisible(); -// expect(projectFindView.findEditor.getText()).toBe('length'); -// expect(projectFindView.pathsEditor.getText()).toBe('fixtures'); -// }); -// -// it("calls project-find:show, and populates only pathsEditor when there is no selection", () => { -// atom.commands.dispatch(workspaceElement, 'project-find:show-in-current-directory'); -// expect(getAtomPanel()).toBeVisible(); -// expect(projectFindView.findEditor.getText()).toBe(''); -// expect(projectFindView.pathsEditor.getText()).toBe('fixtures'); -// }); -// }); -// -// describe("when project-find:toggle is triggered", () => { -// it("toggles the visibility of the ProjectFindView", async () => { -// atom.commands.dispatch(workspaceElement, 'project-find:toggle'); -// await activationPromise; -// -// expect(getAtomPanel()).toBeVisible(); -// atom.commands.dispatch(workspaceElement, 'project-find:toggle'); -// expect(getAtomPanel()).not.toBeVisible(); -// }); -// }); -// -// describe("when project-find:show-in-current-directory is triggered", () => { -// let nested, tree, projectPath; -// -// beforeEach(() => { -// projectPath = temp.mkdirSync("atom"); -// atom.project.setPaths([projectPath]); -// -// tree = document.createElement('div'); -// tree.className = 'directory'; -// tree.innerHTML = dedent` -//
-// ${projectPath} -//
    -//
  • -// one.js -//
  • -//
  • -// two.js -//
  • -//
    -//
    -// nested -//
      -//
    • -// three.js -//
    • -//
    -//
    -//
    -//
-//
-// `; -// -// nested = tree.querySelector('.directory'); -// -// workspaceElement.appendChild(tree); -// }); -// -// function escapePath(filePath) { -// return filePath.replace(/\\/g, '\'); -// } -// -// it("populates the pathsEditor when triggered with a directory", async () => { -// atom.commands.dispatch(nested.querySelector('.name'), 'project-find:show-in-current-directory'); -// await activationPromise; -// -// expect(getAtomPanel()).toBeVisible(); -// expect(projectFindView.pathsEditor.getText()).toBe('nested'); -// expect(projectFindView.findEditor.getElement()).toHaveFocus(); -// -// atom.commands.dispatch(tree.querySelector('.name'), 'project-find:show-in-current-directory'); -// expect(projectFindView.pathsEditor.getText()).toBe(''); -// }); -// -// it("populates the pathsEditor when triggered on a directory's name", async () => { -// atom.commands.dispatch(nested, 'project-find:show-in-current-directory'); -// await activationPromise; -// -// expect(getAtomPanel()).toBeVisible(); -// expect(projectFindView.pathsEditor.getText()).toBe('nested'); -// expect(projectFindView.findEditor.getElement()).toHaveFocus(); -// -// atom.commands.dispatch(tree.querySelector('.name'), 'project-find:show-in-current-directory'); -// expect(projectFindView.pathsEditor.getText()).toBe(''); -// }); -// -// it("populates the pathsEditor when triggered on a file", async () => { -// atom.commands.dispatch(nested.querySelector('.file .name'), 'project-find:show-in-current-directory'); -// await activationPromise; -// -// expect(getAtomPanel()).toBeVisible(); -// expect(projectFindView.pathsEditor.getText()).toBe('nested'); -// expect(projectFindView.findEditor.getElement()).toHaveFocus(); -// -// atom.commands.dispatch(tree.querySelector('.file .name'), 'project-find:show-in-current-directory'); -// expect(projectFindView.pathsEditor.getText()).toBe(''); -// }); -// -// describe("when there are multiple root directories", async () => { -// beforeEach(() => { -// atom.project.addPath(temp.mkdirSync("another-path-")) -// }); -// -// it("includes the basename of the containing root directory in the paths-editor", async () => { -// atom.commands.dispatch(nested.querySelector('.file .name'), 'project-find:show-in-current-directory'); -// await activationPromise; -// -// expect(getAtomPanel()).toBeVisible(); -// expect(projectFindView.pathsEditor.getText()).toBe(path.join(path.basename(projectPath), 'nested')); -// }); -// }); -// }); -// -// describe("finding", () => { -// beforeEach(async () => { -// atom.project.setPaths([path.join(__dirname, 'fixtures/project')]); -// editor = await atom.workspace.open('sample.js'); -// editorElement = atom.views.getView(editor); -// atom.commands.dispatch(workspaceElement, 'project-find:show'); -// await activationPromise; -// workspaceElement.style.height = '800px' -// }); -// -// describe("when the find string contains an escaped char", () => { -// beforeEach(() => { -// jasmine.useRealClock() -// -// let projectPath = temp.mkdirSync("atom"); -// fs.writeFileSync(path.join(projectPath, "tabs.txt"), "\t\n\\\t\n\\\\t"); -// atom.project.setPaths([projectPath]); -// atom.commands.dispatch(workspaceElement, 'project-find:show'); -// }); -// -// describe("when regex search is enabled", () => { -// it("finds a literal tab character", async () => { -// atom.commands.dispatch(projectFindView.element, 'project-find:toggle-regex-option'); -// projectFindView.findEditor.setText('\\t'); -// -// atom.commands.dispatch(projectFindView.element, 'core:confirm'); -// await searchPromise; -// -// const resultsView = getResultsView(); -// expect(resultsView.element).toBeVisible(); -// expect(resultsView.refs.listView.element.querySelectorAll(".match-row")).toHaveLength(2); -// }) -// }); -// -// describe("when regex search is disabled", () => { -// it("finds the escape char", async () => { -// projectFindView.findEditor.setText('\\t'); -// -// atom.commands.dispatch(projectFindView.element, 'core:confirm'); -// await searchPromise; -// -// const resultsView = getResultsView(); -// expect(resultsView.element).toBeVisible(); -// expect(resultsView.refs.listView.element.querySelectorAll(".match-row")).toHaveLength(1); -// }); -// -// it("finds a backslash", async () => { -// projectFindView.findEditor.setText('\\'); -// -// atom.commands.dispatch(projectFindView.element, 'core:confirm'); -// await searchPromise; -// -// const resultsView = getResultsView(); -// expect(resultsView.element).toBeVisible(); -// expect(resultsView.refs.listView.element.querySelectorAll(".match-row")).toHaveLength(2); -// expect(resultsView.refs.listView.element.querySelectorAll(".match.highlight-info")).toHaveLength(3); -// }); -// -// it("doesn't insert a escaped char if there are multiple backslashs in front of the char", async () => { -// projectFindView.findEditor.setText('\\\\t'); -// -// atom.commands.dispatch(projectFindView.element, 'core:confirm'); -// await searchPromise; -// -// const resultsView = getResultsView(); -// expect(resultsView.element).toBeVisible(); -// expect(resultsView.refs.listView.element.querySelectorAll(".match-row")).toHaveLength(1); -// }); -// }); -// }); -// -// describe("when core:cancel is triggered", () => { -// it("detaches from the root view", () => { -// atom.commands.dispatch(workspaceElement, 'project-find:show'); -// projectFindView.element.focus(); -// atom.commands.dispatch(document.activeElement, 'core:cancel'); -// expect(getAtomPanel()).not.toBeVisible(); -// }); -// }); -// -// describe("when close option is true", () => { -// beforeEach(() => { -// atom.config.set('find-and-replace.closeFindPanelAfterSearch', true); -// }) -// -// it("closes the panel after search", async () => { -// projectFindView.findEditor.setText('something'); -// atom.commands.dispatch(projectFindView.element, 'core:confirm'); -// await searchPromise; -// -// expect(getAtomPanel()).not.toBeVisible(); -// }); -// -// it("leaves the panel open after an empty search", async () => { -// projectFindView.findEditor.setText(''); -// atom.commands.dispatch(projectFindView.element, 'core:confirm'); -// await searchPromise; -// -// expect(getAtomPanel()).toBeVisible(); -// }); -// -// it("closes the panel after a no-op search", async () => { -// projectFindView.findEditor.setText('something'); -// atom.commands.dispatch(projectFindView.element, 'core:confirm'); -// await searchPromise; -// -// atom.commands.dispatch(workspaceElement, 'project-find:show'); -// await activationPromise; -// -// expect(getAtomPanel()).toBeVisible(); -// -// atom.commands.dispatch(projectFindView.element, 'core:confirm'); -// await searchPromise; -// -// expect(getAtomPanel()).not.toBeVisible(); -// }); -// -// it("does not close the panel after the replacement text is altered", async () => { -// projectFindView.replaceEditor.setText('something else'); -// -// expect(getAtomPanel()).toBeVisible(); -// }); -// }); -// -// describe("splitting into a second pane", () => { -// beforeEach(() => { -// workspaceElement.style.height = '1000px'; -// atom.commands.dispatch(editorElement, 'project-find:show'); -// jasmine.useRealClock() -// }); -// -// it("splits when option is right", async () => { -// const initialPane = atom.workspace.getCenter().getActivePane(); -// atom.config.set('find-and-replace.projectSearchResultsPaneSplitDirection', 'right'); -// projectFindView.findEditor.setText('items'); -// -// atom.commands.dispatch(projectFindView.element, 'core:confirm'); -// await searchPromise; -// -// expect(atom.workspace.getCenter().getActivePane()).not.toBe(initialPane); -// }); -// -// it("splits when option is bottom", async () => { -// const initialPane = atom.workspace.getCenter().getActivePane(); -// atom.config.set('find-and-replace.projectSearchResultsPaneSplitDirection', 'down'); -// projectFindView.findEditor.setText('items'); -// -// atom.commands.dispatch(projectFindView.element, 'core:confirm'); -// await searchPromise; -// -// expect(atom.workspace.getCenter().getActivePane()).not.toBe(initialPane); -// }); -// -// it("does not split when option is false", async () => { -// const initialPane = atom.workspace.getCenter().getActivePane(); -// projectFindView.findEditor.setText('items'); -// -// atom.commands.dispatch(projectFindView.element, 'core:confirm'); -// await searchPromise; -// -// expect(atom.workspace.getCenter().getActivePane()).toBe(initialPane); -// }); -// -// it("can be duplicated on the right", async () => { -// atom.config.set('find-and-replace.projectSearchResultsPaneSplitDirection', 'right'); -// projectFindView.findEditor.setText('items'); -// -// atom.commands.dispatch(projectFindView.element, 'core:confirm'); -// await searchPromise; -// -// const resultsPaneView1 = atom.views.getView(getExistingResultsPane()); -// const pane1 = atom.workspace.getCenter().getActivePane(); -// const resultsView1 = pane1.getItems()[0].refs.resultsView -// pane1.splitRight({copyActiveItem: true}); -// -// const pane2 = atom.workspace.getCenter().getActivePane(); -// const resultsView2 = pane2.getItems()[0].refs.resultsView -// const resultsPaneView2 = atom.views.getView(pane2.itemForURI(ResultsPaneView.URI)); -// expect(pane1).not.toBe(pane2); -// expect(resultsPaneView1).not.toBe(resultsPaneView2); -// simulateResizeEvent(resultsView2.element); -// -// await etch.update(resultsView1); -// await etch.update(resultsView2); -// await waitForSearchResults(); -// -// const resultCount = resultsPaneView1.querySelectorAll('.match-row').length; -// expect(resultCount).toBeGreaterThan(0); -// expect(resultsPaneView2.querySelectorAll('.match-row')).toHaveLength(resultCount); -// expect(resultsPaneView2.querySelector('.preview-count').innerHTML).toEqual(resultsPaneView1.querySelector('.preview-count').innerHTML); -// }); -// -// it("can be duplicated at the bottom", async () => { -// atom.config.set('find-and-replace.projectSearchResultsPaneSplitDirection', 'down'); -// projectFindView.findEditor.setText('items'); -// -// atom.commands.dispatch(projectFindView.element, 'core:confirm'); -// await searchPromise; -// -// const resultsPaneView1 = atom.views.getView(getExistingResultsPane()); -// const pane1 = atom.workspace.getCenter().getActivePane(); -// const resultsView1 = pane1.getItems()[0].refs.resultsView -// -// pane1.splitDown({copyActiveItem: true}); -// const pane2 = atom.workspace.getCenter().getActivePane(); -// const resultsView2 = pane2.getItems()[0].refs.resultsView -// const resultsPaneView2 = atom.views.getView(pane2.itemForURI(ResultsPaneView.URI)); -// expect(pane1).not.toBe(pane2); -// expect(resultsPaneView1).not.toBe(resultsPaneView2); -// -// await etch.update(resultsView1); -// await etch.update(resultsView2); -// -// expect(resultsPaneView2.querySelector('.preview-count').innerHTML).toEqual(resultsPaneView1.querySelector('.preview-count').innerHTML); -// }); -// }); -// -// describe("serialization", () => { -// it("serializes if the case, regex and whole word options", async () => { -// atom.commands.dispatch(editorElement, 'project-find:show'); -// expect(projectFindView.refs.caseOptionButton).not.toHaveClass('selected'); -// projectFindView.refs.caseOptionButton.click(); -// expect(projectFindView.refs.caseOptionButton).toHaveClass('selected'); -// -// expect(projectFindView.refs.regexOptionButton).not.toHaveClass('selected'); -// projectFindView.refs.regexOptionButton.click(); -// expect(projectFindView.refs.regexOptionButton).toHaveClass('selected'); -// -// expect(projectFindView.refs.wholeWordOptionButton).not.toHaveClass('selected'); -// projectFindView.refs.wholeWordOptionButton.click(); -// expect(projectFindView.refs.wholeWordOptionButton).toHaveClass('selected'); -// -// await atom.packages.deactivatePackage("find-and-replace"); -// -// activationPromise = atom.packages.activatePackage("find-and-replace").then(function({mainModule}) { -// mainModule.createViews(); -// return {projectFindView} = mainModule; -// }); -// -// atom.commands.dispatch(editorElement, 'project-find:show'); -// await activationPromise; -// -// expect(projectFindView.refs.caseOptionButton).toHaveClass('selected'); -// expect(projectFindView.refs.regexOptionButton).toHaveClass('selected'); -// expect(projectFindView.refs.wholeWordOptionButton).toHaveClass('selected'); -// }) -// }); -// -// describe("description label", () => { -// beforeEach(() => { -// atom.commands.dispatch(editorElement, 'project-find:show'); -// }); -// -// it("indicates that it's searching, then shows the results", async () => { -// projectFindView.findEditor.setText('item'); -// atom.commands.dispatch(projectFindView.element, 'core:confirm'); -// -// await projectFindView.showResultPane(); -// -// expect(projectFindView.refs.descriptionLabel.textContent).toContain('Searching...'); -// -// await searchPromise; -// -// expect(projectFindView.refs.descriptionLabel.textContent).toContain('13 results found in 2 files'); -// atom.commands.dispatch(projectFindView.element, 'core:confirm'); -// expect(projectFindView.refs.descriptionLabel.textContent).toContain('13 results found in 2 files'); -// }); -// -// it("shows an error when the pattern is invalid and clears when no error", async () => { -// spyOn(atom.workspace, 'scan').andReturn(Promise.resolve()); -// atom.commands.dispatch(projectFindView.element, 'project-find:toggle-regex-option'); -// projectFindView.findEditor.setText('['); -// atom.commands.dispatch(projectFindView.element, 'core:confirm'); -// -// await searchPromise; -// -// expect(projectFindView.refs.descriptionLabel).toHaveClass('text-error'); -// expect(projectFindView.refs.descriptionLabel.textContent).toContain('Invalid regular expression'); -// -// projectFindView.findEditor.setText(''); -// atom.commands.dispatch(projectFindView.element, 'core:confirm'); -// -// expect(projectFindView.refs.descriptionLabel).not.toHaveClass('text-error'); -// expect(projectFindView.refs.descriptionLabel.textContent).toContain('Find in Project'); -// -// projectFindView.findEditor.setText('items'); -// atom.commands.dispatch(projectFindView.element, 'core:confirm'); -// -// await searchPromise; -// -// expect(projectFindView.refs.descriptionLabel).not.toHaveClass('text-error'); -// expect(projectFindView.refs.descriptionLabel.textContent).toContain('items'); -// }); -// }); -// -// describe("regex", () => { -// beforeEach(() => { -// atom.commands.dispatch(editorElement, 'project-find:show'); -// projectFindView.findEditor.setText('i(\\w)ems+'); -// spyOn(atom.workspace, 'scan').andCallFake(async () => {}); -// }); -// -// it("escapes regex patterns by default", async () => { -// atom.commands.dispatch(projectFindView.element, 'core:confirm'); -// await searchPromise; -// -// expect(atom.workspace.scan.argsForCall[0][0]).toEqual(/i\(\\w\)ems\+/gim); -// }); -// -// it("shows an error when the regex pattern is invalid", async () => { -// atom.commands.dispatch(projectFindView.element, 'project-find:toggle-regex-option'); -// projectFindView.findEditor.setText('['); -// -// atom.commands.dispatch(projectFindView.element, 'core:confirm'); -// await searchPromise; -// -// expect(projectFindView.refs.descriptionLabel).toHaveClass('text-error'); -// }); -// -// describe("when search has not been run yet", () => { -// it("toggles regex option via an event but does not run the search", () => { -// expect(projectFindView.refs.regexOptionButton).not.toHaveClass('selected'); -// atom.commands.dispatch(projectFindView.element, 'project-find:toggle-regex-option'); -// expect(projectFindView.refs.regexOptionButton).toHaveClass('selected'); -// expect(atom.workspace.scan).not.toHaveBeenCalled(); -// }) -// }); -// -// describe("when search has been run", () => { -// beforeEach(async () => { -// atom.commands.dispatch(projectFindView.element, 'core:confirm'); -// await searchPromise; -// }); -// -// it("toggles regex option via an event and finds files matching the pattern", async () => { -// expect(projectFindView.refs.regexOptionButton).not.toHaveClass('selected'); -// atom.commands.dispatch(projectFindView.element, 'project-find:toggle-regex-option'); -// -// await searchPromise; -// -// expect(projectFindView.refs.regexOptionButton).toHaveClass('selected'); -// expect(atom.workspace.scan.mostRecentCall.args[0]).toEqual(/i(\w)ems+/gim); -// }); -// -// it("toggles regex option via a button and finds files matching the pattern", async () => { -// expect(projectFindView.refs.regexOptionButton).not.toHaveClass('selected'); -// projectFindView.refs.regexOptionButton.click(); -// -// await searchPromise; -// -// expect(projectFindView.refs.regexOptionButton).toHaveClass('selected'); -// expect(atom.workspace.scan.mostRecentCall.args[0]).toEqual(/i(\w)ems+/gim); -// }); -// }); -// }); -// -// describe("case sensitivity", () => { -// beforeEach(async () => { -// atom.commands.dispatch(editorElement, 'project-find:show'); -// spyOn(atom.workspace, 'scan').andCallFake(() => Promise.resolve()); -// projectFindView.findEditor.setText('ITEMS'); -// -// atom.commands.dispatch(projectFindView.element, 'core:confirm'); -// await searchPromise; -// }); -// -// it("runs a case insensitive search by default", () => expect(atom.workspace.scan.argsForCall[0][0]).toEqual(/ITEMS/gim)); -// -// it("toggles case sensitive option via an event and finds files matching the pattern", async () => { -// expect(projectFindView.refs.caseOptionButton).not.toHaveClass('selected'); -// -// atom.commands.dispatch(projectFindView.element, 'project-find:toggle-case-option'); -// await searchPromise; -// -// expect(projectFindView.refs.caseOptionButton).toHaveClass('selected'); -// expect(atom.workspace.scan.mostRecentCall.args[0]).toEqual(/ITEMS/gm); -// }); -// -// it("toggles case sensitive option via a button and finds files matching the pattern", async () => { -// expect(projectFindView.refs.caseOptionButton).not.toHaveClass('selected'); -// -// projectFindView.refs.caseOptionButton.click(); -// await searchPromise; -// -// expect(projectFindView.refs.caseOptionButton).toHaveClass('selected'); -// expect(atom.workspace.scan.mostRecentCall.args[0]).toEqual(/ITEMS/gm); -// }); -// }); -// -// describe("whole word", () => { -// beforeEach(async () => { -// atom.commands.dispatch(editorElement, 'project-find:show'); -// spyOn(atom.workspace, 'scan').andCallFake(async () => {}); -// projectFindView.findEditor.setText('wholeword'); -// -// atom.commands.dispatch(projectFindView.element, 'core:confirm'); -// await searchPromise; -// }); -// -// it("does not run whole word search by default", () => { -// expect(atom.workspace.scan.argsForCall[0][0]).toEqual(/wholeword/gim) -// }); -// -// it("toggles whole word option via an event and finds files matching the pattern", async () => { -// expect(projectFindView.refs.wholeWordOptionButton).not.toHaveClass('selected'); -// atom.commands.dispatch(projectFindView.element, 'project-find:toggle-whole-word-option'); -// -// await searchPromise; -// expect(projectFindView.refs.wholeWordOptionButton).toHaveClass('selected'); -// expect(atom.workspace.scan.mostRecentCall.args[0]).toEqual(/\bwholeword\b/gim); -// }); -// -// it("toggles whole word option via a button and finds files matching the pattern", async () => { -// expect(projectFindView.refs.wholeWordOptionButton).not.toHaveClass('selected'); -// -// projectFindView.refs.wholeWordOptionButton.click(); -// await searchPromise; -// -// expect(projectFindView.refs.wholeWordOptionButton).toHaveClass('selected'); -// expect(atom.workspace.scan.mostRecentCall.args[0]).toEqual(/\bwholeword\b/gim); -// }); -// }); -// -// describe("when project-find:confirm is triggered", () => { -// beforeEach(() => { -// jasmine.useRealClock() -// }); -// -// it("displays the results and no errors", async () => { -// projectFindView.findEditor.setText('items'); -// atom.commands.dispatch(projectFindView.element, 'project-find:confirm'); -// -// await searchPromise; -// await waitForSearchResults(); -// -// const resultsView = getResultsView(); -// expect(resultsView.element).toBeVisible(); -// expect(resultsView.refs.listView.element.querySelectorAll(".match-row")).toHaveLength(11); -// expect(resultsView.refs.listView.element.querySelectorAll(".match.highlight-info")).toHaveLength(13); -// }) -// }); -// -// describe("when core:confirm is triggered", () => { -// beforeEach(() => { -// atom.commands.dispatch(workspaceElement, 'project-find:show') -// jasmine.useRealClock() -// }); -// -// describe("when the there search field is empty", () => { -// it("does not run the search but clears the model", () => { -// spyOn(atom.workspace, 'scan'); -// spyOn(projectFindView.model, 'clear'); -// atom.commands.dispatch(projectFindView.element, 'core:confirm'); -// expect(atom.workspace.scan).not.toHaveBeenCalled(); -// expect(projectFindView.model.clear).toHaveBeenCalled(); -// }) -// }); -// -// it("reruns the search when confirmed again after focusing the window", async () => { -// projectFindView.findEditor.setText('thisdoesnotmatch'); -// atom.commands.dispatch(projectFindView.element, 'core:confirm'); -// -// await searchPromise; -// -// spyOn(atom.workspace, 'scan'); -// atom.commands.dispatch(projectFindView.element, 'core:confirm'); -// -// await searchPromise; -// -// expect(atom.workspace.scan).not.toHaveBeenCalled(); -// atom.workspace.scan.reset(); -// window.dispatchEvent(new FocusEvent("focus")); -// atom.commands.dispatch(projectFindView.element, 'core:confirm'); -// -// await searchPromise; -// -// expect(atom.workspace.scan).toHaveBeenCalled(); -// atom.workspace.scan.reset(); -// atom.commands.dispatch(projectFindView.element, 'core:confirm'); -// -// await searchPromise; -// -// expect(atom.workspace.scan).not.toHaveBeenCalled(); -// }); -// -// describe("when results exist", () => { -// beforeEach(() => { -// projectFindView.findEditor.setText('items') -// }); -// -// it("displays the results and no errors", async () => { -// atom.commands.dispatch(projectFindView.element, 'core:confirm'); -// await searchPromise; -// -// const resultsView = getResultsView(); -// const resultsPaneView = getExistingResultsPane(); -// -// expect(resultsView.element).toBeVisible(); -// expect(resultsView.refs.listView.element.querySelectorAll(".match-row")).toHaveLength(11); -// expect(resultsView.refs.listView.element.querySelectorAll(".match.highlight-info")).toHaveLength(13); -// -// expect(resultsPaneView.refs.previewCount.textContent).toBe("13 results found in 2 files for items"); -// expect(projectFindView.errorMessages).not.toBeVisible(); -// }); -// -// it("only searches paths matching text in the path filter", async () => { -// spyOn(atom.workspace, 'scan').andCallFake(async () => {}); -// projectFindView.pathsEditor.setText('*.js'); -// -// atom.commands.dispatch(projectFindView.element, 'core:confirm'); -// await searchPromise; -// -// expect(atom.workspace.scan.argsForCall[0][1].paths).toEqual(['*.js']); -// }); -// -// it("updates the results list when a buffer changes", async () => { -// const editor = await atom.workspace.open('sample.js') -// -// atom.commands.dispatch(projectFindView.element, 'core:confirm'); -// await searchPromise; -// -// const resultsView = getResultsView(); -// const listView = resultsView.refs.listView; -// const resultsPaneView = getExistingResultsPane(); -// -// expect(listView.element.querySelectorAll(".match-row")).toHaveLength(11); -// expect(listView.element.querySelectorAll(".match.highlight-info")).toHaveLength(13); -// expect(resultsPaneView.refs.previewCount.textContent).toBe("13 results found in 2 files for items"); -// -// resultsView.selectFirstResult(); -// for (let i = 0; i < 6; i++) resultsView.moveDown(); -// await resultsView.moveDown(); -// -// expect(listView.element.querySelectorAll(".path-row")[1].parentElement).toHaveClass('selected'); -// -// editor.setText('there is one "items" in this file'); -// await etch.getScheduler().getNextUpdatePromise() -// await searchPromise; -// -// await conditionPromise( -// () => resultsPaneView.refs.previewCount.textContent === "8 results found in 2 files for items" -// ) -// -// expect(listView.element.querySelectorAll(".path-row")[1].parentElement).toHaveClass('selected'); -// -// // Ensure the newly added item can be opened. -// await resultsView.moveDown() -// atom.commands.dispatch(resultsView.element, 'core:confirm'); -// await waitForSearchResults(); -// await conditionPromise( -// () => editor.getSelectedText() === "items" -// ) -// -// editor.setText('no matches in this file'); -// await waitForSearchResults(); -// -// await conditionPromise( -// () => resultsPaneView.refs.previewCount.textContent === "7 results found in 1 file for items" -// ) -// }); -// -// it("doesn't update the results list when a buffer outside the project changes", async () => { -// const editor = await atom.workspace.open('../sample.js') -// -// atom.commands.dispatch(projectFindView.element, 'core:confirm'); -// await searchPromise; -// -// const resultsView = getResultsView(); -// const resultsPaneView = getExistingResultsPane(); -// -// expect(resultsView.refs.listView.element.querySelectorAll(".list-item")).toHaveLength(13); -// expect(resultsPaneView.refs.previewCount.textContent).toBe("13 results found in 2 files for items"); -// -// resultsView.selectFirstResult(); -// for (let i = 0; i < 7; i++) await resultsView.moveDown() -// expect(resultsView.refs.listView.element.querySelectorAll(".list-nested-item")[1]).toHaveClass('selected'); -// -// editor.setText('there is one "items" in this file'); -// advanceClock(editor.getBuffer().stoppedChangingDelay); -// await etch.getScheduler().getNextUpdatePromise() -// expect(resultsPaneView.refs.previewCount.textContent).toBe("13 results found in 2 files for items"); -// expect(resultsView.refs.listView.element.querySelectorAll(".list-nested-item")[1]).toHaveClass('selected'); -// }); -// }); -// -// describe("when no results exist", () => { -// beforeEach(() => { -// projectFindView.findEditor.setText('notintheprojectbro'); -// spyOn(atom.workspace, 'scan').andCallFake(async () => {}); -// }); -// -// it("displays no errors and no results", async () => { -// atom.commands.dispatch(projectFindView.element, 'core:confirm'); -// await searchPromise; -// -// const resultsView = getResultsView(); -// expect(projectFindView.refs.errorMessages).not.toBeVisible(); -// expect(resultsView.element).toBeVisible(); -// expect(resultsView.refs.listView.element.querySelectorAll(".match-row")).toHaveLength(0); -// }); -// }); -// }); -// -// describe("history", () => { -// beforeEach(() => { -// atom.commands.dispatch(workspaceElement, 'project-find:show'); -// spyOn(atom.workspace, 'scan').andCallFake(() => { -// let promise = Promise.resolve(); -// promise.cancel = () => {}; -// return promise; -// }); -// -// projectFindView.findEditor.setText('sort'); -// projectFindView.replaceEditor.setText('bort'); -// projectFindView.pathsEditor.setText('abc'); -// atom.commands.dispatch(projectFindView.findEditor.getElement(), 'core:confirm'); -// -// projectFindView.findEditor.setText('items'); -// projectFindView.replaceEditor.setText('eyetims'); -// projectFindView.pathsEditor.setText('def'); -// atom.commands.dispatch(projectFindView.findEditor.getElement(), 'core:confirm'); -// }); -// -// it("can navigate the entire history stack", () => { -// expect(projectFindView.findEditor.getText()).toEqual('items'); -// -// atom.commands.dispatch(projectFindView.findEditor.getElement(), 'core:move-up'); -// expect(projectFindView.findEditor.getText()).toEqual('sort'); -// -// atom.commands.dispatch(projectFindView.findEditor.getElement(), 'core:move-down'); -// expect(projectFindView.findEditor.getText()).toEqual('items'); -// -// atom.commands.dispatch(projectFindView.findEditor.getElement(), 'core:move-down'); -// expect(projectFindView.findEditor.getText()).toEqual(''); -// -// expect(projectFindView.pathsEditor.getText()).toEqual('def'); -// -// atom.commands.dispatch(projectFindView.pathsEditor.element, 'core:move-up'); -// expect(projectFindView.pathsEditor.getText()).toEqual('abc'); -// -// atom.commands.dispatch(projectFindView.pathsEditor.element, 'core:move-down'); -// expect(projectFindView.pathsEditor.getText()).toEqual('def'); -// -// atom.commands.dispatch(projectFindView.pathsEditor.element, 'core:move-down'); -// expect(projectFindView.pathsEditor.getText()).toEqual(''); -// -// expect(projectFindView.replaceEditor.getText()).toEqual('eyetims'); -// -// atom.commands.dispatch(projectFindView.replaceEditor.element, 'core:move-up'); -// expect(projectFindView.replaceEditor.getText()).toEqual('bort'); -// -// atom.commands.dispatch(projectFindView.replaceEditor.element, 'core:move-down'); -// expect(projectFindView.replaceEditor.getText()).toEqual('eyetims'); -// -// atom.commands.dispatch(projectFindView.replaceEditor.element, 'core:move-down'); -// expect(projectFindView.replaceEditor.getText()).toEqual(''); -// }); -// }); -// -// describe("when find-and-replace:use-selection-as-find-pattern is triggered", () => { -// it("places the selected text into the find editor", () => { -// editor.setSelectedBufferRange([[1, 6], [1, 10]]); -// atom.commands.dispatch(workspaceElement, 'find-and-replace:use-selection-as-find-pattern'); -// expect(projectFindView.findEditor.getText()).toBe('sort'); -// -// editor.setSelectedBufferRange([[1, 13], [1, 21]]); -// atom.commands.dispatch(workspaceElement, 'find-and-replace:use-selection-as-find-pattern'); -// expect(projectFindView.findEditor.getText()).toBe('function'); -// }); -// -// it("places the word under the cursor into the find editor", () => { -// editor.setSelectedBufferRange([[1, 8], [1, 8]]); -// atom.commands.dispatch(workspaceElement, 'find-and-replace:use-selection-as-find-pattern'); -// expect(projectFindView.findEditor.getText()).toBe('sort'); -// -// editor.setSelectedBufferRange([[1, 15], [1, 15]]); -// atom.commands.dispatch(workspaceElement, 'find-and-replace:use-selection-as-find-pattern'); -// expect(projectFindView.findEditor.getText()).toBe('function'); -// }); -// -// it("places the previously selected text into the find editor if no selection and no word under cursor", () => { -// editor.setSelectedBufferRange([[1, 13], [1, 21]]); -// atom.commands.dispatch(workspaceElement, 'find-and-replace:use-selection-as-find-pattern'); -// expect(projectFindView.findEditor.getText()).toBe('function'); -// -// editor.setSelectedBufferRange([[1, 1], [1, 1]]); -// atom.commands.dispatch(workspaceElement, 'find-and-replace:use-selection-as-find-pattern'); -// expect(projectFindView.findEditor.getText()).toBe('function'); -// }); -// -// it("places selected text into the find editor and escapes it when Regex is enabled", () => { -// atom.commands.dispatch(projectFindView.element, 'project-find:toggle-regex-option'); -// editor.setSelectedBufferRange([[6, 6], [6, 65]]); -// atom.commands.dispatch(workspaceElement, 'find-and-replace:use-selection-as-find-pattern'); -// expect(projectFindView.findEditor.getText()).toBe('current < pivot \\? left\\.push\\(current\\) : right\\.push\\(current\\);'); -// }); -// }); -// -// describe("when find-and-replace:use-selection-as-replace-pattern is triggered", () => { -// it("places the selected text into the replace editor", () => { -// editor.setSelectedBufferRange([[1, 6], [1, 10]]); -// atom.commands.dispatch(workspaceElement, 'find-and-replace:use-selection-as-replace-pattern'); -// expect(projectFindView.replaceEditor.getText()).toBe('sort'); -// -// editor.setSelectedBufferRange([[1, 13], [1, 21]]); -// atom.commands.dispatch(workspaceElement, 'find-and-replace:use-selection-as-replace-pattern'); -// expect(projectFindView.replaceEditor.getText()).toBe('function'); -// }); -// -// it("places the word under the cursor into the replace editor", () => { -// editor.setSelectedBufferRange([[1, 8], [1, 8]]); -// atom.commands.dispatch(workspaceElement, 'find-and-replace:use-selection-as-replace-pattern'); -// expect(projectFindView.replaceEditor.getText()).toBe('sort'); -// -// editor.setSelectedBufferRange([[1, 15], [1, 15]]); -// atom.commands.dispatch(workspaceElement, 'find-and-replace:use-selection-as-replace-pattern'); -// expect(projectFindView.replaceEditor.getText()).toBe('function'); -// }); -// -// it("places the previously selected text into the replace editor if no selection and no word under cursor", () => { -// editor.setSelectedBufferRange([[1, 13], [1, 21]]); -// atom.commands.dispatch(workspaceElement, 'find-and-replace:use-selection-as-replace-pattern'); -// expect(projectFindView.replaceEditor.getText()).toBe('function'); -// -// editor.setSelectedBufferRange([[1, 1], [1, 1]]); -// atom.commands.dispatch(workspaceElement, 'find-and-replace:use-selection-as-replace-pattern'); -// expect(projectFindView.replaceEditor.getText()).toBe('function'); -// }); -// -// it("places selected text into the replace editor and escapes it when Regex is enabled", () => { -// atom.commands.dispatch(projectFindView.element, 'project-find:toggle-regex-option') -// editor.setSelectedBufferRange([[6, 6], [6, 65]]); -// atom.commands.dispatch(workspaceElement, 'find-and-replace:use-selection-as-replace-pattern'); -// expect(projectFindView.replaceEditor.getText()).toBe('current < pivot \\? left\\.push\\(current\\) : right\\.push\\(current\\);'); -// }); -// }); -// -// describe("when there is an error searching", () => { -// it("displays the errors in the results pane", async () => { -// projectFindView.findEditor.setText('items'); -// -// let errorList; -// spyOn(atom.workspace, 'scan').andCallFake(async (regex, options, callback) => { -// const resultsPaneView = getExistingResultsPane(); -// ({errorList} = resultsPaneView.refs); -// expect(errorList.querySelectorAll("li")).toHaveLength(0); -// -// callback(null, {path: '/some/path.js', code: 'ENOENT', message: 'Nope'}); -// await etch.update(resultsPaneView); -// expect(errorList).toBeVisible(); -// expect(errorList.querySelectorAll("li")).toHaveLength(1); -// -// callback(null, {path: '/some/path.js', code: 'ENOENT', message: 'Broken'}); -// await etch.update(resultsPaneView); -// expect(errorList.querySelectorAll("li")).toHaveLength(2); -// }); -// -// atom.commands.dispatch(projectFindView.element, 'core:confirm'); -// -// await searchPromise; -// -// expect(errorList).toBeVisible(); -// expect(errorList.querySelectorAll("li")).toHaveLength(2); -// expect(errorList.querySelectorAll("li")[0].textContent).toBe('Nope'); -// expect(errorList.querySelectorAll("li")[1].textContent).toBe('Broken'); -// }) -// }); -// -// describe("buffer search sharing of the find options", () => { -// function getResultDecorations(clazz) { -// const result = []; -// const decorations = editor.decorationsStateForScreenRowRange(0, editor.getLineCount()); -// for (let id in decorations) { -// const decoration = decorations[id]; -// if (decoration.properties.class === clazz) { -// result.push(decoration); -// } -// } -// return result; -// } -// -// it("setting the find text does not interfere with the project replace state", async () => { -// // Not sure why I need to advance the clock before setting the text. If -// // this advanceClock doesnt happen, the text will be ''. wtf. -// advanceClock(projectFindView.findEditor.getBuffer().stoppedChangingDelay + 1); -// spyOn(atom.workspace, 'scan'); -// -// projectFindView.findEditor.setText('findme'); -// advanceClock(projectFindView.findEditor.getBuffer().stoppedChangingDelay + 1); -// -// await projectFindView.search({onlyRunIfActive: false, onlyRunIfChanged: true}); -// expect(atom.workspace.scan).toHaveBeenCalled(); -// }); -// -// it("shares the buffers and history cyclers between both buffer and project views", () => { -// projectFindView.findEditor.setText('findme'); -// projectFindView.replaceEditor.setText('replaceme'); -// -// atom.commands.dispatch(editorElement, 'find-and-replace:show'); -// expect(findView.findEditor.getText()).toBe('findme'); -// expect(findView.replaceEditor.getText()).toBe('replaceme'); -// -// // add some things to the history -// atom.commands.dispatch(findView.findEditor.element, 'core:confirm'); -// findView.findEditor.setText('findme1'); -// atom.commands.dispatch(findView.findEditor.element, 'core:confirm'); -// findView.findEditor.setText(''); -// -// atom.commands.dispatch(findView.replaceEditor.element, 'core:confirm'); -// findView.replaceEditor.setText('replaceme1'); -// atom.commands.dispatch(findView.replaceEditor.element, 'core:confirm'); -// findView.replaceEditor.setText(''); -// -// // Back to the project view to make sure we're using the same cycler -// atom.commands.dispatch(editorElement, 'project-find:show'); -// -// expect(projectFindView.findEditor.getText()).toBe(''); -// atom.commands.dispatch(projectFindView.findEditor.element, 'core:move-up'); -// expect(projectFindView.findEditor.getText()).toBe('findme1'); -// atom.commands.dispatch(projectFindView.findEditor.element, 'core:move-up'); -// expect(projectFindView.findEditor.getText()).toBe('findme'); -// -// expect(projectFindView.replaceEditor.getText()).toBe(''); -// atom.commands.dispatch(projectFindView.replaceEditor.element, 'core:move-up'); -// expect(projectFindView.replaceEditor.getText()).toBe('replaceme1'); -// atom.commands.dispatch(projectFindView.replaceEditor.element, 'core:move-up'); -// expect(projectFindView.replaceEditor.getText()).toBe('replaceme'); -// }); -// -// it('highlights the search results in the selected file', async () => { -// jasmine.useRealClock(); -// // Process here is to -// // * open samplejs -// // * run a search that has sample js results -// // * that should place the pattern in the buffer find -// // * focus project/sample.js by clicking on a project/sample.js result -// // * when the file has been activated, it's results for the project search should be highlighted -// -// editor = await atom.workspace.open('sample.js'); -// expect(getResultDecorations('find-result')).toHaveLength(0); -// -// projectFindView.findEditor.setText('item'); -// atom.commands.dispatch(projectFindView.element, 'core:confirm'); -// await searchPromise; -// await waitForSearchResults(); -// -// const resultsView = getResultsView(); -// resultsView.scrollToBottom(); // To load ALL the results -// await etch.update(resultsView); -// expect(resultsView.element).toBeVisible(); -// expect(resultsView.refs.listView.element.querySelectorAll(".match-row")).toHaveLength(11); -// expect(resultsView.refs.listView.element.querySelectorAll(".match.highlight-info")).toHaveLength(13); -// -// resultsView.selectFirstResult(); -// for (let i = 0; i < 9; i++) resultsView.moveDown(); -// await resultsView.moveDown(); -// -// atom.commands.dispatch(resultsView.element, 'core:confirm'); -// await new Promise(resolve => editor.onDidChangeSelectionRange(resolve)) -// -// // project/sample.js has 6 results -// expect(getResultDecorations('find-result')).toHaveLength(5); -// expect(getResultDecorations('current-result')).toHaveLength(1); -// expect(workspaceElement).toHaveClass('find-visible'); -// -// const initialSelectedRange = editor.getSelectedBufferRange(); -// -// // now we can find next -// atom.commands.dispatch(atom.views.getView(editor), 'find-and-replace:find-next'); -// expect(editor.getSelectedBufferRange()).not.toEqual(initialSelectedRange); -// -// // Now we toggle the whole-word option to make sure it is updated in the buffer find -// atom.commands.dispatch(projectFindView.element, 'project-find:toggle-whole-word-option'); -// await searchPromise; -// -// // project/sample.js has 0 results for whole word `item` -// expect(getResultDecorations('find-result')).toHaveLength(0); -// expect(workspaceElement).toHaveClass('find-visible'); -// -// // Now we toggle the whole-word option to make sure it is updated in the buffer find -// atom.commands.dispatch(projectFindView.element, 'project-find:toggle-whole-word-option'); -// }); -// }); -// -// describe("when user asked not to override last search results", () => { -// beforeEach(async () => { -// atom.commands.dispatch(editorElement, 'project-find:show'); -// projectFindView.findEditor.setText('items'); -// atom.commands.dispatch(projectFindView.element, 'core:confirm'); -// await searchPromise; -// -// }); -// it("opens new search results in new panel", async () => { -// const result_pane = getExistingResultsPane(); -// result_pane.dontOverrideTab(); -// projectFindView.findEditor.setText('items2'); -// atom.commands.dispatch(projectFindView.element, 'core:confirm'); -// await searchPromise; -// expect(result_pane).not.toBe(getExistingResultsPane()); -// }); -// }); -// }); -// -// describe("replacing", () => { -// let testDir, sampleJs, sampleCoffee, replacePromise; -// -// beforeEach(async () => { -// testDir = temp.mkdirSync('atom-find-and-replace'); -// sampleJs = path.join(testDir, 'project/sample.js'); -// sampleCoffee = path.join(testDir, 'sample.coffee'); -// -// fs.makeTreeSync(testDir); -// fs.writeFileSync(sampleCoffee, fs.readFileSync(require.resolve('./fixtures/sample.coffee'))); -// fs.writeFileSync(sampleJs, fs.readFileSync(require.resolve('./fixtures/project/sample.js'))); -// -// atom.commands.dispatch(workspaceElement, 'project-find:show'); -// await activationPromise; -// -// atom.project.setPaths([testDir]); -// const spy = spyOn(projectFindView, 'replaceAll').andCallFake(() => { -// replacePromise = spy.originalValue.call(projectFindView); -// }); -// }); -// -// describe("when the replace string contains an escaped char", () => { -// let filePath = null; -// -// beforeEach(() => { -// let projectPath = temp.mkdirSync("atom"); -// filePath = path.join(projectPath, "tabs.txt"); -// fs.writeFileSync(filePath, "a\nb\na"); -// atom.project.setPaths([projectPath]); -// atom.commands.dispatch(workspaceElement, 'project-find:show'); -// -// spyOn(atom, 'confirm').andReturn({response:0}); -// }); -// -// describe("when the regex option is chosen", () => { -// beforeEach(async () => { -// atom.commands.dispatch(projectFindView.element, 'project-find:toggle-regex-option'); -// projectFindView.findEditor.setText('a'); -// atom.commands.dispatch(projectFindView.element, 'project-find:confirm'); -// await searchPromise; -// }); -// -// it("finds the escape char", async () => { -// projectFindView.replaceEditor.setText('\\t'); -// -// atom.commands.dispatch(projectFindView.element, 'project-find:replace-all'); -// await replacePromise; -// -// expect(fs.readFileSync(filePath, 'utf8')).toBe("\t\nb\n\t"); -// }); -// -// it("doesn't insert a escaped char if there are multiple backslashs in front of the char", async () => { -// projectFindView.replaceEditor.setText('\\\\t'); -// -// atom.commands.dispatch(projectFindView.element, 'project-find:replace-all'); -// await replacePromise; -// -// expect(fs.readFileSync(filePath, 'utf8')).toBe("\\t\nb\n\\t"); -// }); -// }); -// -// describe("when regex option is not set", () => { -// beforeEach(async () => { -// projectFindView.findEditor.setText('a'); -// atom.commands.dispatch(projectFindView.element, 'project-find:confirm'); -// await searchPromise; -// }); -// -// it("finds the escape char", async () => { -// projectFindView.replaceEditor.setText('\\t'); -// -// atom.commands.dispatch(projectFindView.element, 'project-find:replace-all'); -// await replacePromise; -// -// expect(fs.readFileSync(filePath, 'utf8')).toBe("\\t\nb\n\\t"); -// }); -// }); -// }); -// -// describe("replace all button enablement", () => { -// let disposable = null; -// -// it("is disabled initially", () => { -// expect(projectFindView.refs.replaceAllButton).toHaveClass('disabled') -// }); -// -// it("is disabled when a search returns no results", async () => { -// projectFindView.findEditor.setText('items'); -// atom.commands.dispatch(projectFindView.element, 'project-find:confirm'); -// await searchPromise; -// -// expect(projectFindView.refs.replaceAllButton).not.toHaveClass('disabled'); -// -// projectFindView.findEditor.setText('nopenotinthefile'); -// atom.commands.dispatch(projectFindView.element, 'project-find:confirm'); -// await searchPromise; -// -// expect(projectFindView.refs.replaceAllButton).toHaveClass('disabled'); -// }); -// -// it("is enabled when a search has results and disabled when there are no results", async () => { -// projectFindView.findEditor.setText('items'); -// atom.commands.dispatch(projectFindView.element, 'project-find:confirm'); -// -// await searchPromise; -// -// disposable = projectFindView.replaceTooltipSubscriptions; -// spyOn(disposable, 'dispose'); -// -// expect(projectFindView.refs.replaceAllButton).not.toHaveClass('disabled'); -// -// // The replace all button should still be disabled as the text has been changed and a new search has not been run -// projectFindView.findEditor.setText('itemss'); -// advanceClock(stoppedChangingDelay); -// expect(projectFindView.refs.replaceAllButton).toHaveClass('disabled'); -// expect(disposable.dispose).toHaveBeenCalled(); -// -// // The button should still be disabled because the search and search pattern are out of sync -// projectFindView.replaceEditor.setText('omgomg'); -// advanceClock(stoppedChangingDelay); -// expect(projectFindView.refs.replaceAllButton).toHaveClass('disabled'); -// -// disposable = projectFindView.replaceTooltipSubscriptions; -// spyOn(disposable, 'dispose'); -// projectFindView.findEditor.setText('items'); -// advanceClock(stoppedChangingDelay); -// expect(projectFindView.refs.replaceAllButton).not.toHaveClass('disabled'); -// -// projectFindView.findEditor.setText(''); -// atom.commands.dispatch(projectFindView.element, 'project-find:confirm'); -// -// expect(projectFindView.refs.replaceAllButton).toHaveClass('disabled'); -// }); -// }); -// -// describe("when the replace button is pressed", () => { -// beforeEach(() => { -// spyOn(atom, 'confirm').andReturn({ response: 0 }); -// }); -// -// it("runs the search, and replaces all the matches", async () => { -// projectFindView.findEditor.setText('items'); -// atom.commands.dispatch(projectFindView.element, 'core:confirm'); -// await searchPromise; -// -// projectFindView.replaceEditor.setText('sunshine'); -// projectFindView.refs.replaceAllButton.click(); -// await replacePromise; -// -// expect(projectFindView.errorMessages).not.toBeVisible(); -// expect(projectFindView.refs.descriptionLabel.textContent).toContain('Replaced'); -// -// const sampleJsContent = fs.readFileSync(sampleJs, 'utf8'); -// expect(sampleJsContent.match(/items/g)).toBeFalsy(); -// expect(sampleJsContent.match(/sunshine/g)).toHaveLength(6); -// -// const sampleCoffeeContent = fs.readFileSync(sampleCoffee, 'utf8'); -// expect(sampleCoffeeContent.match(/items/g)).toBeFalsy(); -// expect(sampleCoffeeContent.match(/sunshine/g)).toHaveLength(7); -// }); -// -// describe("when there are search results after a replace", () => { -// it("runs the search after the replace", async () => { -// projectFindView.findEditor.setText('items'); -// atom.commands.dispatch(projectFindView.element, 'core:confirm'); -// await searchPromise; -// -// projectFindView.replaceEditor.setText('items-123'); -// projectFindView.refs.replaceAllButton.click(); -// await replacePromise; -// -// await etch.update(getExistingResultsPane()); -// -// expect(projectFindView.errorMessages).not.toBeVisible(); -// expect(getExistingResultsPane().refs.previewCount.textContent).toContain('13 results found in 2 files for items'); -// expect(projectFindView.refs.descriptionLabel.textContent).toContain('Replaced items with items-123 13 times in 2 files'); -// -// projectFindView.replaceEditor.setText('cats'); -// advanceClock(projectFindView.replaceEditor.getBuffer().stoppedChangingDelay); -// expect(projectFindView.refs.descriptionLabel.textContent).not.toContain('Replaced items'); -// expect(projectFindView.refs.descriptionLabel.textContent).toContain("13 results found in 2 files for items"); -// }) -// }); -// }); -// -// describe("when the project-find:replace-all is triggered", () => { -// describe("when no search has been run", () => { -// beforeEach(() => { -// spyOn(atom, 'confirm').andReturn(0) -// }); -// -// it("does nothing", () => { -// projectFindView.findEditor.setText('items'); -// projectFindView.replaceEditor.setText('sunshine'); -// -// spyOn(atom, 'beep'); -// atom.commands.dispatch(projectFindView.element, 'project-find:replace-all'); -// -// expect(replacePromise).toBeUndefined(); -// -// expect(atom.beep).toHaveBeenCalled(); -// expect(projectFindView.refs.descriptionLabel.textContent).toContain("Find in Project"); -// }); -// }); -// -// describe("when a search with no results has been run", () => { -// beforeEach(async () => { -// spyOn(atom, 'confirm').andReturn({ response: 0 }); -// projectFindView.findEditor.setText('nopenotinthefile'); -// atom.commands.dispatch(projectFindView.element, 'core:confirm'); -// -// await searchPromise; -// }); -// -// it("doesnt replace anything", () => { -// projectFindView.replaceEditor.setText('sunshine'); -// -// spyOn(atom.workspace, 'scan').andCallThrough(); -// spyOn(atom, 'beep'); -// atom.commands.dispatch(projectFindView.element, 'project-find:replace-all'); -// -// // The replacement isnt even run -// expect(replacePromise).toBeUndefined(); -// -// expect(atom.workspace.scan).not.toHaveBeenCalled(); -// expect(atom.beep).toHaveBeenCalled(); -// expect(projectFindView.refs.descriptionLabel.textContent.replace(/( )/g, ' ')).toContain("No results"); -// }); -// }); -// -// describe("when a search with results has been run", () => { -// beforeEach(async () => { -// projectFindView.findEditor.setText('items'); -// atom.commands.dispatch(projectFindView.element, 'core:confirm'); -// -// await searchPromise; -// }); -// -// it("messages the user when the search text has changed since that last search", () => { -// spyOn(atom, 'confirm').andReturn({ response: 0 }); -// spyOn(atom.workspace, 'scan').andCallThrough(); -// -// projectFindView.findEditor.setText('sort'); -// projectFindView.replaceEditor.setText('ok'); -// -// advanceClock(stoppedChangingDelay); -// atom.commands.dispatch(projectFindView.element, 'project-find:replace-all'); -// -// expect(replacePromise).toBeUndefined(); -// expect(atom.workspace.scan).not.toHaveBeenCalled(); -// expect(atom.confirm).toHaveBeenCalled(); -// expect(atom.confirm.mostRecentCall.args[0].message).toContain('was changed to'); -// }); -// -// it("replaces all the matches and updates the results view", async () => { -// spyOn(atom, 'confirm').andReturn({ response: 0 }); -// projectFindView.replaceEditor.setText('sunshine'); -// -// expect(projectFindView.errorMessages).not.toBeVisible(); -// atom.commands.dispatch(projectFindView.element, 'project-find:replace-all'); -// await replacePromise; -// -// const resultsView = getResultsView(); -// expect(resultsView.element).toBeVisible(); -// expect(resultsView.refs.listView.element.querySelectorAll(".match-row")).toHaveLength(0); -// -// expect(projectFindView.refs.descriptionLabel.textContent).toContain("Replaced items with sunshine 13 times in 2 files"); -// -// let sampleJsContent = fs.readFileSync(sampleJs, 'utf8'); -// expect(sampleJsContent.match(/items/g)).toBeFalsy(); -// expect(sampleJsContent.match(/sunshine/g)).toHaveLength(6); -// -// let sampleCoffeeContent = fs.readFileSync(sampleCoffee, 'utf8'); -// expect(sampleCoffeeContent.match(/items/g)).toBeFalsy(); -// expect(sampleCoffeeContent.match(/sunshine/g)).toHaveLength(7); -// }); -// -// describe("when the confirm box is cancelled", () => { -// beforeEach(() => { -// spyOn(atom, 'confirm').andReturn(1) -// }); -// -// it("does not replace", async () => { -// projectFindView.replaceEditor.setText('sunshine'); -// -// atom.commands.dispatch(projectFindView.element, 'project-find:replace-all'); -// await replacePromise; -// -// expect(projectFindView.refs.descriptionLabel.textContent).toContain("13 results found"); -// }); -// }); -// }); -// -// describe("when the find field contains a ^ or a $ and the regex option is enabled", () => { -// it("correctly replaces all matches", async () => { -// // TODO: Remove version check when Atom 1.21 reaches stable -// if (parseFloat(atom.getVersion()) < 1.21) { -// return; -// } -// -// atom.commands.dispatch(projectFindView.element, 'project-find:toggle-regex-option'); -// projectFindView.findEditor.setText(';$'); -// atom.commands.dispatch(projectFindView.element, 'core:confirm'); -// await searchPromise; -// -// spyOn(atom, 'confirm').andReturn({ response: 0 }); -// projectFindView.replaceEditor.setText('sunshine'); -// -// expect(projectFindView.errorMessages).not.toBeVisible(); -// atom.commands.dispatch(projectFindView.element, 'project-find:replace-all'); -// await replacePromise; -// -// expect(projectFindView.refs.descriptionLabel.textContent).toContain("Replaced ;$ with sunshine 9 times in 2 files"); -// -// let sampleJsContent = fs.readFileSync(sampleJs, 'utf8'); -// expect(sampleJsContent.match(/;$/gm)).toBeFalsy(); -// expect(sampleJsContent.match(/sunshine/g)).toHaveLength(8); -// }); -// }); -// }); -// -// describe("when there is an error replacing", () => { -// beforeEach(async () => { -// spyOn(atom, 'confirm').andReturn({ response: 0 }); -// projectFindView.findEditor.setText('items'); -// atom.commands.dispatch(projectFindView.element, 'project-find:confirm'); -// await searchPromise; -// }); -// -// it("displays the errors in the results pane", async () => { -// let errorList -// spyOn(atom.workspace, 'replace').andCallFake(async (regex, replacement, paths, callback) => { -// ({ errorList } = getExistingResultsPane().refs); -// expect(errorList.querySelectorAll("li")).toHaveLength(0); -// -// callback(null, {path: '/some/path.js', code: 'ENOENT', message: 'Nope'}); -// await etch.update(getExistingResultsPane()); -// expect(errorList).toBeVisible(); -// expect(errorList.querySelectorAll("li")).toHaveLength(1); -// -// callback(null, {path: '/some/path.js', code: 'ENOENT', message: 'Broken'}); -// await etch.update(getExistingResultsPane()); -// expect(errorList.querySelectorAll("li")).toHaveLength(2); -// }); -// -// projectFindView.replaceEditor.setText('sunshine'); -// atom.commands.dispatch(projectFindView.element, 'project-find:replace-all'); -// await replacePromise; -// -// expect(errorList).toBeVisible(); -// expect(errorList.querySelectorAll("li")).toHaveLength(2); -// expect(errorList.querySelectorAll("li")[0].textContent).toBe('Nope'); -// expect(errorList.querySelectorAll("li")[1].textContent).toBe('Broken'); -// }); -// }); -// }); -// -// describe("panel focus", () => { -// beforeEach(async () => { -// atom.commands.dispatch(workspaceElement, 'project-find:show'); -// await activationPromise; -// }); -// -// it("focuses the find editor when the panel gets focus", () => { -// projectFindView.replaceEditor.element.focus(); -// expect(projectFindView.replaceEditor.element).toHaveFocus(); -// -// projectFindView.element.focus(); -// expect(projectFindView.findEditor.getElement()).toHaveFocus(); -// }); -// -// it("moves focus between editors with find-and-replace:focus-next", () => { -// projectFindView.findEditor.element.focus(); -// expect(projectFindView.findEditor.element).toHaveFocus() -// -// atom.commands.dispatch(projectFindView.findEditor.element, 'find-and-replace:focus-next'); -// expect(projectFindView.replaceEditor.element).toHaveFocus() -// -// atom.commands.dispatch(projectFindView.replaceEditor.element, 'find-and-replace:focus-next'); -// expect(projectFindView.pathsEditor.element).toHaveFocus() -// -// atom.commands.dispatch(projectFindView.replaceEditor.element, 'find-and-replace:focus-next'); -// expect(projectFindView.findEditor.element).toHaveFocus() -// -// atom.commands.dispatch(projectFindView.replaceEditor.element, 'find-and-replace:focus-previous'); -// expect(projectFindView.pathsEditor.element).toHaveFocus() -// -// atom.commands.dispatch(projectFindView.replaceEditor.element, 'find-and-replace:focus-previous'); -// expect(projectFindView.replaceEditor.element).toHaveFocus() -// }); -// }); -// -// describe("panel opening", () => { -// describe("when a panel is already open on the right", () => { -// beforeEach(async () => { -// atom.config.set('find-and-replace.projectSearchResultsPaneSplitDirection', 'right'); -// -// editor = await atom.workspace.open('project/sample.js'); -// editorElement = atom.views.getView(editor); -// -// atom.commands.dispatch(workspaceElement, 'project-find:show'); -// await activationPromise; -// -// projectFindView.findEditor.setText('items'); -// atom.commands.dispatch(projectFindView.element, 'core:confirm'); -// await searchPromise; -// }); -// -// it("doesn't open another panel even if the active pane is vertically split", async () => { -// atom.commands.dispatch(editorElement, 'pane:split-down'); -// projectFindView.findEditor.setText('items'); -// -// atom.commands.dispatch(projectFindView.element, 'core:confirm'); -// await searchPromise; -// -// expect(workspaceElement.querySelectorAll('.preview-pane').length).toBe(1); -// }); -// }); -// -// describe("when a panel is already open at the bottom", () => { -// beforeEach(async () => { -// atom.config.set('find-and-replace.projectSearchResultsPaneSplitDirection', 'down'); -// -// editor = await atom.workspace.open('project/sample.js'); -// editorElement = atom.views.getView(editor); -// -// atom.commands.dispatch(workspaceElement, 'project-find:show'); -// await activationPromise; -// -// projectFindView.findEditor.setText('items'); -// atom.commands.dispatch(projectFindView.element, 'core:confirm'); -// await searchPromise; -// }); -// -// it("doesn't open another panel even if the active pane is horizontally split", async () => { -// atom.commands.dispatch(editorElement, 'pane:split-right'); -// projectFindView.findEditor.setText('items'); -// -// atom.commands.dispatch(projectFindView.element, 'core:confirm'); -// await searchPromise; -// -// expect(workspaceElement.querySelectorAll('.preview-pane').length).toBe(1); -// }); -// }); -// }); -// -// describe("when language-javascript is active", () => { -// beforeEach(async () => { -// await atom.packages.activatePackage("language-javascript"); -// }); -// -// it("uses the regexp grammar when regex-mode is loaded from configuration", async () => { -// atom.config.set('find-and-replace.useRegex', true); -// -// atom.commands.dispatch(workspaceElement, 'project-find:show'); -// await activationPromise; -// -// expect(projectFindView.model.getFindOptions().useRegex).toBe(true); -// expect(projectFindView.findEditor.getGrammar().scopeName).toBe('source.js.regexp'); -// expect(projectFindView.replaceEditor.getGrammar().scopeName).toBe('source.js.regexp.replacement'); -// }); -// -// describe("when panel is active", () => { -// beforeEach(async () => { -// atom.commands.dispatch(workspaceElement, 'project-find:show'); -// await activationPromise; -// }); -// -// it("does not use regexp grammar when in non-regex mode", () => { -// expect(projectFindView.model.getFindOptions().useRegex).not.toBe(true); -// expect(projectFindView.findEditor.getGrammar().scopeName).toBe('text.plain.null-grammar'); -// expect(projectFindView.replaceEditor.getGrammar().scopeName).toBe('text.plain.null-grammar'); -// }); -// -// it("uses regexp grammar when in regex mode and clears the regexp grammar when regex is disabled", () => { -// atom.commands.dispatch(projectFindView.element, 'project-find:toggle-regex-option'); -// -// expect(projectFindView.model.getFindOptions().useRegex).toBe(true); -// expect(projectFindView.findEditor.getGrammar().scopeName).toBe('source.js.regexp'); -// expect(projectFindView.replaceEditor.getGrammar().scopeName).toBe('source.js.regexp.replacement'); -// -// atom.commands.dispatch(projectFindView.element, 'project-find:toggle-regex-option'); -// -// expect(projectFindView.model.getFindOptions().useRegex).not.toBe(true); -// expect(projectFindView.findEditor.getGrammar().scopeName).toBe('text.plain.null-grammar'); -// expect(projectFindView.replaceEditor.getGrammar().scopeName).toBe('text.plain.null-grammar'); -// }); -// }); -// }); -// }); -// } -// -// function simulateResizeEvent(element) { -// Array.from(element.children).forEach((child) => { -// child.dispatchEvent(new AnimationEvent('animationstart')); -// }); -// advanceClock(1); -// } +/** @babel */ + +const path = require('path'); +const temp = require('temp').track(); +const fs = require('fs-plus'); +const dedent = require('dedent'); +const {TextBuffer} = require('atom'); +const ResultsPaneView = require('../lib/project/results-pane'); +const etch = require('etch'); +const {conditionPromise} = require('./async-spec-helpers'); + +for (const ripgrep of [false, true]) { +describe(`ProjectFindView (ripgrep=${ripgrep})`, () => { + const {stoppedChangingDelay} = TextBuffer.prototype; + let activationPromise, searchPromise, editor, editorElement, findView, + projectFindView, workspaceElement; + + function getAtomPanel() { + return workspaceElement.querySelector('.project-find').parentNode; + } + + function getExistingResultsPane() { + const pane = atom.workspace.paneForURI(ResultsPaneView.URI); + if (pane) { + return pane.itemForURI(ResultsPaneView.URI); + } + } + + function getResultsView() { + return getExistingResultsPane().refs.resultsView; + } + + function waitForSearchResults() { + return conditionPromise( + () => projectFindView.refs.descriptionLabel.textContent.includes('results found') + ) + } + + beforeEach(() => { + atom.config.set('find-and-replace.useRipgrep', ripgrep) + workspaceElement = atom.views.getView(atom.workspace); + atom.config.set('core.excludeVcsIgnoredPaths', false); + atom.project.setPaths([path.join(__dirname, 'fixtures')]); + jasmine.attachToDOM(workspaceElement); + + activationPromise = atom.packages.activatePackage("find-and-replace").then(function({mainModule}) { + mainModule.createViews(); + ({findView, projectFindView} = mainModule); + const spy = spyOn(projectFindView, 'search').andCallFake((options) => { + return searchPromise = spy.originalValue.call(projectFindView, options); + }); + }); + }); + + describe("when project-find:show is triggered", () => { + it("attaches ProjectFindView to the root view", async () => { + atom.commands.dispatch(workspaceElement, 'project-find:show'); + await activationPromise; + + projectFindView.findEditor.setText('items'); + expect(getAtomPanel()).toBeVisible(); + expect(projectFindView.findEditor.getSelectedBufferRange()).toEqual([[0, 0], [0, 5]]); + }); + + describe("with an open buffer", () => { + beforeEach(async () => { + atom.commands.dispatch(workspaceElement, 'project-find:show'); + await activationPromise; + projectFindView.findEditor.setText(''); + editor = await atom.workspace.open('project/sample.js'); + }); + + it("populates the findEditor with selection when there is a selection", () => { + editor.setSelectedBufferRange([[2, 8], [2, 13]]); + atom.commands.dispatch(workspaceElement, 'project-find:show'); + expect(getAtomPanel()).toBeVisible(); + expect(projectFindView.findEditor.getText()).toBe('items'); + + editor.setSelectedBufferRange([[2, 14], [2, 20]]); + atom.commands.dispatch(workspaceElement, 'project-find:show'); + expect(getAtomPanel()).toBeVisible(); + expect(projectFindView.findEditor.getText()).toBe('length'); + }); + + it("populates the findEditor with the previous selection when there is no selection", () => { + editor.setSelectedBufferRange([[2, 14], [2, 20]]); + atom.commands.dispatch(workspaceElement, 'project-find:show'); + expect(getAtomPanel()).toBeVisible(); + expect(projectFindView.findEditor.getText()).toBe('length'); + + editor.setSelectedBufferRange([[2, 30], [2, 30]]); + atom.commands.dispatch(workspaceElement, 'project-find:show'); + expect(getAtomPanel()).toBeVisible(); + expect(projectFindView.findEditor.getText()).toBe('length'); + }); + + it("places selected text into the find editor and escapes it when Regex is enabled", () => { + atom.commands.dispatch(projectFindView.element, 'project-find:toggle-regex-option'); + editor.setSelectedBufferRange([[6, 6], [6, 65]]); + atom.commands.dispatch(workspaceElement, 'project-find:show'); + expect(projectFindView.findEditor.getText()).toBe('current < pivot \\? left\\.push\\(current\\) : right\\.push\\(current\\);'); + }); + }); + + describe("when the ProjectFindView is already attached", () => { + beforeEach(async () => { + atom.commands.dispatch(workspaceElement, 'project-find:show'); + await activationPromise; + + projectFindView.findEditor.setText('items'); + projectFindView.findEditor.setSelectedBufferRange([[0, 0], [0, 0]]); + }); + + it("focuses the find editor and selects all the text", () => { + atom.commands.dispatch(workspaceElement, 'project-find:show'); + expect(projectFindView.findEditor.getElement()).toHaveFocus(); + expect(projectFindView.findEditor.getSelectedText()).toBe("items"); + }); + }); + + it("honors config settings for find options", async () => { + atom.config.set('find-and-replace.useRegex', true); + atom.config.set('find-and-replace.caseSensitive', true); + atom.config.set('find-and-replace.wholeWord', true); + + atom.commands.dispatch(workspaceElement, 'project-find:show'); + await activationPromise; + + expect(projectFindView.refs.caseOptionButton).toHaveClass('selected'); + expect(projectFindView.refs.regexOptionButton).toHaveClass('selected'); + expect(projectFindView.refs.wholeWordOptionButton).toHaveClass('selected'); + }); + }); + + describe("when project-find:show-in-current-directory is triggered with an open buffer", () => { + beforeEach(async () => { + atom.project.setPaths([__dirname]); + + atom.commands.dispatch(workspaceElement, 'project-find:show'); + await activationPromise; + + projectFindView.findEditor.setText(''); + projectFindView.pathsEditor.setText(''); + editor = await atom.workspace.open('fixtures/sample.js'); + }); + + it("calls project-find:show, and populates both findEditor and pathsEditor when there is a selection", () => { + editor.setSelectedBufferRange([[3, 8], [3, 13]]); + atom.commands.dispatch(workspaceElement, 'project-find:show-in-current-directory'); + expect(getAtomPanel()).toBeVisible(); + expect(projectFindView.findEditor.getText()).toBe('pivot'); + expect(projectFindView.pathsEditor.getText()).toBe('fixtures'); + + editor.setSelectedBufferRange([[2, 14], [2, 20]]); + atom.commands.dispatch(workspaceElement, 'project-find:show-in-current-directory'); + expect(getAtomPanel()).toBeVisible(); + expect(projectFindView.findEditor.getText()).toBe('length'); + expect(projectFindView.pathsEditor.getText()).toBe('fixtures'); + }); + + it("calls project-find:show, and populates only pathsEditor when there is no selection", () => { + atom.commands.dispatch(workspaceElement, 'project-find:show-in-current-directory'); + expect(getAtomPanel()).toBeVisible(); + expect(projectFindView.findEditor.getText()).toBe(''); + expect(projectFindView.pathsEditor.getText()).toBe('fixtures'); + }); + }); + + describe("when project-find:toggle is triggered", () => { + it("toggles the visibility of the ProjectFindView", async () => { + atom.commands.dispatch(workspaceElement, 'project-find:toggle'); + await activationPromise; + + expect(getAtomPanel()).toBeVisible(); + atom.commands.dispatch(workspaceElement, 'project-find:toggle'); + expect(getAtomPanel()).not.toBeVisible(); + }); + }); + + describe("when project-find:show-in-current-directory is triggered", () => { + let nested, tree, projectPath; + + beforeEach(() => { + projectPath = temp.mkdirSync("atom"); + atom.project.setPaths([projectPath]); + + tree = document.createElement('div'); + tree.className = 'directory'; + tree.innerHTML = dedent` +
+ ${projectPath} +
    +
  • + one.js +
  • +
  • + two.js +
  • +
    +
    + nested +
      +
    • + three.js +
    • +
    +
    +
    +
+
+ `; + + nested = tree.querySelector('.directory'); + + workspaceElement.appendChild(tree); + }); + + function escapePath(filePath) { + return filePath.replace(/\\/g, '\'); + } + + it("populates the pathsEditor when triggered with a directory", async () => { + atom.commands.dispatch(nested.querySelector('.name'), 'project-find:show-in-current-directory'); + await activationPromise; + + expect(getAtomPanel()).toBeVisible(); + expect(projectFindView.pathsEditor.getText()).toBe('nested'); + expect(projectFindView.findEditor.getElement()).toHaveFocus(); + + atom.commands.dispatch(tree.querySelector('.name'), 'project-find:show-in-current-directory'); + expect(projectFindView.pathsEditor.getText()).toBe(''); + }); + + it("populates the pathsEditor when triggered on a directory's name", async () => { + atom.commands.dispatch(nested, 'project-find:show-in-current-directory'); + await activationPromise; + + expect(getAtomPanel()).toBeVisible(); + expect(projectFindView.pathsEditor.getText()).toBe('nested'); + expect(projectFindView.findEditor.getElement()).toHaveFocus(); + + atom.commands.dispatch(tree.querySelector('.name'), 'project-find:show-in-current-directory'); + expect(projectFindView.pathsEditor.getText()).toBe(''); + }); + + it("populates the pathsEditor when triggered on a file", async () => { + atom.commands.dispatch(nested.querySelector('.file .name'), 'project-find:show-in-current-directory'); + await activationPromise; + + expect(getAtomPanel()).toBeVisible(); + expect(projectFindView.pathsEditor.getText()).toBe('nested'); + expect(projectFindView.findEditor.getElement()).toHaveFocus(); + + atom.commands.dispatch(tree.querySelector('.file .name'), 'project-find:show-in-current-directory'); + expect(projectFindView.pathsEditor.getText()).toBe(''); + }); + + describe("when there are multiple root directories", async () => { + beforeEach(() => { + atom.project.addPath(temp.mkdirSync("another-path-")) + }); + + it("includes the basename of the containing root directory in the paths-editor", async () => { + atom.commands.dispatch(nested.querySelector('.file .name'), 'project-find:show-in-current-directory'); + await activationPromise; + + expect(getAtomPanel()).toBeVisible(); + expect(projectFindView.pathsEditor.getText()).toBe(path.join(path.basename(projectPath), 'nested')); + }); + }); + }); + + describe("finding", () => { + beforeEach(async () => { + atom.project.setPaths([path.join(__dirname, 'fixtures/project')]); + editor = await atom.workspace.open('sample.js'); + editorElement = atom.views.getView(editor); + atom.commands.dispatch(workspaceElement, 'project-find:show'); + await activationPromise; + workspaceElement.style.height = '800px' + }); + + describe("when the find string contains an escaped char", () => { + beforeEach(() => { + jasmine.useRealClock() + + let projectPath = temp.mkdirSync("atom"); + fs.writeFileSync(path.join(projectPath, "tabs.txt"), "\t\n\\\t\n\\\\t"); + atom.project.setPaths([projectPath]); + atom.commands.dispatch(workspaceElement, 'project-find:show'); + }); + + describe("when regex search is enabled", () => { + it("finds a literal tab character", async () => { + atom.commands.dispatch(projectFindView.element, 'project-find:toggle-regex-option'); + projectFindView.findEditor.setText('\\t'); + + atom.commands.dispatch(projectFindView.element, 'core:confirm'); + await searchPromise; + + const resultsView = getResultsView(); + expect(resultsView.element).toBeVisible(); + expect(resultsView.refs.listView.element.querySelectorAll(".match-row")).toHaveLength(2); + }) + }); + + describe("when regex search is disabled", () => { + it("finds the escape char", async () => { + projectFindView.findEditor.setText('\\t'); + + atom.commands.dispatch(projectFindView.element, 'core:confirm'); + await searchPromise; + + const resultsView = getResultsView(); + expect(resultsView.element).toBeVisible(); + expect(resultsView.refs.listView.element.querySelectorAll(".match-row")).toHaveLength(1); + }); + + it("finds a backslash", async () => { + projectFindView.findEditor.setText('\\'); + + atom.commands.dispatch(projectFindView.element, 'core:confirm'); + await searchPromise; + + const resultsView = getResultsView(); + expect(resultsView.element).toBeVisible(); + expect(resultsView.refs.listView.element.querySelectorAll(".match-row")).toHaveLength(2); + expect(resultsView.refs.listView.element.querySelectorAll(".match.highlight-info")).toHaveLength(3); + }); + + it("doesn't insert a escaped char if there are multiple backslashs in front of the char", async () => { + projectFindView.findEditor.setText('\\\\t'); + + atom.commands.dispatch(projectFindView.element, 'core:confirm'); + await searchPromise; + + const resultsView = getResultsView(); + expect(resultsView.element).toBeVisible(); + expect(resultsView.refs.listView.element.querySelectorAll(".match-row")).toHaveLength(1); + }); + }); + }); + + describe("when core:cancel is triggered", () => { + it("detaches from the root view", () => { + atom.commands.dispatch(workspaceElement, 'project-find:show'); + projectFindView.element.focus(); + atom.commands.dispatch(document.activeElement, 'core:cancel'); + expect(getAtomPanel()).not.toBeVisible(); + }); + }); + + describe("when close option is true", () => { + beforeEach(() => { + atom.config.set('find-and-replace.closeFindPanelAfterSearch', true); + }) + + it("closes the panel after search", async () => { + projectFindView.findEditor.setText('something'); + atom.commands.dispatch(projectFindView.element, 'core:confirm'); + await searchPromise; + + expect(getAtomPanel()).not.toBeVisible(); + }); + + it("leaves the panel open after an empty search", async () => { + projectFindView.findEditor.setText(''); + atom.commands.dispatch(projectFindView.element, 'core:confirm'); + await searchPromise; + + expect(getAtomPanel()).toBeVisible(); + }); + + it("closes the panel after a no-op search", async () => { + projectFindView.findEditor.setText('something'); + atom.commands.dispatch(projectFindView.element, 'core:confirm'); + await searchPromise; + + atom.commands.dispatch(workspaceElement, 'project-find:show'); + await activationPromise; + + expect(getAtomPanel()).toBeVisible(); + + atom.commands.dispatch(projectFindView.element, 'core:confirm'); + await searchPromise; + + expect(getAtomPanel()).not.toBeVisible(); + }); + + it("does not close the panel after the replacement text is altered", async () => { + projectFindView.replaceEditor.setText('something else'); + + expect(getAtomPanel()).toBeVisible(); + }); + }); + + describe("splitting into a second pane", () => { + beforeEach(() => { + workspaceElement.style.height = '1000px'; + atom.commands.dispatch(editorElement, 'project-find:show'); + jasmine.useRealClock() + }); + + it("splits when option is right", async () => { + const initialPane = atom.workspace.getCenter().getActivePane(); + atom.config.set('find-and-replace.projectSearchResultsPaneSplitDirection', 'right'); + projectFindView.findEditor.setText('items'); + + atom.commands.dispatch(projectFindView.element, 'core:confirm'); + await searchPromise; + + expect(atom.workspace.getCenter().getActivePane()).not.toBe(initialPane); + }); + + it("splits when option is bottom", async () => { + const initialPane = atom.workspace.getCenter().getActivePane(); + atom.config.set('find-and-replace.projectSearchResultsPaneSplitDirection', 'down'); + projectFindView.findEditor.setText('items'); + + atom.commands.dispatch(projectFindView.element, 'core:confirm'); + await searchPromise; + + expect(atom.workspace.getCenter().getActivePane()).not.toBe(initialPane); + }); + + it("does not split when option is false", async () => { + const initialPane = atom.workspace.getCenter().getActivePane(); + projectFindView.findEditor.setText('items'); + + atom.commands.dispatch(projectFindView.element, 'core:confirm'); + await searchPromise; + + expect(atom.workspace.getCenter().getActivePane()).toBe(initialPane); + }); + + it("can be duplicated on the right", async () => { + atom.config.set('find-and-replace.projectSearchResultsPaneSplitDirection', 'right'); + projectFindView.findEditor.setText('items'); + + atom.commands.dispatch(projectFindView.element, 'core:confirm'); + await searchPromise; + + const resultsPaneView1 = atom.views.getView(getExistingResultsPane()); + const pane1 = atom.workspace.getCenter().getActivePane(); + const resultsView1 = pane1.getItems()[0].refs.resultsView + pane1.splitRight({copyActiveItem: true}); + + const pane2 = atom.workspace.getCenter().getActivePane(); + const resultsView2 = pane2.getItems()[0].refs.resultsView + const resultsPaneView2 = atom.views.getView(pane2.itemForURI(ResultsPaneView.URI)); + expect(pane1).not.toBe(pane2); + expect(resultsPaneView1).not.toBe(resultsPaneView2); + simulateResizeEvent(resultsView2.element); + + await etch.update(resultsView1); + await etch.update(resultsView2); + await waitForSearchResults(); + + const resultCount = resultsPaneView1.querySelectorAll('.match-row').length; + expect(resultCount).toBeGreaterThan(0); + expect(resultsPaneView2.querySelectorAll('.match-row')).toHaveLength(resultCount); + expect(resultsPaneView2.querySelector('.preview-count').innerHTML).toEqual(resultsPaneView1.querySelector('.preview-count').innerHTML); + }); + + it("can be duplicated at the bottom", async () => { + atom.config.set('find-and-replace.projectSearchResultsPaneSplitDirection', 'down'); + projectFindView.findEditor.setText('items'); + + atom.commands.dispatch(projectFindView.element, 'core:confirm'); + await searchPromise; + + const resultsPaneView1 = atom.views.getView(getExistingResultsPane()); + const pane1 = atom.workspace.getCenter().getActivePane(); + const resultsView1 = pane1.getItems()[0].refs.resultsView + + pane1.splitDown({copyActiveItem: true}); + const pane2 = atom.workspace.getCenter().getActivePane(); + const resultsView2 = pane2.getItems()[0].refs.resultsView + const resultsPaneView2 = atom.views.getView(pane2.itemForURI(ResultsPaneView.URI)); + expect(pane1).not.toBe(pane2); + expect(resultsPaneView1).not.toBe(resultsPaneView2); + + await etch.update(resultsView1); + await etch.update(resultsView2); + + expect(resultsPaneView2.querySelector('.preview-count').innerHTML).toEqual(resultsPaneView1.querySelector('.preview-count').innerHTML); + }); + }); + + describe("serialization", () => { + it("serializes if the case, regex and whole word options", async () => { + atom.commands.dispatch(editorElement, 'project-find:show'); + expect(projectFindView.refs.caseOptionButton).not.toHaveClass('selected'); + projectFindView.refs.caseOptionButton.click(); + expect(projectFindView.refs.caseOptionButton).toHaveClass('selected'); + + expect(projectFindView.refs.regexOptionButton).not.toHaveClass('selected'); + projectFindView.refs.regexOptionButton.click(); + expect(projectFindView.refs.regexOptionButton).toHaveClass('selected'); + + expect(projectFindView.refs.wholeWordOptionButton).not.toHaveClass('selected'); + projectFindView.refs.wholeWordOptionButton.click(); + expect(projectFindView.refs.wholeWordOptionButton).toHaveClass('selected'); + + await atom.packages.deactivatePackage("find-and-replace"); + + activationPromise = atom.packages.activatePackage("find-and-replace").then(function({mainModule}) { + mainModule.createViews(); + return {projectFindView} = mainModule; + }); + + atom.commands.dispatch(editorElement, 'project-find:show'); + await activationPromise; + + expect(projectFindView.refs.caseOptionButton).toHaveClass('selected'); + expect(projectFindView.refs.regexOptionButton).toHaveClass('selected'); + expect(projectFindView.refs.wholeWordOptionButton).toHaveClass('selected'); + }) + }); + + describe("description label", () => { + beforeEach(() => { + atom.commands.dispatch(editorElement, 'project-find:show'); + }); + + it("indicates that it's searching, then shows the results", async () => { + projectFindView.findEditor.setText('item'); + atom.commands.dispatch(projectFindView.element, 'core:confirm'); + + await projectFindView.showResultPane(); + + expect(projectFindView.refs.descriptionLabel.textContent).toContain('Searching...'); + + await searchPromise; + + expect(projectFindView.refs.descriptionLabel.textContent).toContain('13 results found in 2 files'); + atom.commands.dispatch(projectFindView.element, 'core:confirm'); + expect(projectFindView.refs.descriptionLabel.textContent).toContain('13 results found in 2 files'); + }); + + it("shows an error when the pattern is invalid and clears when no error", async () => { + spyOn(atom.workspace, 'scan').andReturn(Promise.resolve()); + atom.commands.dispatch(projectFindView.element, 'project-find:toggle-regex-option'); + projectFindView.findEditor.setText('['); + atom.commands.dispatch(projectFindView.element, 'core:confirm'); + + await searchPromise; + + expect(projectFindView.refs.descriptionLabel).toHaveClass('text-error'); + expect(projectFindView.refs.descriptionLabel.textContent).toContain('Invalid regular expression'); + + projectFindView.findEditor.setText(''); + atom.commands.dispatch(projectFindView.element, 'core:confirm'); + + expect(projectFindView.refs.descriptionLabel).not.toHaveClass('text-error'); + expect(projectFindView.refs.descriptionLabel.textContent).toContain('Find in Project'); + + projectFindView.findEditor.setText('items'); + atom.commands.dispatch(projectFindView.element, 'core:confirm'); + + await searchPromise; + + expect(projectFindView.refs.descriptionLabel).not.toHaveClass('text-error'); + expect(projectFindView.refs.descriptionLabel.textContent).toContain('items'); + }); + }); + + describe("regex", () => { + beforeEach(() => { + atom.commands.dispatch(editorElement, 'project-find:show'); + projectFindView.findEditor.setText('i(\\w)ems+'); + spyOn(atom.workspace, 'scan').andCallFake(async () => {}); + }); + + it("escapes regex patterns by default", async () => { + atom.commands.dispatch(projectFindView.element, 'core:confirm'); + await searchPromise; + + expect(atom.workspace.scan.argsForCall[0][0]).toEqual(/i\(\\w\)ems\+/gim); + }); + + it("shows an error when the regex pattern is invalid", async () => { + atom.commands.dispatch(projectFindView.element, 'project-find:toggle-regex-option'); + projectFindView.findEditor.setText('['); + + atom.commands.dispatch(projectFindView.element, 'core:confirm'); + await searchPromise; + + expect(projectFindView.refs.descriptionLabel).toHaveClass('text-error'); + }); + + describe("when search has not been run yet", () => { + it("toggles regex option via an event but does not run the search", () => { + expect(projectFindView.refs.regexOptionButton).not.toHaveClass('selected'); + atom.commands.dispatch(projectFindView.element, 'project-find:toggle-regex-option'); + expect(projectFindView.refs.regexOptionButton).toHaveClass('selected'); + expect(atom.workspace.scan).not.toHaveBeenCalled(); + }) + }); + + describe("when search has been run", () => { + beforeEach(async () => { + atom.commands.dispatch(projectFindView.element, 'core:confirm'); + await searchPromise; + }); + + it("toggles regex option via an event and finds files matching the pattern", async () => { + expect(projectFindView.refs.regexOptionButton).not.toHaveClass('selected'); + atom.commands.dispatch(projectFindView.element, 'project-find:toggle-regex-option'); + + await searchPromise; + + expect(projectFindView.refs.regexOptionButton).toHaveClass('selected'); + expect(atom.workspace.scan.mostRecentCall.args[0]).toEqual(/i(\w)ems+/gim); + }); + + it("toggles regex option via a button and finds files matching the pattern", async () => { + expect(projectFindView.refs.regexOptionButton).not.toHaveClass('selected'); + projectFindView.refs.regexOptionButton.click(); + + await searchPromise; + + expect(projectFindView.refs.regexOptionButton).toHaveClass('selected'); + expect(atom.workspace.scan.mostRecentCall.args[0]).toEqual(/i(\w)ems+/gim); + }); + }); + }); + + describe("case sensitivity", () => { + beforeEach(async () => { + atom.commands.dispatch(editorElement, 'project-find:show'); + spyOn(atom.workspace, 'scan').andCallFake(() => Promise.resolve()); + projectFindView.findEditor.setText('ITEMS'); + + atom.commands.dispatch(projectFindView.element, 'core:confirm'); + await searchPromise; + }); + + it("runs a case insensitive search by default", () => expect(atom.workspace.scan.argsForCall[0][0]).toEqual(/ITEMS/gim)); + + it("toggles case sensitive option via an event and finds files matching the pattern", async () => { + expect(projectFindView.refs.caseOptionButton).not.toHaveClass('selected'); + + atom.commands.dispatch(projectFindView.element, 'project-find:toggle-case-option'); + await searchPromise; + + expect(projectFindView.refs.caseOptionButton).toHaveClass('selected'); + expect(atom.workspace.scan.mostRecentCall.args[0]).toEqual(/ITEMS/gm); + }); + + it("toggles case sensitive option via a button and finds files matching the pattern", async () => { + expect(projectFindView.refs.caseOptionButton).not.toHaveClass('selected'); + + projectFindView.refs.caseOptionButton.click(); + await searchPromise; + + expect(projectFindView.refs.caseOptionButton).toHaveClass('selected'); + expect(atom.workspace.scan.mostRecentCall.args[0]).toEqual(/ITEMS/gm); + }); + }); + + describe("whole word", () => { + beforeEach(async () => { + atom.commands.dispatch(editorElement, 'project-find:show'); + spyOn(atom.workspace, 'scan').andCallFake(async () => {}); + projectFindView.findEditor.setText('wholeword'); + + atom.commands.dispatch(projectFindView.element, 'core:confirm'); + await searchPromise; + }); + + it("does not run whole word search by default", () => { + expect(atom.workspace.scan.argsForCall[0][0]).toEqual(/wholeword/gim) + }); + + it("toggles whole word option via an event and finds files matching the pattern", async () => { + expect(projectFindView.refs.wholeWordOptionButton).not.toHaveClass('selected'); + atom.commands.dispatch(projectFindView.element, 'project-find:toggle-whole-word-option'); + + await searchPromise; + expect(projectFindView.refs.wholeWordOptionButton).toHaveClass('selected'); + expect(atom.workspace.scan.mostRecentCall.args[0]).toEqual(/\bwholeword\b/gim); + }); + + it("toggles whole word option via a button and finds files matching the pattern", async () => { + expect(projectFindView.refs.wholeWordOptionButton).not.toHaveClass('selected'); + + projectFindView.refs.wholeWordOptionButton.click(); + await searchPromise; + + expect(projectFindView.refs.wholeWordOptionButton).toHaveClass('selected'); + expect(atom.workspace.scan.mostRecentCall.args[0]).toEqual(/\bwholeword\b/gim); + }); + }); + + describe("when project-find:confirm is triggered", () => { + beforeEach(() => { + jasmine.useRealClock() + }); + + it("displays the results and no errors", async () => { + projectFindView.findEditor.setText('items'); + atom.commands.dispatch(projectFindView.element, 'project-find:confirm'); + + await searchPromise; + await waitForSearchResults(); + + const resultsView = getResultsView(); + expect(resultsView.element).toBeVisible(); + expect(resultsView.refs.listView.element.querySelectorAll(".match-row")).toHaveLength(11); + expect(resultsView.refs.listView.element.querySelectorAll(".match.highlight-info")).toHaveLength(13); + }) + }); + + describe("when core:confirm is triggered", () => { + beforeEach(() => { + atom.commands.dispatch(workspaceElement, 'project-find:show') + jasmine.useRealClock() + }); + + describe("when the there search field is empty", () => { + it("does not run the search but clears the model", () => { + spyOn(atom.workspace, 'scan'); + spyOn(projectFindView.model, 'clear'); + atom.commands.dispatch(projectFindView.element, 'core:confirm'); + expect(atom.workspace.scan).not.toHaveBeenCalled(); + expect(projectFindView.model.clear).toHaveBeenCalled(); + }) + }); + + it("reruns the search when confirmed again after focusing the window", async () => { + projectFindView.findEditor.setText('thisdoesnotmatch'); + atom.commands.dispatch(projectFindView.element, 'core:confirm'); + + await searchPromise; + + spyOn(atom.workspace, 'scan'); + atom.commands.dispatch(projectFindView.element, 'core:confirm'); + + await searchPromise; + + expect(atom.workspace.scan).not.toHaveBeenCalled(); + atom.workspace.scan.reset(); + window.dispatchEvent(new FocusEvent("focus")); + atom.commands.dispatch(projectFindView.element, 'core:confirm'); + + await searchPromise; + + expect(atom.workspace.scan).toHaveBeenCalled(); + atom.workspace.scan.reset(); + atom.commands.dispatch(projectFindView.element, 'core:confirm'); + + await searchPromise; + + expect(atom.workspace.scan).not.toHaveBeenCalled(); + }); + + describe("when results exist", () => { + beforeEach(() => { + projectFindView.findEditor.setText('items') + }); + + it("displays the results and no errors", async () => { + atom.commands.dispatch(projectFindView.element, 'core:confirm'); + await searchPromise; + + const resultsView = getResultsView(); + const resultsPaneView = getExistingResultsPane(); + + expect(resultsView.element).toBeVisible(); + expect(resultsView.refs.listView.element.querySelectorAll(".match-row")).toHaveLength(11); + expect(resultsView.refs.listView.element.querySelectorAll(".match.highlight-info")).toHaveLength(13); + + expect(resultsPaneView.refs.previewCount.textContent).toBe("13 results found in 2 files for items"); + expect(projectFindView.errorMessages).not.toBeVisible(); + }); + + it("only searches paths matching text in the path filter", async () => { + spyOn(atom.workspace, 'scan').andCallFake(async () => {}); + projectFindView.pathsEditor.setText('*.js'); + + atom.commands.dispatch(projectFindView.element, 'core:confirm'); + await searchPromise; + + expect(atom.workspace.scan.argsForCall[0][1].paths).toEqual(['*.js']); + }); + + it("updates the results list when a buffer changes", async () => { + const editor = await atom.workspace.open('sample.js') + + atom.commands.dispatch(projectFindView.element, 'core:confirm'); + await searchPromise; + + const resultsView = getResultsView(); + const listView = resultsView.refs.listView; + const resultsPaneView = getExistingResultsPane(); + + expect(listView.element.querySelectorAll(".match-row")).toHaveLength(11); + expect(listView.element.querySelectorAll(".match.highlight-info")).toHaveLength(13); + expect(resultsPaneView.refs.previewCount.textContent).toBe("13 results found in 2 files for items"); + + resultsView.selectFirstResult(); + for (let i = 0; i < 6; i++) resultsView.moveDown(); + await resultsView.moveDown(); + + expect(listView.element.querySelectorAll(".path-row")[1].parentElement).toHaveClass('selected'); + + editor.setText('there is one "items" in this file'); + await etch.getScheduler().getNextUpdatePromise() + await searchPromise; + + await conditionPromise( + () => resultsPaneView.refs.previewCount.textContent === "8 results found in 2 files for items" + ) + + expect(listView.element.querySelectorAll(".path-row")[1].parentElement).toHaveClass('selected'); + + // Ensure the newly added item can be opened. + await resultsView.moveDown() + atom.commands.dispatch(resultsView.element, 'core:confirm'); + await waitForSearchResults(); + await conditionPromise( + () => editor.getSelectedText() === "items" + ) + + editor.setText('no matches in this file'); + await waitForSearchResults(); + + await conditionPromise( + () => resultsPaneView.refs.previewCount.textContent === "7 results found in 1 file for items" + ) + }); + + it("doesn't update the results list when a buffer outside the project changes", async () => { + const editor = await atom.workspace.open('../sample.js') + + atom.commands.dispatch(projectFindView.element, 'core:confirm'); + await searchPromise; + + const resultsView = getResultsView(); + const resultsPaneView = getExistingResultsPane(); + + expect(resultsView.refs.listView.element.querySelectorAll(".list-item")).toHaveLength(13); + expect(resultsPaneView.refs.previewCount.textContent).toBe("13 results found in 2 files for items"); + + resultsView.selectFirstResult(); + for (let i = 0; i < 7; i++) await resultsView.moveDown() + expect(resultsView.refs.listView.element.querySelectorAll(".list-nested-item")[1]).toHaveClass('selected'); + + editor.setText('there is one "items" in this file'); + advanceClock(editor.getBuffer().stoppedChangingDelay); + await etch.getScheduler().getNextUpdatePromise() + expect(resultsPaneView.refs.previewCount.textContent).toBe("13 results found in 2 files for items"); + expect(resultsView.refs.listView.element.querySelectorAll(".list-nested-item")[1]).toHaveClass('selected'); + }); + }); + + describe("when no results exist", () => { + beforeEach(() => { + projectFindView.findEditor.setText('notintheprojectbro'); + spyOn(atom.workspace, 'scan').andCallFake(async () => {}); + }); + + it("displays no errors and no results", async () => { + atom.commands.dispatch(projectFindView.element, 'core:confirm'); + await searchPromise; + + const resultsView = getResultsView(); + expect(projectFindView.refs.errorMessages).not.toBeVisible(); + expect(resultsView.element).toBeVisible(); + expect(resultsView.refs.listView.element.querySelectorAll(".match-row")).toHaveLength(0); + }); + }); + }); + + describe("history", () => { + beforeEach(() => { + atom.commands.dispatch(workspaceElement, 'project-find:show'); + spyOn(atom.workspace, 'scan').andCallFake(() => { + let promise = Promise.resolve(); + promise.cancel = () => {}; + return promise; + }); + + projectFindView.findEditor.setText('sort'); + projectFindView.replaceEditor.setText('bort'); + projectFindView.pathsEditor.setText('abc'); + atom.commands.dispatch(projectFindView.findEditor.getElement(), 'core:confirm'); + + projectFindView.findEditor.setText('items'); + projectFindView.replaceEditor.setText('eyetims'); + projectFindView.pathsEditor.setText('def'); + atom.commands.dispatch(projectFindView.findEditor.getElement(), 'core:confirm'); + }); + + it("can navigate the entire history stack", () => { + expect(projectFindView.findEditor.getText()).toEqual('items'); + + atom.commands.dispatch(projectFindView.findEditor.getElement(), 'core:move-up'); + expect(projectFindView.findEditor.getText()).toEqual('sort'); + + atom.commands.dispatch(projectFindView.findEditor.getElement(), 'core:move-down'); + expect(projectFindView.findEditor.getText()).toEqual('items'); + + atom.commands.dispatch(projectFindView.findEditor.getElement(), 'core:move-down'); + expect(projectFindView.findEditor.getText()).toEqual(''); + + expect(projectFindView.pathsEditor.getText()).toEqual('def'); + + atom.commands.dispatch(projectFindView.pathsEditor.element, 'core:move-up'); + expect(projectFindView.pathsEditor.getText()).toEqual('abc'); + + atom.commands.dispatch(projectFindView.pathsEditor.element, 'core:move-down'); + expect(projectFindView.pathsEditor.getText()).toEqual('def'); + + atom.commands.dispatch(projectFindView.pathsEditor.element, 'core:move-down'); + expect(projectFindView.pathsEditor.getText()).toEqual(''); + + expect(projectFindView.replaceEditor.getText()).toEqual('eyetims'); + + atom.commands.dispatch(projectFindView.replaceEditor.element, 'core:move-up'); + expect(projectFindView.replaceEditor.getText()).toEqual('bort'); + + atom.commands.dispatch(projectFindView.replaceEditor.element, 'core:move-down'); + expect(projectFindView.replaceEditor.getText()).toEqual('eyetims'); + + atom.commands.dispatch(projectFindView.replaceEditor.element, 'core:move-down'); + expect(projectFindView.replaceEditor.getText()).toEqual(''); + }); + }); + + describe("when find-and-replace:use-selection-as-find-pattern is triggered", () => { + it("places the selected text into the find editor", () => { + editor.setSelectedBufferRange([[1, 6], [1, 10]]); + atom.commands.dispatch(workspaceElement, 'find-and-replace:use-selection-as-find-pattern'); + expect(projectFindView.findEditor.getText()).toBe('sort'); + + editor.setSelectedBufferRange([[1, 13], [1, 21]]); + atom.commands.dispatch(workspaceElement, 'find-and-replace:use-selection-as-find-pattern'); + expect(projectFindView.findEditor.getText()).toBe('function'); + }); + + it("places the word under the cursor into the find editor", () => { + editor.setSelectedBufferRange([[1, 8], [1, 8]]); + atom.commands.dispatch(workspaceElement, 'find-and-replace:use-selection-as-find-pattern'); + expect(projectFindView.findEditor.getText()).toBe('sort'); + + editor.setSelectedBufferRange([[1, 15], [1, 15]]); + atom.commands.dispatch(workspaceElement, 'find-and-replace:use-selection-as-find-pattern'); + expect(projectFindView.findEditor.getText()).toBe('function'); + }); + + it("places the previously selected text into the find editor if no selection and no word under cursor", () => { + editor.setSelectedBufferRange([[1, 13], [1, 21]]); + atom.commands.dispatch(workspaceElement, 'find-and-replace:use-selection-as-find-pattern'); + expect(projectFindView.findEditor.getText()).toBe('function'); + + editor.setSelectedBufferRange([[1, 1], [1, 1]]); + atom.commands.dispatch(workspaceElement, 'find-and-replace:use-selection-as-find-pattern'); + expect(projectFindView.findEditor.getText()).toBe('function'); + }); + + it("places selected text into the find editor and escapes it when Regex is enabled", () => { + atom.commands.dispatch(projectFindView.element, 'project-find:toggle-regex-option'); + editor.setSelectedBufferRange([[6, 6], [6, 65]]); + atom.commands.dispatch(workspaceElement, 'find-and-replace:use-selection-as-find-pattern'); + expect(projectFindView.findEditor.getText()).toBe('current < pivot \\? left\\.push\\(current\\) : right\\.push\\(current\\);'); + }); + }); + + describe("when find-and-replace:use-selection-as-replace-pattern is triggered", () => { + it("places the selected text into the replace editor", () => { + editor.setSelectedBufferRange([[1, 6], [1, 10]]); + atom.commands.dispatch(workspaceElement, 'find-and-replace:use-selection-as-replace-pattern'); + expect(projectFindView.replaceEditor.getText()).toBe('sort'); + + editor.setSelectedBufferRange([[1, 13], [1, 21]]); + atom.commands.dispatch(workspaceElement, 'find-and-replace:use-selection-as-replace-pattern'); + expect(projectFindView.replaceEditor.getText()).toBe('function'); + }); + + it("places the word under the cursor into the replace editor", () => { + editor.setSelectedBufferRange([[1, 8], [1, 8]]); + atom.commands.dispatch(workspaceElement, 'find-and-replace:use-selection-as-replace-pattern'); + expect(projectFindView.replaceEditor.getText()).toBe('sort'); + + editor.setSelectedBufferRange([[1, 15], [1, 15]]); + atom.commands.dispatch(workspaceElement, 'find-and-replace:use-selection-as-replace-pattern'); + expect(projectFindView.replaceEditor.getText()).toBe('function'); + }); + + it("places the previously selected text into the replace editor if no selection and no word under cursor", () => { + editor.setSelectedBufferRange([[1, 13], [1, 21]]); + atom.commands.dispatch(workspaceElement, 'find-and-replace:use-selection-as-replace-pattern'); + expect(projectFindView.replaceEditor.getText()).toBe('function'); + + editor.setSelectedBufferRange([[1, 1], [1, 1]]); + atom.commands.dispatch(workspaceElement, 'find-and-replace:use-selection-as-replace-pattern'); + expect(projectFindView.replaceEditor.getText()).toBe('function'); + }); + + it("places selected text into the replace editor and escapes it when Regex is enabled", () => { + atom.commands.dispatch(projectFindView.element, 'project-find:toggle-regex-option') + editor.setSelectedBufferRange([[6, 6], [6, 65]]); + atom.commands.dispatch(workspaceElement, 'find-and-replace:use-selection-as-replace-pattern'); + expect(projectFindView.replaceEditor.getText()).toBe('current < pivot \\? left\\.push\\(current\\) : right\\.push\\(current\\);'); + }); + }); + + describe("when there is an error searching", () => { + it("displays the errors in the results pane", async () => { + projectFindView.findEditor.setText('items'); + + let errorList; + spyOn(atom.workspace, 'scan').andCallFake(async (regex, options, callback) => { + const resultsPaneView = getExistingResultsPane(); + ({errorList} = resultsPaneView.refs); + expect(errorList.querySelectorAll("li")).toHaveLength(0); + + callback(null, {path: '/some/path.js', code: 'ENOENT', message: 'Nope'}); + await etch.update(resultsPaneView); + expect(errorList).toBeVisible(); + expect(errorList.querySelectorAll("li")).toHaveLength(1); + + callback(null, {path: '/some/path.js', code: 'ENOENT', message: 'Broken'}); + await etch.update(resultsPaneView); + expect(errorList.querySelectorAll("li")).toHaveLength(2); + }); + + atom.commands.dispatch(projectFindView.element, 'core:confirm'); + + await searchPromise; + + expect(errorList).toBeVisible(); + expect(errorList.querySelectorAll("li")).toHaveLength(2); + expect(errorList.querySelectorAll("li")[0].textContent).toBe('Nope'); + expect(errorList.querySelectorAll("li")[1].textContent).toBe('Broken'); + }) + }); + + describe("buffer search sharing of the find options", () => { + function getResultDecorations(clazz) { + const result = []; + const decorations = editor.decorationsStateForScreenRowRange(0, editor.getLineCount()); + for (let id in decorations) { + const decoration = decorations[id]; + if (decoration.properties.class === clazz) { + result.push(decoration); + } + } + return result; + } + + it("setting the find text does not interfere with the project replace state", async () => { + // Not sure why I need to advance the clock before setting the text. If + // this advanceClock doesnt happen, the text will be ''. wtf. + advanceClock(projectFindView.findEditor.getBuffer().stoppedChangingDelay + 1); + spyOn(atom.workspace, 'scan'); + + projectFindView.findEditor.setText('findme'); + advanceClock(projectFindView.findEditor.getBuffer().stoppedChangingDelay + 1); + + await projectFindView.search({onlyRunIfActive: false, onlyRunIfChanged: true}); + expect(atom.workspace.scan).toHaveBeenCalled(); + }); + + it("shares the buffers and history cyclers between both buffer and project views", () => { + projectFindView.findEditor.setText('findme'); + projectFindView.replaceEditor.setText('replaceme'); + + atom.commands.dispatch(editorElement, 'find-and-replace:show'); + expect(findView.findEditor.getText()).toBe('findme'); + expect(findView.replaceEditor.getText()).toBe('replaceme'); + + // add some things to the history + atom.commands.dispatch(findView.findEditor.element, 'core:confirm'); + findView.findEditor.setText('findme1'); + atom.commands.dispatch(findView.findEditor.element, 'core:confirm'); + findView.findEditor.setText(''); + + atom.commands.dispatch(findView.replaceEditor.element, 'core:confirm'); + findView.replaceEditor.setText('replaceme1'); + atom.commands.dispatch(findView.replaceEditor.element, 'core:confirm'); + findView.replaceEditor.setText(''); + + // Back to the project view to make sure we're using the same cycler + atom.commands.dispatch(editorElement, 'project-find:show'); + + expect(projectFindView.findEditor.getText()).toBe(''); + atom.commands.dispatch(projectFindView.findEditor.element, 'core:move-up'); + expect(projectFindView.findEditor.getText()).toBe('findme1'); + atom.commands.dispatch(projectFindView.findEditor.element, 'core:move-up'); + expect(projectFindView.findEditor.getText()).toBe('findme'); + + expect(projectFindView.replaceEditor.getText()).toBe(''); + atom.commands.dispatch(projectFindView.replaceEditor.element, 'core:move-up'); + expect(projectFindView.replaceEditor.getText()).toBe('replaceme1'); + atom.commands.dispatch(projectFindView.replaceEditor.element, 'core:move-up'); + expect(projectFindView.replaceEditor.getText()).toBe('replaceme'); + }); + + it('highlights the search results in the selected file', async () => { + jasmine.useRealClock(); + // Process here is to + // * open samplejs + // * run a search that has sample js results + // * that should place the pattern in the buffer find + // * focus project/sample.js by clicking on a project/sample.js result + // * when the file has been activated, it's results for the project search should be highlighted + + editor = await atom.workspace.open('sample.js'); + expect(getResultDecorations('find-result')).toHaveLength(0); + + projectFindView.findEditor.setText('item'); + atom.commands.dispatch(projectFindView.element, 'core:confirm'); + await searchPromise; + await waitForSearchResults(); + + const resultsView = getResultsView(); + resultsView.scrollToBottom(); // To load ALL the results + await etch.update(resultsView); + expect(resultsView.element).toBeVisible(); + expect(resultsView.refs.listView.element.querySelectorAll(".match-row")).toHaveLength(11); + expect(resultsView.refs.listView.element.querySelectorAll(".match.highlight-info")).toHaveLength(13); + + resultsView.selectFirstResult(); + for (let i = 0; i < 9; i++) resultsView.moveDown(); + await resultsView.moveDown(); + + atom.commands.dispatch(resultsView.element, 'core:confirm'); + await new Promise(resolve => editor.onDidChangeSelectionRange(resolve)) + + // project/sample.js has 6 results + expect(getResultDecorations('find-result')).toHaveLength(5); + expect(getResultDecorations('current-result')).toHaveLength(1); + expect(workspaceElement).toHaveClass('find-visible'); + + const initialSelectedRange = editor.getSelectedBufferRange(); + + // now we can find next + atom.commands.dispatch(atom.views.getView(editor), 'find-and-replace:find-next'); + expect(editor.getSelectedBufferRange()).not.toEqual(initialSelectedRange); + + // Now we toggle the whole-word option to make sure it is updated in the buffer find + atom.commands.dispatch(projectFindView.element, 'project-find:toggle-whole-word-option'); + await searchPromise; + + // project/sample.js has 0 results for whole word `item` + expect(getResultDecorations('find-result')).toHaveLength(0); + expect(workspaceElement).toHaveClass('find-visible'); + + // Now we toggle the whole-word option to make sure it is updated in the buffer find + atom.commands.dispatch(projectFindView.element, 'project-find:toggle-whole-word-option'); + }); + }); + + describe("when user asked not to override last search results", () => { + beforeEach(async () => { + atom.commands.dispatch(editorElement, 'project-find:show'); + projectFindView.findEditor.setText('items'); + atom.commands.dispatch(projectFindView.element, 'core:confirm'); + await searchPromise; + + }); + it("opens new search results in new panel", async () => { + const result_pane = getExistingResultsPane(); + result_pane.dontOverrideTab(); + projectFindView.findEditor.setText('items2'); + atom.commands.dispatch(projectFindView.element, 'core:confirm'); + await searchPromise; + expect(result_pane).not.toBe(getExistingResultsPane()); + }); + }); + }); + + describe("replacing", () => { + let testDir, sampleJs, sampleCoffee, replacePromise; + + beforeEach(async () => { + testDir = temp.mkdirSync('atom-find-and-replace'); + sampleJs = path.join(testDir, 'project/sample.js'); + sampleCoffee = path.join(testDir, 'sample.coffee'); + + fs.makeTreeSync(testDir); + fs.writeFileSync(sampleCoffee, fs.readFileSync(require.resolve('./fixtures/sample.coffee'))); + fs.writeFileSync(sampleJs, fs.readFileSync(require.resolve('./fixtures/project/sample.js'))); + + atom.commands.dispatch(workspaceElement, 'project-find:show'); + await activationPromise; + + atom.project.setPaths([testDir]); + const spy = spyOn(projectFindView, 'replaceAll').andCallFake(() => { + replacePromise = spy.originalValue.call(projectFindView); + }); + }); + + describe("when the replace string contains an escaped char", () => { + let filePath = null; + + beforeEach(() => { + let projectPath = temp.mkdirSync("atom"); + filePath = path.join(projectPath, "tabs.txt"); + fs.writeFileSync(filePath, "a\nb\na"); + atom.project.setPaths([projectPath]); + atom.commands.dispatch(workspaceElement, 'project-find:show'); + + spyOn(atom, 'confirm').andReturn({response:0}); + }); + + describe("when the regex option is chosen", () => { + beforeEach(async () => { + atom.commands.dispatch(projectFindView.element, 'project-find:toggle-regex-option'); + projectFindView.findEditor.setText('a'); + atom.commands.dispatch(projectFindView.element, 'project-find:confirm'); + await searchPromise; + }); + + it("finds the escape char", async () => { + projectFindView.replaceEditor.setText('\\t'); + + atom.commands.dispatch(projectFindView.element, 'project-find:replace-all'); + await replacePromise; + + expect(fs.readFileSync(filePath, 'utf8')).toBe("\t\nb\n\t"); + }); + + it("doesn't insert a escaped char if there are multiple backslashs in front of the char", async () => { + projectFindView.replaceEditor.setText('\\\\t'); + + atom.commands.dispatch(projectFindView.element, 'project-find:replace-all'); + await replacePromise; + + expect(fs.readFileSync(filePath, 'utf8')).toBe("\\t\nb\n\\t"); + }); + }); + + describe("when regex option is not set", () => { + beforeEach(async () => { + projectFindView.findEditor.setText('a'); + atom.commands.dispatch(projectFindView.element, 'project-find:confirm'); + await searchPromise; + }); + + it("finds the escape char", async () => { + projectFindView.replaceEditor.setText('\\t'); + + atom.commands.dispatch(projectFindView.element, 'project-find:replace-all'); + await replacePromise; + + expect(fs.readFileSync(filePath, 'utf8')).toBe("\\t\nb\n\\t"); + }); + }); + }); + + describe("replace all button enablement", () => { + let disposable = null; + + it("is disabled initially", () => { + expect(projectFindView.refs.replaceAllButton).toHaveClass('disabled') + }); + + it("is disabled when a search returns no results", async () => { + projectFindView.findEditor.setText('items'); + atom.commands.dispatch(projectFindView.element, 'project-find:confirm'); + await searchPromise; + + expect(projectFindView.refs.replaceAllButton).not.toHaveClass('disabled'); + + projectFindView.findEditor.setText('nopenotinthefile'); + atom.commands.dispatch(projectFindView.element, 'project-find:confirm'); + await searchPromise; + + expect(projectFindView.refs.replaceAllButton).toHaveClass('disabled'); + }); + + it("is enabled when a search has results and disabled when there are no results", async () => { + projectFindView.findEditor.setText('items'); + atom.commands.dispatch(projectFindView.element, 'project-find:confirm'); + + await searchPromise; + + disposable = projectFindView.replaceTooltipSubscriptions; + spyOn(disposable, 'dispose'); + + expect(projectFindView.refs.replaceAllButton).not.toHaveClass('disabled'); + + // The replace all button should still be disabled as the text has been changed and a new search has not been run + projectFindView.findEditor.setText('itemss'); + advanceClock(stoppedChangingDelay); + expect(projectFindView.refs.replaceAllButton).toHaveClass('disabled'); + expect(disposable.dispose).toHaveBeenCalled(); + + // The button should still be disabled because the search and search pattern are out of sync + projectFindView.replaceEditor.setText('omgomg'); + advanceClock(stoppedChangingDelay); + expect(projectFindView.refs.replaceAllButton).toHaveClass('disabled'); + + disposable = projectFindView.replaceTooltipSubscriptions; + spyOn(disposable, 'dispose'); + projectFindView.findEditor.setText('items'); + advanceClock(stoppedChangingDelay); + expect(projectFindView.refs.replaceAllButton).not.toHaveClass('disabled'); + + projectFindView.findEditor.setText(''); + atom.commands.dispatch(projectFindView.element, 'project-find:confirm'); + + expect(projectFindView.refs.replaceAllButton).toHaveClass('disabled'); + }); + }); + + describe("when the replace button is pressed", () => { + beforeEach(() => { + spyOn(atom, 'confirm').andReturn({ response: 0 }); + }); + + it("runs the search, and replaces all the matches", async () => { + projectFindView.findEditor.setText('items'); + atom.commands.dispatch(projectFindView.element, 'core:confirm'); + await searchPromise; + + projectFindView.replaceEditor.setText('sunshine'); + projectFindView.refs.replaceAllButton.click(); + await replacePromise; + + expect(projectFindView.errorMessages).not.toBeVisible(); + expect(projectFindView.refs.descriptionLabel.textContent).toContain('Replaced'); + + const sampleJsContent = fs.readFileSync(sampleJs, 'utf8'); + expect(sampleJsContent.match(/items/g)).toBeFalsy(); + expect(sampleJsContent.match(/sunshine/g)).toHaveLength(6); + + const sampleCoffeeContent = fs.readFileSync(sampleCoffee, 'utf8'); + expect(sampleCoffeeContent.match(/items/g)).toBeFalsy(); + expect(sampleCoffeeContent.match(/sunshine/g)).toHaveLength(7); + }); + + describe("when there are search results after a replace", () => { + it("runs the search after the replace", async () => { + projectFindView.findEditor.setText('items'); + atom.commands.dispatch(projectFindView.element, 'core:confirm'); + await searchPromise; + + projectFindView.replaceEditor.setText('items-123'); + projectFindView.refs.replaceAllButton.click(); + await replacePromise; + + await etch.update(getExistingResultsPane()); + + expect(projectFindView.errorMessages).not.toBeVisible(); + expect(getExistingResultsPane().refs.previewCount.textContent).toContain('13 results found in 2 files for items'); + expect(projectFindView.refs.descriptionLabel.textContent).toContain('Replaced items with items-123 13 times in 2 files'); + + projectFindView.replaceEditor.setText('cats'); + advanceClock(projectFindView.replaceEditor.getBuffer().stoppedChangingDelay); + expect(projectFindView.refs.descriptionLabel.textContent).not.toContain('Replaced items'); + expect(projectFindView.refs.descriptionLabel.textContent).toContain("13 results found in 2 files for items"); + }) + }); + }); + + describe("when the project-find:replace-all is triggered", () => { + describe("when no search has been run", () => { + beforeEach(() => { + spyOn(atom, 'confirm').andReturn(0) + }); + + it("does nothing", () => { + projectFindView.findEditor.setText('items'); + projectFindView.replaceEditor.setText('sunshine'); + + spyOn(atom, 'beep'); + atom.commands.dispatch(projectFindView.element, 'project-find:replace-all'); + + expect(replacePromise).toBeUndefined(); + + expect(atom.beep).toHaveBeenCalled(); + expect(projectFindView.refs.descriptionLabel.textContent).toContain("Find in Project"); + }); + }); + + describe("when a search with no results has been run", () => { + beforeEach(async () => { + spyOn(atom, 'confirm').andReturn({ response: 0 }); + projectFindView.findEditor.setText('nopenotinthefile'); + atom.commands.dispatch(projectFindView.element, 'core:confirm'); + + await searchPromise; + }); + + it("doesnt replace anything", () => { + projectFindView.replaceEditor.setText('sunshine'); + + spyOn(atom.workspace, 'scan').andCallThrough(); + spyOn(atom, 'beep'); + atom.commands.dispatch(projectFindView.element, 'project-find:replace-all'); + + // The replacement isnt even run + expect(replacePromise).toBeUndefined(); + + expect(atom.workspace.scan).not.toHaveBeenCalled(); + expect(atom.beep).toHaveBeenCalled(); + expect(projectFindView.refs.descriptionLabel.textContent.replace(/( )/g, ' ')).toContain("No results"); + }); + }); + + describe("when a search with results has been run", () => { + beforeEach(async () => { + projectFindView.findEditor.setText('items'); + atom.commands.dispatch(projectFindView.element, 'core:confirm'); + + await searchPromise; + }); + + it("messages the user when the search text has changed since that last search", () => { + spyOn(atom, 'confirm').andReturn({ response: 0 }); + spyOn(atom.workspace, 'scan').andCallThrough(); + + projectFindView.findEditor.setText('sort'); + projectFindView.replaceEditor.setText('ok'); + + advanceClock(stoppedChangingDelay); + atom.commands.dispatch(projectFindView.element, 'project-find:replace-all'); + + expect(replacePromise).toBeUndefined(); + expect(atom.workspace.scan).not.toHaveBeenCalled(); + expect(atom.confirm).toHaveBeenCalled(); + expect(atom.confirm.mostRecentCall.args[0].message).toContain('was changed to'); + }); + + it("replaces all the matches and updates the results view", async () => { + spyOn(atom, 'confirm').andReturn({ response: 0 }); + projectFindView.replaceEditor.setText('sunshine'); + + expect(projectFindView.errorMessages).not.toBeVisible(); + atom.commands.dispatch(projectFindView.element, 'project-find:replace-all'); + await replacePromise; + + const resultsView = getResultsView(); + expect(resultsView.element).toBeVisible(); + expect(resultsView.refs.listView.element.querySelectorAll(".match-row")).toHaveLength(0); + + expect(projectFindView.refs.descriptionLabel.textContent).toContain("Replaced items with sunshine 13 times in 2 files"); + + let sampleJsContent = fs.readFileSync(sampleJs, 'utf8'); + expect(sampleJsContent.match(/items/g)).toBeFalsy(); + expect(sampleJsContent.match(/sunshine/g)).toHaveLength(6); + + let sampleCoffeeContent = fs.readFileSync(sampleCoffee, 'utf8'); + expect(sampleCoffeeContent.match(/items/g)).toBeFalsy(); + expect(sampleCoffeeContent.match(/sunshine/g)).toHaveLength(7); + }); + + describe("when the confirm box is cancelled", () => { + beforeEach(() => { + spyOn(atom, 'confirm').andReturn(1) + }); + + it("does not replace", async () => { + projectFindView.replaceEditor.setText('sunshine'); + + atom.commands.dispatch(projectFindView.element, 'project-find:replace-all'); + await replacePromise; + + expect(projectFindView.refs.descriptionLabel.textContent).toContain("13 results found"); + }); + }); + }); + + describe("when the find field contains a ^ or a $ and the regex option is enabled", () => { + it("correctly replaces all matches", async () => { + // TODO: Remove version check when Atom 1.21 reaches stable + if (parseFloat(atom.getVersion()) < 1.21) { + return; + } + + atom.commands.dispatch(projectFindView.element, 'project-find:toggle-regex-option'); + projectFindView.findEditor.setText(';$'); + atom.commands.dispatch(projectFindView.element, 'core:confirm'); + await searchPromise; + + spyOn(atom, 'confirm').andReturn({ response: 0 }); + projectFindView.replaceEditor.setText('sunshine'); + + expect(projectFindView.errorMessages).not.toBeVisible(); + atom.commands.dispatch(projectFindView.element, 'project-find:replace-all'); + await replacePromise; + + expect(projectFindView.refs.descriptionLabel.textContent).toContain("Replaced ;$ with sunshine 9 times in 2 files"); + + let sampleJsContent = fs.readFileSync(sampleJs, 'utf8'); + expect(sampleJsContent.match(/;$/gm)).toBeFalsy(); + expect(sampleJsContent.match(/sunshine/g)).toHaveLength(8); + }); + }); + }); + + describe("when there is an error replacing", () => { + beforeEach(async () => { + spyOn(atom, 'confirm').andReturn({ response: 0 }); + projectFindView.findEditor.setText('items'); + atom.commands.dispatch(projectFindView.element, 'project-find:confirm'); + await searchPromise; + }); + + it("displays the errors in the results pane", async () => { + let errorList + spyOn(atom.workspace, 'replace').andCallFake(async (regex, replacement, paths, callback) => { + ({ errorList } = getExistingResultsPane().refs); + expect(errorList.querySelectorAll("li")).toHaveLength(0); + + callback(null, {path: '/some/path.js', code: 'ENOENT', message: 'Nope'}); + await etch.update(getExistingResultsPane()); + expect(errorList).toBeVisible(); + expect(errorList.querySelectorAll("li")).toHaveLength(1); + + callback(null, {path: '/some/path.js', code: 'ENOENT', message: 'Broken'}); + await etch.update(getExistingResultsPane()); + expect(errorList.querySelectorAll("li")).toHaveLength(2); + }); + + projectFindView.replaceEditor.setText('sunshine'); + atom.commands.dispatch(projectFindView.element, 'project-find:replace-all'); + await replacePromise; + + expect(errorList).toBeVisible(); + expect(errorList.querySelectorAll("li")).toHaveLength(2); + expect(errorList.querySelectorAll("li")[0].textContent).toBe('Nope'); + expect(errorList.querySelectorAll("li")[1].textContent).toBe('Broken'); + }); + }); + }); + + describe("panel focus", () => { + beforeEach(async () => { + atom.commands.dispatch(workspaceElement, 'project-find:show'); + await activationPromise; + }); + + it("focuses the find editor when the panel gets focus", () => { + projectFindView.replaceEditor.element.focus(); + expect(projectFindView.replaceEditor.element).toHaveFocus(); + + projectFindView.element.focus(); + expect(projectFindView.findEditor.getElement()).toHaveFocus(); + }); + + it("moves focus between editors with find-and-replace:focus-next", () => { + projectFindView.findEditor.element.focus(); + expect(projectFindView.findEditor.element).toHaveFocus() + + atom.commands.dispatch(projectFindView.findEditor.element, 'find-and-replace:focus-next'); + expect(projectFindView.replaceEditor.element).toHaveFocus() + + atom.commands.dispatch(projectFindView.replaceEditor.element, 'find-and-replace:focus-next'); + expect(projectFindView.pathsEditor.element).toHaveFocus() + + atom.commands.dispatch(projectFindView.replaceEditor.element, 'find-and-replace:focus-next'); + expect(projectFindView.findEditor.element).toHaveFocus() + + atom.commands.dispatch(projectFindView.replaceEditor.element, 'find-and-replace:focus-previous'); + expect(projectFindView.pathsEditor.element).toHaveFocus() + + atom.commands.dispatch(projectFindView.replaceEditor.element, 'find-and-replace:focus-previous'); + expect(projectFindView.replaceEditor.element).toHaveFocus() + }); + }); + + describe("panel opening", () => { + describe("when a panel is already open on the right", () => { + beforeEach(async () => { + atom.config.set('find-and-replace.projectSearchResultsPaneSplitDirection', 'right'); + + editor = await atom.workspace.open('project/sample.js'); + editorElement = atom.views.getView(editor); + + atom.commands.dispatch(workspaceElement, 'project-find:show'); + await activationPromise; + + projectFindView.findEditor.setText('items'); + atom.commands.dispatch(projectFindView.element, 'core:confirm'); + await searchPromise; + }); + + it("doesn't open another panel even if the active pane is vertically split", async () => { + atom.commands.dispatch(editorElement, 'pane:split-down'); + projectFindView.findEditor.setText('items'); + + atom.commands.dispatch(projectFindView.element, 'core:confirm'); + await searchPromise; + + expect(workspaceElement.querySelectorAll('.preview-pane').length).toBe(1); + }); + }); + + describe("when a panel is already open at the bottom", () => { + beforeEach(async () => { + atom.config.set('find-and-replace.projectSearchResultsPaneSplitDirection', 'down'); + + editor = await atom.workspace.open('project/sample.js'); + editorElement = atom.views.getView(editor); + + atom.commands.dispatch(workspaceElement, 'project-find:show'); + await activationPromise; + + projectFindView.findEditor.setText('items'); + atom.commands.dispatch(projectFindView.element, 'core:confirm'); + await searchPromise; + }); + + it("doesn't open another panel even if the active pane is horizontally split", async () => { + atom.commands.dispatch(editorElement, 'pane:split-right'); + projectFindView.findEditor.setText('items'); + + atom.commands.dispatch(projectFindView.element, 'core:confirm'); + await searchPromise; + + expect(workspaceElement.querySelectorAll('.preview-pane').length).toBe(1); + }); + }); + }); + + describe("when language-javascript is active", () => { + beforeEach(async () => { + await atom.packages.activatePackage("language-javascript"); + }); + + it("uses the regexp grammar when regex-mode is loaded from configuration", async () => { + atom.config.set('find-and-replace.useRegex', true); + + atom.commands.dispatch(workspaceElement, 'project-find:show'); + await activationPromise; + + expect(projectFindView.model.getFindOptions().useRegex).toBe(true); + expect(projectFindView.findEditor.getGrammar().scopeName).toBe('source.js.regexp'); + expect(projectFindView.replaceEditor.getGrammar().scopeName).toBe('source.js.regexp.replacement'); + }); + + describe("when panel is active", () => { + beforeEach(async () => { + atom.commands.dispatch(workspaceElement, 'project-find:show'); + await activationPromise; + }); + + it("does not use regexp grammar when in non-regex mode", () => { + expect(projectFindView.model.getFindOptions().useRegex).not.toBe(true); + expect(projectFindView.findEditor.getGrammar().scopeName).toBe('text.plain.null-grammar'); + expect(projectFindView.replaceEditor.getGrammar().scopeName).toBe('text.plain.null-grammar'); + }); + + it("uses regexp grammar when in regex mode and clears the regexp grammar when regex is disabled", () => { + atom.commands.dispatch(projectFindView.element, 'project-find:toggle-regex-option'); + + expect(projectFindView.model.getFindOptions().useRegex).toBe(true); + expect(projectFindView.findEditor.getGrammar().scopeName).toBe('source.js.regexp'); + expect(projectFindView.replaceEditor.getGrammar().scopeName).toBe('source.js.regexp.replacement'); + + atom.commands.dispatch(projectFindView.element, 'project-find:toggle-regex-option'); + + expect(projectFindView.model.getFindOptions().useRegex).not.toBe(true); + expect(projectFindView.findEditor.getGrammar().scopeName).toBe('text.plain.null-grammar'); + expect(projectFindView.replaceEditor.getGrammar().scopeName).toBe('text.plain.null-grammar'); + }); + }); + }); +}); +} + +function simulateResizeEvent(element) { + Array.from(element.children).forEach((child) => { + child.dispatchEvent(new AnimationEvent('animationstart')); + }); + advanceClock(1); +} diff --git a/spec/results-view-spec.js b/spec/results-view-spec.js index c818f0ae..1585cb80 100644 --- a/spec/results-view-spec.js +++ b/spec/results-view-spec.js @@ -302,6 +302,8 @@ describe('ResultsView', () => { it("selects the first/last item when core:move-to-top/move-to-bottom is triggered", async () => { console.log("Running bad test"); const {listView} = resultsView.refs; + expect(listView.element.querySelectorAll('.match-row').length).toBeGreaterThan(0); + expect(listView.element.querySelectorAll('li').length).toBeLessThan(resultsView.model.getPathCount() + resultsView.model.getMatchCount()); expect(listView.element.querySelectorAll('li').length).toBeGreaterThan(0); @@ -309,6 +311,7 @@ describe('ResultsView', () => { await resultsView.moveToBottom(); + expect(listView.element.querySelectorAll('li').length).toBeGreaterThan(0); expect(listView.element.querySelectorAll('.match-row').length).toBeGreaterThan(0); expect(_.last(listView.element.querySelectorAll('.match-row'))).toHaveClass('selected');