Skip to content

Repository files navigation

coc-test logo

coc-test

CI

coc-test is an integration test runner for coc.nvim extensions. It bundles JavaScript and TypeScript tests, starts Vim or Neovim with coc.nvim and the current extension activated, and runs the tests with Node.js's built-in test runner.

Each test file runs in an isolated child process with its own editor, coc.nvim instance, and data directory. The runner reports per-file progress in real time, cleans up all child resources when a test finishes, and prints failure details with source-mapped stack traces.

Requirements

  • Node.js 22.15 or newer
  • Vim or Neovim
  • A coc.nvim extension with a valid main entry in package.json

Installation

Install coc-test as a development dependency in the extension root:

npm install --save-dev coc-test

Quick start

Run the interactive initializer:

npx coc-test --init

The initializer:

  • checks whether vim and nvim are available;
  • optionally adds the coc-test configuration to package.json;
  • creates a starter test in test/ using a filename you choose;
  • optionally adds a test script when one does not already exist; and
  • optionally creates a GitHub Actions workflow, with a filename you choose, for both Vim and Neovim.

Existing test files, scripts, and workflows are not overwritten without confirmation.

Run all TypeScript tests under test/:

npx coc-test 'test/**/*.test.ts'

Neovim is used by default. Select Vim explicitly with --vim:

npx coc-test --vim 'test/**/*.test.ts'

Writing tests

Tests use the APIs from node:test. Imports from coc.nvim refer to the coc.nvim instance attached to that test's editor. Importing the extension's main entry returns the exports of the activated extension.

import assert from 'node:assert/strict'
import { beforeEach, describe, it } from 'node:test'
import { commands, workspace } from 'coc.nvim'
import extension from '../lib/index.js'

beforeEach(async () => {
  await workspace.nvim.command('enew!')
})

describe('extension', () => {
  it('loads the activated extension', () => {
    assert.ok(extension)
    assert.equal(typeof commands.executeCommand, 'function')
  })

  it('communicates with the editor', async () => {
    assert.equal(await workspace.nvim.eval('1 + 1'), 2)
  })
})

When the extension is built before testing, the extension import path must resolve to the same file as the package's main field.

Extensions can configure entryFile (see [Configuration] (#configuration)); their source modules can then be imported directly with relative paths.

Configuration

Configure the runner with a coc-test object in the extension's package.json:

{
  "coc-test": {
    "entryFile": "src/index.ts",
    "user-settings": {
      "suggest.noselect": true
    },
    "externals": ["vscode-languageserver"],
    "target": "commonjs"
  }
}
Property Default Description
user-settings {} coc.nvim settings written to the isolated test configuration.
entryFile Source entry to bundle and activate instead of the package main file.
externals [] esbuild external specifiers to leave out of the entryFile bundle.
target "commonjs" Bundle format: "commonjs" or "esm".

Source entry and shared modules

Without entryFile, coc-test activates the extension's main file. With entryFile, it builds the source in memory and activates that bundle; no bundle file or generated package manifest is written to the project.

Tests can import source modules with normal relative paths:

import { getStore } from '../src/index.ts'
import { store } from '../src/store.ts'

These imports resolve to the same module instances the plugin itself runs, so state is shared between the plugin and the tests instead of loading independent copies.

Dependency bundling

Dependencies imported by entryFile, including packages in node_modules, are bundled by default. Add a package to externals when it must be resolved at runtime instead. Values are passed to esbuild's external option; a package name also covers its subpaths.

coc.nvim is supplied by the test runtime rather than bundled. Node.js built-in modules also remain external.

Bundle target

target chooses both the esbuild output and how coc.nvim loads the in-memory source:

  • "commonjs" is the default and works with Node.js 22.15 or newer.
  • "esm" uses coc.nvim's ESM source loader and requires Node.js 24 or newer.

Watch mode

Pass -w or --watch to keep the runner active:

npx coc-test --watch 'test/**/*.test.ts'

When a test file or one of its imported dependencies changes, only the affected test file is rerun. When the extension entry or one of its local dependencies changes, all tests are rerun.

If a change occurs while tests are running, the affected run is cancelled first. Its Node.js child process, editor, and coc.nvim environment are fully released before the replacement run starts.

Downloading coc.nvim

By default, coc-test downloads the latest coc.nvim release and caches it by version, so repeated runs reuse the extracted checkout.

Using a local coc.nvim build

During coc.nvim or runner development, use an existing build to avoid downloading:

npx coc-test --coc-path /path/to/coc.nvim 'test/**/*.test.ts'

You can also set COC_TEST_COC_PATH:

COC_TEST_COC_PATH=/path/to/coc.nvim npm test

Useful options

--nvim                         Run tests on Neovim (default)
--vim                          Run tests on Vim
-w, --watch                    Watch files and rerun affected tests
--test-name-pattern <pattern>  Run tests matching a regular expression (must be valid)
--coc-path <directory>         Use an existing coc.nvim build
-u, --use <version>            Use a specific coc.nvim release tag
-d, --download                 Force a fresh coc.nvim download
--force-exit                   Force the main process to exit after the run

Long options also accept --option=value, for example --test-name-pattern=^foo$ or --coc-path=/path/to/coc.nvim.

Run npx coc-test --help for the complete command reference.

Environment variables

  • VIM_COMMAND overrides the vim executable.
  • NVIM_COMMAND overrides the nvim executable.
  • COC_TEST_COC_PATH provides a local coc.nvim directory instead of --coc-path.
  • NO_COLOR disables ANSI colors during --init.
  • FORCE_COLOR forces ANSI colors during --init.

Developing coc-test

The unit tests do not download coc.nvim:

npm test

Run the integration fixture against an existing coc.nvim checkout or build:

npm run test:nvim -- --coc-path /path/to/coc.nvim
npm run test:vim -- --coc-path /path/to/coc.nvim

# Alternatively, provide the path through the environment.
COC_TEST_COC_PATH=/path/to/coc.nvim npm run test:nvim

LICENSE

MIT

About

Integration test runner for coc.nvim extensions

Resources

Stars

2 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages