diff options
Diffstat (limited to 'browser/devtools/sourceeditor/test/browser_sourceeditor_initialization.js')
-rw-r--r-- | browser/devtools/sourceeditor/test/browser_sourceeditor_initialization.js | 499 |
1 files changed, 499 insertions, 0 deletions
diff --git a/browser/devtools/sourceeditor/test/browser_sourceeditor_initialization.js b/browser/devtools/sourceeditor/test/browser_sourceeditor_initialization.js new file mode 100644 index 000000000..c605f9860 --- /dev/null +++ b/browser/devtools/sourceeditor/test/browser_sourceeditor_initialization.js @@ -0,0 +1,499 @@ +/* vim: set ts=2 et sw=2 tw=80: */ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +let tempScope = {}; +Cu.import("resource:///modules/source-editor.jsm", tempScope); +let SourceEditor = tempScope.SourceEditor; + +let testWin; +let testDoc; +let editor; + +function test() +{ + waitForExplicitFinish(); + + const windowUrl = "data:text/xml,<?xml version='1.0'?>" + + "<window xmlns='http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul'" + + " title='test for bug 660784' width='600' height='500'><hbox flex='1'/></window>"; + const windowFeatures = "chrome,titlebar,toolbar,centerscreen,resizable,dialog=no"; + + testWin = Services.ww.openWindow(null, windowUrl, "_blank", windowFeatures, null); + testWin.addEventListener("load", function onWindowLoad() { + testWin.removeEventListener("load", onWindowLoad, false); + waitForFocus(initEditor, testWin); + }, false); +} + +function initEditor() +{ + testDoc = testWin.document; + + let hbox = testDoc.querySelector("hbox"); + + editor = new SourceEditor(); + let config = { + showLineNumbers: true, + initialText: "foobarbaz", + tabSize: 7, + expandTab: true, + }; + + editor.init(hbox, config, editorLoaded); +} + +function editorLoaded() +{ + ok(editor.editorElement, "editor loaded"); + + is(editor.parentElement, testDoc.querySelector("hbox"), + "parentElement is correct"); + + editor.focus(); + + is(editor.getMode(), SourceEditor.DEFAULTS.mode, "default editor mode"); + + // Test general editing methods. + + ok(!editor.canUndo(), "canUndo() works (nothing to undo), just loaded"); + + ok(!editor.readOnly, "editor is not read-only"); + + is(editor.getText(), "foobarbaz", "placeholderText works"); + + is(editor.getText().length, editor.getCharCount(), + "getCharCount() is correct"); + + is(editor.getText(3, 5), "ba", "getText() range works"); + + editor.setText("source-editor"); + + is(editor.getText(), "source-editor", "setText() works"); + + editor.setText("code", 0, 6); + + is(editor.getText(), "code-editor", "setText() range works"); + + ok(editor.canUndo(), "canUndo() works (things to undo)"); + ok(!editor.canRedo(), "canRedo() works (nothing to redo yet)"); + + editor.undo(); + + is(editor.getText(), "source-editor", "undo() works"); + + ok(editor.canRedo(), "canRedo() works (things to redo)"); + + editor.redo(); + + is(editor.getText(), "code-editor", "redo() works"); + + EventUtils.synthesizeKey("VK_Z", {accelKey: true}, testWin); + + is(editor.getText(), "source-editor", "Ctrl-Z (undo) works"); + + EventUtils.synthesizeKey("VK_Z", {accelKey: true, shiftKey: true}, testWin); + + is(editor.getText(), "code-editor", "Ctrl-Shift-Z (redo) works"); + + editor.undo(); + + EventUtils.synthesizeKey("VK_Y", {accelKey: true}, testWin); + if (Services.appinfo.OS == "WINNT" || + Services.appinfo.OS == "Linux") { + is(editor.getText(), "code-editor", + "CTRL+Y does redo on Linux and Windows"); + } else { + is(editor.getText(), "source-editor", + "CTRL+Y doesn't redo on machines other than Linux and Windows"); + editor.setText("code-editor"); + } + + // Test selection methods. + + editor.setSelection(0, 4); + + is(editor.getSelectedText(), "code", "getSelectedText() works"); + + let selection = editor.getSelection(); + ok(selection.start == 0 && selection.end == 4, "getSelection() works"); + + editor.dropSelection(); + + selection = editor.getSelection(); + ok(selection.start == 4 && selection.end == 4, "dropSelection() works"); + + editor.setCaretOffset(7); + is(editor.getCaretOffset(), 7, "setCaretOffset() works"); + + // Test grouped changes. + + editor.setText("foobar"); + + editor.startCompoundChange(); + + editor.setText("foo1"); + editor.setText("foo2"); + editor.setText("foo3"); + + editor.endCompoundChange(); + + is(editor.getText(), "foo3", "editor content is correct"); + + editor.undo(); + is(editor.getText(), "foobar", "compound change undo() works"); + + editor.redo(); + is(editor.getText(), "foo3", "compound change redo() works"); + + // Minimal keyboard usage tests. + + ok(editor.hasFocus(), "editor has focus"); + + editor.setText("code-editor"); + editor.setCaretOffset(7); + EventUtils.synthesizeKey(".", {}, testWin); + + is(editor.getText(), "code-ed.itor", "focus() and typing works"); + + EventUtils.synthesizeKey("a", {}, testWin); + + is(editor.getText(), "code-ed.aitor", "typing works"); + + is(editor.getCaretOffset(), 9, "caret moved"); + + EventUtils.synthesizeKey("VK_LEFT", {}, testWin); + + is(editor.getCaretOffset(), 8, "caret moved to the left"); + + EventUtils.synthesizeKey(".", {}, testWin); + EventUtils.synthesizeKey("VK_TAB", {}, testWin); + + is(editor.getText(), "code-ed.. aitor", "Tab works"); + + is(editor.getCaretOffset(), 14, "caret location is correct"); + + // Test the Tab key. + + editor.setText("a\n b\n c"); + editor.setCaretOffset(0); + + EventUtils.synthesizeKey("VK_TAB", {}, testWin); + is(editor.getText(), " a\n b\n c", "Tab works"); + + // Code editor specific tests. These are not applicable when the textarea + // fallback is used. + let component = Services.prefs.getCharPref(SourceEditor.PREFS.COMPONENT); + if (component != "textarea") { + editor.setMode(SourceEditor.MODES.JAVASCRIPT); + is(editor.getMode(), SourceEditor.MODES.JAVASCRIPT, "setMode() works"); + + editor.setSelection(0, editor.getCharCount() - 1); + EventUtils.synthesizeKey("VK_TAB", {}, testWin); + is(editor.getText(), " a\n b\n c", "lines indented"); + + EventUtils.synthesizeKey("VK_TAB", {shiftKey: true}, testWin); + is(editor.getText(), " a\n b\n c", "lines outdented (shift-tab)"); + + testEclipseBug362107(); + testBug687577(); + testBackspaceKey(); + testReturnKey(); + } + + // Test the read-only mode. + + editor.setText("foofoo"); + + editor.readOnly = true; + EventUtils.synthesizeKey("b", {}, testWin); + is(editor.getText(), "foofoo", "editor is now read-only (keyboard)"); + + editor.setText("foobar"); + is(editor.getText(), "foobar", "editor allows programmatic changes (setText)"); + + EventUtils.synthesizeKey("VK_RETURN", {}, testWin); + is(editor.getText(), "foobar", "Enter key does nothing"); + + EventUtils.synthesizeKey("VK_TAB", {}, testWin); + is(editor.getText(), "foobar", "Tab does nothing"); + + editor.setText(" foobar"); + EventUtils.synthesizeKey("VK_TAB", {shiftKey: true}, testWin); + is(editor.getText(), " foobar", "Shift+Tab does nothing"); + + editor.readOnly = false; + + editor.setCaretOffset(editor.getCharCount()); + EventUtils.synthesizeKey("-", {}, testWin); + is(editor.getText(), " foobar-", "editor is now editable again"); + + // Test the Selection event. + + editor.setText("foobarbaz"); + + editor.setSelection(1, 4); + + let event = null; + + let eventHandler = function(aEvent) { + event = aEvent; + }; + editor.addEventListener(SourceEditor.EVENTS.SELECTION, eventHandler); + + editor.setSelection(0, 3); + + ok(event, "selection event fired"); + ok(event.oldValue.start == 1 && event.oldValue.end == 4, + "event.oldValue is correct"); + ok(event.newValue.start == 0 && event.newValue.end == 3, + "event.newValue is correct"); + + event = null; + editor.dropSelection(); + + ok(event, "selection dropped"); + ok(event.oldValue.start == 0 && event.oldValue.end == 3, + "event.oldValue is correct"); + ok(event.newValue.start == 3 && event.newValue.end == 3, + "event.newValue is correct"); + + event = null; + EventUtils.synthesizeKey("a", {accelKey: true}, testWin); + + ok(event, "select all worked"); + ok(event.oldValue.start == 3 && event.oldValue.end == 3, + "event.oldValue is correct"); + ok(event.newValue.start == 0 && event.newValue.end == 9, + "event.newValue is correct"); + + event = null; + editor.removeEventListener(SourceEditor.EVENTS.SELECTION, eventHandler); + editor.dropSelection(); + + ok(!event, "selection event listener removed"); + + // Test the TextChanged event. + + editor.addEventListener(SourceEditor.EVENTS.TEXT_CHANGED, eventHandler); + + EventUtils.synthesizeKey(".", {}, testWin); + + ok(event, "the TextChanged event fired after keypress"); + is(event.start, 9, "event.start is correct"); + is(event.removedCharCount, 0, "event.removedCharCount is correct"); + is(event.addedCharCount, 1, "event.addedCharCount is correct"); + + editor.setText("line1\nline2\nline3"); + let chars = editor.getText().length; + event = null; + + editor.setText("a\nline4\nline5", chars); + + ok(event, "the TextChanged event fired after setText()"); + is(event.start, chars, "event.start is correct"); + is(event.removedCharCount, 0, "event.removedCharCount is correct"); + is(event.addedCharCount, 13, "event.addedCharCount is correct"); + + event = null; + editor.setText("line3b\nline4b\nfoo", 12, 24); + + ok(event, "the TextChanged event fired after setText() again"); + is(event.start, 12, "event.start is correct"); + is(event.removedCharCount, 12, "event.removedCharCount is correct"); + is(event.addedCharCount, 17, "event.addedCharCount is correct"); + + editor.removeEventListener(SourceEditor.EVENTS.TEXT_CHANGED, eventHandler); + + testClipboardEvents(); +} + +function testEnd() +{ + editor.destroy(); + ok(!editor.parentElement && !editor.editorElement, "destroy() works"); + + testWin.close(); + + testWin = testDoc = editor = null; + + waitForFocus(finish, window); +} + +function testBackspaceKey() +{ + editor.setText(" a\n b\n c"); + editor.setCaretOffset(7); + EventUtils.synthesizeKey("VK_BACK_SPACE", {}, testWin); + is(editor.getText(), "a\n b\n c", "line outdented (Backspace)"); + + editor.undo(); + + editor.setCaretOffset(6); + EventUtils.synthesizeKey("VK_BACK_SPACE", {}, testWin); + is(editor.getText(), " a\n b\n c", "backspace one char works"); +} + +function testReturnKey() +{ + editor.setText(" a\n b\n c"); + + editor.setCaretOffset(8); + EventUtils.synthesizeKey("VK_RETURN", {}, testWin); + EventUtils.synthesizeKey("x", {}, testWin); + + let lineDelimiter = editor.getLineDelimiter(); + ok(lineDelimiter, "we have the line delimiter"); + + let indentationString = editor.getIndentationString(); + is(" ", indentationString, "we have an indentation string of 7 spaces"); + + is(editor.getText(), " a" + lineDelimiter + " x\n b\n c", + "return maintains indentation"); + + editor.setCaretOffset(12 + lineDelimiter.length); + EventUtils.synthesizeKey("z", {}, testWin); + EventUtils.synthesizeKey("VK_RETURN", {}, testWin); + EventUtils.synthesizeKey("y", {}, testWin); + is(editor.getText(), " a" + lineDelimiter + + " z" + lineDelimiter + " yx\n b\n c", + "return maintains indentation (again)"); +} + +function testClipboardEvents() +{ + editor.setText("foobar"); + + let doCut = function() { + EventUtils.synthesizeKey("a", {accelKey: true}, testWin); + + is(editor.getSelectedText(), "foobar", "select all worked"); + + EventUtils.synthesizeKey("x", {accelKey: true}, testWin); + }; + + let onCut = function() { + ok(!editor.getText(), "cut works"); + editor.setText("test--"); + editor.setCaretOffset(5); + + editor.addEventListener(SourceEditor.EVENTS.TEXT_CHANGED, onPaste1); + EventUtils.synthesizeKey("v", {accelKey: true}, testWin); + }; + + let onPaste1 = function() { + editor.removeEventListener(SourceEditor.EVENTS.TEXT_CHANGED, onPaste1); + + is(editor.getText(), "test-foobar-", "paste works"); + + executeSoon(waitForClipboard.bind(this, "test", doCopy, onCopy, testEnd)); + }; + + let doCopy = function() { + editor.setSelection(0, 4); + EventUtils.synthesizeKey("c", {accelKey: true}, testWin); + }; + + let onCopy = function() { + editor.setSelection(5, 11); + editor.addEventListener(SourceEditor.EVENTS.TEXT_CHANGED, onPaste2); + EventUtils.synthesizeKey("v", {accelKey: true}, testWin); + }; + + let pasteTextChanges = 0; + let removedCharCount = 0; + let addedCharCount = 0; + let onPaste2 = function(aEvent) { + pasteTextChanges++; + ok(aEvent && (pasteTextChanges == 1 || pasteTextChanges == 2), + "event TEXT_CHANGED fired " + pasteTextChanges + " time(s)"); + + is(aEvent.start, 5, "event.start is correct"); + if (aEvent.removedCharCount) { + removedCharCount = aEvent.removedCharCount; + } + if (aEvent.addedCharCount) { + addedCharCount = aEvent.addedCharCount; + } + + if (pasteTextChanges == 2 || addedCharCount && removedCharCount) { + editor.removeEventListener(SourceEditor.EVENTS.TEXT_CHANGED, onPaste2); + executeSoon(checkPaste2Result); + } + }; + + let checkPaste2Result = function() { + is(removedCharCount, 6, "event.removedCharCount is correct"); + is(addedCharCount, 4, "event.addedCharCount is correct"); + + is(editor.getText(), "test-test-", "paste works after copy"); + testEnd(); + }; + + waitForClipboard("foobar", doCut, onCut, testEnd); +} + +function testEclipseBug362107() +{ + // Test for Eclipse Bug 362107: + // https://bugs.eclipse.org/bugs/show_bug.cgi?id=362107 + let OS = Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULRuntime).OS; + if (OS != "Linux") { + return; + } + + editor.setText("line 1\nline 2\nline 3"); + editor.setCaretOffset(16); + + EventUtils.synthesizeKey("VK_UP", {ctrlKey: true}, testWin); + is(editor.getCaretOffset(), 9, "Ctrl-Up works"); + + EventUtils.synthesizeKey("VK_UP", {ctrlKey: true}, testWin); + is(editor.getCaretOffset(), 2, "Ctrl-Up works twice"); + + EventUtils.synthesizeKey("VK_DOWN", {ctrlKey: true}, testWin); + is(editor.getCaretOffset(), 9, "Ctrl-Down works"); + + EventUtils.synthesizeKey("VK_DOWN", {ctrlKey: true}, testWin); + is(editor.getCaretOffset(), 16, "Ctrl-Down works twice"); +} + +function testBug687577() +{ + // Test for Mozilla Bug 687577: + // https://bugzilla.mozilla.org/show_bug.cgi?id=687577 + let OS = Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULRuntime).OS; + if (OS != "Linux") { + return; + } + + editor.setText("line foobar 1\nline foobar 2\nline foobar 3"); + editor.setCaretOffset(39); + + EventUtils.synthesizeKey("VK_LEFT", {ctrlKey: true, shiftKey: true}, testWin); + let selection = editor.getSelection(); + is(selection.start, 33, "select.start after Ctrl-Shift-Left"); + is(selection.end, 39, "select.end after Ctrl-Shift-Left"); + + EventUtils.synthesizeKey("VK_UP", {ctrlKey: true, shiftKey: true}, testWin); + selection = editor.getSelection(); + is(selection.start, 14, "select.start after Ctrl-Shift-Up"); + is(selection.end, 39, "select.end after Ctrl-Shift-Up"); + + EventUtils.synthesizeKey("VK_UP", {ctrlKey: true, shiftKey: true}, testWin); + selection = editor.getSelection(); + is(selection.start, 0, "select.start after Ctrl-Shift-Up (again)"); + is(selection.end, 39, "select.end after Ctrl-Shift-Up (again)"); + + EventUtils.synthesizeKey("VK_DOWN", {ctrlKey: true, shiftKey: true}, testWin); + selection = editor.getSelection(); + is(selection.start, 27, "select.start after Ctrl-Shift-Down"); + is(selection.end, 39, "select.end after Ctrl-Shift-Down"); + + EventUtils.synthesizeKey("VK_DOWN", {ctrlKey: true, shiftKey: true}, testWin); + selection = editor.getSelection(); + is(selection.start, 39, "select.start after Ctrl-Shift-Down (again)"); + is(selection.end, 41, "select.end after Ctrl-Shift-Down (again)"); +} |