diff options
| author | Ben Beltran <ben@nsovocal.com> | 2015-07-10 11:12:25 -0500 |
|---|---|---|
| committer | Ben Beltran <ben@nsovocal.com> | 2015-07-10 11:12:25 -0500 |
| commit | 24c7594d62d8d7fbbcdb64b11ce4adc5d8e6991a (patch) | |
| tree | ded312222bb108923da1820ba40b04d710d20e5b /atom/packages/vim-mode/spec/vim-state-spec.coffee | |
| parent | eb786e82d170e2abc351a432ade616d6ecdeeb6b (diff) | |
Adds atom
Diffstat (limited to 'atom/packages/vim-mode/spec/vim-state-spec.coffee')
| -rw-r--r-- | atom/packages/vim-mode/spec/vim-state-spec.coffee | 420 |
1 files changed, 420 insertions, 0 deletions
diff --git a/atom/packages/vim-mode/spec/vim-state-spec.coffee b/atom/packages/vim-mode/spec/vim-state-spec.coffee new file mode 100644 index 0000000..741c371 --- /dev/null +++ b/atom/packages/vim-mode/spec/vim-state-spec.coffee @@ -0,0 +1,420 @@ +_ = require 'underscore-plus' +helpers = require './spec-helper' +VimState = require '../lib/vim-state' +StatusBarManager = require '../lib/status-bar-manager' + +describe "VimState", -> + [editor, editorElement, vimState] = [] + + beforeEach -> + vimMode = atom.packages.loadPackage('vim-mode') + vimMode.activateResources() + + helpers.getEditorElement (element) -> + editorElement = element + editor = editorElement.getModel() + vimState = editorElement.vimState + vimState.activateCommandMode() + vimState.resetCommandMode() + + keydown = (key, options={}) -> + options.element ?= editorElement + helpers.keydown(key, options) + + commandModeInputKeydown = (key, opts = {}) -> + editor.commandModeInputView.editorElement.getModel().setText(key) + + describe "initialization", -> + it "puts the editor in command-mode initially by default", -> + expect(editorElement.classList.contains('vim-mode')).toBe(true) + expect(editorElement.classList.contains('command-mode')).toBe(true) + + it "puts the editor in insert-mode if startInInsertMode is true", -> + atom.config.set 'vim-mode.startInInsertMode', true + editor.vimState = new VimState(editorElement, new StatusBarManager) + expect(editorElement.classList.contains('insert-mode')).toBe(true) + + describe "::destroy", -> + it "re-enables text input on the editor", -> + expect(editorElement.component.isInputEnabled()).toBeFalsy() + vimState.destroy() + expect(editorElement.component.isInputEnabled()).toBeTruthy() + + it "removes the mode classes from the editor", -> + expect(editorElement.classList.contains("command-mode")).toBeTruthy() + vimState.destroy() + expect(editorElement.classList.contains("command-mode")).toBeFalsy() + + it "is a noop when the editor is already destroyed", -> + editorElement.getModel().destroy() + vimState.destroy() + + describe "command-mode", -> + describe "when entering an insertable character", -> + beforeEach -> keydown('\\') + + it "stops propagation", -> + expect(editor.getText()).toEqual '' + + describe "when entering an operator", -> + beforeEach -> keydown('d') + + describe "with an operator that can't be composed", -> + beforeEach -> keydown('x') + + it "clears the operator stack", -> + expect(vimState.opStack.length).toBe 0 + + describe "the escape keybinding", -> + beforeEach -> keydown('escape') + + it "clears the operator stack", -> + expect(vimState.opStack.length).toBe 0 + + describe "the ctrl-c keybinding", -> + beforeEach -> keydown('c', ctrl: true) + + it "clears the operator stack", -> + expect(vimState.opStack.length).toBe 0 + + describe "the escape keybinding", -> + it "clears any extra cursors", -> + editor.setText("one-two-three") + editor.addCursorAtBufferPosition([0, 3]) + expect(editor.getCursors().length).toBe 2 + keydown('escape') + expect(editor.getCursors().length).toBe 1 + + describe "the v keybinding", -> + beforeEach -> keydown('v') + + it "puts the editor into visual characterwise mode", -> + expect(editorElement.classList.contains('visual-mode')).toBe(true) + expect(vimState.submode).toEqual 'characterwise' + expect(editorElement.classList.contains('command-mode')).toBe(false) + + describe "the V keybinding", -> + beforeEach -> + editor.setText("012345\nabcdef") + editor.setCursorScreenPosition([0, 0]) + keydown('V', shift: true) + + it "puts the editor into visual linewise mode", -> + expect(editorElement.classList.contains('visual-mode')).toBe(true) + expect(vimState.submode).toEqual 'linewise' + expect(editorElement.classList.contains('command-mode')).toBe(false) + + it "selects the current line", -> + expect(editor.getLastSelection().getText()).toEqual '012345\n' + + describe "the ctrl-v keybinding", -> + beforeEach -> keydown('v', ctrl: true) + + it "puts the editor into visual characterwise mode", -> + expect(editorElement.classList.contains('visual-mode')).toBe(true) + expect(vimState.submode).toEqual 'blockwise' + expect(editorElement.classList.contains('command-mode')).toBe(false) + + describe "selecting text", -> + beforeEach -> + spyOn(_._, "now").andCallFake -> window.now + editor.setText("abc def") + + it "puts the editor into visual mode", -> + expect(vimState.mode).toEqual 'command' + editor.setSelectedBufferRanges([[[0, 0], [0, 3]]]) + + advanceClock(100) + + expect(vimState.mode).toEqual 'visual' + expect(vimState.submode).toEqual 'characterwise' + expect(editor.getSelectedBufferRanges()).toEqual([[[0, 0], [0, 3]]]) + + it "handles the editor being destroyed shortly after selecting text", -> + editor.setSelectedBufferRanges([[[0, 0], [0, 3]]]) + editor.destroy() + vimState.destroy() + advanceClock(100) + + describe "the i keybinding", -> + beforeEach -> keydown('i') + + it "puts the editor into insert mode", -> + expect(editorElement.classList.contains('insert-mode')).toBe(true) + expect(editorElement.classList.contains('command-mode')).toBe(false) + + describe "with content", -> + beforeEach -> editor.setText("012345\n\nabcdef") + + # FIXME: See atom/vim-mode#2 + xdescribe "on a line with content", -> + beforeEach -> editor.setCursorScreenPosition([0, 6]) + + it "does not allow the cursor to be placed on the \n character", -> + expect(editor.getCursorScreenPosition()).toEqual [0, 5] + + describe "on an empty line", -> + beforeEach -> editor.setCursorScreenPosition([1, 0]) + + it "allows the cursor to be placed on the \n character", -> + expect(editor.getCursorScreenPosition()).toEqual [1, 0] + + describe 'with character-input operations', -> + beforeEach -> editor.setText('012345\nabcdef') + + it 'properly clears the opStack', -> + keydown('d') + keydown('r') + expect(vimState.mode).toBe 'command' + expect(vimState.opStack.length).toBe 0 + atom.commands.dispatch(editor.commandModeInputView.editorElement, "core:cancel") + keydown('d') + expect(editor.getText()).toBe '012345\nabcdef' + + describe "insert-mode", -> + beforeEach -> + keydown('i') + + describe "with content", -> + beforeEach -> editor.setText("012345\n\nabcdef") + + describe "when cursor is in the middle of the line", -> + beforeEach -> editor.setCursorScreenPosition([0, 3]) + + it "moves the cursor to the left when exiting insert mode", -> + keydown('escape') + expect(editor.getCursorScreenPosition()).toEqual [0, 2] + + describe "when cursor is at the beginning of line", -> + beforeEach -> editor.setCursorScreenPosition([1, 0]) + + it "leaves the cursor at the beginning of line", -> + keydown('escape') + expect(editor.getCursorScreenPosition()).toEqual [1, 0] + + describe "on a line with content", -> + beforeEach -> editor.setCursorScreenPosition([0, 6]) + + it "allows the cursor to be placed on the \n character", -> + expect(editor.getCursorScreenPosition()).toEqual [0, 6] + + it "puts the editor into command mode when <escape> is pressed", -> + keydown('escape') + + expect(editorElement.classList.contains('command-mode')).toBe(true) + expect(editorElement.classList.contains('insert-mode')).toBe(false) + expect(editorElement.classList.contains('visual-mode')).toBe(false) + + it "puts the editor into command mode when <ctrl-c> is pressed", -> + helpers.mockPlatform(editorElement, 'platform-darwin') + keydown('c', ctrl: true) + helpers.unmockPlatform(editorElement) + + expect(editorElement.classList.contains('command-mode')).toBe(true) + expect(editorElement.classList.contains('insert-mode')).toBe(false) + expect(editorElement.classList.contains('visual-mode')).toBe(false) + + describe "visual-mode", -> + beforeEach -> + editor.setText("one two three") + editor.setCursorBufferPosition([0, 4]) + keydown('v') + + it "selects the character under the cursor", -> + expect(editor.getSelectedBufferRanges()).toEqual [[[0, 4], [0, 5]]] + expect(editor.getSelectedText()).toBe("t") + + it "puts the editor into command mode when <escape> is pressed", -> + keydown('escape') + + expect(editor.getCursorBufferPositions()).toEqual [[0, 4]] + expect(editorElement.classList.contains('command-mode')).toBe(true) + expect(editorElement.classList.contains('visual-mode')).toBe(false) + + it "puts the editor into command mode when <escape> is pressed on selection is reversed", -> + expect(editor.getSelectedText()).toBe("t") + keydown("h") + keydown("h") + expect(editor.getSelectedText()).toBe("e t") + expect(editor.getLastSelection().isReversed()).toBe(true) + keydown('escape') + expect(editorElement.classList.contains('command-mode')).toBe(true) + expect(editor.getCursorBufferPositions()).toEqual [[0, 2]] + + describe "motions", -> + it "transforms the selection", -> + keydown('w') + expect(editor.getLastSelection().getText()).toEqual 'two t' + + it "always leaves the initially selected character selected", -> + keydown("h") + expect(editor.getSelectedText()).toBe(" t") + + keydown("l") + expect(editor.getSelectedText()).toBe("t") + + keydown("l") + keydown("l") + expect(editor.getSelectedText()).toBe("tw") + + describe "operators", -> + beforeEach -> + editor.setText("012345\n\nabcdef") + editor.setCursorScreenPosition([0, 0]) + editor.selectLinesContainingCursors() + keydown('d') + + it "operate on the current selection", -> + expect(editor.getText()).toEqual "\nabcdef" + + describe "returning to command-mode", -> + beforeEach -> + editor.setText("012345\n\nabcdef") + editor.selectLinesContainingCursors() + keydown('escape') + + it "operate on the current selection", -> + expect(editor.getLastSelection().getText()).toEqual '' + + describe "the o keybinding", -> + it "reversed each selection", -> + editor.addCursorAtBufferPosition([0, Infinity]) + keydown("i") + keydown("w") + + expect(editor.getSelectedBufferRanges()).toEqual([ + [[0, 4], [0, 7]], + [[0, 8], [0, 13]] + ]) + expect(editor.getCursorBufferPositions()).toEqual([ + [0, 7] + [0, 13] + ]) + + keydown("o") + + expect(editor.getSelectedBufferRanges()).toEqual([ + [[0, 4], [0, 7]], + [[0, 8], [0, 13]] + ]) + expect(editor.getCursorBufferPositions()).toEqual([ + [0, 4] + [0, 8] + ]) + + describe "activate visualmode witin visualmode", -> + beforeEach -> + keydown('escape') + expect(vimState.mode).toEqual 'command' + expect(editorElement.classList.contains('command-mode')).toBe(true) + + it "activateVisualMode with same type puts the editor into command mode", -> + keydown('v') + expect(editorElement.classList.contains('visual-mode')).toBe(true) + expect(vimState.submode).toEqual 'characterwise' + expect(editorElement.classList.contains('command-mode')).toBe(false) + + keydown('v') + expect(vimState.mode).toEqual 'command' + expect(editorElement.classList.contains('command-mode')).toBe(true) + + keydown('V', shift: true) + expect(editorElement.classList.contains('visual-mode')).toBe(true) + expect(vimState.submode).toEqual 'linewise' + expect(editorElement.classList.contains('command-mode')).toBe(false) + + keydown('V', shift: true) + expect(vimState.mode).toEqual 'command' + expect(editorElement.classList.contains('command-mode')).toBe(true) + + keydown('v', ctrl: true) + expect(editorElement.classList.contains('visual-mode')).toBe(true) + expect(vimState.submode).toEqual 'blockwise' + expect(editorElement.classList.contains('command-mode')).toBe(false) + + keydown('v', ctrl: true) + expect(vimState.mode).toEqual 'command' + expect(editorElement.classList.contains('command-mode')).toBe(true) + + describe "change submode within visualmode", -> + beforeEach -> + editor.setText("line one\nline two\nline three\n") + editor.setCursorBufferPosition([0, 5]) + editor.addCursorAtBufferPosition([2, 5]) + + it "can change submode within visual mode", -> + keydown('v') + expect(editorElement.classList.contains('visual-mode')).toBe(true) + expect(vimState.submode).toEqual 'characterwise' + expect(editorElement.classList.contains('command-mode')).toBe(false) + + keydown('V', shift: true) + expect(editorElement.classList.contains('visual-mode')).toBe(true) + expect(vimState.submode).toEqual 'linewise' + expect(editorElement.classList.contains('command-mode')).toBe(false) + + keydown('v', ctrl: true) + expect(editorElement.classList.contains('visual-mode')).toBe(true) + expect(vimState.submode).toEqual 'blockwise' + expect(editorElement.classList.contains('command-mode')).toBe(false) + + keydown('v') + expect(editorElement.classList.contains('visual-mode')).toBe(true) + expect(vimState.submode).toEqual 'characterwise' + expect(editorElement.classList.contains('command-mode')).toBe(false) + + + it "recover original range when shift from linewse to characterwise", -> + keydown('v') + keydown('i') + keydown('w') + + expect(_.map(editor.getSelections(), (selection) -> + selection.getText()) + ).toEqual(['one', 'three']) + + keydown('V', shift: true) + expect(_.map(editor.getSelections(), (selection) -> + selection.getText()) + ).toEqual(["line one\n", "line three\n"]) + + keydown('v', ctrl: true) + expect(_.map(editor.getSelections(), (selection) -> + selection.getText()) + ).toEqual(['one', 'three']) + + describe "marks", -> + beforeEach -> editor.setText("text in line 1\ntext in line 2\ntext in line 3") + + it "basic marking functionality", -> + editor.setCursorScreenPosition([1, 1]) + keydown('m') + commandModeInputKeydown('t') + expect(editor.getText()).toEqual "text in line 1\ntext in line 2\ntext in line 3" + editor.setCursorScreenPosition([2, 2]) + keydown('`') + commandModeInputKeydown('t') + expect(editor.getCursorScreenPosition()).toEqual [1, 1] + + it "real (tracking) marking functionality", -> + editor.setCursorScreenPosition([2, 2]) + keydown('m') + commandModeInputKeydown('q') + editor.setCursorScreenPosition([1, 2]) + keydown('o') + keydown('escape') + keydown('`') + commandModeInputKeydown('q') + expect(editor.getCursorScreenPosition()).toEqual [3, 2] + + it "real (tracking) marking functionality", -> + editor.setCursorScreenPosition([2, 2]) + keydown('m') + commandModeInputKeydown('q') + editor.setCursorScreenPosition([1, 2]) + keydown('d') + keydown('d') + keydown('escape') + keydown('`') + commandModeInputKeydown('q') + expect(editor.getCursorScreenPosition()).toEqual [1, 2] |