/**
* Copyright 2009 Google Inc.
*
* 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 org.waveprotocol.wave.client.editor.keys;
import com.google.gwt.dom.client.Document;
import com.google.gwt.dom.client.Element;
import com.google.gwt.junit.client.GWTTestCase;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.ui.Panel;
import org.waveprotocol.wave.client.common.util.KeyCombo;
import org.waveprotocol.wave.client.editor.Editor;
import org.waveprotocol.wave.client.editor.EditorAction;
import org.waveprotocol.wave.client.editor.EditorContext;
import org.waveprotocol.wave.client.editor.EditorImpl;
import org.waveprotocol.wave.client.editor.EditorSettings;
import org.waveprotocol.wave.client.editor.EditorStaticDeps;
import org.waveprotocol.wave.client.editor.EditorTestingUtil;
import org.waveprotocol.wave.client.editor.Editors;
import org.waveprotocol.wave.client.editor.content.Registries;
import org.waveprotocol.wave.client.editor.testing.ContentSerialisationUtil;
import org.waveprotocol.wave.client.widget.popup.PopupChrome;
import org.waveprotocol.wave.client.widget.popup.PopupProvider;
import org.waveprotocol.wave.client.widget.popup.RelativePopupPositioner;
import org.waveprotocol.wave.client.widget.popup.UniversalPopup;
import org.waveprotocol.wave.client.widget.popup.simple.Popup;
/**
* Integration tests to make sure the key bindings passed into an editor are called properly
* when key events are passed in from outside the editor.
*
* @author patcoleman@google.com (Pat Coleman)
*/
public class KeyBindingRegistryIntegrationGwtTest extends GWTTestCase {
private static final int G_CODE = 'g';
private int callTracker;
@Override
public String getModuleName() {
return "org.waveprotocol.wave.client.editor.keys.Tests";
}
@Override
protected void gwtSetUp() throws Exception {
EditorTestingUtil.setupTestEnvironment();
}
/**
* Ensure that an action bound to ORDER_G is executed when the appropriate JS keypress
* event is fired at the editor.
*/
public void testKeyBinding() {
KeyBindingRegistry bindings = new KeyBindingRegistry();
callTracker = 0;
EditorAction testAction = new EditorAction() {
public void execute(EditorContext context) {
callTracker++;
}
};
bindings.registerAction(KeyCombo.ORDER_G, testAction);
EditorImpl editor = createEditor(bindings);
// 103 = g, this event = CTRL_G which is bound to ORDER_G by the EventWrapper
Event rawEvent = Document.get().createKeyPressEvent(
true, false, false, false, G_CODE, G_CODE).cast();
editor.onJavaScriptEvent("keypress", rawEvent);
assertEquals("Callback action not called on registered keypress", callTracker, 1);
}
/** Ensure that when other keys are pressed, they are not passed to the action. */
public void testAlternativeKeyPress() {
KeyBindingRegistry bindings = new KeyBindingRegistry();
callTracker = 0;
EditorAction testAction = new EditorAction() {
public void execute(EditorContext context) {
callTracker++;
}
};
bindings.registerAction(KeyCombo.ORDER_G, testAction);
EditorImpl editor = createEditor(bindings);
// This event is not ORDER_G, it has other accelerators thrown in.
Event rawEvent = Document.get().createKeyPressEvent(
true, true, true, false, G_CODE, G_CODE).cast();
editor.onJavaScriptEvent("keypress", rawEvent);
assertEquals("Callback action called on unregistered keypress", callTracker, 0);
}
/**
* Ensure that new keybindings are used after changing them in the editor.
*/
public void testReregistrationKeyBinding() {
KeyBindingRegistry bindings = new KeyBindingRegistry();
callTracker = 0;
EditorAction testAction = new EditorAction() {
public void execute(EditorContext context) {
callTracker++;
}
};
bindings.registerAction(KeyCombo.ORDER_G, testAction);
EditorImpl editor = createEditor(bindings);
Event rawEvent = Document.get().createKeyPressEvent(
true, false, false, false, G_CODE, G_CODE).cast();
editor.onJavaScriptEvent("keypress", rawEvent);
// callTracker should be 1 assuming the test above passes
bindings.removeAction(KeyCombo.ORDER_G);
initEditor(editor, Editor.ROOT_REGISTRIES, bindings);
editor.onJavaScriptEvent("keypress", rawEvent);
assertEquals("Callback action called on deregistered keypress", callTracker, 1);
}
/** Util to help construct an editor instance. */
private EditorImpl createEditor(KeyBindingRegistry keyBinding) {
EditorStaticDeps.setPopupProvider(new PopupProvider() {
@Override
public UniversalPopup createPopup(Element reference, RelativePopupPositioner positioner,
PopupChrome chrome, boolean autoHide) {
return new Popup(reference, positioner);
}
@Override
public void setRootPanel(Panel rootPanel) {
// Not used as we use our own popup implementation.
}
});
Editor editor = Editors.create();
initEditor(editor, Editor.ROOT_REGISTRIES, keyBinding);
return (EditorImpl) editor;
}
/** Util to help set the editor up with content and selection. */
private void initEditor(Editor editor,
Registries registries, KeyBindingRegistry keys) {
editor.init(registries, keys, EditorSettings.DEFAULT);
editor.setEditing(true);
ContentSerialisationUtil.setContentString(editor, "<body><line></line>X</body>");
editor.getSelectionHelper().setCaret(editor.getDocument().locate(3));
}
}