/
githubmirror
/
brackets
Обзор
Документация
Войти
/
githubmirror
/
brackets
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
test/spec/FindReplace-test.js
1 982 строки
91 KB
Tory Herman
Add find/replace test for read only
17 ноя 2017, 06:47
17 ноя 2017, 06:47
c1ed83c
Код
Авторство
О чём код?
/* * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. * */ /*global describe, it, expect, beforeFirst, afterLast, beforeEach, afterEach, waitsFor, waitsForDone, runs, jasmine */ /*unittests: FindReplace*/ define(function (require, exports, module) { 'use strict'; var Commands = require("command/Commands"), FindReplace = require("search/FindReplace"), KeyEvent = require("utils/KeyEvent"), SpecRunnerUtils = require("spec/SpecRunnerUtils"), StringUtils = require("utils/StringUtils"), Strings = require("strings"); var defaultContent = "/* Test comment */\n" + "define(function (require, exports, module) {\n" + " var Foo = require(\"modules/Foo\"),\n" + " Bar = require(\"modules/Bar\"),\n" + " Baz = require(\"modules/Baz\");\n" + " \n" + " function callFoo() {\n" + " \n" + " foo();\n" + " \n" + " }\n" + "\n" + "}"; // Helper functions for testing cursor position / selection range function fixPos(pos) { if (!("sticky" in pos)) { pos.sticky = null; } return pos; } function fixSel(sel) { fixPos(sel.start); fixPos(sel.end); if (!("reversed" in sel)) { sel.reversed = false; } return sel; } function fixSels(sels) { sels.forEach(function (sel) { fixSel(sel); }); return sels; } describe("FindReplace - Unit", function () { var editor, doc; beforeEach(function () { var mocks = SpecRunnerUtils.createMockEditor(defaultContent, "javascript"); editor = mocks.editor; doc = mocks.doc; }); afterEach(function () { SpecRunnerUtils.destroyMockEditor(doc); editor = null; doc = null; }); describe("getWordAt", function () { it("should select a word bounded by whitespace from a pos in the middle of the word", function () { expect(FindReplace._getWordAt(editor, {line: 2, ch: 9})) .toEqual({start: {line: 2, ch: 8}, end: {line: 2, ch: 11}, text: "Foo"}); }); it("should select a word bounded by whitespace from a pos at the beginning of the word", function () { expect(FindReplace._getWordAt(editor, {line: 2, ch: 8})) .toEqual({start: {line: 2, ch: 8}, end: {line: 2, ch: 11}, text: "Foo"}); }); it("should select a word bounded by whitespace from a pos at the end of the word", function () { expect(FindReplace._getWordAt(editor, {line: 2, ch: 11})) .toEqual({start: {line: 2, ch: 8}, end: {line: 2, ch: 11}, text: "Foo"}); }); it("should select a word bounded by nonword characters from a pos in the middle of the word", function () { expect(FindReplace._getWordAt(editor, {line: 2, ch: 26})) .toEqual({start: {line: 2, ch: 23}, end: {line: 2, ch: 30}, text: "modules"}); }); it("should select a word bounded by nonword characters from a pos at the beginning of the word", function () { expect(FindReplace._getWordAt(editor, {line: 2, ch: 23})) .toEqual({start: {line: 2, ch: 23}, end: {line: 2, ch: 30}, text: "modules"}); }); it("should select a word bounded by nonword characters from a pos at the end of the word", function () { expect(FindReplace._getWordAt(editor, {line: 2, ch: 23})) .toEqual({start: {line: 2, ch: 23}, end: {line: 2, ch: 30}, text: "modules"}); }); it("should return an empty range in the middle of whitespace", function () { expect(FindReplace._getWordAt(editor, {line: 8, ch: 4})) .toEqual({start: {line: 8, ch: 4}, end: {line: 8, ch: 4}, text: ""}); }); it("should return an empty range in the middle of non-word chars", function () { expect(FindReplace._getWordAt(editor, {line: 8, ch: 13})) .toEqual({start: {line: 8, ch: 13}, end: {line: 8, ch: 13}, text: ""}); }); }); describe("expandAndAddNextToSelection", function () { it("should do nothing if the cursor is in non-word/whitespace", function () { editor.setSelection({line: 8, ch: 4}); FindReplace._expandWordAndAddNextToSelection(editor); expect(editor.getSelections()).toEqual(fixSels([ {start: {line: 8, ch: 4}, end: {line: 8, ch: 4}, primary: true, reversed: false} ])); }); it("should expand a single cursor to the containing word without adding a new selection", function () { editor.setSelection({line: 2, ch: 26}); FindReplace._expandWordAndAddNextToSelection(editor); expect(editor.getSelections()).toEqual(fixSels([ {start: {line: 2, ch: 23}, end: {line: 2, ch: 30}, primary: true, reversed: false} ])); }); it("should add the next match for a single word selection as a new primary selection", function () { editor.setSelection({line: 2, ch: 23}, {line: 2, ch: 30}); FindReplace._expandWordAndAddNextToSelection(editor); expect(editor.getSelections()).toEqual(fixSels([ {start: {line: 2, ch: 23}, end: {line: 2, ch: 30}, primary: false, reversed: false}, {start: {line: 3, ch: 23}, end: {line: 3, ch: 30}, primary: true, reversed: false} ])); }); it("should add the next match for an existing range that isn't actually a word", function () { editor.setSelection({line: 2, ch: 14}, {line: 2, ch: 22}); // "require(" FindReplace._expandWordAndAddNextToSelection(editor); expect(editor.getSelections()).toEqual(fixSels([ {start: {line: 2, ch: 14}, end: {line: 2, ch: 22}, primary: false, reversed: false}, {start: {line: 3, ch: 14}, end: {line: 3, ch: 22}, primary: true, reversed: false} ])); }); it("should find the next match case-insensitively", function () { editor.setSelection({line: 6, ch: 17}, {line: 6, ch: 20}); // "Foo" in "callFoo" - should next find "foo" in "foo()" FindReplace._expandWordAndAddNextToSelection(editor); expect(editor.getSelections()).toEqual(fixSels([ {start: {line: 6, ch: 17}, end: {line: 6, ch: 20}, primary: false, reversed: false}, {start: {line: 8, ch: 8}, end: {line: 8, ch: 11}, primary: true, reversed: false} ])); }); it("should expand two cursors without adding a new selection", function () { editor.setSelections([{start: {line: 2, ch: 26}, end: {line: 2, ch: 26}}, {start: {line: 3, ch: 16}, end: {line: 3, ch: 16}}]); FindReplace._expandWordAndAddNextToSelection(editor); expect(editor.getSelections()).toEqual(fixSels([ {start: {line: 2, ch: 23}, end: {line: 2, ch: 30}, primary: false, reversed: false}, {start: {line: 3, ch: 14}, end: {line: 3, ch: 21}, primary: true, reversed: false} ])); }); it("should, when one cursor and one range are selected, expand the cursor and add the next match for the range to the selection", function () { editor.setSelections([{start: {line: 2, ch: 26}, end: {line: 2, ch: 26}}, {start: {line: 3, ch: 14}, end: {line: 3, ch: 21}}]); // "require" FindReplace._expandWordAndAddNextToSelection(editor); expect(editor.getSelections()).toEqual(fixSels([ {start: {line: 2, ch: 23}, end: {line: 2, ch: 30}, primary: false, reversed: false}, {start: {line: 3, ch: 14}, end: {line: 3, ch: 21}, primary: false, reversed: false}, {start: {line: 4, ch: 14}, end: {line: 4, ch: 21}, primary: true, reversed: false} ])); }); it("should wrap around the end of the document and add the next instance at the beginning of the document", function () { editor.setSelection({line: 4, ch: 14}, {line: 4, ch: 21}); // "require" FindReplace._expandWordAndAddNextToSelection(editor); expect(editor.getSelections()).toEqual(fixSels([ {start: {line: 1, ch: 17}, end: {line: 1, ch: 24}, primary: true, reversed: false}, {start: {line: 4, ch: 14}, end: {line: 4, ch: 21}, primary: false, reversed: false} ])); }); it("should skip over matches that are already in the selection", function () { // select all instances of "require" except the second one editor.setSelections([{start: {line: 1, ch: 17}, end: {line: 1, ch: 24}}, {start: {line: 3, ch: 14}, end: {line: 3, ch: 21}}, {start: {line: 4, ch: 14}, end: {line: 4, ch: 21}}]); FindReplace._expandWordAndAddNextToSelection(editor); expect(editor.getSelections()).toEqual(fixSels([ {start: {line: 1, ch: 17}, end: {line: 1, ch: 24}, primary: false, reversed: false}, {start: {line: 2, ch: 14}, end: {line: 2, ch: 21}, primary: true, reversed: false}, {start: {line: 3, ch: 14}, end: {line: 3, ch: 21}, primary: false, reversed: false}, {start: {line: 4, ch: 14}, end: {line: 4, ch: 21}, primary: false, reversed: false} ])); }); it("should do nothing if all instances are already selected", function () { editor.setSelections([{start: {line: 1, ch: 17}, end: {line: 1, ch: 24}}, {start: {line: 2, ch: 14}, end: {line: 2, ch: 21}}, {start: {line: 3, ch: 14}, end: {line: 3, ch: 21}}, {start: {line: 4, ch: 14}, end: {line: 4, ch: 21}}]); FindReplace._expandWordAndAddNextToSelection(editor); expect(editor.getSelections()).toEqual(fixSels([ {start: {line: 1, ch: 17}, end: {line: 1, ch: 24}, primary: false, reversed: false}, {start: {line: 2, ch: 14}, end: {line: 2, ch: 21}, primary: false, reversed: false}, {start: {line: 3, ch: 14}, end: {line: 3, ch: 21}, primary: false, reversed: false}, {start: {line: 4, ch: 14}, end: {line: 4, ch: 21}, primary: true, reversed: false} ])); }); }); describe("expandAndAddNextToSelection - with removeCurrent (for Skip Match)", function () { it("should remove a single range selection and select the next instance", function () { editor.setSelection({line: 2, ch: 23}, {line: 2, ch: 30}); FindReplace._expandWordAndAddNextToSelection(editor, true); expect(editor.getSelections()).toEqual(fixSels([ {start: {line: 3, ch: 23}, end: {line: 3, ch: 30}, primary: true, reversed: false} ])); }); it("should expand a single cursor to a range, then change the selection to the next instance of that range", function () { editor.setSelection({line: 2, ch: 26}, {line: 2, ch: 26}); FindReplace._expandWordAndAddNextToSelection(editor, true); expect(editor.getSelections()).toEqual(fixSels([ {start: {line: 3, ch: 23}, end: {line: 3, ch: 30}, primary: true, reversed: false} ])); }); it("should, when one cursor and one range are selected, expand the cursor and change the range selection to its next match", function () { editor.setSelections([{start: {line: 2, ch: 26}, end: {line: 2, ch: 26}}, {start: {line: 3, ch: 14}, end: {line: 3, ch: 21}}]); // "require" FindReplace._expandWordAndAddNextToSelection(editor, true); expect(editor.getSelections()).toEqual(fixSels([ {start: {line: 2, ch: 23}, end: {line: 2, ch: 30}, primary: false, reversed: false}, {start: {line: 4, ch: 14}, end: {line: 4, ch: 21}, primary: true, reversed: false} ])); }); it("should wrap around the end of the document and switch to the next instance at the beginning of the document", function () { editor.setSelection({line: 4, ch: 14}, {line: 4, ch: 21}); // "require" FindReplace._expandWordAndAddNextToSelection(editor, true); expect(editor.getSelections()).toEqual(fixSels([ {start: {line: 1, ch: 17}, end: {line: 1, ch: 24}, primary: true, reversed: false} ])); }); it("should skip over matches that are already in the selection (but still remove the current one)", function () { // select all instances of "require" except the second one editor.setSelections([{start: {line: 1, ch: 17}, end: {line: 1, ch: 24}}, {start: {line: 3, ch: 14}, end: {line: 3, ch: 21}}, {start: {line: 4, ch: 14}, end: {line: 4, ch: 21}}]); FindReplace._expandWordAndAddNextToSelection(editor, true); expect(editor.getSelections()).toEqual(fixSels([ {start: {line: 1, ch: 17}, end: {line: 1, ch: 24}, primary: false, reversed: false}, {start: {line: 2, ch: 14}, end: {line: 2, ch: 21}, primary: true, reversed: false}, {start: {line: 3, ch: 14}, end: {line: 3, ch: 21}, primary: false, reversed: false} ])); }); it("should just remove the primary selection if all instances are already selected", function () { editor.setSelections([{start: {line: 1, ch: 17}, end: {line: 1, ch: 24}}, {start: {line: 2, ch: 14}, end: {line: 2, ch: 21}}, {start: {line: 3, ch: 14}, end: {line: 3, ch: 21}}, {start: {line: 4, ch: 14}, end: {line: 4, ch: 21}}]); FindReplace._expandWordAndAddNextToSelection(editor, true); expect(editor.getSelections()).toEqual(fixSels([ {start: {line: 1, ch: 17}, end: {line: 1, ch: 24}, primary: false, reversed: false}, {start: {line: 2, ch: 14}, end: {line: 2, ch: 21}, primary: false, reversed: false}, {start: {line: 3, ch: 14}, end: {line: 3, ch: 21}, primary: true, reversed: false} ])); }); }); describe("findAllAndSelect", function () { it("should find all instances of a selected range when first instance is selected, keeping it primary", function () { editor.setSelection({line: 1, ch: 17}, {line: 1, ch: 24}); FindReplace._findAllAndSelect(editor); expect(editor.getSelections()).toEqual(fixSels([ {start: {line: 1, ch: 17}, end: {line: 1, ch: 24}, primary: true, reversed: false}, {start: {line: 2, ch: 14}, end: {line: 2, ch: 21}, primary: false, reversed: false}, {start: {line: 3, ch: 14}, end: {line: 3, ch: 21}, primary: false, reversed: false}, {start: {line: 4, ch: 14}, end: {line: 4, ch: 21}, primary: false, reversed: false} ])); }); it("should find all instances of a selected range when instance other than first is selected, keeping it primary", function () { editor.setSelection({line: 3, ch: 14}, {line: 3, ch: 21}); FindReplace._findAllAndSelect(editor); expect(editor.getSelections()).toEqual(fixSels([ {start: {line: 1, ch: 17}, end: {line: 1, ch: 24}, primary: false, reversed: false}, {start: {line: 2, ch: 14}, end: {line: 2, ch: 21}, primary: false, reversed: false}, {start: {line: 3, ch: 14}, end: {line: 3, ch: 21}, primary: true, reversed: false}, {start: {line: 4, ch: 14}, end: {line: 4, ch: 21}, primary: false, reversed: false} ])); }); it("should throw away selections other than the primary selection", function () { editor.setSelections([{start: {line: 3, ch: 14}, end: {line: 3, ch: 21}, primary: true}, {start: {line: 6, ch: 4}, end: {line: 6, ch: 6}}]); FindReplace._findAllAndSelect(editor); expect(editor.getSelections()).toEqual(fixSels([ {start: {line: 1, ch: 17}, end: {line: 1, ch: 24}, primary: false, reversed: false}, {start: {line: 2, ch: 14}, end: {line: 2, ch: 21}, primary: false, reversed: false}, {start: {line: 3, ch: 14}, end: {line: 3, ch: 21}, primary: true, reversed: false}, {start: {line: 4, ch: 14}, end: {line: 4, ch: 21}, primary: false, reversed: false} ])); }); it("should expand cursor to range, then find other instances", function () { editor.setSelection({line: 3, ch: 18}, {line: 3, ch: 18}); FindReplace._findAllAndSelect(editor); expect(editor.getSelections()).toEqual(fixSels([ {start: {line: 1, ch: 17}, end: {line: 1, ch: 24}, primary: false, reversed: false}, {start: {line: 2, ch: 14}, end: {line: 2, ch: 21}, primary: false, reversed: false}, {start: {line: 3, ch: 14}, end: {line: 3, ch: 21}, primary: true, reversed: false}, {start: {line: 4, ch: 14}, end: {line: 4, ch: 21}, primary: false, reversed: false} ])); }); it("should find all case insensitively", function () { editor.setSelection({line: 8, ch: 10}, {line: 8, ch: 10}); // inside "foo", should also find "Foo"s FindReplace._findAllAndSelect(editor); expect(editor.getSelections()).toEqual(fixSels([ {start: {line: 2, ch: 8}, end: {line: 2, ch: 11}, primary: false, reversed: false}, {start: {line: 2, ch: 31}, end: {line: 2, ch: 34}, primary: false, reversed: false}, {start: {line: 6, ch: 17}, end: {line: 6, ch: 20}, primary: false, reversed: false}, {start: {line: 8, ch: 8}, end: {line: 8, ch: 11}, primary: true, reversed: false} ])); }); it("should not change the selection if the primary selection is a cursor inside a non-word", function () { editor.setSelections([{start: {line: 1, ch: 4}, end: {line: 1, ch: 10}}, {start: {line: 8, ch: 0}, end: {line: 8, ch: 0}}]); FindReplace._findAllAndSelect(editor); expect(editor.getSelections()).toEqual(fixSels([ {start: {line: 1, ch: 4}, end: {line: 1, ch: 10}, primary: false, reversed: false}, {start: {line: 8, ch: 0}, end: {line: 8, ch: 0}, primary: true, reversed: false} ])); }); }); }); describe("FindReplace - Integration", function () { this.category = "integration"; var LINE_FIRST_REQUIRE = 2; var CH_REQUIRE_START = 14; var CH_REQUIRE_PAREN = CH_REQUIRE_START + "require".length; var fooExpectedMatches = [ {start: {line: LINE_FIRST_REQUIRE, ch: 8}, end: {line: LINE_FIRST_REQUIRE, ch: 11}}, {start: {line: LINE_FIRST_REQUIRE, ch: 31}, end: {line: LINE_FIRST_REQUIRE, ch: 34}}, {start: {line: 6, ch: 17}, end: {line: 6, ch: 20}}, {start: {line: 8, ch: 8}, end: {line: 8, ch: 11}} ]; var capitalFooSelections = [ {start: {line: LINE_FIRST_REQUIRE, ch: 8}, end: {line: LINE_FIRST_REQUIRE, ch: 11}}, {start: {line: LINE_FIRST_REQUIRE, ch: 31}, end: {line: LINE_FIRST_REQUIRE, ch: 34}}, {start: {line: 6, ch: 17}, end: {line: 6, ch: 20}} ]; var barExpectedMatches = [ {start: {line: LINE_FIRST_REQUIRE + 1, ch: 8}, end: {line: LINE_FIRST_REQUIRE + 1, ch: 11}}, {start: {line: LINE_FIRST_REQUIRE + 1, ch: 31}, end: {line: LINE_FIRST_REQUIRE + 1, ch: 34}} ]; var testWindow, twCommandManager, twEditorManager, twFindInFiles, tw$; var myDocument, myEditor; // Helper functions for testing cursor position / selection range // TODO: duplicated from EditorCommandHandlers-test function expectSelection(sel) { if (!sel.reversed) { sel.reversed = false; } expect(fixSel(myEditor.getSelection())).toEqual(fixSel(sel)); } function expectMatchIndex(index, count) { var matchInfo = StringUtils.format(Strings.FIND_MATCH_INDEX, index + 1, count); expect(myEditor._codeMirror._searchState.matchIndex).toEqual(index); expect(myEditor._codeMirror._searchState.resultSet.length).toEqual(count); expect($(testWindow.document).find("#find-counter").text()).toBe(matchInfo); } function expectHighlightedMatches(selections, expectedDOMHighlightCount) { var cm = myEditor._codeMirror; var searchState = cm._searchState; expect(searchState).toBeDefined(); expect(searchState.marked).toBeDefined(); expect(searchState.marked.length).toEqual(selections.length); // Verify that searchState's marked ranges match expected ranges if (selections) { selections.forEach(function (location, index) { var textMarker = searchState.marked[index]; var markerLocation = textMarker.find(); expect(fixPos(markerLocation.from)).toEqual(fixPos(location.start)); expect(fixPos(markerLocation.to)).toEqual(fixPos(location.end)); }); } // Verify number of tickmarks equals number of highlights var tickmarks = tw$(".tickmark-track .tickmark", myEditor.getRootElement()); expect(tickmarks.length).toEqual(selections.length); // Verify that editor UI doesn't have extra ranges left highlighted from earlier // (note: this only works for text that's short enough to not get virtualized) var lineDiv = tw$(".CodeMirror-lines .CodeMirror-code", myEditor.getRootElement()); var actualHighlights = tw$(".CodeMirror-searching", lineDiv); if (expectedDOMHighlightCount === undefined) { expectedDOMHighlightCount = selections.length; } expect(actualHighlights.length).toEqual(expectedDOMHighlightCount); } function expectFindNextSelections(selections) { var i; for (i = 0; i < selections.length; i++) { expectSelection(selections[i]); twCommandManager.execute(Commands.CMD_FIND_NEXT); } // next find should wraparound expectSelection(selections[0]); } function getSearchBar() { return tw$(".modal-bar"); } function getSearchField() { return tw$("#find-what"); } function getReplaceField() { return tw$("#replace-with"); } function expectSearchBarOpen() { expect(getSearchBar()[0]).toBeDefined(); } function waitsForSearchBarClose() { waitsFor(function () { return getSearchBar().length === 0; }, 1000, "search bar closing"); } function waitsForSearchBarReopen() { // If Find is invoked again while a previous Find bar is already up, we want to // wait for the old Find bar to disappear before continuing our test, so we know // which modal bar to look at. waitsFor(function () { return getSearchBar().length === 1; }, 1000, "search bar reopening"); } function enterSearchText(str) { expectSearchBarOpen(); var $input = getSearchField(); $input.val(str); $input.trigger("input"); } function enterReplaceText(str) { expectSearchBarOpen(); var $input = getReplaceField(); $input.val(str); $input.trigger("input"); } function pressEscape() { expectSearchBarOpen(); SpecRunnerUtils.simulateKeyEvent(KeyEvent.DOM_VK_ESCAPE, "keydown", getSearchField()[0]); } function toggleCaseSensitive(val) { if (tw$("#find-case-sensitive").is(".active") !== val) { tw$("#find-case-sensitive").click(); } } function toggleRegexp(val) { if (tw$("#find-regexp").is(".active") !== val) { tw$("#find-regexp").click(); } } beforeFirst(function () { SpecRunnerUtils.createTempDirectory(); // Create a new window that will be shared by ALL tests in this spec. SpecRunnerUtils.createTestWindowAndRun(this, function (w) { testWindow = w; // Load module instances from brackets.test twCommandManager = testWindow.brackets.test.CommandManager; twEditorManager = testWindow.brackets.test.EditorManager; twFindInFiles = testWindow.brackets.test.FindInFiles; tw$ = testWindow.$; SpecRunnerUtils.loadProjectInTestWindow(SpecRunnerUtils.getTempDirectory()); }); }); afterLast(function () { testWindow = null; twCommandManager = null; twEditorManager = null; twFindInFiles = null; tw$ = null; SpecRunnerUtils.closeTestWindow(); SpecRunnerUtils.removeTempDirectory(); }); beforeEach(function () { runs(function () { waitsForDone(twCommandManager.execute(Commands.FILE_NEW_UNTITLED)); }); runs(function () { myEditor = twEditorManager.getCurrentFullEditor(); myDocument = myEditor.document; myDocument.replaceRange(defaultContent, {line: 0, ch: 0}); myEditor.centerOnCursor = jasmine.createSpy("centering"); }); }); afterEach(function () { runs(function () { // Reset search options for next test, since these are persisted and the window is shared // Note: tests that explicitly close the search bar before finishing will need to reset any changed options themselves toggleCaseSensitive(false); toggleRegexp(false); waitsForDone(twCommandManager.execute(Commands.FILE_CLOSE, { _forceClose: true })); }); waitsForSearchBarClose(); runs(function () { myEditor = null; myDocument = null; }); }); describe("Search", function () { it("should have the correct match count even if DOM highlighting is turned off when over 2000 matches", function () { var text = "bbbbbbbbbb", i; // Create a text string that is 2430 (10 x 3^5) characters long for (i = 0; i < 5; i++) { text += text + text; } myEditor._codeMirror.setValue(text); myEditor.setCursorPos(0, 0); twCommandManager.execute(Commands.CMD_FIND); enterSearchText("b"); expectMatchIndex(0, 2430); // When exceeding 2000 matches, tickmarks disabled and only the *current* editor highlight is shown expectHighlightedMatches([], 1); }); it("should find all case-insensitive matches with lowercase text", function () { myEditor.setCursorPos(0, 0); twCommandManager.execute(Commands.CMD_FIND); // The previous search term "b" was pre-filled, so the editor was centered there already expect(myEditor.centerOnCursor.calls.length).toEqual(1); enterSearchText("foo"); expectHighlightedMatches(fooExpectedMatches); expectSelection(fooExpectedMatches[0]); expectMatchIndex(0, 4); expect(myEditor.centerOnCursor.calls.length).toEqual(2); twCommandManager.execute(Commands.CMD_FIND_NEXT); expectSelection(fooExpectedMatches[1]); expectMatchIndex(1, 4); expect(myEditor.centerOnCursor.calls.length).toEqual(3); twCommandManager.execute(Commands.CMD_FIND_NEXT); expectSelection(fooExpectedMatches[2]); expectMatchIndex(2, 4); twCommandManager.execute(Commands.CMD_FIND_NEXT); expectSelection(fooExpectedMatches[3]); expectMatchIndex(3, 4); expectHighlightedMatches(fooExpectedMatches); // no change in highlights // wraparound twCommandManager.execute(Commands.CMD_FIND_NEXT); expectSelection(fooExpectedMatches[0]); expectMatchIndex(0, 4); expect(myEditor.centerOnCursor.calls.length).toEqual(6); }); it("should find all case-insensitive matches with mixed-case text", function () { myEditor.setCursorPos(0, 0); twCommandManager.execute(Commands.CMD_FIND); // The previous search term "foo" was pre-filled, so the editor was centered there already expect(myEditor.centerOnCursor.calls.length).toEqual(1); enterSearchText("Foo"); expectHighlightedMatches(fooExpectedMatches); expectSelection(fooExpectedMatches[0]); expectMatchIndex(0, 4); expect(myEditor.centerOnCursor.calls.length).toEqual(2); twCommandManager.execute(Commands.CMD_FIND_NEXT); expectSelection(fooExpectedMatches[1]); expectMatchIndex(1, 4); expect(myEditor.centerOnCursor.calls.length).toEqual(3); twCommandManager.execute(Commands.CMD_FIND_NEXT); expectSelection(fooExpectedMatches[2]); expectMatchIndex(2, 4); twCommandManager.execute(Commands.CMD_FIND_NEXT); expectSelection(fooExpectedMatches[3]); expectMatchIndex(3, 4); expectHighlightedMatches(fooExpectedMatches); // no change in highlights // wraparound twCommandManager.execute(Commands.CMD_FIND_NEXT); expectSelection(fooExpectedMatches[0]); expectMatchIndex(0, 4); expect(myEditor.centerOnCursor.calls.length).toEqual(6); }); it("should find all case-sensitive matches with mixed-case text", function () { myEditor.setCursorPos(0, 0); twCommandManager.execute(Commands.CMD_FIND); toggleCaseSensitive(true); enterSearchText("Foo"); expectHighlightedMatches(capitalFooSelections); expectSelection(capitalFooSelections[0]); expectMatchIndex(0, 3); twCommandManager.execute(Commands.CMD_FIND_NEXT); expectSelection(capitalFooSelections[1]); expectMatchIndex(1, 3); twCommandManager.execute(Commands.CMD_FIND_NEXT); expectSelection(capitalFooSelections[2]); expectMatchIndex(2, 3); // note the lowercase "foo()" is NOT matched // wraparound twCommandManager.execute(Commands.CMD_FIND_NEXT); expectSelection(capitalFooSelections[0]); expectMatchIndex(0, 3); }); it("should have a scroll track marker for every match", function () { twCommandManager.execute(Commands.CMD_FIND); enterSearchText("foo"); expectHighlightedMatches(fooExpectedMatches); var marks = testWindow.brackets.test.ScrollTrackMarkers._getTickmarks(); expect(marks.length).toEqual(fooExpectedMatches.length); marks.forEach(function (mark, index) { expect(mark.line).toEqual(fooExpectedMatches[index].start.line); }); }); it("toggling case-sensitive option should update results immediately", function () { myEditor.setCursorPos(0, 0); twCommandManager.execute(Commands.CMD_FIND); enterSearchText("Foo"); expectHighlightedMatches(fooExpectedMatches); expectSelection(fooExpectedMatches[0]); expectMatchIndex(0, 4); toggleCaseSensitive(true); expectHighlightedMatches(capitalFooSelections); expectSelection(capitalFooSelections[0]); expectMatchIndex(0, 3); twCommandManager.execute(Commands.CMD_FIND_NEXT); expectSelection(capitalFooSelections[1]); expectMatchIndex(1, 3); }); it("should Find Next after search bar closed, including wraparound", function () { runs(function () { myEditor.setCursorPos(0, 0); twCommandManager.execute(Commands.CMD_FIND); // The previous search term "Foo" was pre-filled, so the editor was centered there already expect(myEditor.centerOnCursor.calls.length).toEqual(1); enterSearchText("foo"); pressEscape(); expectHighlightedMatches([]); }); waitsForSearchBarClose(); runs(function () { expectSelection({start: {line: LINE_FIRST_REQUIRE, ch: 8}, end: {line: LINE_FIRST_REQUIRE, ch: 11}}); expect(myEditor.centerOnCursor.calls.length).toEqual(2); // Simple linear Find Next twCommandManager.execute(Commands.CMD_FIND_NEXT); expectSelection({start: {line: LINE_FIRST_REQUIRE, ch: 31}, end: {line: LINE_FIRST_REQUIRE, ch: 34}}); expect(myEditor.centerOnCursor.calls.length).toEqual(3); twCommandManager.execute(Commands.CMD_FIND_NEXT); expectSelection({start: {line: 6, ch: 17}, end: {line: 6, ch: 20}}); twCommandManager.execute(Commands.CMD_FIND_NEXT); expectSelection({start: {line: 8, ch: 8}, end: {line: 8, ch: 11}}); // Wrap around to first result twCommandManager.execute(Commands.CMD_FIND_NEXT); expectSelection({start: {line: LINE_FIRST_REQUIRE, ch: 8}, end: {line: LINE_FIRST_REQUIRE, ch: 11}}); }); }); it("should Find Previous after search bar closed, including wraparound", function () { runs(function () { myEditor.setCursorPos(0, 0); twCommandManager.execute(Commands.CMD_FIND); enterSearchText("foo"); pressEscape(); }); waitsForSearchBarClose(); runs(function () { expectSelection({start: {line: LINE_FIRST_REQUIRE, ch: 8}, end: {line: LINE_FIRST_REQUIRE, ch: 11}}); // Wrap around to last result twCommandManager.execute(Commands.CMD_FIND_PREVIOUS); expectSelection({start: {line: 8, ch: 8}, end: {line: 8, ch: 11}}); // Simple linear Find Previous twCommandManager.execute(Commands.CMD_FIND_PREVIOUS); expectSelection({start: {line: 6, ch: 17}, end: {line: 6, ch: 20}}); twCommandManager.execute(Commands.CMD_FIND_PREVIOUS); expectSelection({start: {line: LINE_FIRST_REQUIRE, ch: 31}, end: {line: LINE_FIRST_REQUIRE, ch: 34}}); twCommandManager.execute(Commands.CMD_FIND_PREVIOUS); expectSelection({start: {line: LINE_FIRST_REQUIRE, ch: 8}, end: {line: LINE_FIRST_REQUIRE, ch: 11}}); }); }); it("should Find Next after search bar closed, relative to cursor position", function () { runs(function () { myEditor.setCursorPos(0, 0); twCommandManager.execute(Commands.CMD_FIND); enterSearchText("foo"); pressEscape(); expectHighlightedMatches([]); }); waitsForSearchBarClose(); runs(function () { expectSelection({start: {line: LINE_FIRST_REQUIRE, ch: 8}, end: {line: LINE_FIRST_REQUIRE, ch: 11}}); twCommandManager.execute(Commands.CMD_FIND_NEXT); expectSelection({start: {line: LINE_FIRST_REQUIRE, ch: 31}, end: {line: LINE_FIRST_REQUIRE, ch: 34}}); // skip forward myEditor.setCursorPos(7, 0); twCommandManager.execute(Commands.CMD_FIND_NEXT); expectSelection({start: {line: 8, ch: 8}, end: {line: 8, ch: 11}}); // skip backward myEditor.setCursorPos(LINE_FIRST_REQUIRE, 14); twCommandManager.execute(Commands.CMD_FIND_NEXT); expectSelection({start: {line: LINE_FIRST_REQUIRE, ch: 31}, end: {line: LINE_FIRST_REQUIRE, ch: 34}}); }); }); it("should Find Next after search bar closed, remembering case sensitivity state", function () { runs(function () { myEditor.setCursorPos(0, 0); twCommandManager.execute(Commands.CMD_FIND); toggleCaseSensitive(true); enterSearchText("Foo"); pressEscape(); expectHighlightedMatches([]); }); waitsForSearchBarClose(); runs(function () { expectFindNextSelections(capitalFooSelections); }); }); it("should remember the last search query", function () { runs(function () { myEditor.setCursorPos(0, 0); twCommandManager.execute(Commands.CMD_FIND); enterSearchText("Foo"); pressEscape(); }); waitsForSearchBarClose(); runs(function () { // Open search bar a second time myEditor.setCursorPos(0, 0); twCommandManager.execute(Commands.CMD_FIND); expectSearchBarOpen(); expect(getSearchField().val()).toEqual("Foo"); expectHighlightedMatches(capitalFooSelections); expectSelection(capitalFooSelections[0]); expectMatchIndex(0, 3); expect(myEditor.centerOnCursor.calls.length).toEqual(3); twCommandManager.execute(Commands.CMD_FIND_NEXT); expectSelection(capitalFooSelections[1]); expectMatchIndex(1, 3); }); }); it("should open search bar on Find Next with no previous search", function () { runs(function () { // Make sure we have no previous query twCommandManager.execute(Commands.CMD_FIND); enterSearchText(""); pressEscape(); }); waitsForSearchBarClose(); runs(function () { myEditor.setCursorPos(0, 0); twCommandManager.execute(Commands.CMD_FIND_NEXT); expectSearchBarOpen(); expect(myEditor).toHaveCursorPosition(0, 0); }); }); it("should select-all without affecting search state if Find invoked while search bar open", function () { // #2478 runs(function () { myEditor.setCursorPos(0, 0); twCommandManager.execute(Commands.CMD_FIND); enterSearchText("foo"); // position cursor first // Search for something that doesn't exist; otherwise we can't tell whether search state is cleared or bar is reopened, // since reopening the bar will just prepopulate it with selected text from first search's result enterSearchText("foobar"); expect(myEditor).toHaveCursorPosition(LINE_FIRST_REQUIRE, 11); // cursor left at end of last good match ("foo") // Invoke Find a 2nd time - this time while search bar is open twCommandManager.execute(Commands.CMD_FIND); }); waitsForSearchBarReopen(); runs(function () { expectSearchBarOpen(); expect(getSearchField().val()).toEqual("foobar"); expect(getSearchField()[0].selectionStart).toBe(0); expect(getSearchField()[0].selectionEnd).toBe(6); expect(myEditor).toHaveCursorPosition(LINE_FIRST_REQUIRE, 11); }); }); }); describe("Incremental search", function () { it("should re-search from original position when text changes", function () { myEditor.setCursorPos(0, 0); twCommandManager.execute(Commands.CMD_FIND); enterSearchText("baz"); var expectedSelections = [ {start: {line: LINE_FIRST_REQUIRE + 2, ch: 8}, end: {line: LINE_FIRST_REQUIRE + 2, ch: 11}}, {start: {line: LINE_FIRST_REQUIRE + 2, ch: 31}, end: {line: LINE_FIRST_REQUIRE + 2, ch: 34}} ]; expectSelection(expectedSelections[0]); expectMatchIndex(0, 2); expectHighlightedMatches(expectedSelections); enterSearchText("bar"); expectSelection(barExpectedMatches[0]); // selection one line earlier than previous selection expectMatchIndex(0, 2); expectHighlightedMatches(barExpectedMatches); }); it("should re-search from original position when text changes, even after Find Next", function () { myEditor.setCursorPos(0, 0); twCommandManager.execute(Commands.CMD_FIND); enterSearchText("foo"); expectSelection(fooExpectedMatches[0]); expectMatchIndex(0, 4); // get search highlight down below where the "bar" match will be twCommandManager.execute(Commands.CMD_FIND_NEXT); twCommandManager.execute(Commands.CMD_FIND_NEXT); expectSelection(fooExpectedMatches[2]); expectMatchIndex(2, 4); enterSearchText("bar"); expectSelection(barExpectedMatches[0]); expectMatchIndex(0, 2); }); it("should use empty initial query for single cursor selection", function () { runs(function () { // Make sure we have no previous query twCommandManager.execute(Commands.CMD_FIND); enterSearchText(""); pressEscape(); }); waitsForSearchBarClose(); runs(function () { myEditor.setSelection({line: LINE_FIRST_REQUIRE, ch: CH_REQUIRE_START}); twCommandManager.execute(Commands.CMD_FIND); expect(getSearchField().val()).toEqual(""); }); }); it("should use empty initial query for multiple cursor selection", function () { runs(function () { // Make sure we have no previous query twCommandManager.execute(Commands.CMD_FIND); enterSearchText(""); pressEscape(); }); waitsForSearchBarClose(); runs(function () { myEditor.setSelections([{start: {line: LINE_FIRST_REQUIRE, ch: CH_REQUIRE_START}, end: {line: LINE_FIRST_REQUIRE, ch: CH_REQUIRE_START}, primary: true}, {start: {line: 1, ch: 0}, end: {line: 1, ch: 0}}]); twCommandManager.execute(Commands.CMD_FIND); expect(getSearchField().val()).toEqual(""); }); }); it("should get single selection as initial query", function () { myEditor.setSelection({line: LINE_FIRST_REQUIRE, ch: CH_REQUIRE_START}, {line: LINE_FIRST_REQUIRE, ch: CH_REQUIRE_PAREN}); twCommandManager.execute(Commands.CMD_FIND); expect(getSearchField().val()).toEqual("require"); }); it("should get primary selection as initial query", function () { myEditor.setSelections([{start: {line: LINE_FIRST_REQUIRE, ch: CH_REQUIRE_START}, end: {line: LINE_FIRST_REQUIRE, ch: CH_REQUIRE_PAREN}, primary: true}, {start: {line: 1, ch: 0}, end: {line: 1, ch: 1}}]); twCommandManager.execute(Commands.CMD_FIND); expect(getSearchField().val()).toEqual("require"); }); it("should extend original selection when appending to prepopulated text", function () { myEditor.setSelection({line: LINE_FIRST_REQUIRE, ch: CH_REQUIRE_START}, {line: LINE_FIRST_REQUIRE, ch: CH_REQUIRE_PAREN}); twCommandManager.execute(Commands.CMD_FIND); expect(getSearchField().val()).toEqual("require"); var requireExpectedMatches = [ {start: {line: 1, ch: 17}, end: {line: 1, ch: 24}}, {start: {line: LINE_FIRST_REQUIRE, ch: CH_REQUIRE_START}, end: {line: LINE_FIRST_REQUIRE, ch: CH_REQUIRE_PAREN}}, {start: {line: LINE_FIRST_REQUIRE + 1, ch: CH_REQUIRE_START}, end: {line: LINE_FIRST_REQUIRE + 1, ch: CH_REQUIRE_PAREN}}, {start: {line: LINE_FIRST_REQUIRE + 2, ch: CH_REQUIRE_START}, end: {line: LINE_FIRST_REQUIRE + 2, ch: CH_REQUIRE_PAREN}} ]; expectHighlightedMatches(requireExpectedMatches); expectSelection(requireExpectedMatches[1]); // cursor was below 1st match, so 2nd match is selected expectMatchIndex(1, 4); enterSearchText("require("); requireExpectedMatches.shift(); // first result no longer matches requireExpectedMatches[0].end.ch++; // other results now include one more char requireExpectedMatches[1].end.ch++; requireExpectedMatches[2].end.ch++; expectHighlightedMatches(requireExpectedMatches, 3); // in a new file, JS isn't color coded, so there's only one span each expectSelection(requireExpectedMatches[0]); expectMatchIndex(0, 3); }); it("should collapse selection when appending to prepopulated text causes no result", function () { myEditor.setSelection({line: LINE_FIRST_REQUIRE, ch: CH_REQUIRE_START}, {line: LINE_FIRST_REQUIRE, ch: CH_REQUIRE_PAREN}); twCommandManager.execute(Commands.CMD_FIND); expectSelection({start: {line: LINE_FIRST_REQUIRE, ch: CH_REQUIRE_START}, end: {line: LINE_FIRST_REQUIRE, ch: CH_REQUIRE_PAREN}}); enterSearchText("requireX"); expectHighlightedMatches([]); expect(myEditor).toHaveCursorPosition(LINE_FIRST_REQUIRE, CH_REQUIRE_PAREN); }); it("should clear selection, return cursor to start after backspacing to empty query", function () { myEditor.setCursorPos(2, 0); twCommandManager.execute(Commands.CMD_FIND); enterSearchText("require"); expectSelection({start: {line: LINE_FIRST_REQUIRE, ch: CH_REQUIRE_START}, end: {line: LINE_FIRST_REQUIRE, ch: CH_REQUIRE_PAREN}}); enterSearchText(""); expect(myEditor).toHaveCursorPosition(2, 0); }); it("should incremental search & highlight from Replace mode too", function () { myEditor.setCursorPos(0, 0); twCommandManager.execute(Commands.CMD_REPLACE); enterSearchText("baz"); var expectedSelections = [ {start: {line: LINE_FIRST_REQUIRE + 2, ch: 8}, end: {line: LINE_FIRST_REQUIRE + 2, ch: 11}}, {start: {line: LINE_FIRST_REQUIRE + 2, ch: 31}, end: {line: LINE_FIRST_REQUIRE + 2, ch: 34}} ]; expectSelection(expectedSelections[0]); expectMatchIndex(0, 2); expectHighlightedMatches(expectedSelections); enterSearchText("baz\""); expectedSelections = [ {start: {line: LINE_FIRST_REQUIRE + 2, ch: 31}, end: {line: LINE_FIRST_REQUIRE + 2, ch: 35}} ]; expectSelection(expectedSelections[0]); expectMatchIndex(0, 1); expectHighlightedMatches(expectedSelections); }); }); describe("Terminating search", function () { it("shouldn't change selection on Escape after typing text, no Find Nexts", function () { runs(function () { // Make sure we have no previous query twCommandManager.execute(Commands.CMD_FIND); enterSearchText(""); pressEscape(); }); waitsForSearchBarClose(); runs(function () { myEditor.setCursorPos(LINE_FIRST_REQUIRE, 0); twCommandManager.execute(Commands.CMD_FIND); expect(myEditor).toHaveCursorPosition(LINE_FIRST_REQUIRE, 0); enterSearchText("require"); expectSelection({start: {line: LINE_FIRST_REQUIRE, ch: CH_REQUIRE_START}, end: {line: LINE_FIRST_REQUIRE, ch: CH_REQUIRE_PAREN}}); pressEscape(); }); waitsForSearchBarClose(); runs(function () { expectSelection({start: {line: LINE_FIRST_REQUIRE, ch: CH_REQUIRE_START}, end: {line: LINE_FIRST_REQUIRE, ch: CH_REQUIRE_PAREN}}); }); }); it("shouldn't change selection on Escape after typing text & Find Next", function () { runs(function () { myEditor.setCursorPos(LINE_FIRST_REQUIRE, 0); twCommandManager.execute(Commands.CMD_FIND); expectSelection({start: {line: LINE_FIRST_REQUIRE, ch: CH_REQUIRE_START}, end: {line: LINE_FIRST_REQUIRE, ch: CH_REQUIRE_PAREN}}); twCommandManager.execute(Commands.CMD_FIND_NEXT); expectSelection({start: {line: LINE_FIRST_REQUIRE + 1, ch: CH_REQUIRE_START}, end: {line: LINE_FIRST_REQUIRE + 1, ch: CH_REQUIRE_PAREN}}); pressEscape(); }); waitsForSearchBarClose(); runs(function () { expectSelection({start: {line: LINE_FIRST_REQUIRE + 1, ch: CH_REQUIRE_START}, end: {line: LINE_FIRST_REQUIRE + 1, ch: CH_REQUIRE_PAREN}}); }); }); it("should no-op on Find Next with blank search", function () { runs(function () { // Make sure we have no previous query twCommandManager.execute(Commands.CMD_FIND); enterSearchText(""); pressEscape(); }); waitsForSearchBarClose(); runs(function () { myEditor.setCursorPos(LINE_FIRST_REQUIRE, 0); twCommandManager.execute(Commands.CMD_FIND); expect(myEditor).toHaveCursorPosition(LINE_FIRST_REQUIRE, 0); twCommandManager.execute(Commands.CMD_FIND_NEXT); expect(myEditor).toHaveCursorPosition(LINE_FIRST_REQUIRE, 0); // no change }); }); }); describe("RegExp Search", function () { it("should find based on regexp", function () { var expectedSelections = [ {start: {line: LINE_FIRST_REQUIRE + 1, ch: 8}, end: {line: LINE_FIRST_REQUIRE + 1, ch: 11}}, {start: {line: LINE_FIRST_REQUIRE + 1, ch: 31}, end: {line: LINE_FIRST_REQUIRE + 1, ch: 34}}, {start: {line: LINE_FIRST_REQUIRE + 2, ch: 8}, end: {line: LINE_FIRST_REQUIRE + 2, ch: 11}}, {start: {line: LINE_FIRST_REQUIRE + 2, ch: 31}, end: {line: LINE_FIRST_REQUIRE + 2, ch: 34}} ]; myEditor.setCursorPos(0, 0); twCommandManager.execute(Commands.CMD_FIND); toggleRegexp(true); toggleCaseSensitive(true); enterSearchText("Ba."); expectHighlightedMatches(expectedSelections); expectSelection(expectedSelections[0]); expectMatchIndex(0, 4); twCommandManager.execute(Commands.CMD_FIND_NEXT); expectSelection(expectedSelections[1]); expectMatchIndex(1, 4); twCommandManager.execute(Commands.CMD_FIND_NEXT); expectSelection(expectedSelections[2]); expectMatchIndex(2, 4); twCommandManager.execute(Commands.CMD_FIND_NEXT); expectSelection(expectedSelections[3]); expectMatchIndex(3, 4); // wraparound twCommandManager.execute(Commands.CMD_FIND_NEXT); expectSelection(expectedSelections[0]); expectMatchIndex(0, 4); }); it("should Find Next after search bar closed, remembering last used regexp", function () { var expectedSelections = [ {start: {line: LINE_FIRST_REQUIRE + 1, ch: 8}, end: {line: LINE_FIRST_REQUIRE + 1, ch: 11}}, {start: {line: LINE_FIRST_REQUIRE + 1, ch: 31}, end: {line: LINE_FIRST_REQUIRE + 1, ch: 34}}, {start: {line: LINE_FIRST_REQUIRE + 2, ch: 8}, end: {line: LINE_FIRST_REQUIRE + 2, ch: 11}}, {start: {line: LINE_FIRST_REQUIRE + 2, ch: 31}, end: {line: LINE_FIRST_REQUIRE + 2, ch: 34}} ]; runs(function () { myEditor.setCursorPos(0, 0); twCommandManager.execute(Commands.CMD_FIND); toggleRegexp(true); enterSearchText("Ba."); pressEscape(); expectHighlightedMatches([]); }); waitsForSearchBarClose(); runs(function () { expectFindNextSelections(expectedSelections); // explicitly clean up since we closed the search bar twCommandManager.execute(Commands.CMD_FIND); toggleRegexp(false); }); }); it("toggling regexp option should update results immediately", function () { myEditor.setCursorPos(0, 0); twCommandManager.execute(Commands.CMD_FIND); enterSearchText("t ."); expectHighlightedMatches([]); expect(myEditor).toHaveCursorPosition(0, 0); toggleRegexp(true); var expectedSelections = [ {start: {line: 0, ch: 6}, end: {line: 0, ch: 9}}, {start: {line: 0, ch: 14}, end: {line: 0, ch: 17}} ]; expectHighlightedMatches(expectedSelections); expectSelection(expectedSelections[0]); expectMatchIndex(0, 2); }); it("should support case-sensitive regexp", function () { var expectedSelections = [ {start: {line: 8, ch: 8}, end: {line: 8, ch: 11}} ]; myEditor.setCursorPos(0, 0); twCommandManager.execute(Commands.CMD_FIND); toggleRegexp(true); toggleCaseSensitive(true); enterSearchText("f.o"); expectHighlightedMatches(expectedSelections); expectSelection(expectedSelections[0]); expectMatchIndex(0, 1); }); it("should support case-insensitive regexp", function () { var expectedSelections = [ {start: {line: LINE_FIRST_REQUIRE, ch: 8}, end: {line: LINE_FIRST_REQUIRE, ch: 11}}, {start: {line: LINE_FIRST_REQUIRE, ch: 31}, end: {line: LINE_FIRST_REQUIRE, ch: 34}}, {start: {line: 6, ch: 17}, end: {line: 6, ch: 20}}, {start: {line: 8, ch: 8}, end: {line: 8, ch: 11}} ]; myEditor.setCursorPos(0, 0); twCommandManager.execute(Commands.CMD_FIND); toggleRegexp(true); toggleCaseSensitive(false); enterSearchText("f.o"); expectHighlightedMatches(expectedSelections); expectSelection(expectedSelections[0]); expectMatchIndex(0, 4); }); it("shouldn't choke on invalid regexp", function () { myEditor.setCursorPos(0, 0); twCommandManager.execute(Commands.CMD_FIND); toggleRegexp(true); enterSearchText("+"); expect(tw$(".modal-bar .error").length).toBe(1); expectHighlightedMatches([]); expect(myEditor).toHaveCursorPosition(0, 0); // no change }); it("shouldn't choke on empty regexp", function () { myEditor.setCursorPos(0, 0); twCommandManager.execute(Commands.CMD_FIND); toggleRegexp(true); enterSearchText(""); expectHighlightedMatches([]); expect(myEditor).toHaveCursorPosition(0, 0); // no change }); it("shouldn't freeze on /.*/ regexp", function () { myEditor.setCursorPos(0, 0); twCommandManager.execute(Commands.CMD_FIND); toggleRegexp(true); enterSearchText(".*"); expectSelection({start: {line: 0, ch: 0}, end: {line: 0, ch: 18}}); }); it("shouldn't freeze on /.*/ regexp", function () { myEditor.setCursorPos(0, 0); twCommandManager.execute(Commands.CMD_FIND); toggleRegexp(true); enterSearchText(".*"); expectSelection({start: {line: 0, ch: 0}, end: {line: 0, ch: 18}}); }); it("shouldn't freeze on regexp with 0-length matches", function () { myEditor.setCursorPos(0, 0); twCommandManager.execute(Commands.CMD_FIND); // CodeMirror coerces all 0-length matches to 1 char toggleRegexp(true); enterSearchText("^"); // matches pos before start of every line, but 0-length match text expectSelection({start: {line: 0, ch: 0}, end: {line: 0, ch: 1}}); enterSearchText("()"); // matches pos before every char, but 0-length match text expectSelection({start: {line: 0, ch: 0}, end: {line: 0, ch: 1}}); }); }); describe("Search -> Replace", function () { it("should find and replace one string", function () { runs(function () { twCommandManager.execute(Commands.CMD_REPLACE); enterSearchText("foo"); expectSelection(fooExpectedMatches[0]); expectMatchIndex(0, 4); expect(/foo/i.test(myEditor.getSelectedText())).toBe(true); expect(tw$("#replace-yes").is(":enabled")).toBe(true); enterReplaceText("bar"); tw$("#replace-yes").click(); expectSelection(fooExpectedMatches[1]); expectMatchIndex(0, 3); myEditor.setSelection(fooExpectedMatches[0].start, fooExpectedMatches[0].end); expect(/bar/i.test(myEditor.getSelectedText())).toBe(true); }); }); it("should find and skip then replace string", function () { runs(function () { twCommandManager.execute(Commands.CMD_REPLACE); enterSearchText("foo"); enterReplaceText("bar"); expectSelection(fooExpectedMatches[0]); expectMatchIndex(0, 4); expect(/foo/i.test(myEditor.getSelectedText())).toBe(true); // Skip first expect(tw$("#find-next").is(":enabled")).toBe(true); tw$("#find-next").click(); expectSelection(fooExpectedMatches[1]); expectMatchIndex(1, 4); expect(/foo/i.test(myEditor.getSelectedText())).toBe(true); // Replace second expect(tw$("#replace-yes").is(":enabled")).toBe(true); tw$("#replace-yes").click(); expectSelection(fooExpectedMatches[2]); expectMatchIndex(1, 3); myEditor.setSelection(fooExpectedMatches[0].start, fooExpectedMatches[0].end); expect(/foo/i.test(myEditor.getSelectedText())).toBe(true); myEditor.setSelection(fooExpectedMatches[1].start, fooExpectedMatches[1].end); expect(/bar/i.test(myEditor.getSelectedText())).toBe(true); }); }); it("should not replace string if document is read only", function () { runs(function () { myEditor._codeMirror.options.readOnly = true; twCommandManager.execute(Commands.CMD_REPLACE); enterSearchText("foo"); expectSelection(fooExpectedMatches[0]); expectMatchIndex(0, 4); expect(/foo/i.test(myEditor.getSelectedText())).toBe(true); expect(tw$("#replace-yes").is(":enabled")).toBe(true); enterReplaceText("bar"); tw$("#replace-yes").click(); expectSelection(fooExpectedMatches[0]); expectMatchIndex(0, 4); myEditor.setSelection(fooExpectedMatches[0].start, fooExpectedMatches[0].end); expect(/bar/i.test(myEditor.getSelectedText())).toBe(false); }); }); it("should use replace keyboard shortcut for single Replace while search bar open", function () { runs(function () { twCommandManager.execute(Commands.CMD_REPLACE); enterSearchText("foo"); expectSelection(fooExpectedMatches[0]); expectMatchIndex(0, 4); enterReplaceText("bar"); twCommandManager.execute(Commands.CMD_REPLACE); expectSelection(fooExpectedMatches[1]); expectMatchIndex(0, 3); myEditor.setSelection(fooExpectedMatches[0].start, fooExpectedMatches[0].end); expect(/bar/i.test(myEditor.getSelectedText())).toBe(true); }); }); it("should find and replace a regexp with $n substitutions", function () { runs(function () { twCommandManager.execute(Commands.CMD_REPLACE); toggleRegexp(true); enterSearchText("(modules)\\/(\\w+)"); enterReplaceText("$2:$1"); var expectedMatch = {start: {line: LINE_FIRST_REQUIRE, ch: 23}, end: {line: LINE_FIRST_REQUIRE, ch: 34}}; expectSelection(expectedMatch); expect(/foo/i.test(myEditor.getSelectedText())).toBe(true); expect(tw$("#replace-yes").is(":enabled")).toBe(true); tw$("#replace-yes").click(); myEditor.setSelection(expectedMatch.start, expectedMatch.end); expect(/Foo:modules/i.test(myEditor.getSelectedText())).toBe(true); }); }); it("should find a regexp and replace it with $0n (leading zero)", function () { runs(function () { twCommandManager.execute(Commands.CMD_REPLACE); toggleRegexp(true); enterSearchText("(modules)\\/(\\w+)"); enterReplaceText("$02:$01"); var expectedMatch = {start: {line: LINE_FIRST_REQUIRE, ch: 23}, end: {line: LINE_FIRST_REQUIRE, ch: 34}}; expectSelection(expectedMatch); expect(/foo/i.test(myEditor.getSelectedText())).toBe(true); expect(tw$("#replace-yes").is(":enabled")).toBe(true); tw$("#replace-yes").click(); myEditor.setSelection(expectedMatch.start, expectedMatch.end); expect(/Foo:modules/i.test(myEditor.getSelectedText())).toBe(true); }); }); it("should find a regexp and replace it with $0 (literal)", function () { runs(function () { twCommandManager.execute(Commands.CMD_REPLACE); toggleRegexp(true); enterSearchText("(modules)\\/(\\w+)"); enterReplaceText("$0_:$01"); var expectedMatch = {start: {line: LINE_FIRST_REQUIRE, ch: 23}, end: {line: LINE_FIRST_REQUIRE, ch: 34}}; expectSelection(expectedMatch); expect(/foo/i.test(myEditor.getSelectedText())).toBe(true); expect(tw$("#replace-yes").is(":enabled")).toBe(true); tw$("#replace-yes").click(); myEditor.setSelection(expectedMatch.start, expectedMatch.end); expect(/\$0_:modules/i.test(myEditor.getSelectedText())).toBe(true); }); }); it("should find a regexp and replace it with $n (empty subexpression)", function () { runs(function () { twCommandManager.execute(Commands.CMD_REPLACE); toggleRegexp(true); enterSearchText("(modules)(.*)\\/(\\w+)"); enterReplaceText("$3$2:$1"); var expectedMatch = {start: {line: LINE_FIRST_REQUIRE, ch: 23}, end: {line: LINE_FIRST_REQUIRE, ch: 34}}; expectSelection(expectedMatch); expect(/foo/i.test(myEditor.getSelectedText())).toBe(true); expect(tw$("#replace-yes").is(":enabled")).toBe(true); tw$("#replace-yes").click(); myEditor.setSelection(expectedMatch.start, expectedMatch.end); expect(/Foo:modules/i.test(myEditor.getSelectedText())).toBe(true); }); }); it("should find a regexp and replace it with $nn (n has two digits)", function () { runs(function () { twCommandManager.execute(Commands.CMD_REPLACE); toggleRegexp(true); enterSearchText("()()()()()()()()()()(modules)\\/()()()(\\w+)"); enterReplaceText("$15:$11"); var expectedMatch = {start: {line: LINE_FIRST_REQUIRE, ch: 23}, end: {line: LINE_FIRST_REQUIRE, ch: 34}}; expectSelection(expectedMatch); expect(/foo/i.test(myEditor.getSelectedText())).toBe(true); expect(tw$("#replace-yes").is(":enabled")).toBe(true); tw$("#replace-yes").click(); myEditor.setSelection(expectedMatch.start, expectedMatch.end); expect(/Foo:modules/i.test(myEditor.getSelectedText())).toBe(true); }); }); it("should find a regexp and replace it with $$n (not a subexpression, escaped dollar)", function () { runs(function () { twCommandManager.execute(Commands.CMD_REPLACE); toggleRegexp(true); enterSearchText("(modules)\\/(\\w+)"); enterReplaceText("$$2_$$10:$2"); var expectedMatch = {start: {line: LINE_FIRST_REQUIRE, ch: 23}, end: {line: LINE_FIRST_REQUIRE, ch: 34}}; expectSelection(expectedMatch); expect(/foo/i.test(myEditor.getSelectedText())).toBe(true); expect(tw$("#replace-yes").is(":enabled")).toBe(true); tw$("#replace-yes").click(); myEditor.setSelection(expectedMatch.start, expectedMatch.end); expect(/\$2_\$10:Foo/i.test(myEditor.getSelectedText())).toBe(true); }); }); it("should find a regexp and replace it with $$$n (correct subexpression)", function () { runs(function () { twCommandManager.execute(Commands.CMD_REPLACE); toggleRegexp(true); enterSearchText("(modules)\\/(\\w+)"); enterReplaceText("$2$$$1"); var expectedMatch = {start: {line: LINE_FIRST_REQUIRE, ch: 23}, end: {line: LINE_FIRST_REQUIRE, ch: 34}}; expectSelection(expectedMatch); expect(/foo/i.test(myEditor.getSelectedText())).toBe(true); expect(tw$("#replace-yes").is(":enabled")).toBe(true); tw$("#replace-yes").click(); myEditor.setSelection(expectedMatch.start, expectedMatch.end); expect(/Foo\$modules/i.test(myEditor.getSelectedText())).toBe(true); }); }); it("should find a regexp and replace it with $& (whole match)", function () { runs(function () { twCommandManager.execute(Commands.CMD_REPLACE); toggleRegexp(true); enterSearchText("(modules)\\/(\\w+)"); enterReplaceText("_$&-$2$$&"); var expectedMatch = {start: {line: LINE_FIRST_REQUIRE, ch: 23}, end: {line: LINE_FIRST_REQUIRE, ch: 34}}; expectSelection(expectedMatch); expect(/foo/i.test(myEditor.getSelectedText())).toBe(true); expect(tw$("#replace-yes").is(":enabled")).toBe(true); tw$("#replace-yes").click(); myEditor.setSelection({line: LINE_FIRST_REQUIRE, ch: 23}, {line: LINE_FIRST_REQUIRE, ch: 41}); expect(/_modules\/Foo-Foo\$&/i.test(myEditor.getSelectedText())).toBe(true); }); }); }); describe("Search -> Replace All in untitled document", function () { function expectTextAtPositions(text, posArray) { posArray.forEach(function (pos) { expect(myEditor.document.getRange(pos, {line: pos.line, ch: pos.ch + text.length})).toEqual(text); }); } function dontExpectTextAtPositions(text, posArray) { posArray.forEach(function (pos) { expect(myEditor.document.getRange(pos, {line: pos.line, ch: pos.ch + text.length})).not.toEqual(text); }); } beforeEach(function () { twFindInFiles._searchDone = false; twFindInFiles._replaceDone = false; }); it("should find and replace all using replace all button", function () { var searchText = "require", replaceText = "brackets.getModule"; runs(function () { twCommandManager.execute(Commands.CMD_REPLACE); enterSearchText(searchText); enterReplaceText(replaceText); expectSelection({start: {line: 1, ch: 17}, end: {line: 1, ch: 17 + searchText.length}}); expect(myEditor.getSelectedText()).toBe(searchText); expect(tw$("#replace-all").is(":enabled")).toBe(true); tw$("#replace-all").click(); }); waitsFor(function () { return twFindInFiles._replaceDone; }, "replace finished"); runs(function () { // Note: LINE_FIRST_REQUIRE and CH_REQUIRE_START refer to first call to "require", // but not first instance of "require" in text expectTextAtPositions(replaceText, [ {line: 1, ch: 17}, {line: LINE_FIRST_REQUIRE, ch: CH_REQUIRE_START}, {line: LINE_FIRST_REQUIRE + 1, ch: CH_REQUIRE_START}, {line: LINE_FIRST_REQUIRE + 2, ch: CH_REQUIRE_START} ]); }); }); it("should find and replace all using batch replace button", function () { var searchText = "require", replaceText = "brackets.getModule"; runs(function () { twCommandManager.execute(Commands.CMD_REPLACE); enterSearchText(searchText); enterReplaceText(replaceText); expectSelection({start: {line: 1, ch: 17}, end: {line: 1, ch: 17 + searchText.length}}); expect(myEditor.getSelectedText()).toBe(searchText); expect(tw$("#replace-batch").is(":enabled")).toBe(true); tw$("#replace-batch").click(); }); waitsFor(function () { return twFindInFiles._searchDone; }, "search finished"); runs(function () { tw$(".replace-checked").click(); }); waitsFor(function () { return twFindInFiles._replaceDone; }, "replace finished"); runs(function () { // Note: LINE_FIRST_REQUIRE and CH_REQUIRE_START refer to first call to "require", // but not first instance of "require" in text expectTextAtPositions(replaceText, [ {line: 1, ch: 17}, {line: LINE_FIRST_REQUIRE, ch: CH_REQUIRE_START}, {line: LINE_FIRST_REQUIRE + 1, ch: CH_REQUIRE_START}, {line: LINE_FIRST_REQUIRE + 2, ch: CH_REQUIRE_START} ]); }); }); it("should close panel if document modified", function () { var searchText = "require", replaceText = "brackets.getModule"; runs(function () { twCommandManager.execute(Commands.CMD_REPLACE); enterSearchText(searchText); enterReplaceText(replaceText); expectSelection({start: {line: 1, ch: 17}, end: {line: 1, ch: 17 + searchText.length}}); expect(myEditor.getSelectedText()).toBe(searchText); expect(tw$("#replace-batch").is(":enabled")).toBe(true); tw$("#replace-batch").click(); }); waitsFor(function () { return twFindInFiles._searchDone; }, "search finished"); runs(function () { expect(tw$("#find-in-files-results").is(":visible")).toBe(true); myEditor.document.replaceRange("", {line: 0, ch: 0}, {line: 1, ch: 0}); expect(tw$("#find-in-files-results").is(":visible")).toBe(false); }); }); it("should not replace unchecked items", function () { var searchText = "require", replaceText = "brackets.getModule"; runs(function () { twCommandManager.execute(Commands.CMD_REPLACE); enterSearchText(searchText); enterReplaceText(replaceText); expectSelection({start: {line: 1, ch: 17}, end: {line: 1, ch: 17 + searchText.length}}); expect(myEditor.getSelectedText()).toBe(searchText); expect(tw$("#replace-batch").is(":enabled")).toBe(true); tw$("#replace-batch").click(); }); waitsFor(function () { return twFindInFiles._searchDone; }, "search finished"); runs(function () { // verify that all items are checked by default var $checked = tw$(".check-one:checked"); expect($checked.length).toBe(4); // uncheck second and fourth $checked.eq(1).click(); $checked.eq(3).click(); expect(tw$(".check-one:checked").length).toBe(2); tw$(".replace-checked").click(); }); waitsFor(function () { return twFindInFiles._replaceDone; }, "replace finished"); runs(function () { myEditor.setSelection({line: 1, ch: 17}, {line: 1, ch: 17 + replaceText.length}); expect(myEditor.getSelectedText()).toBe(replaceText); expectTextAtPositions(replaceText, [ {line: 1, ch: 17}, {line: LINE_FIRST_REQUIRE + 1, ch: CH_REQUIRE_START} ]); dontExpectTextAtPositions(replaceText, [ {line: LINE_FIRST_REQUIRE, ch: CH_REQUIRE_START}, {line: LINE_FIRST_REQUIRE + 2, ch: CH_REQUIRE_START} ]); }); }); it("should find all regexps and replace them with $n", function () { var expectedMatch = {start: {line: LINE_FIRST_REQUIRE, ch: 23}, end: {line: LINE_FIRST_REQUIRE, ch: 34}}; runs(function () { twCommandManager.execute(Commands.CMD_REPLACE); toggleRegexp(true); enterSearchText("(modules)\\/(\\w+)"); enterReplaceText("$2:$1"); expectSelection(expectedMatch); expect(/foo/i.test(myEditor.getSelectedText())).toBe(true); expect(tw$("#replace-batch").is(":enabled")).toBe(true); tw$("#replace-batch").click(); }); waitsFor(function () { return twFindInFiles._searchDone; }, "search finished"); runs(function () { tw$(".replace-checked").click(); }); waitsFor(function () { return twFindInFiles._replaceDone; }, "replace finished"); runs(function () { myEditor.setSelection(expectedMatch.start, expectedMatch.end); expect(/Foo:modules/i.test(myEditor.getSelectedText())).toBe(true); myEditor.setSelection({line: LINE_FIRST_REQUIRE + 1, ch: 23}, {line: LINE_FIRST_REQUIRE + 1, ch: 34}); expect(/Bar:modules/i.test(myEditor.getSelectedText())).toBe(true); myEditor.setSelection({line: LINE_FIRST_REQUIRE + 2, ch: 23}, {line: LINE_FIRST_REQUIRE + 2, ch: 34}); expect(/Baz:modules/i.test(myEditor.getSelectedText())).toBe(true); }); }); it("should find all regexps and replace them with $n (empty subexpression)", function () { var expectedMatch = {start: {line: LINE_FIRST_REQUIRE, ch: 23}, end: {line: LINE_FIRST_REQUIRE, ch: 34}}; runs(function () { twCommandManager.execute(Commands.CMD_REPLACE); toggleRegexp(true); enterSearchText("(modules)(.*)\\/(\\w+)"); enterReplaceText("$3$2:$1"); expectSelection(expectedMatch); expect(/foo/i.test(myEditor.getSelectedText())).toBe(true); expect(tw$("#replace-batch").is(":enabled")).toBe(true); tw$("#replace-batch").click(); }); waitsFor(function () { return twFindInFiles._searchDone; }, "search finished"); runs(function () { tw$(".replace-checked").click(); }); waitsFor(function () { return twFindInFiles._replaceDone; }, "replace finished"); runs(function () { myEditor.setSelection(expectedMatch.start, expectedMatch.end); expect(/Foo:modules/i.test(myEditor.getSelectedText())).toBe(true); myEditor.setSelection({line: LINE_FIRST_REQUIRE + 1, ch: 23}, {line: LINE_FIRST_REQUIRE + 1, ch: 34}); expect(/Bar:modules/i.test(myEditor.getSelectedText())).toBe(true); myEditor.setSelection({line: LINE_FIRST_REQUIRE + 2, ch: 23}, {line: LINE_FIRST_REQUIRE + 2, ch: 34}); expect(/Baz:modules/i.test(myEditor.getSelectedText())).toBe(true); }); }); it("should find all regexps and replace them with $nn (n has two digits)", function () { var expectedMatch = {start: {line: LINE_FIRST_REQUIRE, ch: 23}, end: {line: LINE_FIRST_REQUIRE, ch: 34}}; runs(function () { twCommandManager.execute(Commands.CMD_REPLACE); toggleRegexp(true); enterSearchText("()()()()()()()()()()(modules)\\/()()()(\\w+)"); enterReplaceText("$15:$11"); expectSelection(expectedMatch); expect(/foo/i.test(myEditor.getSelectedText())).toBe(true); expect(tw$("#replace-batch").is(":enabled")).toBe(true); tw$("#replace-batch").click(); }); waitsFor(function () { return twFindInFiles._searchDone; }, "search finished"); runs(function () { tw$(".replace-checked").click(); }); waitsFor(function () { return twFindInFiles._replaceDone; }, "replace finished"); runs(function () { myEditor.setSelection(expectedMatch.start, expectedMatch.end); expect(/Foo:modules/i.test(myEditor.getSelectedText())).toBe(true); myEditor.setSelection({line: LINE_FIRST_REQUIRE + 1, ch: 23}, {line: LINE_FIRST_REQUIRE + 1, ch: 34}); expect(/Bar:modules/i.test(myEditor.getSelectedText())).toBe(true); myEditor.setSelection({line: LINE_FIRST_REQUIRE + 2, ch: 23}, {line: LINE_FIRST_REQUIRE + 2, ch: 34}); expect(/Baz:modules/i.test(myEditor.getSelectedText())).toBe(true); }); }); it("should find all regexps and replace them with $$n (not a subexpression, escaped dollar)", function () { var expectedMatch = {start: {line: LINE_FIRST_REQUIRE, ch: 23}, end: {line: LINE_FIRST_REQUIRE, ch: 34}}; runs(function () { twCommandManager.execute(Commands.CMD_REPLACE); toggleRegexp(true); enterSearchText("(modules)\\/(\\w+)"); enterReplaceText("$$2_$$10:$2"); expectSelection(expectedMatch); expect(/foo/i.test(myEditor.getSelectedText())).toBe(true); expect(tw$("#replace-batch").is(":enabled")).toBe(true); tw$("#replace-batch").click(); }); waitsFor(function () { return twFindInFiles._searchDone; }, "search finished"); runs(function () { tw$(".replace-checked").click(); }); waitsFor(function () { return twFindInFiles._replaceDone; }, "replace finished"); runs(function () { myEditor.setSelection(expectedMatch.start, expectedMatch.end); expect(/\$2_\$10:Foo/i.test(myEditor.getSelectedText())).toBe(true); myEditor.setSelection({line: LINE_FIRST_REQUIRE + 1, ch: 23}, {line: LINE_FIRST_REQUIRE + 1, ch: 34}); expect(/\$2_\$10:Bar/i.test(myEditor.getSelectedText())).toBe(true); myEditor.setSelection({line: LINE_FIRST_REQUIRE + 2, ch: 23}, {line: LINE_FIRST_REQUIRE + 2, ch: 34}); expect(/\$2_\$10:Baz/i.test(myEditor.getSelectedText())).toBe(true); }); }); it("should find all regexps and replace them with $$$n (correct subexpression)", function () { var expectedMatch = {start: {line: LINE_FIRST_REQUIRE, ch: 23}, end: {line: LINE_FIRST_REQUIRE, ch: 34}}; runs(function () { twCommandManager.execute(Commands.CMD_REPLACE); toggleRegexp(true); enterSearchText("(modules)\\/(\\w+)"); enterReplaceText("$2$$$1"); expectSelection(expectedMatch); expect(/foo/i.test(myEditor.getSelectedText())).toBe(true); expect(tw$("#replace-batch").is(":enabled")).toBe(true); tw$("#replace-batch").click(); }); waitsFor(function () { return twFindInFiles._searchDone; }, "search finished"); runs(function () { tw$(".replace-checked").click(); }); waitsFor(function () { return twFindInFiles._replaceDone; }, "replace finished"); runs(function () { myEditor.setSelection(expectedMatch.start, expectedMatch.end); expect(/Foo\$modules/i.test(myEditor.getSelectedText())).toBe(true); myEditor.setSelection({line: LINE_FIRST_REQUIRE + 1, ch: 23}, {line: LINE_FIRST_REQUIRE + 1, ch: 34}); expect(/Bar\$modules/i.test(myEditor.getSelectedText())).toBe(true); myEditor.setSelection({line: LINE_FIRST_REQUIRE + 2, ch: 23}, {line: LINE_FIRST_REQUIRE + 2, ch: 34}); expect(/Baz\$modules/i.test(myEditor.getSelectedText())).toBe(true); }); }); it("should find all regexps and replace them with $& (whole match)", function () { var expectedMatch = {start: {line: LINE_FIRST_REQUIRE, ch: 23}, end: {line: LINE_FIRST_REQUIRE, ch: 34}}; runs(function () { twCommandManager.execute(Commands.CMD_REPLACE); toggleRegexp(true); enterSearchText("(modules)\\/(\\w+)"); enterReplaceText("_$&-$2$$&"); expectSelection(expectedMatch); expect(/foo/i.test(myEditor.getSelectedText())).toBe(true); expect(tw$("#replace-batch").is(":enabled")).toBe(true); tw$("#replace-batch").click(); }); waitsFor(function () { return twFindInFiles._searchDone; }, "search finished"); runs(function () { tw$(".replace-checked").click(); }); waitsFor(function () { return twFindInFiles._replaceDone; }, "replace finished"); runs(function () { myEditor.setSelection({line: LINE_FIRST_REQUIRE, ch: 23}, {line: LINE_FIRST_REQUIRE, ch: 41}); expect(/_modules\/Foo-Foo\$&/i.test(myEditor.getSelectedText())).toBe(true); myEditor.setSelection({line: LINE_FIRST_REQUIRE + 1, ch: 23}, {line: LINE_FIRST_REQUIRE + 1, ch: 41}); expect(/_modules\/Bar-Bar\$&/i.test(myEditor.getSelectedText())).toBe(true); myEditor.setSelection({line: LINE_FIRST_REQUIRE + 2, ch: 23}, {line: LINE_FIRST_REQUIRE + 2, ch: 41}); expect(/_modules\/Baz-Baz\$&/i.test(myEditor.getSelectedText())).toBe(true); }); }); }); }); });