// Copyright 2012 Google Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package com.google.collide.client.editor.search; import static com.google.collide.client.editor.search.SearchTestsUtil.createDocument; import static com.google.collide.client.editor.search.SearchTestsUtil.createMockViewport; import static org.easymock.EasyMock.expect; import static org.easymock.EasyMock.replay; import com.google.collide.client.editor.Buffer; import com.google.collide.client.editor.Buffer.MouseDragListener; import com.google.collide.client.editor.search.SearchModel.MatchCountListener; import com.google.collide.client.editor.selection.SelectionModel; import com.google.collide.client.testing.StubIncrementalScheduler; import com.google.collide.shared.document.Document; import com.google.collide.shared.document.LineInfo; import com.google.collide.shared.document.Position; import com.google.collide.shared.util.ListenerManager; import com.google.gwt.regexp.shared.RegExp; import junit.framework.TestCase; import org.easymock.EasyMock; public class SearchMatchManagerTests extends TestCase { private Document document; private SelectionModel model; @Override public void setUp() { document = createDocument(); createSelectionModel(document); } private void createSelectionModel(Document document) { Buffer buffer = EasyMock.createNiceMock(Buffer.class); ListenerManager<MouseDragListener> listener = ListenerManager.create(); expect(buffer.getMouseDragListenerRegistrar()).andReturn(listener).anyTimes(); replay(buffer); model = SelectionModel.create(document, buffer); model.setSelection(document.getFirstLineInfo(), 0, document.getFirstLineInfo(), 0); } public void testTotalMatchesChangedListener() { SearchMatchManager manager = createMatchManager(document, model); manager.setSearchPattern(RegExp.compile("doug")); MatchCountListener callback = EasyMock.createMock(MatchCountListener.class); callback.onMatchCountChanged(10); callback.onMatchCountChanged(15); callback.onMatchCountChanged(0); replay(callback); manager.getMatchCountChangedListenerRegistrar().add(callback); LineInfo line = document.getFirstLineInfo(); manager.addMatches(line, 10); manager.addMatches(line, 5); manager.clearMatches(); } public void testAddGetAndClearMatches() { SearchMatchManager manager = createMatchManager(document, model); manager.setSearchPattern(RegExp.compile("testing")); LineInfo line = document.getFirstLineInfo(); manager.addMatches(line, 5); line.moveToNext(); manager.addMatches(line, 5); line.moveToNext(); manager.addMatches(line, 5); line.moveToNext(); manager.addMatches(line, 5); assertEquals(20, manager.getTotalMatches()); manager.clearMatches(); assertEquals(0, manager.getTotalMatches()); manager.addMatches(line, 10); manager.addMatches(line, 10); assertEquals(20, manager.getTotalMatches()); } public void testSelectMatchOnAddMatches() { SearchMatchManager manager = createMatchManager(document, model); manager.setSearchPattern(RegExp.compile("do")); // Should end up only selecting the first match in line 0 LineInfo line = document.getFirstLineInfo(); manager.addMatches(line, 3); assertSelection(document.getFirstLineInfo(), 5, 7); line.moveToNext(); manager.addMatches(line, 2); assertSelection(document.getFirstLineInfo(), 5, 7); } public void testFindNextMatchOnLine() { LineInfo lineEight = SearchTestsUtil.gotoLineInfo(document, 8); SearchMatchManager manager = createMatchManager(document, model); manager.setSearchPattern(RegExp.compile("doug", "gi")); // Select the first match then move forward two manager.addMatches(lineEight, 7); manager.selectNextMatch(); assertSelection(lineEight, 5, 9); manager.selectNextMatch(); assertSelection(lineEight, 13, 17); } public void testFindPreviousMatchOnLine() { LineInfo lineEight = SearchTestsUtil.gotoLineInfo(document, 8); SearchMatchManager manager = createMatchManager(document, model); manager.setSearchPattern(RegExp.compile("doug", "gi")); // Select the first match then move forward two manager.addMatches(lineEight, 7); manager.selectNextMatch(); manager.selectNextMatch(); // Go back a few matches manager.selectPreviousMatch(); assertSelection(lineEight, 5, 9); manager.selectPreviousMatch(); assertSelection(lineEight, 0, 4); } public void testFindPreviousMatchOnPreviousLine() { LineInfo lineSix = SearchTestsUtil.gotoLineInfo(document, 6); LineInfo lineEight = SearchTestsUtil.gotoLineInfo(document, 8); SearchMatchManager manager = createMatchManager(document, model); manager.setSearchPattern(RegExp.compile("doug", "gi")); manager.addMatches(lineEight, 7); manager.addMatches(lineSix, 1); // we should be on the very first match, go back and find the prev match manager.selectPreviousMatch(); assertSelection(lineSix, 41, 45); manager.selectPreviousMatch(); assertSelection(lineEight, 35, 39); } public void testFindNextMatchOnNextLine() { LineInfo lineSix = SearchTestsUtil.gotoLineInfo(document, 6); LineInfo lineEight = SearchTestsUtil.gotoLineInfo(document, 8); SearchMatchManager manager = createMatchManager(document, model); manager.setSearchPattern(RegExp.compile("doug", "gi")); manager.addMatches(lineSix, 1); manager.addMatches(lineEight, 7); // There is one match on line six so this will move us to line eight manager.selectNextMatch(); assertSelection(lineEight, 0, 4); // Now let's iterate through matches and wrap around for (int i = 0; i < 6; i++) { manager.selectNextMatch(); } manager.selectNextMatch(); assertSelection(lineSix, 41, 45); } public void testFindMatchAfterAndBeforePosition() { LineInfo lineSix = SearchTestsUtil.gotoLineInfo(document, 6); LineInfo lineEight = SearchTestsUtil.gotoLineInfo(document, 8); SearchMatchManager manager = createMatchManager(document, model); manager.setSearchPattern(RegExp.compile("doug", "gi")); manager.addMatches(lineSix, 1); manager.addMatches(lineEight, 7); manager.selectNextMatchFromPosition(lineEight, 20); assertSelection(lineEight, 23, 27); manager.selectPreviousMatchFromPosition(lineEight, 10); assertSelection(lineEight, 5, 9); } public void testWrapFindNextWhenMatchesOnSameLine() { LineInfo lineEleven = SearchTestsUtil.gotoLineInfo(document, 11); SearchMatchManager manager = createMatchManager(document, model); manager.setSearchPattern(RegExp.compile("Awesome", "gi")); manager.addMatches(lineEleven, 1); assertSelection(lineEleven, 0, 7); manager.selectNextMatch(); assertSelection(lineEleven, 8, 15); manager.selectNextMatch(); assertSelection(lineEleven, 0, 7); } public void testWrapFindPreviousWhenMatchesOnSameLine() { LineInfo lineEleven = SearchTestsUtil.gotoLineInfo(document, 11); SearchMatchManager manager = createMatchManager(document, model); manager.setSearchPattern(RegExp.compile("Awesome", "gi")); manager.addMatches(lineEleven, 1); assertSelection(lineEleven, 0, 7); manager.selectPreviousMatch(); assertSelection(lineEleven, 8, 15); } public void testReplaceMatch() { LineInfo lineThree = SearchTestsUtil.gotoLineInfo(document, 3); LineInfo lineSix = SearchTestsUtil.gotoLineInfo(document, 6); LineInfo lineEight = SearchTestsUtil.gotoLineInfo(document, 8); SearchMatchManager manager = createMatchManager(document, model); manager.setSearchPattern(RegExp.compile("doug", "gi")); // NOTE! Since this a not an editor mutator, selection won't be replaced // so you will get newtextoldtext when calling replace. manager.addMatches(lineSix, 1); assertTrue(manager.replaceMatch("boug")); assertEquals("boug", document.getText(lineSix.line(), 41, 4)); document.deleteText(lineSix.line(), 45, 4); assertTrue(manager.replaceMatch("soug")); assertEquals("soug", document.getText(lineEight.line(), 0, 4)); model.setSelection(lineThree, 0, lineThree, 0); manager.setSearchPattern(RegExp.compile("catwoman")); manager.addMatches(lineThree, 1); assertTrue(manager.replaceMatch("dogwoman")); assertEquals("dogwoman", document.getText(lineThree.line(), 22, 8)); } public void testReplaceAll() { SearchTask task = new SearchTask( document, createMockViewport(document, 3), new StubIncrementalScheduler(50, 50)); SearchMatchManager manager = new SearchMatchManager(document, model, document, task); manager.setSearchPattern(RegExp.compile("doug", "gi")); LineInfo lineSix = SearchTestsUtil.gotoLineInfo(document, 6); manager.addMatches(lineSix, 1); manager.replaceAllMatches("boug"); assertNull(manager.selectNextMatch()); } public void testReplaceAllOnlyOneMatch() { document = Document.createFromString("foo"); createSelectionModel(document); SearchTask task = new SearchTask(document, createMockViewport(document, 1), new StubIncrementalScheduler( 50, 50)); SearchMatchManager manager = new SearchMatchManager(document, model, document, task); manager.setSearchPattern(RegExp.compile("foo", "gi")); LineInfo lineOne = document.getFirstLineInfo(); manager.addMatches(lineOne, 1); manager.replaceAllMatches("notit"); assertNull(manager.selectNextMatch()); } public void testReplaceRecursive() { document = Document.createFromString("foo"); createSelectionModel(document); SearchTask task = new SearchTask(document, createMockViewport(document, 1), new StubIncrementalScheduler( 50, 50)); SearchMatchManager manager = new SearchMatchManager(document, model, document, task); manager.setSearchPattern(RegExp.compile("foo", "gi")); LineInfo lineOne = document.getFirstLineInfo(); manager.addMatches(lineOne, 1); manager.replaceAllMatches("foofoo"); assertNotNull(manager.selectNextMatch()); } void assertSelection(LineInfo line, int start, int end) { Position[] selection = model.getSelectionRange(false); assertEquals(line, selection[0].getLineInfo()); assertEquals(line, selection[1].getLineInfo()); assertEquals(start, selection[0].getColumn()); assertEquals(end, selection[1].getColumn()); } /** * Covers the 99% case when creating, only replaceAll relies on searchTask. */ static SearchMatchManager createMatchManager(Document document, SelectionModel selection) { return new SearchMatchManager( document, selection, document, EasyMock.createNiceMock(SearchTask.class)); } }