Developer Hub
Testing
A focused guide for the testing stage of extension development. coc.nvim extensions expose an activate(context) entry point to the Node.js extension host.
Testing extensions
coc-test runs Node.js tests against an editor process. Keep unit tests independent, and use editor-backed tests for commands, buffers, and UI behavior.
Terminal
| 1 | npm install --save-dev coc-test |
| 2 | npm run typecheck |
| 3 | npm run build |
| 4 | npm run test:nvim |
| 5 | npm run test:vim |
test/index.test.ts
| 1 | import assert from 'node:assert/strict' |
| 2 | import { beforeEach, describe, it } from 'node:test' |
| 3 | import { commands, workspace } from 'coc.nvim' |
| 4 | import { commandId } from '../src/index.ts' |
| 5 | |
| 6 | beforeEach(async () => { |
| 7 | await workspace.nvim.command('enew!') |
| 8 | }) |
| 9 | |
| 10 | describe('coc-demo', () => { |
| 11 | it('activates and registers its command', () => { |
| 12 | assert.equal(commands.has(commandId), true) |
| 13 | }) |
| 14 | |
| 15 | it('executes through the editor-backed coc.nvim runtime', async () => { |
| 16 | const message = await commands.executeCommand(commandId, 'Vim') |
| 17 | assert.equal(message, 'Hello from Vim!') |
| 18 | assert.equal(await workspace.nvim.eval('bufexists(bufnr())'), 1) |
| 19 | }) |
| 20 | }) |
Test both editors
Vim and Neovim differ in RPC, floating windows, and terminal behavior. Run the same suite in both lanes when the extension uses editor APIs. A passing lane means assertions, RPC, unhandled rejections, and teardown all complete cleanly.
Headless CI matrix
The coc-test --nvim and coc-test --vim lanes start the corresponding editor for the test process. Keep both commands in CI and inspect their exit status; do not replace them with a unit-only test.