2 # Copyright Simon Lydell 2015, 2016.
4 # This file is part of VimFx.
6 # VimFx is free software: you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation, either version 3 of the License, or
9 # (at your option) any later version.
11 # VimFx is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
16 # You should have received a copy of the GNU General Public License
17 # along with VimFx. If not, see <http://www.gnu.org/licenses/>.
20 testUtils = require('./utils')
21 createConfigAPI = require('../lib/api')
22 defaults = require('../lib/defaults')
23 prefs = require('../lib/prefs')
24 utils = require('../lib/utils')
28 exports['test exports'] = (assert, $vimfx) ->
29 vimfx = createConfigAPI($vimfx)
31 assert.equal(typeof vimfx.get, 'function', 'get')
32 assert.equal(typeof vimfx.getDefault, 'function', 'getDefault')
33 assert.equal(typeof vimfx.set, 'function', 'set')
34 assert.equal(typeof vimfx.addCommand, 'function', 'addCommand')
35 assert.equal(typeof vimfx.addOptionOverrides, 'function',
37 assert.equal(typeof vimfx.addKeyOverrides, 'function', 'addKeyOverrides')
38 assert.equal(typeof vimfx.send, 'function', 'send')
39 assert.equal(typeof vimfx.on, 'function', 'on')
40 assert.equal(typeof vimfx.off, 'function', 'off')
41 assert.equal(vimfx.modes, $vimfx.modes, 'modes')
43 exports['test vimfx.get and vimfx.set'] = (assert, $vimfx, teardown) ->
44 vimfx = createConfigAPI($vimfx)
46 resetHintChars = prefs.tmp('hint_chars', 'abcd')
47 resetBlacklist = prefs.tmp('black_list', null)
48 originalOptions = Object.assign({}, $vimfx.options)
52 $vimfx.options = originalOptions
55 assert.equal(vimfx.get('hint_chars'), 'abcd')
56 assert.ok(not prefs.has('black_list'))
58 vimfx.set('hint_chars', 'xyz')
59 assert.equal(vimfx.get('hint_chars'), 'xyz')
61 vimfx.set('black_list', 'test')
62 assert.equal(vimfx.get('black_list'), 'test')
64 vimfx.set('translations', {KeyQ: ['ö', 'Ö']})
65 assert.deepEqual(vimfx.get('translations'), {KeyQ: ['ö', 'Ö']})
67 $vimfx.emit('shutdown')
68 assert.equal(vimfx.get('hint_chars'), 'abcd')
69 assert.ok(not prefs.has('black_list'))
70 assert.deepEqual(vimfx.get('translations'), {})
72 exports['test vimfx.getDefault'] = (assert, $vimfx, teardown) ->
73 vimfx = createConfigAPI($vimfx)
75 reset = prefs.tmp('hint_chars', 'abcd')
80 assert.equal(vimfx.getDefault('hint_chars'), defaults.options.hint_chars)
82 exports['test customization'] = (assert, $vimfx, teardown) ->
83 vimfx = createConfigAPI($vimfx)
85 originalOptions = Object.assign({}, $vimfx.options)
86 originalCategories = Object.assign({}, $vimfx.options.categories)
87 $vimfx.options.keyValidator = null
88 $vimfx.options.ignore_keyboard_layout = true
89 vimfx.set('translations', {KeyQ: ['ö', 'Ö']})
91 $vimfx.options = originalOptions
92 $vimfx.options.categories = originalCategories
93 delete $vimfx.modes.normal.commands.test_command
94 delete $vimfx.modes.ignore.commands.test_command
98 event = {code: 'KeyQ'}
100 # Add a simple test command.
103 description: 'Test command'
105 vimfx.set('custom.mode.normal.test_command', 'ö')
107 # Add a slightly more complex command.
108 vimfx.get('categories')['new_category'] = {
114 description: 'Test ignore mode command'
116 category: 'new_category'
118 vimfx.set('custom.mode.ignore.test_command', 'ö <ö> <c-c-invalid>')
120 $vimfx.createKeyTrees()
122 # Test that the new simple command can be run.
123 $vimfx.reset('normal')
124 match = $vimfx.consumeKeyEvent(event, {mode: 'normal'}, null)
125 assert.equal(match.type, 'full')
126 assert.equal(match.command.run(), nonce)
128 # Test that the new complex command can be run.
129 $vimfx.reset('ignore')
130 match = $vimfx.consumeKeyEvent(event, {mode: 'ignore'}, null)
131 assert.equal(match.type, 'full')
132 assert.equal(match.command.run(), nonce)
134 modes = $vimfx.getGroupedCommands({enabledOnly: true})
136 # Test that the new simple command can show up in the help dialog.
137 mode_normal = modes.find((mode) -> mode._name == 'normal')
138 category_misc = mode_normal.categories.find(
139 (category) -> category._name == 'misc'
141 [..., {command: test_command}] = category_misc.commands
142 assert.equal(test_command.description, 'Test command')
144 # Test that the new complex command can show up in the help dialog.
145 mode_ignore = modes.find((mode) -> mode._name == 'ignore')
146 [category_new] = mode_ignore.categories
147 assert.equal(category_new.name, 'New category')
148 [test_command] = category_new.commands
149 assert.equal(test_command.command.description, 'Test ignore mode command')
150 assert.deepEqual(test_command.enabledSequences, ['ö'])
152 # Remove the added commands.
153 delete vimfx.modes.normal.commands.test_command
154 delete vimfx.modes.ignore.commands.test_command
155 $vimfx.createKeyTrees()
157 # Test that the new simple command cannot be run.
158 $vimfx.reset('normal')
159 match = $vimfx.consumeKeyEvent(event, {mode: 'normal'}, null)
160 if match.type == 'full'
161 value = try match.command.run() catch then null
162 assert.notEqual(value, nonce)
164 # Test that the new complex command cannot be run.
165 $vimfx.reset('ignore')
166 match = $vimfx.consumeKeyEvent(event, {mode: 'ignore'}, null)
167 if match.type == 'full'
168 value = try match.command.run() catch then null
169 assert.notEqual(value, nonce)
171 modes = $vimfx.getGroupedCommands({enabledOnly: true})
173 # Test that the new simple command cannot show up in the help dialog.
174 mode_normal = modes.find((mode) -> mode._name == 'normal')
175 category_misc = mode_normal.categories.find(
176 (category) -> category._name == 'misc'
178 [..., {command: last_command}] = category_misc.commands
179 assert.notEqual(last_command.description, 'Test command')
181 # Test that the new complex command cannot show up in the help dialog.
182 mode_ignore = modes.find((mode) -> mode._name == 'ignore')
183 [first_category] = mode_ignore.categories
184 assert.notEqual(first_category.name, 'New category')
186 exports['test vimfx.addCommand order'] = (assert, $vimfx, teardown) ->
187 vimfx = createConfigAPI($vimfx)
190 delete vimfx.modes.normal.commands.test_command
195 description: 'Test command'
197 }, Function.prototype)
198 vimfx.set('custom.mode.normal.test_command', 'ö')
200 modes = $vimfx.getGroupedCommands()
201 mode_normal = modes.find((mode) -> mode._name == 'normal')
202 category_misc = mode_normal.categories.find(
203 (category) -> category._name == 'misc'
205 [{command: first_command}] = category_misc.commands
206 assert.equal(first_command.description, 'Test command')
208 assert.ok('test_command' of vimfx.modes.normal.commands)
209 $vimfx.emit('shutdown')
210 assert.ok('test_command' not of vimfx.modes.normal.commands)
212 exports['test vimfx.addOptionOverrides'] = (assert, $vimfx, teardown) ->
213 vimfx = createConfigAPI($vimfx)
215 originalOptions = Object.assign({}, $vimfx.options)
216 originalOptionOverrides = Object.assign({}, $vimfx.optionOverrides)
217 $vimfx.optionOverrides = null
218 $vimfx.options.prevent_autofocus = true
220 reset?() # Defined below.
221 $vimfx.options = originalOptions
222 $vimfx.optionOverrides = originalOptionOverrides
225 vimfx.addOptionOverrides(
227 (location) -> location.hostname == 'example.com'
228 {prevent_autofocus: false}
232 assert.equal($vimfx.options.prevent_autofocus, true)
234 reset = testUtils.stub(utils, 'getCurrentLocation', -> {
235 hostname: 'example.com'
238 assert.equal($vimfx.options.prevent_autofocus, false)
240 $vimfx.emit('shutdown')
241 assert.equal($vimfx.options.prevent_autofocus, true)
243 exports['test vimfx.addKeyOverrides'] = (assert, $vimfx, teardown) ->
244 vimfx = createConfigAPI($vimfx)
246 originalOptions = Object.assign({}, $vimfx.options)
247 originalKeyOverrides = Object.assign({}, $vimfx.keyOverrides)
248 $vimfx.options.keyValidator = null
249 $vimfx.options.ignore_keyboard_layout = false
250 $vimfx.options.translations = {}
252 resetScrollToBottom?() # Defined below.
253 resetGetCurrentLocation?() # Defined below.
254 $vimfx.options = originalOptions
255 $vimfx.keyOverrides = originalKeyOverrides
258 vimfx.addKeyOverrides(
260 (location, mode) -> mode == 'normal' and location.hostname == 'example.co'
264 (location, mode) -> mode == 'ignore' and location.href == 'about:blank'
269 resetScrollToBottom = prefs.tmp('mode.normal.scroll_to_bottom', '<foobar>j')
270 $vimfx.createKeyTrees()
271 $vimfx.reset('normal')
273 match = $vimfx.consumeKeyEvent({key: 'j'}, {mode: 'ignore'}, null)
276 resetGetCurrentLocation = testUtils.stub(utils, 'getCurrentLocation', -> {
277 hostname: 'example.co'
281 match = $vimfx.consumeKeyEvent({key: '1'}, {mode: 'normal'}, null)
282 assert.equal(match.type, 'count')
283 assert.equal(match.count, 1)
285 match = $vimfx.consumeKeyEvent({key: 'j'}, {mode: 'normal'}, null)
288 match = $vimfx.consumeKeyEvent({key: 'foobar', ctrlKey: true},
289 {mode: 'normal'}, null)
292 match = $vimfx.consumeKeyEvent({key: 'foobar'}, {mode: 'normal'}, null)
293 assert.equal(match.type, 'partial')
294 match = $vimfx.consumeKeyEvent({key: 'j'}, {mode: 'normal'}, null)
295 assert.equal(match.type, 'full')
296 assert.strictEqual(match.count, undefined)
298 $vimfx.reset('ignore')
300 match = $vimfx.consumeKeyEvent({key: 'j'}, {mode: 'ignore'}, null)
303 match = $vimfx.consumeKeyEvent({key: 'escape'}, {mode: 'ignore'}, null)
306 $vimfx.emit('shutdown')
308 $vimfx.reset('normal')
309 match = $vimfx.consumeKeyEvent({key: 'j'}, {mode: 'normal'}, null)
312 $vimfx.reset('ignore')
313 match = $vimfx.consumeKeyEvent({key: 'escape'}, {mode: 'ignore'}, null)
316 exports['test vimfx.send'] = (assert, $vimfx) ->
317 vimfx = createConfigAPI($vimfx)
319 messageManager = new testUtils.MockMessageManager()
320 vim = new testUtils.MockVim(messageManager)
322 vimfx.send(vim, 'message', {example: 5})
323 assert.equal(messageManager.sendAsyncMessageCalls, 1)
324 assert.equal(messageManager.addMessageListenerCalls, 0)
325 assert.equal(messageManager.removeMessageListenerCalls, 0)
327 vimfx.send(vim, 'message2', null, ->)
328 assert.equal(messageManager.sendAsyncMessageCalls, 2)
329 assert.equal(messageManager.addMessageListenerCalls, 1)
330 assert.equal(messageManager.removeMessageListenerCalls, 0)
332 $vimfx.emit('shutdown')
333 assert.equal(messageManager.sendAsyncMessageCalls, 2)
334 assert.equal(messageManager.addMessageListenerCalls, 1)
335 assert.equal(messageManager.removeMessageListenerCalls, 0)
337 exports['test vimfx.on and vimfx.off'] = (assert, $vimfx) ->
338 vimfx = createConfigAPI($vimfx)
341 count = -> callCount += 1
342 vimfx.on('foo', count)
343 vimfx.on('bar', count)
346 assert.equal(callCount, 1)
349 assert.equal(callCount, 2)
351 vimfx.off('bar', count)
353 assert.equal(callCount, 2)
355 $vimfx.emit('shutdown')
358 assert.equal(callCount, 2)
360 exports['test vimfx.[gs]et(Default)? errors'] = (assert, $vimfx) ->
361 vimfx = createConfigAPI($vimfx)
363 throws(assert, /unknown pref/i, 'undefined', ->
367 throws(assert, /unknown pref/i, 'undefined', ->
371 throws(assert, /unknown pref/i, 'undefined', ->
375 throws(assert, /unknown pref/i, 'unknown_pref', ->
376 vimfx.get('unknown_pref')
379 throws(assert, /unknown pref/i, 'unknown_pref', ->
380 vimfx.getDefault('unknown_pref')
383 throws(assert, /no default/i, 'custom.mode.normal.foo', ->
384 vimfx.getDefault('custom.mode.normal.foo')
387 throws(assert, /no default/i, 'translations', ->
388 vimfx.getDefault('translations')
391 throws(assert, /unknown pref/i, 'unknown_pref', ->
392 vimfx.set('unknown_pref', 'foo')
395 throws(assert, /boolean, number, string or null/i, 'undefined', ->
396 vimfx.set('hint_chars')
399 throws(assert, /boolean, number, string or null/i, 'object', ->
400 vimfx.set('hint_chars', ['a', 'b', 'c'])
403 exports['test vimfx.addCommand errors'] = (assert, $vimfx) ->
404 vimfx = createConfigAPI($vimfx)
406 throws(assert, /name.+string.+required/i, 'undefined', ->
410 throws(assert, /name.+a-z.+underscore/i, 'Command', ->
411 vimfx.addCommand({name: 'Command'})
414 throws(assert, /name.+a-z.+underscore/i, 'command-name', ->
415 vimfx.addCommand({name: 'command-name'})
418 throws(assert, /name.+a-z.+underscore/i, 'ö', ->
419 vimfx.addCommand({name: 'ö'})
422 throws(assert, /non-empty description/i, 'undefined', ->
423 vimfx.addCommand({name: 'test'})
426 throws(assert, /non-empty description/i, '', ->
427 vimfx.addCommand({name: 'test', description: ''})
430 throws(assert, /unknown mode.+available.+normal/i, 'toString', ->
431 vimfx.addCommand({name: 'test', description: 'Test', mode: 'toString'})
434 throws(assert, /unknown category.+available.+location/i, 'toString', ->
435 vimfx.addCommand({name: 'test', description: 'Test', category: 'toString'})
438 throws(assert, /order.+number/i, 'false', ->
439 vimfx.addCommand({name: 'test', description: 'Test', order: false})
442 throws(assert, /function/i, 'undefined', ->
443 vimfx.addCommand({name: 'test', description: 'Test'})
446 throws(assert, /function/i, 'false', ->
447 vimfx.addCommand({name: 'test_command', description: 'Test command'}, false)
450 exports['test vimfx.send errors'] = (assert, $vimfx) ->
451 vimfx = createConfigAPI($vimfx)
453 vim = new testUtils.MockVim()
455 throws(assert, /vim object/i, 'undefined', ->
459 throws(assert, /vim object/i, '[object Object]', ->
460 vimfx.send({mode: 'normal'})
463 throws(assert, /message string/i, 'undefined', ->
467 throws(assert, /message string/i, 'false', ->
468 vimfx.send(vim, false)
471 throws(assert, /not.+function/i, 'function () {}', ->
472 vimfx.send(vim, 'message', ->)
475 throws(assert, /if provided.+function/i, '5', ->
476 vimfx.send(vim, 'message', null, 5)