mirror of
https://github.com/atom/atom.git
synced 2026-04-28 03:01:47 -04:00
Rename extensions to packages
We now look at the `core.disabledPackages` config key. Rename the `src/extensions` directory to `src/packages`. The config object now talks about loading packages instead of extensions.
This commit is contained in:
446
src/packages/command-panel/spec/command-interpreter-spec.coffee
Normal file
446
src/packages/command-panel/spec/command-interpreter-spec.coffee
Normal file
@@ -0,0 +1,446 @@
|
||||
CommandInterpreter = require 'command-panel/src/command-interpreter'
|
||||
Project = require 'project'
|
||||
Buffer = require 'buffer'
|
||||
EditSession = require 'edit-session'
|
||||
|
||||
describe "CommandInterpreter", ->
|
||||
[project, interpreter, editSession, buffer, anchorCountBefore] = []
|
||||
|
||||
beforeEach ->
|
||||
project = new Project(fixturesProject.resolve('dir/'))
|
||||
interpreter = new CommandInterpreter(fixturesProject)
|
||||
editSession = fixturesProject.buildEditSessionForPath('sample.js')
|
||||
buffer = editSession.buffer
|
||||
|
||||
afterEach ->
|
||||
editSession?.destroy()
|
||||
expect(buffer.getAnchors().length).toBe 0
|
||||
|
||||
describe "addresses", ->
|
||||
beforeEach ->
|
||||
editSession.addSelectionForBufferRange([[7,0], [7,11]])
|
||||
editSession.addSelectionForBufferRange([[8,0], [8,11]])
|
||||
|
||||
describe "a line address", ->
|
||||
it "selects the specified line", ->
|
||||
waitsForPromise -> interpreter.eval('4', editSession)
|
||||
runs ->
|
||||
expect(editSession.getSelections().length).toBe 1
|
||||
expect(editSession.getSelection().getBufferRange()).toEqual [[3, 0], [4, 0]]
|
||||
|
||||
describe "0", ->
|
||||
it "selects the zero-length string at the start of the file", ->
|
||||
waitsForPromise -> interpreter.eval('0', editSession)
|
||||
runs ->
|
||||
expect(editSession.getSelections().length).toBe 1
|
||||
expect(editSession.getSelection().getBufferRange()).toEqual [[0,0], [0,0]]
|
||||
|
||||
interpreter.eval('0,1', editSession)
|
||||
expect(editSession.getSelections().length).toBe 1
|
||||
expect(editSession.getSelection().getBufferRange()).toEqual [[0,0], [1,0]]
|
||||
|
||||
describe "$", ->
|
||||
it "selects EOF", ->
|
||||
waitsForPromise -> interpreter.eval('$', editSession)
|
||||
runs ->
|
||||
expect(editSession.getSelections().length).toBe 1
|
||||
expect(editSession.getSelection().getBufferRange()).toEqual [[12,2], [12,2]]
|
||||
|
||||
waitsForPromise -> interpreter.eval('1,$', editSession)
|
||||
runs ->
|
||||
expect(editSession.getSelections().length).toBe 1
|
||||
expect(editSession.getSelection().getBufferRange()).toEqual [[0,0], [12,2]]
|
||||
|
||||
describe ".", ->
|
||||
describe "when a single selection", ->
|
||||
it 'maintains the current selection', ->
|
||||
editSession.clearSelections()
|
||||
|
||||
waitsForPromise ->
|
||||
editSession.setSelectedBufferRange([[1,1], [2,2]])
|
||||
interpreter.eval('.', editSession)
|
||||
|
||||
runs ->
|
||||
expect(editSession.getSelection().getBufferRange()).toEqual [[1,1], [2,2]]
|
||||
|
||||
waitsForPromise ->
|
||||
editSession.setSelectedBufferRange([[1,1], [2,2]])
|
||||
interpreter.eval('.,', editSession)
|
||||
|
||||
runs ->
|
||||
expect(editSession.getSelection().getBufferRange()).toEqual [[1,1], [12,2]]
|
||||
|
||||
waitsForPromise ->
|
||||
editSession.setSelectedBufferRange([[1,1], [2,2]])
|
||||
interpreter.eval(',.', editSession)
|
||||
|
||||
runs ->
|
||||
expect(editSession.getSelection().getBufferRange()).toEqual [[0,0], [2,2]]
|
||||
|
||||
describe "with multiple selections", ->
|
||||
it "maintains the current selections", ->
|
||||
preSelections = editSession.getSelections()
|
||||
expect(preSelections.length).toBe 3
|
||||
[preRange1, preRange2, preRange3] = preSelections.map (s) -> s.getScreenRange()
|
||||
|
||||
waitsForPromise -> interpreter.eval('.', editSession)
|
||||
|
||||
runs ->
|
||||
selections = editSession.getSelections()
|
||||
expect(selections.length).toBe 3
|
||||
[selection1, selection2, selection3] = selections
|
||||
expect(selection1.getScreenRange()).toEqual preRange1
|
||||
expect(selection2.getScreenRange()).toEqual preRange2
|
||||
expect(selection3.getScreenRange()).toEqual preRange3
|
||||
|
||||
describe "/regex/", ->
|
||||
beforeEach ->
|
||||
editSession.clearSelections()
|
||||
|
||||
it 'selects text matching regex after current selection', ->
|
||||
waitsForPromise ->
|
||||
editSession.setSelectedBufferRange([[4,16], [4,20]])
|
||||
interpreter.eval('/pivot/', editSession)
|
||||
|
||||
runs ->
|
||||
expect(editSession.getSelection().getBufferRange()).toEqual [[6,16], [6,21]]
|
||||
|
||||
it 'does not require the trailing slash', ->
|
||||
waitsForPromise ->
|
||||
editSession.setSelectedBufferRange([[4,16], [4,20]])
|
||||
interpreter.eval('/pivot', editSession)
|
||||
|
||||
runs ->
|
||||
expect(editSession.getSelection().getBufferRange()).toEqual [[6,16], [6,21]]
|
||||
|
||||
it "searches from the end of each selection in the buffer", ->
|
||||
waitsForPromise ->
|
||||
editSession.clearSelections()
|
||||
editSession.setSelectedBufferRange([[4,16], [4,20]])
|
||||
editSession.addSelectionForBufferRange([[1,16], [2,20]])
|
||||
expect(editSession.getSelections().length).toBe 2
|
||||
interpreter.eval('/pivot', editSession)
|
||||
|
||||
runs ->
|
||||
selections = editSession.getSelections()
|
||||
expect(selections.length).toBe 2
|
||||
expect(selections[0].getBufferRange()).toEqual [[3,8], [3,13]]
|
||||
expect(selections[1].getBufferRange()).toEqual [[6,16], [6,21]]
|
||||
|
||||
it "wraps around to the beginning of the buffer, but doesn't infinitely loop if no matches are found", ->
|
||||
waitsForPromise ->
|
||||
editSession.setSelectedBufferRange([[10, 0], [10,3]])
|
||||
interpreter.eval('/pivot', editSession)
|
||||
|
||||
runs ->
|
||||
expect(editSession.getSelection().getBufferRange()).toEqual [[3,8], [3,13]]
|
||||
|
||||
waitsForPromise ->
|
||||
interpreter.eval('/mike tyson', editSession)
|
||||
|
||||
runs ->
|
||||
expect(editSession.getSelection().getBufferRange()).toEqual [[3,8], [3,13]]
|
||||
|
||||
it "searches in reverse when prefixed with a -", ->
|
||||
waitsForPromise ->
|
||||
editSession.setSelectedBufferRange([[6, 16], [6, 22]])
|
||||
interpreter.eval('-/pivot', editSession)
|
||||
|
||||
runs ->
|
||||
expect(editSession.getSelection().getBufferRange()).toEqual [[3,8], [3,13]]
|
||||
|
||||
it "removes folds that contain the selections", ->
|
||||
waitsForPromise ->
|
||||
editSession.createFold(5, 6)
|
||||
editSession.createFold(10, 11)
|
||||
editSession.setSelectedBufferRange([[4,16], [4,20]])
|
||||
interpreter.eval('/pivot/', editSession)
|
||||
|
||||
runs ->
|
||||
expect(editSession.getSelection().getBufferRange()).toEqual [[6,16], [6,21]]
|
||||
expect(editSession.lineForScreenRow(5).fold).toBeUndefined()
|
||||
expect(editSession.lineForScreenRow(10).fold).toBeDefined()
|
||||
|
||||
it "is case-insentive when the pattern contains no non-escaped uppercase letters (behavior copied from vim)", ->
|
||||
waitsForPromise ->
|
||||
interpreter.eval('/array', editSession)
|
||||
runs ->
|
||||
expect(interpreter.lastRelativeAddress.subcommands[0].regex.toString()).toEqual "/array/i"
|
||||
|
||||
waitsForPromise ->
|
||||
interpreter.eval('/a\\Sray', editSession)
|
||||
runs ->
|
||||
expect(interpreter.lastRelativeAddress.subcommands[0].regex.toString()).toEqual "/a\\Sray/i"
|
||||
|
||||
it "allows the regex to contain an escaped forward slash", ->
|
||||
buffer.setText "hey/baby"
|
||||
|
||||
waitsForPromise ->
|
||||
interpreter.eval('/y\\/b/', editSession)
|
||||
runs ->
|
||||
expect(editSession.getSelectedText()).toBe "y/b"
|
||||
|
||||
it "does not push to the undo stack (since the buffer is not modified)", ->
|
||||
waitsForPromise ->
|
||||
editSession.setSelectedBufferRange([[4,16], [4,20]])
|
||||
interpreter.eval('/pivot/', editSession)
|
||||
|
||||
runs ->
|
||||
selectedRangeBeforeUndo = editSession.getSelection().getBufferRange()
|
||||
editSession.undo()
|
||||
expect(editSession.getSelection().getBufferRange()).toEqual selectedRangeBeforeUndo
|
||||
|
||||
describe "when no match is found", ->
|
||||
it "it returns an error messages", ->
|
||||
errorMessages = null
|
||||
waitsForPromise ->
|
||||
interpreter.eval('/garbage!', editSession).done (results) -> { errorMessages } = results
|
||||
|
||||
runs ->
|
||||
expect(errorMessages.length).toBe 1
|
||||
|
||||
waitsForPromise ->
|
||||
interpreter.eval('/Array', editSession)
|
||||
runs ->
|
||||
expect(interpreter.lastRelativeAddress.subcommands[0].regex.toString()).toEqual "/Array/"
|
||||
|
||||
describe "address range", ->
|
||||
describe "when two addresses are specified", ->
|
||||
it "selects from the begining of the left address to the end of the right address", ->
|
||||
waitsForPromise -> interpreter.eval('4,7', editSession)
|
||||
|
||||
runs ->
|
||||
expect(editSession.getSelections().length).toBe 1
|
||||
expect(editSession.getSelection().getBufferRange()).toEqual [[3, 0], [7, 0]]
|
||||
|
||||
describe "when the left address is unspecified", ->
|
||||
it "selects from the begining of buffer to the end of the right address", ->
|
||||
waitsForPromise -> interpreter.eval(',7', editSession)
|
||||
runs ->
|
||||
expect(editSession.getSelections().length).toBe 1
|
||||
expect(editSession.getSelection().getBufferRange()).toEqual [[0, 0], [7, 0]]
|
||||
|
||||
describe "when the right address is unspecified", ->
|
||||
it "selects from the begining of left address to the end file", ->
|
||||
waitsForPromise -> interpreter.eval('4,', editSession)
|
||||
runs ->
|
||||
expect(editSession.getSelections().length).toBe 1
|
||||
expect(editSession.getSelection().getBufferRange()).toEqual [[3, 0], [12, 2]]
|
||||
|
||||
describe "when the neither address is specified", ->
|
||||
it "selects the entire file", ->
|
||||
waitsForPromise -> interpreter.eval(',', editSession)
|
||||
runs ->
|
||||
expect(editSession.getSelections().length).toBe 1
|
||||
expect(editSession.getSelection().getBufferRange()).toEqual [[0, 0], [12, 2]]
|
||||
|
||||
describe "x/regex/", ->
|
||||
it "sets the current selection to every match of the regex in the current selection", ->
|
||||
waitsForPromise -> interpreter.eval('6,7 x/current/', editSession)
|
||||
|
||||
runs ->
|
||||
selections = editSession.getSelections()
|
||||
expect(selections.length).toBe 4
|
||||
|
||||
expect(selections[0].getBufferRange()).toEqual [[5,6], [5,13]]
|
||||
expect(selections[1].getBufferRange()).toEqual [[6,6], [6,13]]
|
||||
expect(selections[2].getBufferRange()).toEqual [[6,34], [6,41]]
|
||||
expect(selections[3].getBufferRange()).toEqual [[6,56], [6,63]]
|
||||
|
||||
describe "when there is no address range is given", ->
|
||||
describe "when there is no text selection", ->
|
||||
it "uses the entire file as the address range", ->
|
||||
waitsForPromise ->
|
||||
editSession.clearSelections()
|
||||
interpreter.eval('x/return', editSession)
|
||||
runs ->
|
||||
expect(editSession.getSelectedBufferRanges()).toEqual [
|
||||
[[2,27],[2,33]]
|
||||
[[8,4], [8,10]]
|
||||
[[11,2],[11,8]]
|
||||
]
|
||||
|
||||
describe "when text is selected", ->
|
||||
it "uses the selection as the address range", ->
|
||||
waitsForPromise ->
|
||||
editSession.setSelectedBufferRange([[2, 0], [9, 0]])
|
||||
interpreter.eval('x/return', editSession)
|
||||
runs ->
|
||||
expect(editSession.getSelectedBufferRanges()).toEqual [
|
||||
[[2,27],[2,33]]
|
||||
[[8,4], [8,10]]
|
||||
]
|
||||
|
||||
describe "when matching /$/", ->
|
||||
it "matches the end of each line in the selected region", ->
|
||||
waitsForPromise -> interpreter.eval('6,8 x/$/', editSession)
|
||||
|
||||
runs ->
|
||||
cursors = editSession.getCursors()
|
||||
expect(cursors.length).toBe 3
|
||||
|
||||
expect(cursors[0].getBufferPosition()).toEqual [5, 30]
|
||||
expect(cursors[1].getBufferPosition()).toEqual [6, 65]
|
||||
expect(cursors[2].getBufferPosition()).toEqual [7, 5]
|
||||
|
||||
describe "when text is initially selected", ->
|
||||
it "loops through current selections and selects text matching the regex", ->
|
||||
waitsForPromise ->
|
||||
editSession.setSelectedBufferRange [[3,0], [3,62]]
|
||||
editSession.addSelectionForBufferRange [[6,0], [6,65]]
|
||||
interpreter.eval('x/current', editSession)
|
||||
|
||||
runs ->
|
||||
selections = editSession.getSelections()
|
||||
expect(selections.length).toBe 4
|
||||
|
||||
expect(selections[0].getBufferRange()).toEqual [[3,31], [3,38]]
|
||||
expect(selections[1].getBufferRange()).toEqual [[6,6], [6,13]]
|
||||
expect(selections[2].getBufferRange()).toEqual [[6,34], [6,41]]
|
||||
expect(selections[3].getBufferRange()).toEqual [[6,56], [6,63]]
|
||||
|
||||
describe "substitution", ->
|
||||
describe "when there is no address range is given", ->
|
||||
describe "when there is no text selection", ->
|
||||
it "uses the entire file as the address range", ->
|
||||
waitsForPromise ->
|
||||
editSession.clearSelections()
|
||||
interpreter.eval('s/current/foo/g', editSession)
|
||||
runs ->
|
||||
expect(buffer.lineForRow(3)).toBe ' var pivot = items.shift(), foo, left = [], right = [];'
|
||||
expect(buffer.lineForRow(6)).toBe ' foo < pivot ? left.push(foo) : right.push(foo);'
|
||||
|
||||
describe "when text is selected", ->
|
||||
it "uses the selection as the address range", ->
|
||||
waitsForPromise ->
|
||||
editSession.setSelectedBufferRange([[6, 0], [6, 44]])
|
||||
interpreter.eval('s/current/foo/g', editSession)
|
||||
runs ->
|
||||
expect(buffer.lineForRow(3)).toBe ' var pivot = items.shift(), current, left = [], right = [];'
|
||||
expect(buffer.lineForRow(6)).toBe ' foo < pivot ? left.push(foo) : right.push(current);'
|
||||
|
||||
describe "when not global", ->
|
||||
describe "when there is a single selection", ->
|
||||
it "performs a single substitution within the current selection", ->
|
||||
waitsForPromise ->
|
||||
editSession.setSelectedBufferRange([[6, 0], [6, 44]])
|
||||
interpreter.eval('s/current/foo/', editSession)
|
||||
runs ->
|
||||
expect(buffer.lineForRow(6)).toBe ' foo < pivot ? left.push(current) : right.push(current);'
|
||||
|
||||
describe "when there are multiple selections", ->
|
||||
it "performs a single substitutions within each of the selections", ->
|
||||
waitsForPromise ->
|
||||
editSession.setSelectedBufferRange([[5, 0], [5, 20]])
|
||||
editSession.addSelectionForBufferRange([[6, 0], [6, 44]])
|
||||
interpreter.eval('s/current/foo/', editSession)
|
||||
|
||||
runs ->
|
||||
expect(buffer.lineForRow(5)).toBe ' foo = items.shift();'
|
||||
expect(buffer.lineForRow(6)).toBe ' foo < pivot ? left.push(current) : right.push(current);'
|
||||
|
||||
describe "when global", ->
|
||||
it "performs a multiple substitutions within the current selection as a batch that can be undone in a single operation", ->
|
||||
waitsForPromise ->
|
||||
editSession.setSelectedBufferRange([[6, 0], [6, 44]])
|
||||
interpreter.eval('s/current/foo/g', editSession)
|
||||
|
||||
runs ->
|
||||
expect(buffer.lineForRow(6)).toBe ' foo < pivot ? left.push(foo) : right.push(current);'
|
||||
buffer.undo()
|
||||
expect(buffer.getText()).not.toContain('foo')
|
||||
|
||||
describe "when prefixed with an address", ->
|
||||
it "only makes substitutions within given lines", ->
|
||||
waitsForPromise -> interpreter.eval('4,6s/ /!/g', editSession)
|
||||
|
||||
runs ->
|
||||
expect(buffer.lineForRow(2)).toBe ' if (items.length <= 1) return items;'
|
||||
expect(buffer.lineForRow(3)).toBe '!!!!var!pivot!=!items.shift(),!current,!left!=![],!right!=![];'
|
||||
expect(buffer.lineForRow(4)).toBe '!!!!while(items.length!>!0)!{'
|
||||
expect(buffer.lineForRow(5)).toBe '!!!!!!current!=!items.shift();'
|
||||
expect(buffer.lineForRow(6)).toBe ' current < pivot ? left.push(current) : right.push(current);'
|
||||
|
||||
describe "when matching $", ->
|
||||
it "matches the end of each line and avoids infinitely looping on a zero-width match", ->
|
||||
waitsForPromise -> interpreter.eval(',s/$/!!!/g', editSession)
|
||||
runs ->
|
||||
expect(buffer.lineForRow(0)).toBe 'var quicksort = function () {!!!'
|
||||
expect(buffer.lineForRow(2)).toBe ' if (items.length <= 1) return items;!!!'
|
||||
expect(buffer.lineForRow(6)).toBe ' current < pivot ? left.push(current) : right.push(current);!!!'
|
||||
expect(buffer.lineForRow(12)).toBe '};!!!'
|
||||
|
||||
describe "when matching ^", ->
|
||||
it "matches the beginning of each line and avoids infinitely looping on a zero-width match", ->
|
||||
waitsForPromise -> interpreter.eval(',s/^/!!!/g', editSession)
|
||||
runs ->
|
||||
expect(buffer.lineForRow(0)).toBe '!!!var quicksort = function () {'
|
||||
expect(buffer.lineForRow(2)).toBe '!!! if (items.length <= 1) return items;'
|
||||
expect(buffer.lineForRow(6)).toBe '!!! current < pivot ? left.push(current) : right.push(current);'
|
||||
expect(buffer.lineForRow(12)).toBe '!!!};'
|
||||
|
||||
describe "when there are multiple selections", ->
|
||||
it "performs a multiple substitutions within each of the selections", ->
|
||||
waitsForPromise ->
|
||||
editSession.setSelectedBufferRange([[5, 0], [5, 20]])
|
||||
editSession.addSelectionForBufferRange([[6, 0], [6, 44]])
|
||||
interpreter.eval('s/current/foo/g', editSession)
|
||||
|
||||
runs ->
|
||||
expect(buffer.lineForRow(5)).toBe ' foo = items.shift();'
|
||||
expect(buffer.lineForRow(6)).toBe ' foo < pivot ? left.push(foo) : right.push(current);'
|
||||
|
||||
describe "when prefixed with an address", ->
|
||||
it "restores the original selections upon completion if it is the last command", ->
|
||||
waitsForPromise ->
|
||||
editSession.setSelectedBufferRanges([[[5, 0], [5, 20]], [[6, 0], [6, 44]]])
|
||||
interpreter.eval(',s/current/foo/g', editSession)
|
||||
|
||||
runs ->
|
||||
expect(editSession.getSelectedBufferRanges()).toEqual [[[5, 0], [5, 16]], [[6, 0], [6, 36]]]
|
||||
|
||||
it "does nothing if there are no matches", ->
|
||||
waitsForPromise ->
|
||||
editSession.setSelectedBufferRange([[6, 0], [6, 44]])
|
||||
interpreter.eval('s/not-in-text/foo/', editSession)
|
||||
|
||||
runs ->
|
||||
expect(buffer.lineForRow(6)).toBe ' current < pivot ? left.push(current) : right.push(current);'
|
||||
|
||||
it "properly handles escaped text in the replacement text", ->
|
||||
waitsForPromise ->
|
||||
interpreter.eval('s/ /\\t/g', editSession)
|
||||
runs ->
|
||||
expect(buffer.lineForRow(6)).toBe '\t\t\tcurrent < pivot ? left.push(current) : right.push(current);'
|
||||
|
||||
describe "X x/regex/", ->
|
||||
it "returns selection operations for all regex matches in all the project's files", ->
|
||||
editSession.destroy()
|
||||
project = new Project(fixturesProject.resolve('dir/'))
|
||||
interpreter = new CommandInterpreter(project)
|
||||
|
||||
operationsToPreview = null
|
||||
waitsForPromise ->
|
||||
interpreter.eval("X x/a+/").done (result) -> {operationsToPreview} = result
|
||||
|
||||
runs ->
|
||||
expect(operationsToPreview.length).toBeGreaterThan 3
|
||||
for operation in operationsToPreview
|
||||
editSession = project.buildEditSessionForPath(operation.getPath())
|
||||
editSession.setSelectedBufferRange(operation.execute(editSession))
|
||||
expect(editSession.getSelectedText()).toMatch /a+/
|
||||
editSession.destroy()
|
||||
operation.destroy()
|
||||
|
||||
editSession = null
|
||||
|
||||
describe "nested commands", ->
|
||||
describe "/regex/ /regex", ->
|
||||
it "returns an error message if the last regex has no matches", ->
|
||||
previousSelections = null
|
||||
errorMessages = null
|
||||
waitsForPromise ->
|
||||
previousSelections = editSession.getSelectedBufferRanges()
|
||||
interpreter.eval('/sort/ /no match', editSession).done (results) -> { errorMessages } = results
|
||||
runs ->
|
||||
expect(errorMessages.length).toBe 1
|
||||
458
src/packages/command-panel/spec/command-panel-spec.coffee
Normal file
458
src/packages/command-panel/spec/command-panel-spec.coffee
Normal file
@@ -0,0 +1,458 @@
|
||||
RootView = require 'root-view'
|
||||
CommandPanel = require 'command-panel'
|
||||
_ = require 'underscore'
|
||||
|
||||
describe "CommandPanel", ->
|
||||
[rootView, editor, buffer, commandPanel, project] = []
|
||||
|
||||
beforeEach ->
|
||||
rootView = new RootView
|
||||
rootView.open(require.resolve 'fixtures/sample.js')
|
||||
rootView.enableKeymap()
|
||||
project = rootView.project
|
||||
editor = rootView.getActiveEditor()
|
||||
buffer = editor.activeEditSession.buffer
|
||||
atom.loadPackage('command-panel')
|
||||
commandPanel = CommandPanel.instance
|
||||
commandPanel.history = []
|
||||
commandPanel.historyIndex = 0
|
||||
|
||||
afterEach ->
|
||||
rootView.deactivate()
|
||||
|
||||
describe "serialization", ->
|
||||
it "preserves the command panel's mini-editor text, visibility, focus, and history across reloads", ->
|
||||
rootView.attachToDom()
|
||||
rootView.trigger 'command-panel:toggle'
|
||||
expect(commandPanel.miniEditor.isFocused).toBeTruthy()
|
||||
commandPanel.execute('/.')
|
||||
expect(commandPanel.history.length).toBe(1)
|
||||
expect(commandPanel.history[0]).toBe('/.')
|
||||
expect(commandPanel.historyIndex).toBe(1)
|
||||
rootView.trigger 'command-panel:toggle'
|
||||
expect(commandPanel.miniEditor.isFocused).toBeTruthy()
|
||||
commandPanel.miniEditor.insertText 'abc'
|
||||
rootView2 = RootView.deserialize(rootView.serialize())
|
||||
rootView.deactivate()
|
||||
rootView2.attachToDom()
|
||||
|
||||
commandPanel = rootView2.activateExtension(CommandPanel)
|
||||
expect(rootView2.find('.command-panel')).toExist()
|
||||
expect(commandPanel.miniEditor.getText()).toBe 'abc'
|
||||
expect(commandPanel.miniEditor.isFocused).toBeTruthy()
|
||||
expect(commandPanel.history.length).toBe(1)
|
||||
expect(commandPanel.history[0]).toBe('/.')
|
||||
expect(commandPanel.historyIndex).toBe(1)
|
||||
|
||||
rootView2.focus()
|
||||
expect(commandPanel.miniEditor.isFocused).toBeFalsy()
|
||||
rootView3 = RootView.deserialize(rootView2.serialize())
|
||||
rootView2.deactivate()
|
||||
rootView3.attachToDom()
|
||||
commandPanel = rootView3.activateExtension(CommandPanel)
|
||||
|
||||
expect(commandPanel.miniEditor.isFocused).toBeFalsy()
|
||||
rootView3.deactivate()
|
||||
|
||||
it "only retains the configured max serialized history size", ->
|
||||
rootView.attachToDom()
|
||||
|
||||
commandPanel.maxSerializedHistorySize = 2
|
||||
commandPanel.execute('/test1')
|
||||
commandPanel.execute('/test2')
|
||||
commandPanel.execute('/test3')
|
||||
expect(commandPanel.history.length).toBe(3)
|
||||
expect(commandPanel.history[0]).toBe('/test1')
|
||||
expect(commandPanel.history[1]).toBe('/test2')
|
||||
expect(commandPanel.history[2]).toBe('/test3')
|
||||
expect(commandPanel.historyIndex).toBe(3)
|
||||
|
||||
rootView2 = RootView.deserialize(rootView.serialize())
|
||||
rootView.deactivate()
|
||||
rootView2.attachToDom()
|
||||
|
||||
commandPanel = rootView2.activateExtension(CommandPanel)
|
||||
expect(commandPanel.history.length).toBe(2)
|
||||
expect(commandPanel.history[0]).toBe('/test2')
|
||||
expect(commandPanel.history[1]).toBe('/test3')
|
||||
expect(commandPanel.historyIndex).toBe(2)
|
||||
|
||||
rootView2.deactivate()
|
||||
|
||||
describe "when core:close is triggered on the command panel", ->
|
||||
it "detaches the command panel, focuses the RootView and does not bubble the core:close event", ->
|
||||
commandPanel.attach()
|
||||
rootViewCloseHandler = jasmine.createSpy('rootViewCloseHandler')
|
||||
rootView.on 'core:close', rootViewCloseHandler
|
||||
spyOn(rootView, 'focus')
|
||||
|
||||
commandPanel.trigger('core:close')
|
||||
|
||||
expect(rootView.focus).toHaveBeenCalled()
|
||||
expect(rootViewCloseHandler).not.toHaveBeenCalled()
|
||||
expect(commandPanel.hasParent()).toBeFalsy()
|
||||
|
||||
describe "when command-panel:toggle is triggered on the root view", ->
|
||||
beforeEach ->
|
||||
rootView.attachToDom()
|
||||
|
||||
describe "when the command panel is visible", ->
|
||||
beforeEach ->
|
||||
commandPanel.attach()
|
||||
|
||||
describe "when the mini editor is focused", ->
|
||||
it "closes the command panel", ->
|
||||
expect(commandPanel.miniEditor.hiddenInput).toMatchSelector ':focus'
|
||||
rootView.trigger 'command-panel:toggle'
|
||||
expect(commandPanel.hasParent()).toBeFalsy()
|
||||
|
||||
describe "when the mini editor is not focused", ->
|
||||
it "focuses the mini editor", ->
|
||||
rootView.focus()
|
||||
expect(commandPanel.miniEditor.hiddenInput).not.toMatchSelector ':focus'
|
||||
rootView.trigger 'command-panel:toggle'
|
||||
expect(commandPanel.hasParent()).toBeTruthy()
|
||||
expect(commandPanel.miniEditor.hiddenInput).toMatchSelector ':focus'
|
||||
|
||||
describe "when the command panel is not visible", ->
|
||||
it "shows and focuses the command panel", ->
|
||||
expect(commandPanel.hasParent()).toBeFalsy()
|
||||
rootView.trigger 'command-panel:toggle'
|
||||
expect(commandPanel.hasParent()).toBeTruthy()
|
||||
|
||||
describe "when command-panel:toggle-preview is triggered on the root view", ->
|
||||
beforeEach ->
|
||||
rootView.attachToDom()
|
||||
|
||||
describe "when the preview list is/was previously visible", ->
|
||||
beforeEach ->
|
||||
rootView.trigger 'command-panel:toggle'
|
||||
waitsForPromise -> commandPanel.execute('X x/a+/')
|
||||
|
||||
describe "when the command panel is visible", ->
|
||||
beforeEach ->
|
||||
expect(commandPanel.hasParent()).toBeTruthy()
|
||||
|
||||
describe "when the preview list is visible", ->
|
||||
beforeEach ->
|
||||
expect(commandPanel.previewList).toBeVisible()
|
||||
|
||||
describe "when the preview list is focused", ->
|
||||
it "hides the command panel", ->
|
||||
expect(commandPanel.previewList).toMatchSelector(':focus')
|
||||
rootView.trigger 'command-panel:toggle-preview'
|
||||
expect(commandPanel.hasParent()).toBeFalsy()
|
||||
|
||||
describe "when the preview list is not focused", ->
|
||||
it "focuses the preview list", ->
|
||||
commandPanel.miniEditor.focus()
|
||||
rootView.trigger 'command-panel:toggle-preview'
|
||||
expect(commandPanel.previewList).toMatchSelector(':focus')
|
||||
|
||||
describe "when the preview list is not visible", ->
|
||||
beforeEach ->
|
||||
commandPanel.miniEditor.focus()
|
||||
rootView.trigger 'command-panel:toggle'
|
||||
rootView.trigger 'command-panel:toggle'
|
||||
expect(commandPanel.hasParent()).toBeTruthy()
|
||||
expect(commandPanel.previewList).toBeHidden()
|
||||
|
||||
it "shows and focuses the preview list", ->
|
||||
rootView.trigger 'command-panel:toggle-preview'
|
||||
expect(commandPanel.previewList).toBeVisible()
|
||||
expect(commandPanel.previewList).toMatchSelector(':focus')
|
||||
|
||||
describe "when the command panel is not visible", ->
|
||||
it "shows the command panel and the preview list, and focuses the preview list", ->
|
||||
commandPanel.miniEditor.focus()
|
||||
rootView.trigger 'command-panel:toggle'
|
||||
expect(commandPanel.hasParent()).toBeFalsy()
|
||||
|
||||
rootView.trigger 'command-panel:toggle-preview'
|
||||
expect(commandPanel.hasParent()).toBeTruthy()
|
||||
expect(commandPanel.previewList).toBeVisible()
|
||||
expect(commandPanel.previewList).toMatchSelector(':focus')
|
||||
|
||||
describe "when the preview list has never been opened", ->
|
||||
describe "when the command panel is visible", ->
|
||||
beforeEach ->
|
||||
rootView.trigger 'command-panel:toggle'
|
||||
expect(commandPanel.hasParent()).toBeTruthy()
|
||||
|
||||
describe "when the mini editor is focused", ->
|
||||
it "retains focus on the mini editor and does not show the preview list", ->
|
||||
expect(commandPanel.miniEditor.isFocused).toBeTruthy()
|
||||
rootView.trigger 'command-panel:toggle-preview'
|
||||
expect(commandPanel.previewList).toBeHidden()
|
||||
expect(commandPanel.miniEditor.isFocused).toBeTruthy()
|
||||
|
||||
describe "when the mini editor is not focused", ->
|
||||
it "focuses the mini editor and does not show the preview list", ->
|
||||
rootView.focus()
|
||||
rootView.trigger 'command-panel:toggle-preview'
|
||||
expect(commandPanel.previewList).toBeHidden()
|
||||
expect(commandPanel.miniEditor.isFocused).toBeTruthy()
|
||||
|
||||
describe "when the command panel is not visible", ->
|
||||
it "shows the command panel and focuses the mini editor, but does not show the preview list", ->
|
||||
|
||||
describe "when tool-panel:unfocus is triggered on the command panel", ->
|
||||
it "returns focus to the root view but does not hide the command panel", ->
|
||||
rootView.attachToDom()
|
||||
commandPanel.attach()
|
||||
expect(commandPanel.miniEditor.hiddenInput).toMatchSelector ':focus'
|
||||
commandPanel.trigger 'tool-panel:unfocus'
|
||||
expect(commandPanel.hasParent()).toBeTruthy()
|
||||
expect(commandPanel.miniEditor.hiddenInput).not.toMatchSelector ':focus'
|
||||
|
||||
describe "when command-panel:repeat-relative-address is triggered on the root view", ->
|
||||
it "repeats the last search command if there is one", ->
|
||||
rootView.trigger 'command-panel:repeat-relative-address'
|
||||
|
||||
editor.setCursorScreenPosition([4, 0])
|
||||
|
||||
commandPanel.execute("/current")
|
||||
expect(editor.getSelection().getBufferRange()).toEqual [[5,6], [5,13]]
|
||||
|
||||
rootView.trigger 'command-panel:repeat-relative-address'
|
||||
expect(editor.getSelection().getBufferRange()).toEqual [[6,6], [6,13]]
|
||||
|
||||
commandPanel.execute('s/r/R/g')
|
||||
|
||||
rootView.trigger 'command-panel:repeat-relative-address'
|
||||
expect(editor.getSelection().getBufferRange()).toEqual [[6,34], [6,41]]
|
||||
|
||||
commandPanel.execute('0')
|
||||
commandPanel.execute('/sort/ s/r/R/') # this contains a substitution... won't be repeated
|
||||
|
||||
rootView.trigger 'command-panel:repeat-relative-address'
|
||||
expect(editor.getSelection().getBufferRange()).toEqual [[3,31], [3,38]]
|
||||
|
||||
describe "when command-panel:repeat-relative-address-in-reverse is triggered on the root view", ->
|
||||
it "it repeats the last relative address in the reverse direction", ->
|
||||
rootView.trigger 'command-panel:repeat-relative-address-in-reverse'
|
||||
|
||||
editor.setCursorScreenPosition([6, 0])
|
||||
|
||||
commandPanel.execute("/current")
|
||||
expect(editor.getSelection().getBufferRange()).toEqual [[6,6], [6,13]]
|
||||
|
||||
rootView.trigger 'command-panel:repeat-relative-address-in-reverse'
|
||||
expect(editor.getSelection().getBufferRange()).toEqual [[5,6], [5,13]]
|
||||
|
||||
describe "when command-panel:set-selection-as-regex-address is triggered on the root view", ->
|
||||
it "sets the @lastRelativeAddress to a RegexAddress of the current selection", ->
|
||||
rootView.open(require.resolve('fixtures/sample.js'))
|
||||
rootView.getActiveEditor().setSelectedBufferRange([[1,21],[1,28]])
|
||||
|
||||
commandInterpreter = commandPanel.commandInterpreter
|
||||
expect(commandInterpreter.lastRelativeAddress).toBeUndefined()
|
||||
rootView.trigger 'command-panel:set-selection-as-regex-address'
|
||||
expect(commandInterpreter.lastRelativeAddress.subcommands.length).toBe 1
|
||||
expect(commandInterpreter.lastRelativeAddress.subcommands[0].regex.toString()).toEqual "/\\(items\\)/i"
|
||||
|
||||
describe "when command-panel:find-in-file is triggered on an editor", ->
|
||||
it "pre-populates the command panel's editor with / and moves the cursor to the last column", ->
|
||||
spyOn(commandPanel, 'attach').andCallThrough()
|
||||
commandPanel.miniEditor.setText("foo")
|
||||
commandPanel.miniEditor.setCursorBufferPosition([0, 0])
|
||||
|
||||
rootView.getActiveEditor().trigger "command-panel:find-in-file"
|
||||
expect(commandPanel.attach).toHaveBeenCalled()
|
||||
expect(commandPanel.parent).not.toBeEmpty()
|
||||
expect(commandPanel.miniEditor.getText()).toBe "/"
|
||||
expect(commandPanel.miniEditor.getCursorBufferPosition()).toEqual [0, 1]
|
||||
|
||||
describe "when command-panel:find-in-project is triggered on the root view", ->
|
||||
it "pre-populates the command panel's editor with Xx/ and moves the cursor to the last column", ->
|
||||
spyOn(commandPanel, 'attach').andCallThrough()
|
||||
commandPanel.miniEditor.setText("foo")
|
||||
commandPanel.miniEditor.setCursorBufferPosition([0, 0])
|
||||
|
||||
rootView.trigger "command-panel:find-in-project"
|
||||
expect(commandPanel.attach).toHaveBeenCalled()
|
||||
expect(commandPanel.parent).not.toBeEmpty()
|
||||
expect(commandPanel.miniEditor.getText()).toBe "Xx/"
|
||||
expect(commandPanel.miniEditor.getCursorBufferPosition()).toEqual [0, 3]
|
||||
|
||||
describe "when return is pressed on the panel's editor", ->
|
||||
describe "if the command has an immediate effect", ->
|
||||
it "executes it immediately on the current buffer", ->
|
||||
rootView.trigger 'command-panel:toggle'
|
||||
commandPanel.miniEditor.insertText ',s/sort/torta/g'
|
||||
commandPanel.miniEditor.hiddenInput.trigger keydownEvent('enter')
|
||||
|
||||
expect(buffer.lineForRow(0)).toMatch /quicktorta/
|
||||
expect(buffer.lineForRow(1)).toMatch /var torta/
|
||||
|
||||
describe "when the command returns operations to be previewed", ->
|
||||
beforeEach ->
|
||||
rootView.attachToDom()
|
||||
editor.remove()
|
||||
rootView.trigger 'command-panel:toggle'
|
||||
waitsForPromise -> commandPanel.execute('X x/a+/')
|
||||
|
||||
it "displays and focuses the operation preview list", ->
|
||||
expect(commandPanel).toBeVisible()
|
||||
expect(commandPanel.previewList).toBeVisible()
|
||||
expect(commandPanel.previewList).toMatchSelector ':focus'
|
||||
previewItem = commandPanel.previewList.find("li:contains(dir/a):first")
|
||||
expect(previewItem.find('.path').text()).toBe "dir/a"
|
||||
expect(previewItem.find('.preview').text()).toBe "aaa bbb"
|
||||
expect(previewItem.find('.preview > .match').text()).toBe "aaa"
|
||||
|
||||
rootView.trigger 'command-panel:toggle-preview' # ensure we can close panel without problems
|
||||
expect(commandPanel).toBeHidden()
|
||||
|
||||
it "destroys previously previewed operations if there are any", ->
|
||||
waitsForPromise -> commandPanel.execute('X x/b+/')
|
||||
# there shouldn't be any dangling operations after this
|
||||
|
||||
describe "if the command is malformed", ->
|
||||
it "adds and removes an error class to the command panel and does not close it", ->
|
||||
rootView.trigger 'command-panel:toggle'
|
||||
commandPanel.miniEditor.insertText 'garbage-command!!'
|
||||
|
||||
commandPanel.miniEditor.hiddenInput.trigger keydownEvent('enter')
|
||||
expect(commandPanel.parent()).toExist()
|
||||
expect(commandPanel).toHaveClass 'error'
|
||||
|
||||
advanceClock 400
|
||||
|
||||
expect(commandPanel).not.toHaveClass 'error'
|
||||
|
||||
describe "if the command returns an error message", ->
|
||||
beforeEach ->
|
||||
rootView.attachToDom()
|
||||
rootView.trigger 'command-panel:toggle'
|
||||
commandPanel.miniEditor.insertText '/garbage'
|
||||
expect(commandPanel.errorMessages).not.toBeVisible()
|
||||
commandPanel.miniEditor.hiddenInput.trigger keydownEvent('enter')
|
||||
|
||||
it "adds and removes an error class to the command panel and displays the error message", ->
|
||||
expect(commandPanel).toBeVisible()
|
||||
expect(commandPanel.errorMessages).toBeVisible()
|
||||
expect(commandPanel).toHaveClass 'error'
|
||||
|
||||
it "removes the error message when the command-panel is toggled", ->
|
||||
rootView.trigger 'command-panel:toggle' # off
|
||||
rootView.trigger 'command-panel:toggle' # on
|
||||
expect(commandPanel).toBeVisible()
|
||||
expect(commandPanel.errorMessages).not.toBeVisible()
|
||||
|
||||
|
||||
describe "when the command contains an escaped charachter", ->
|
||||
it "executes the command with the escaped character (instead of as a backslash followed by the character)", ->
|
||||
rootView.trigger 'command-panel:toggle'
|
||||
|
||||
editSession = rootView.open(require.resolve 'fixtures/sample-with-tabs.coffee')
|
||||
editor.edit(editSession)
|
||||
commandPanel.miniEditor.setText "/\\tsell"
|
||||
commandPanel.miniEditor.hiddenInput.trigger keydownEvent('enter')
|
||||
expect(editor.getSelectedBufferRange()).toEqual [[3,1],[3,6]]
|
||||
|
||||
describe "when move-up and move-down are triggerred on the editor", ->
|
||||
it "navigates forward and backward through the command history", ->
|
||||
commandPanel.execute 's/war/peace/g'
|
||||
commandPanel.execute 's/twinkies/wheatgrass/g'
|
||||
|
||||
rootView.trigger 'command-panel:toggle'
|
||||
|
||||
commandPanel.miniEditor.trigger 'core:move-up'
|
||||
expect(commandPanel.miniEditor.getText()).toBe 's/twinkies/wheatgrass/g'
|
||||
commandPanel.miniEditor.trigger 'core:move-up'
|
||||
expect(commandPanel.miniEditor.getText()).toBe 's/war/peace/g'
|
||||
commandPanel.miniEditor.trigger 'core:move-up'
|
||||
expect(commandPanel.miniEditor.getText()).toBe 's/war/peace/g'
|
||||
commandPanel.miniEditor.trigger 'core:move-down'
|
||||
expect(commandPanel.miniEditor.getText()).toBe 's/twinkies/wheatgrass/g'
|
||||
commandPanel.miniEditor.trigger 'core:move-down'
|
||||
expect(commandPanel.miniEditor.getText()).toBe ''
|
||||
|
||||
describe "when the preview list is focused with search operations", ->
|
||||
previewList = null
|
||||
|
||||
beforeEach ->
|
||||
previewList = commandPanel.previewList
|
||||
rootView.trigger 'command-panel:toggle'
|
||||
waitsForPromise -> commandPanel.execute('X x/a/')
|
||||
|
||||
describe "when move-down and move-up are triggered on the preview list", ->
|
||||
it "selects the next/previous operation (if there is one), and scrolls the list if needed", ->
|
||||
rootView.attachToDom()
|
||||
expect(previewList.find('li:eq(0)')).toHaveClass 'selected'
|
||||
expect(previewList.getSelectedOperation()).toBe previewList.getOperations()[0]
|
||||
|
||||
previewList.trigger 'core:move-up'
|
||||
expect(previewList.find('li:eq(0)')).toHaveClass 'selected'
|
||||
expect(previewList.getSelectedOperation()).toBe previewList.getOperations()[0]
|
||||
|
||||
previewList.trigger 'core:move-down'
|
||||
expect(previewList.find('li:eq(1)')).toHaveClass 'selected'
|
||||
expect(previewList.getSelectedOperation()).toBe previewList.getOperations()[1]
|
||||
|
||||
previewList.trigger 'core:move-down'
|
||||
expect(previewList.find('li:eq(2)')).toHaveClass 'selected'
|
||||
expect(previewList.getSelectedOperation()).toBe previewList.getOperations()[2]
|
||||
|
||||
previewList.trigger 'core:move-up'
|
||||
expect(previewList.find('li:eq(1)')).toHaveClass 'selected'
|
||||
expect(previewList.getSelectedOperation()).toBe previewList.getOperations()[1]
|
||||
|
||||
_.times previewList.getOperations().length, -> previewList.trigger 'core:move-down'
|
||||
|
||||
expect(previewList.find('li:last')).toHaveClass 'selected'
|
||||
expect(previewList.getSelectedOperation()).toBe _.last(previewList.getOperations())
|
||||
|
||||
expect(previewList.scrollBottom()).toBeCloseTo previewList.prop('scrollHeight'), -1
|
||||
|
||||
_.times previewList.getOperations().length, -> previewList.trigger 'core:move-up'
|
||||
|
||||
it "doesn't bubble up the event and the command panel text doesn't change", ->
|
||||
rootView.attachToDom()
|
||||
commandPanel.miniEditor.setText "command"
|
||||
previewList.focus()
|
||||
previewList.trigger 'core:move-up'
|
||||
expect(previewList.find('li:eq(0)')).toHaveClass 'selected'
|
||||
expect(commandPanel.miniEditor.getText()).toBe 'command'
|
||||
previewList.trigger 'core:move-down'
|
||||
expect(previewList.find('li:eq(1)')).toHaveClass 'selected'
|
||||
expect(commandPanel.miniEditor.getText()).toBe 'command'
|
||||
|
||||
describe "when core:confirm is triggered on the preview list", ->
|
||||
it "opens the operation's buffer, selects and scrolls to the search result, and focuses the active editor", ->
|
||||
rootView.height(200)
|
||||
rootView.attachToDom()
|
||||
|
||||
waitsForPromise -> commandPanel.execute('X x/apply/') # use apply because it is at the end of the file
|
||||
runs ->
|
||||
spyOn(rootView, 'focus')
|
||||
executeHandler = jasmine.createSpy('executeHandler')
|
||||
commandPanel.on 'core:confirm', executeHandler
|
||||
|
||||
_.times 4, -> previewList.trigger 'core:move-down'
|
||||
operation = previewList.getSelectedOperation()
|
||||
|
||||
previewList.trigger 'core:confirm'
|
||||
|
||||
editSession = rootView.getActiveEditSession()
|
||||
expect(editSession.buffer.getPath()).toBe project.resolve(operation.getPath())
|
||||
expect(editSession.getSelectedBufferRange()).toEqual operation.getBufferRange()
|
||||
expect(editSession.getSelectedBufferRange()).toEqual operation.getBufferRange()
|
||||
expect(editor.isScreenRowVisible(editor.getCursorScreenRow())).toBeTruthy()
|
||||
expect(rootView.focus).toHaveBeenCalled()
|
||||
|
||||
expect(executeHandler).not.toHaveBeenCalled()
|
||||
|
||||
describe "when an operation in the preview list is clicked", ->
|
||||
it "opens the operation's buffer, selects the search result, and focuses the active editor", ->
|
||||
spyOn(rootView, 'focus')
|
||||
operation = previewList.getOperations()[4]
|
||||
|
||||
previewList.find('li:eq(4) span').mousedown()
|
||||
|
||||
expect(previewList.getSelectedOperation()).toBe operation
|
||||
editSession = rootView.getActiveEditSession()
|
||||
expect(editSession.buffer.getPath()).toBe project.resolve(operation.getPath())
|
||||
expect(editSession.getSelectedBufferRange()).toEqual operation.getBufferRange()
|
||||
expect(rootView.focus).toHaveBeenCalled()
|
||||
Reference in New Issue
Block a user