// 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.code.autocomplete;
import static com.google.collide.client.code.autocomplete.TestUtils.createDocumentParser;
import com.google.collide.client.code.autocomplete.AutocompleteProposals.ProposalWithContext;
import com.google.collide.client.code.autocomplete.AutocompleteResult.PopupAction;
import com.google.collide.client.code.autocomplete.MockAutocompleterEnvironment.MockAutocompleter;
import com.google.collide.client.code.autocomplete.codegraph.CodeGraphAutocompleter;
import com.google.collide.client.code.autocomplete.css.CssAutocompleter;
import com.google.collide.client.code.autocomplete.html.HtmlAutocompleter;
import com.google.collide.client.editor.Editor;
import com.google.collide.client.editor.selection.SelectionModel;
import com.google.collide.client.testutil.SynchronousTestCase;
import com.google.collide.client.util.PathUtil;
import com.google.collide.codemirror2.SyntaxType;
import com.google.collide.json.shared.JsonArray;
import com.google.collide.shared.document.LineInfo;
import com.google.collide.shared.util.JsonCollections;
/**
* Test for some aspects of autocompletion life cycle.
*
*/
public class AutocompleterTest extends SynchronousTestCase {
private static class StubAutocompleter extends NoneAutocompleter {
public StubAutocompleter() {
super(SyntaxType.HTML);
}
@Override
public AutocompleteProposals findAutocompletions(SelectionModel selection,
SignalEventEssence trigger) {
return new AutocompleteProposals(SyntaxType.NONE, "",
JsonCollections.createArray(new AutocompleteProposal("ab")));
}
@Override
public AutocompleteResult computeAutocompletionResult(
ProposalWithContext proposal) {
return new DefaultAutocompleteResult("ab", 2, 0, 0, 0, PopupAction.CLOSE, "a");
}
}
private MockAutocompleterEnvironment helper;
private PathUtil path;
@Override
public String getModuleName() {
return
"com.google.collide.client.TestCode";
}
@Override
public void gwtSetUp() throws Exception {
super.gwtSetUp();
helper = new MockAutocompleterEnvironment();
path = new PathUtil("/test.none");
}
private static void changeAutocompleterPath(Autocompleter autocompleter, PathUtil path) {
autocompleter.reset(path, createDocumentParser(path));
}
public void testAutocompleteControllerLifecycleImplicitOnDocEvent() {
helper.specificAutocompleter = new StubAutocompleter();
Autocompleter autocompleter = helper.setup(path, "<a", 0, 2, false);
assertNotNull(autocompleter.getController());
autocompleter.requestAutocomplete(autocompleter.getController(), null);
assertNotNull(autocompleter.getController());
autocompleter.dismissAutocompleteBox();
assertNotNull(autocompleter.getController());
}
public void testDismissAutocompleteBox() {
helper.specificAutocompleter = new StubAutocompleter();
MockAutocompleter autocompleter = helper.setup(path, "a", 0, 1, false);
autocompleter.requestAutocomplete(autocompleter.getController(), null);
assertTrue("expected: popup appeared", helper.popup.isShowing());
autocompleter.dismissAutocompleteBox();
assertFalse("expected: popup disappeared", helper.popup.isShowing());
}
public void testDoAutocomplete() {
helper.specificAutocompleter = new StubAutocompleter();
MockAutocompleter autocompleter = helper.setup(path, "a", 0, 1, false);
autocompleter.requestAutocomplete(autocompleter.getController(), null);
assertTrue("expected: popup appeared", helper.popup.isShowing());
assertEquals("expected: 1 proposal found", 1, helper.popup.proposals.size());
}
public void testEditorContentsReplaced() {
Autocompleter autocompleter = helper.setup(path, "", 0, 0, false);
changeAutocompleterPath(autocompleter, new PathUtil("/test.html"));
assertEquals(SyntaxType.HTML, autocompleter.getMode());
changeAutocompleterPath(autocompleter, new PathUtil("/test.js"));
assertEquals(SyntaxType.JS, autocompleter.getMode());
changeAutocompleterPath(autocompleter, new PathUtil("/test.py"));
assertEquals(SyntaxType.PY, autocompleter.getMode());
changeAutocompleterPath(autocompleter, new PathUtil("/test.css"));
assertEquals(SyntaxType.CSS, autocompleter.getMode());
changeAutocompleterPath(autocompleter, new PathUtil("/test.foo"));
assertEquals(SyntaxType.NONE, autocompleter.getMode());
changeAutocompleterPath(autocompleter, new PathUtil(""));
assertEquals(SyntaxType.NONE, autocompleter.getMode());
}
public void testFinishAutocompletion() {
helper.specificAutocompleter = new StubAutocompleter();
MockAutocompleter autocompleter = helper.setup(path, "a", 0, 1, false);
AutocompleteController controller = autocompleter.getController();
assertNotNull(controller);
autocompleter.requestAutocomplete(controller, null);
autocompleter.reallyFinishAutocompletion(helper.popup.proposals.select(0));
assertEquals("ab", helper.editor.getDocument().asText());
// check that the caret is in the right place
assertEquals(2, helper.editor.getSelection().getCursorColumn());
assertNotNull(autocompleter.getController());
}
public void testProposalsUpdate() {
helper.specificAutocompleter = new StubAutocompleter();
Autocompleter autocompleter = helper.setup(path, "a", 0, 1, false);
AutocompleteController controller = autocompleter.getController();
autocompleter.requestAutocomplete(controller, null);
// Requesting completions again
controller.start(helper.editor.getSelection(), null);
assertEquals(1, helper.popup.proposals.size());
}
public void testProposalsSorting() {
JsonArray<AutocompleteProposal> unsortedCompletions = JsonCollections.createArray();
unsortedCompletions.add(new AutocompleteProposal("ur"));
unsortedCompletions.add(new AutocompleteProposal("go"));
unsortedCompletions.add(new AutocompleteProposal("Gb"));
unsortedCompletions.add(new AutocompleteProposal("ga"));
unsortedCompletions.add(new AutocompleteProposal("ab"));
unsortedCompletions.add(new AutocompleteProposal("gA"));
unsortedCompletions.add(new AutocompleteProposal("go"));
AutocompleteProposals proposals =
new AutocompleteProposals(SyntaxType.NONE, "", unsortedCompletions);
assertEquals("input/output size", unsortedCompletions.size(), proposals.size());
String previous = proposals.get(0).getLabel();
for (int i = 1, l = proposals.size(); i < l; i++) {
String current = proposals.get(i).getLabel();
assertTrue("order", current.compareToIgnoreCase(previous) >= 0);
previous = current;
}
}
public void testAutocompletionMode() {
Autocompleter autocompleter = helper.setup(path, "", 0, 0, false);
SyntaxType mode = SyntaxType.NONE;
assertTrue(autocompleter.getAutocompleter(mode) instanceof NoneAutocompleter);
mode = SyntaxType.YAML;
assertTrue(autocompleter.getAutocompleter(mode) instanceof NoneAutocompleter);
mode = SyntaxType.SVG;
assertTrue(autocompleter.getAutocompleter(mode) instanceof NoneAutocompleter);
mode = SyntaxType.XML;
assertTrue(autocompleter.getAutocompleter(mode) instanceof NoneAutocompleter);
mode = SyntaxType.CSS;
assertTrue(autocompleter.getAutocompleter(mode) instanceof CssAutocompleter);
mode = SyntaxType.HTML;
assertTrue(autocompleter.getAutocompleter(mode) instanceof HtmlAutocompleter);
mode = SyntaxType.JS;
LanguageSpecificAutocompleter jsAutocompleter = autocompleter.getAutocompleter(mode);
assertTrue(jsAutocompleter instanceof CodeGraphAutocompleter);
assertEquals(mode, jsAutocompleter.getMode());
}
public void testAutocompletionDoNotBreakAppOnSelectedText() {
helper.specificAutocompleter = new LanguageSpecificAutocompleter(SyntaxType.HTML) {
@Override
public AutocompleteResult computeAutocompletionResult(ProposalWithContext proposal) {
return new DefaultAutocompleteResult("[]", 1, 0, 0, 0, PopupAction.CLOSE, "");
}
@Override
public AutocompleteProposals findAutocompletions(
SelectionModel selection, SignalEventEssence trigger) {
return AutocompleteProposals.EMPTY;
}
@Override
public void cleanup() {}
};
// Forward selection
Autocompleter autocompleter = helper.setup(path, "go (veryLongSelection).q!", 0, 0, false);
Editor editor = helper.editor;
LineInfo lineInfo = editor.getDocument().getLineFinder().findLine(0);
editor.getSelection().setSelection(lineInfo, 4, lineInfo, 21);
ProposalWithContext proposal = new ProposalWithContext(SyntaxType.NONE,
new AutocompleteProposal(""), new AutocompleteProposals.Context(""));
autocompleter.reallyFinishAutocompletion(proposal);
assertEquals("go ([]).q!", editor.getDocument().getFirstLine().getText());
assertFalse(editor.getSelection().hasSelection());
assertEquals(5, editor.getSelection().getCursorPosition().getColumn());
// Reverse selection
autocompleter = helper.setup(path, "go (veryLongSelection).q!", 0, 0, false);
editor = helper.editor;
lineInfo = editor.getDocument().getLineFinder().findLine(0);
editor.getSelection().setSelection(lineInfo, 21, lineInfo, 4);
autocompleter.reallyFinishAutocompletion(proposal);
assertEquals("go ([]).q!", editor.getDocument().getFirstLine().getText());
assertFalse(editor.getSelection().hasSelection());
assertEquals(5, editor.getSelection().getCursorPosition().getColumn());
}
}