neovim
Version:
Nvim msgpack API client and remote plugin provider
385 lines (384 loc) • 20.4 kB
JavaScript
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const node_assert_1 = __importDefault(require("node:assert"));
const expect_1 = require("expect");
const jestMock = __importStar(require("jest-mock"));
const testUtil = __importStar(require("../testUtil"));
function wait(ms) {
return new Promise(resolve => {
setTimeout(() => {
resolve();
}, ms);
});
}
describe('Buffer API', () => {
let nvim;
// utility to allow each test to be run in its
// own buffer
function withBuffer(lines, test) {
return () => __awaiter(this, void 0, void 0, function* () {
yield nvim.command('new!');
const buffer = yield nvim.buffer;
if (lines) {
yield buffer.replace(lines, 0);
}
yield test(buffer);
yield nvim.command(`bd! ${buffer.id}`);
});
}
before(() => __awaiter(void 0, void 0, void 0, function* () {
[, nvim] = testUtil.startNvim();
}));
after(() => {
testUtil.stopNvim();
});
it('gets the current buffer', withBuffer([], (buffer) => __awaiter(void 0, void 0, void 0, function* () {
(0, expect_1.expect)(buffer).toBeInstanceOf(nvim.Buffer);
})));
it('get bufnr by id', withBuffer([], (buffer) => __awaiter(void 0, void 0, void 0, function* () {
const bufnr = yield nvim.call('bufnr', ['%']);
(0, expect_1.expect)(buffer.id).toBe(bufnr);
})));
describe('Normal API calls', () => {
it('gets changedtick of buffer', withBuffer([], (buffer) => __awaiter(void 0, void 0, void 0, function* () {
const initial = yield buffer.changedtick;
// insert a line
buffer.append('hi');
(0, expect_1.expect)(yield buffer.changedtick).toBe(initial + 1);
// clear buffer
buffer.remove(0, -1, false);
(0, expect_1.expect)(yield buffer.changedtick).toBe(initial + 2);
})));
it('sets/gets the current buffer name', () => __awaiter(void 0, void 0, void 0, function* () {
(yield nvim.buffers)[0].name = 'hello.txt';
const name = yield (yield nvim.buffers)[0].name;
(0, expect_1.expect)(name).toMatch('hello.txt');
}));
it('is a valid buffer', withBuffer([], (buffer) => __awaiter(void 0, void 0, void 0, function* () {
(0, expect_1.expect)(yield buffer.valid).toBe(true);
})));
it('sets current buffer name to "foo.txt"', withBuffer([], (buffer) => __awaiter(void 0, void 0, void 0, function* () {
// eslint-disable-next-line no-param-reassign
buffer.name = 'foo.txt';
(0, expect_1.expect)(yield buffer.name).toMatch('foo.txt');
// eslint-disable-next-line no-param-reassign
buffer.name = 'test2.txt';
(0, expect_1.expect)(yield buffer.name).toMatch('test2.txt');
})));
it('can replace first line of buffer with a string', withBuffer(['foo'], (buffer) => __awaiter(void 0, void 0, void 0, function* () {
buffer.replace('test', 0);
(0, expect_1.expect)(yield buffer.lines).toEqual(['test']);
})));
it('can insert lines at beginning of buffer', withBuffer(['test'], (buffer) => __awaiter(void 0, void 0, void 0, function* () {
yield buffer.insert(['test', 'foo'], 0);
(0, expect_1.expect)(yield buffer.lines).toEqual(['test', 'foo', 'test']);
})));
it('replaces the right lines', withBuffer(['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'], (buffer) => __awaiter(void 0, void 0, void 0, function* () {
yield buffer.replace(['a', 'b', 'c'], 2);
(0, expect_1.expect)(yield buffer.lines).toEqual(['0', '1', 'a', 'b', 'c', '5', '6', '7', '8', '9']);
})));
it('inserts line at index 2', withBuffer(['test', 'bar', 'bar', 'bar'], (buffer) => __awaiter(void 0, void 0, void 0, function* () {
buffer.insert(['foo'], 2);
(0, expect_1.expect)(yield buffer.lines).toEqual(['test', 'bar', 'foo', 'bar', 'bar']);
})));
it('removes last 2 lines', withBuffer(['test', 'bar', 'foo', 'a', 'b'], (buffer) => __awaiter(void 0, void 0, void 0, function* () {
buffer.remove(-3, -1, true);
(0, expect_1.expect)(yield buffer.lines).toEqual(['test', 'bar', 'foo']);
})));
it('checks if buffer is loaded', () => __awaiter(void 0, void 0, void 0, function* () {
yield nvim.command('new');
const buffer = yield nvim.buffer;
(0, expect_1.expect)(yield buffer.loaded).toBe(true);
yield nvim.command('bunload!');
(0, expect_1.expect)(yield buffer.loaded).toBe(false);
}));
it('gets byte offset for a line', withBuffer(['test', 'bar', ''], (buffer) => __awaiter(void 0, void 0, void 0, function* () {
(0, expect_1.expect)(yield buffer.getOffset(0)).toEqual(0);
(0, expect_1.expect)(yield buffer.getOffset(1)).toEqual(5); // test\n
(0, expect_1.expect)(yield buffer.getOffset(2)).toEqual(9); // test\n + bar\n
(0, expect_1.expect)(yield buffer.getOffset(3)).toEqual(10); // test\n + bar\n + \n
(0, expect_1.expect)(buffer.getOffset(4)).rejects.toThrow();
})));
it('returns -1 for byte offset of unloaded buffer', () => __awaiter(void 0, void 0, void 0, function* () {
yield nvim.command('new');
yield nvim.command('bunload!');
const buffer = yield nvim.buffer;
(0, expect_1.expect)(yield buffer.getOffset(0)).toEqual(-1);
}));
it('append lines to end of buffer', withBuffer(['test', 'bar', 'foo'], (buffer) => __awaiter(void 0, void 0, void 0, function* () {
yield buffer.append(['test', 'test']);
(0, expect_1.expect)(yield buffer.lines).toEqual(['test', 'bar', 'foo', 'test', 'test']);
})));
it('can clear the buffer', withBuffer(['foo'], (buffer) => __awaiter(void 0, void 0, void 0, function* () {
buffer.remove(0, -1, true);
// One empty line
(0, expect_1.expect)(yield buffer.length).toEqual(1);
(0, expect_1.expect)(yield buffer.lines).toEqual(['']);
})));
it('changes buffer options', withBuffer([], (buffer) => __awaiter(void 0, void 0, void 0, function* () {
const initial = yield buffer.getOption('copyindent');
buffer.setOption('copyindent', true);
(0, expect_1.expect)(yield buffer.getOption('copyindent')).toBe(true);
buffer.setOption('copyindent', false);
(0, expect_1.expect)(yield buffer.getOption('copyindent')).toBe(false);
(0, node_assert_1.default)(initial !== undefined);
// Restore option
buffer.setOption('copyindent', initial);
(0, expect_1.expect)(yield buffer.getOption('copyindent')).toBe(initial);
})));
it('returns null if variable is not found', withBuffer([], (buffer) => __awaiter(void 0, void 0, void 0, function* () {
const test = yield buffer.getVar('test');
(0, expect_1.expect)(test).toBe(null);
})));
it('can set and delete a b: variable to an object', withBuffer([], (buffer) => __awaiter(void 0, void 0, void 0, function* () {
buffer.setVar('test', { foo: 'testValue' });
(0, expect_1.expect)(yield buffer.getVar('test')).toEqual({ foo: 'testValue' });
(0, expect_1.expect)(yield nvim.eval('b:test')).toEqual({ foo: 'testValue' });
buffer.deleteVar('test');
(0, expect_1.expect)(yield nvim.eval('exists("b:test")')).toBe(0);
(0, expect_1.expect)(yield buffer.getVar('test')).toBe(null);
})));
it('can get list of commands', () => __awaiter(void 0, void 0, void 0, function* () {
(0, expect_1.expect)(yield nvim.buffer.commands).toEqual({});
}));
it('sets virtual text and clears namespace', withBuffer(['test'], (buffer) => __awaiter(void 0, void 0, void 0, function* () {
const ns = yield nvim.createNamespace();
yield buffer.setVirtualText(ns, 0, [['annotation', '']]);
yield buffer.clearNamespace({ nsId: ns });
})));
// TODO: How do we run integration tests for add/clear highlights? and get mark
});
describe('Chainable API calls', () => {
it('sets/gets the current buffer name using api chaining', () => __awaiter(void 0, void 0, void 0, function* () {
const buffer = yield nvim.buffer;
buffer.name = 'goodbye.txt';
(0, expect_1.expect)(yield nvim.buffer.name).toMatch('goodbye.txt');
}));
it('can chain calls from Base class i.e. getOption', () => __awaiter(void 0, void 0, void 0, function* () {
const buffer = yield nvim.buffer;
const initial = yield buffer.getOption('copyindent');
buffer.setOption('copyindent', true);
(0, expect_1.expect)(yield buffer.getOption('copyindent')).toBe(true);
buffer.setOption('copyindent', false);
(0, expect_1.expect)(yield buffer.getOption('copyindent')).toBe(false);
(0, node_assert_1.default)(initial !== undefined);
// Restore option
buffer.setOption('copyindent', initial);
(0, expect_1.expect)(yield buffer.getOption('copyindent')).toBe(initial);
}));
it('sets current buffer name to "bar.js" using api chaining', () => __awaiter(void 0, void 0, void 0, function* () {
const buffer = yield nvim.buffer;
buffer.name = 'bar.js';
(0, expect_1.expect)(yield buffer.name).toMatch('bar.js');
buffer.name = 'test2.js';
(0, expect_1.expect)(yield buffer.name).toMatch('test2.js');
}));
it('can replace first line of nvim.buffer with a string', withBuffer([], () => __awaiter(void 0, void 0, void 0, function* () {
const buffer = yield nvim.buffer;
yield buffer.replace('test', 0);
(0, expect_1.expect)(yield buffer.lines).toEqual(['test']);
})));
it('replaces the right lines', withBuffer(['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'], () => __awaiter(void 0, void 0, void 0, function* () {
const buffer = yield nvim.buffer;
yield buffer.replace(['a', 'b', 'c'], 2);
(0, expect_1.expect)(yield buffer.lines).toEqual(['0', '1', 'a', 'b', 'c', '5', '6', '7', '8', '9']);
})));
it('can insert lines at beginning of buffer', withBuffer(['test'], () => __awaiter(void 0, void 0, void 0, function* () {
const buffer = yield nvim.buffer;
yield buffer.insert(['test', 'foo'], 0);
(0, expect_1.expect)(yield buffer.lines).toEqual(['test', 'foo', 'test']);
})));
it('can replace nvim.buffer starting at line 1', withBuffer(['test', 'foo'], () => __awaiter(void 0, void 0, void 0, function* () {
const buffer = yield nvim.buffer;
yield buffer.replace(['bar', 'bar', 'bar'], 1);
(0, expect_1.expect)(yield buffer.lines).toEqual(['test', 'bar', 'bar', 'bar']);
})));
it('inserts line at index 2', withBuffer(['test', 'bar', 'bar', 'bar'], () => __awaiter(void 0, void 0, void 0, function* () {
const buffer = yield nvim.buffer;
yield buffer.insert(['foo'], 2);
(0, expect_1.expect)(yield buffer.lines).toEqual(['test', 'bar', 'foo', 'bar', 'bar']);
})));
it('removes last 2 lines', withBuffer(['test', 'bar', 'foo', 'a', 'b'], () => __awaiter(void 0, void 0, void 0, function* () {
const buffer = yield nvim.buffer;
yield buffer.remove(-3, -1, true);
(0, expect_1.expect)(yield buffer.lines).toEqual(['test', 'bar', 'foo']);
})));
it('append lines to end of buffer', withBuffer(['test', 'bar', 'foo'], () => __awaiter(void 0, void 0, void 0, function* () {
const buffer = yield nvim.buffer;
yield buffer.append(['test', 'test']);
(0, expect_1.expect)(yield buffer.lines).toEqual(['test', 'bar', 'foo', 'test', 'test']);
})));
it('can clear the buffer', withBuffer(['foo'], () => __awaiter(void 0, void 0, void 0, function* () {
const buffer = yield nvim.buffer;
yield buffer.remove(0, -1, true);
// One empty line
(0, expect_1.expect)(yield buffer.length).toEqual(1);
(0, expect_1.expect)(yield buffer.lines).toEqual(['']);
})));
});
});
describe('Buffer event updates', () => {
let nvim;
before(() => __awaiter(void 0, void 0, void 0, function* () {
[, nvim] = testUtil.startNvim();
}));
after(() => {
testUtil.stopNvim();
});
beforeEach(() => __awaiter(void 0, void 0, void 0, function* () {
yield (yield nvim.buffer).remove(0, -1, true);
}));
it('can listen and unlisten', () => __awaiter(void 0, void 0, void 0, function* () {
const buffer = yield nvim.buffer;
const mock = jestMock.fn();
const unlisten = buffer.listen('lines', mock);
yield buffer.insert(['bar'], 1);
(0, expect_1.expect)(mock).toHaveBeenCalledTimes(1);
unlisten();
yield buffer.insert(['bar'], 1);
(0, expect_1.expect)(mock).toHaveBeenCalledTimes(1);
}));
it('can reattach for buffer events', () => __awaiter(void 0, void 0, void 0, function* () {
const buffer = yield nvim.buffer;
let unlisten = buffer.listen('lines', jestMock.fn());
unlisten();
yield wait(10);
const mock = jestMock.fn();
unlisten = buffer.listen('lines', mock);
yield buffer.insert(['bar'], 1);
(0, expect_1.expect)(mock).toHaveBeenCalledTimes(1);
unlisten();
}));
it('should return attached state', () => __awaiter(void 0, void 0, void 0, function* () {
const buffer = yield nvim.buffer;
const unlisten = buffer.listen('lines', jestMock.fn());
yield wait(30);
let attached = buffer.isAttached;
(0, expect_1.expect)(attached).toBe(true);
unlisten();
yield wait(30);
attached = buffer.isAttached;
(0, expect_1.expect)(attached).toBe(false);
}));
it('only bind once for the same event and handler ', () => __awaiter(void 0, void 0, void 0, function* () {
const buffer = yield nvim.buffer;
const mock = jestMock.fn();
buffer.listen('lines', mock);
buffer.listen('lines', mock);
yield buffer.insert(['bar'], 1);
(0, expect_1.expect)(mock).toHaveBeenCalledTimes(1);
}));
it('can use `buffer.unlisten` to unlisten', () => __awaiter(void 0, void 0, void 0, function* () {
const buffer = yield nvim.buffer;
const mock = jestMock.fn();
buffer.listen('lines', mock);
yield buffer.insert(['bar'], 1);
(0, expect_1.expect)(mock).toHaveBeenCalledTimes(1);
buffer.unlisten('lines', mock);
yield buffer.insert(['bar'], 1);
(0, expect_1.expect)(mock).toHaveBeenCalledTimes(1);
}));
it('listens to line updates', () => __awaiter(void 0, void 0, void 0, function* () {
const buffer = yield nvim.buffer;
const bufferName = yield buffer.name;
yield buffer.insert(['test', 'foo'], 0);
const promise = new Promise(resolve => {
const unlisten = buffer.listen('lines', (currentBuffer, tick, start, end, data) => __awaiter(void 0, void 0, void 0, function* () {
(0, expect_1.expect)(yield currentBuffer.name).toBe(bufferName);
(0, expect_1.expect)(start).toBe(1);
(0, expect_1.expect)(end).toBe(1);
(0, expect_1.expect)(data).toEqual(['bar']);
unlisten();
resolve();
}));
});
yield buffer.insert(['bar'], 1);
yield promise;
}));
it('has listener on multiple buffers ', () => __awaiter(void 0, void 0, void 0, function* () {
yield nvim.command('new!');
const buffers = yield nvim.buffers;
const foo = jestMock.fn();
const bar = jestMock.fn();
buffers[0].listen('lines', foo);
buffers[1].listen('lines', bar);
yield (yield nvim.buffer).insert(['bar'], 1);
(0, expect_1.expect)(foo).toHaveBeenCalledTimes(0);
(0, expect_1.expect)(bar).toHaveBeenCalledTimes(1);
yield nvim.command('q!');
yield (yield nvim.buffer).insert(['foo'], 0);
(0, expect_1.expect)(foo).toHaveBeenCalledTimes(1);
(0, expect_1.expect)(bar).toHaveBeenCalledTimes(1);
buffers[0].unlisten('lines', foo);
buffers[1].unlisten('lines', bar);
}));
it('has multiple listeners for same event, on same buffer', () => __awaiter(void 0, void 0, void 0, function* () {
yield nvim.command('new!');
const buffer = yield nvim.buffer;
const foo = jestMock.fn();
const bar = jestMock.fn();
const unlisten1 = buffer.listen('lines', foo);
const unlisten2 = buffer.listen('lines', bar);
yield buffer.insert(['bar'], 1);
(0, expect_1.expect)(foo).toHaveBeenCalledTimes(1);
(0, expect_1.expect)(bar).toHaveBeenCalledTimes(1);
unlisten2();
yield buffer.insert(['foo'], 0);
(0, expect_1.expect)(foo).toHaveBeenCalledTimes(2);
(0, expect_1.expect)(bar).toHaveBeenCalledTimes(1);
unlisten1();
yield nvim.command('q!');
}));
it('has multiple listeners for different events, on same buffer', () => __awaiter(void 0, void 0, void 0, function* () {
yield nvim.command('new!');
const buffer = yield nvim.buffer;
const foo = jestMock.fn();
const bar = jestMock.fn();
const unlisten1 = buffer.listen('lines', foo);
const unlisten2 = buffer.listen('changedtick', bar);
yield buffer.insert(['bar'], 1);
(0, expect_1.expect)(foo).toHaveBeenCalledTimes(1);
(0, expect_1.expect)(bar).toHaveBeenCalledTimes(1);
unlisten2();
yield buffer.insert(['foo'], 0);
(0, expect_1.expect)(foo).toHaveBeenCalledTimes(2);
(0, expect_1.expect)(bar).toHaveBeenCalledTimes(1);
unlisten1();
yield nvim.command('q!');
}));
});
;