Skip to content

Commit

Permalink
refactor(tests): drop "global test setup"
Browse files Browse the repository at this point in the history
Can't do "global beforeAll" because jest sucks.
  • Loading branch information
justinmk committed Mar 16, 2024
1 parent 7d1e1fe commit 865abe8
Show file tree
Hide file tree
Showing 9 changed files with 141 additions and 83 deletions.
11 changes: 9 additions & 2 deletions packages/neovim/src/api/Base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,14 +98,21 @@ export class BaseApi extends EventEmitter {
return this[DO_REQUEST](name, args).catch(err => {
const newError = new Error(err.message);
newError.stack = stack;
this.logger.error(`failed request to "%s": %s: %s`, name, newError.name, newError.message);
this.logger.error(
`failed request to "%s": %s: %s`,
name,
newError.name,
newError.message
);
throw newError;
});
}

request(name: string, args: any[] = []): Promise<any> {
// Dummy error, to get stacktrace.
const error = new Error(`failed request to "${name}" (see $NVIM_NODE_LOG_FILE for details, if it was set)`);
const error = new Error(
`failed request to "${name}" (see $NVIM_NODE_LOG_FILE for details, if it was set)`
);

return this.asyncRequest(name, args, error.stack);
}
Expand Down
18 changes: 13 additions & 5 deletions packages/neovim/src/api/Buffer.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/* eslint-env jest */
import * as testSetup from '../testSetup';
import * as testUtil from '../testUtil';

function wait(ms: number): Promise<void> {
return new Promise(resolve => {
Expand All @@ -10,7 +10,7 @@ function wait(ms: number): Promise<void> {
}

describe('Buffer API', () => {
let nvim: ReturnType<typeof testSetup.getNvim>;
let nvim: ReturnType<typeof testUtil.startNvim>[1];

// utility to allow each test to be run in its
// own buffer
Expand All @@ -32,7 +32,11 @@ describe('Buffer API', () => {
}

beforeAll(async () => {
nvim = testSetup.getNvim();
[, nvim] = testUtil.startNvim();
});

afterAll(() => {
testUtil.stopNvim();
});

it(
Expand Down Expand Up @@ -379,10 +383,14 @@ describe('Buffer API', () => {
});

describe('Buffer event updates', () => {
let nvim: ReturnType<typeof testSetup.getNvim>;
let nvim: ReturnType<typeof testUtil.startNvim>[1];

beforeAll(async () => {
nvim = testSetup.getNvim();
[, nvim] = testUtil.startNvim();
});

afterAll(() => {
testUtil.stopNvim();
});

beforeEach(async () => {
Expand Down
12 changes: 8 additions & 4 deletions packages/neovim/src/api/Neovim.test.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
/* eslint-env jest */
import * as path from 'node:path';
import { Neovim } from './Neovim';
import * as testSetup from '../testSetup';
import * as testUtil from '../testUtil';

describe('Neovim API', () => {
let nvim: ReturnType<typeof testSetup.getNvim>;
let nvim: ReturnType<typeof testUtil.startNvim>[1];

beforeAll(async () => {
nvim = testSetup.getNvim();
[, nvim] = testUtil.startNvim();
});

afterAll(() => {
testUtil.stopNvim();
});

it('sets transport when initialized', () => {
Expand All @@ -24,7 +28,7 @@ describe('Neovim API', () => {
expect(buffers.length).toBe(1);
buffers[0].name = 'hello.txt';

nvim.command('e! goodbye.txt');
nvim.command('noswapfile e! goodbye.txt');
expect((await nvim.buffers).length).toBe(2);
expect(await nvim.buffer.name).toMatch(/goodbye\.txt$/);

Expand Down
10 changes: 7 additions & 3 deletions packages/neovim/src/api/Tabpage.test.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
/* eslint-env jest */
import * as testSetup from '../testSetup';
import * as testUtil from '../testUtil';

describe('Tabpage API', () => {
let nvim: ReturnType<typeof testSetup.getNvim>;
let nvim: ReturnType<typeof testUtil.startNvim>[1];

beforeAll(async () => {
nvim = testSetup.getNvim();
[, nvim] = testUtil.startNvim();
});

afterAll(() => {
testUtil.stopNvim();
});

it('gets the current Tabpage', async () => {
Expand Down
10 changes: 7 additions & 3 deletions packages/neovim/src/api/Window.test.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
/* eslint-env jest */
import * as testSetup from '../testSetup';
import * as testUtil from '../testUtil';

describe('Window API', () => {
let nvim: ReturnType<typeof testSetup.getNvim>;
let nvim: ReturnType<typeof testUtil.startNvim>[1];

beforeAll(async () => {
nvim = testSetup.getNvim();
[, nvim] = testUtil.startNvim();
});

afterAll(() => {
testUtil.stopNvim();
});

it('gets the current Window', async () => {
Expand Down
34 changes: 24 additions & 10 deletions packages/neovim/src/attach/attach.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@
import { attach } from './attach';
import { Logger } from '../utils/logger';
import * as testUtil from '../testUtil';
import * as testSetup from '../testSetup';

describe('Nvim API', () => {
let nvim: ReturnType<typeof testSetup.getNvim>;
let requests;
let notifications;
let proc: ReturnType<typeof testUtil.startNvim>[0];
let nvim: ReturnType<typeof testUtil.startNvim>[1];
let requests: { method: string; args: number[] }[];
let notifications: { method: string; args: number[] }[];

beforeAll(async () => {
nvim = testSetup.getNvim();
[proc, nvim] = testUtil.startNvim();

nvim.on('request', (method, args, resp) => {
requests.push({ method, args });
Expand All @@ -21,6 +21,10 @@ describe('Nvim API', () => {
});
});

afterAll(() => {
testUtil.stopNvim();
});

beforeEach(() => {
requests = [];
notifications = [];
Expand Down Expand Up @@ -48,8 +52,11 @@ describe('Nvim API', () => {
warn: fakeLog,
debug: fakeLog,
error: fakeLog,
} as Logger;
const nvim2 = attach({ proc: proc2, options: { logger: logger2 } });
};
const nvim2 = attach({
proc: proc2,
options: { logger: logger2 as Logger },
});

const spy = jest.spyOn(nvim2.logger, 'info');
// eslint-disable-next-line no-console
Expand Down Expand Up @@ -112,16 +119,23 @@ describe('Nvim API', () => {
const buf = await nvim.buffer;
expect(buf instanceof nvim.Buffer).toEqual(true);

const lines = await buf.getLines({ start: 0, end: -1 });
const lines = await buf.getLines({
start: 0,
end: -1,
strictIndexing: true,
});
expect(lines).toEqual([]);

buf.setLines(['line1', 'line2'], { start: 0, end: 1 });
const newLines = await buf.getLines({ start: 0, end: -1 });
const newLines = await buf.getLines({
start: 0,
end: -1,
strictIndexing: true,
});
expect(newLines).toEqual(['line1', 'line2']);
});

it('emits "disconnect" after quit', done => {
const proc = testSetup.getNvimProc();
const disconnectMock = jest.fn();
nvim.on('disconnect', disconnectMock);
nvim.quit();
Expand Down
35 changes: 6 additions & 29 deletions packages/neovim/src/testSetup.ts
Original file line number Diff line number Diff line change
@@ -1,35 +1,12 @@
// Global test setup. Runs before each test.

import * as testUtil from './testUtil';
import * as jest from '@jest/globals'
// import * as jest from '@jest/globals'

testUtil.findNvimOrFail();

let proc: ReturnType<typeof testUtil.startNvim>[0];
let nvim: ReturnType<typeof testUtil.startNvim>[1];

/**
* Gets the current Nvim client being used in the current test.
*/
export function getNvim() {
return nvim!;
}

export function getNvimProc() {
return proc!;
}

jest.beforeAll(() => {
const testName = jest.expect.getState().testPath;
console.log('xxxxxxxxxxxx BEFORE %O', testName);
[proc, nvim] = testUtil.startNvim(true);
});

jest.afterAll(() => {
const testName = jest.expect.getState().currentTestName;
console.log('xxxxxxxxxxxx AFTER %O', testName);
testUtil.stopNvim(proc);
testUtil.stopNvim(nvim);
proc = undefined;
nvim = undefined;
});
// TODO: this doesn't work because jest sucks. use mocha instead.
// jest.beforeAll(() => {
// });
// jest.afterAll(() => {
// });
67 changes: 52 additions & 15 deletions packages/neovim/src/testUtil.ts
Original file line number Diff line number Diff line change
@@ -1,41 +1,78 @@
import * as cp from 'node:child_process';
// eslint-disable-next-line import/no-extraneous-dependencies
import * as jest from '@jest/globals';
import * as fs from 'node:fs';
import * as path from 'node:path';
import { NeovimClient } from './api/client';
import { attach } from './attach';
import { findNvim } from './utils/findNvim';

export function startNvim(): [cp.ChildProcessWithoutNullStreams, NeovimClient]
export function startNvim(doAttach: false): [cp.ChildProcessWithoutNullStreams, undefined]
export function startNvim(doAttach: true): [cp.ChildProcessWithoutNullStreams, NeovimClient]
export function findNvimOrFail() {
const minVersion = '0.9.5';
const found = findNvim({ minVersion });
if (found.matches.length === 0) {
throw new Error(`nvim ${minVersion} not found`);

Check warning on line 14 in packages/neovim/src/testUtil.ts

View check run for this annotation

Codecov / codecov/patch

packages/neovim/src/testUtil.ts#L14

Added line #L14 was not covered by tests
}
return found.matches[0].path;
}

const nvimPath = findNvimOrFail();

let proc: cp.ChildProcessWithoutNullStreams;
let nvim: NeovimClient;

export function startNvim(): [cp.ChildProcessWithoutNullStreams, NeovimClient];
export function startNvim(
doAttach: false
): [cp.ChildProcessWithoutNullStreams, undefined];
export function startNvim(
doAttach: true
): [cp.ChildProcessWithoutNullStreams, NeovimClient];
export function startNvim(
doAttach: boolean = true
): [cp.ChildProcessWithoutNullStreams, NeovimClient | undefined] {
const proc = cp.spawn('nvim', ['-u', 'NONE', '--embed', '-n', '--noplugin'], {
const testFile = jest.expect.getState().testPath?.replace(/.*[\\/]/, '');
const msg = `startNvim in test: ${testFile}`;
// console.log(msg);
if (process.env.NVIM_NODE_LOG_FILE) {
const logfile = path.resolve(process.env.NVIM_NODE_LOG_FILE);
fs.writeFileSync(logfile, `${msg}\n`, { flag: 'a' });
}

proc = cp.spawn(nvimPath, ['-u', 'NONE', '--embed', '-n', '--noplugin'], {
cwd: __dirname,
});
if (!doAttach) {
return [proc, undefined];
}
const nvim = attach({ proc });
nvim = attach({ proc });
return [proc, nvim];
}

export function stopNvim(
proc_: cp.ChildProcessWithoutNullStreams | NeovimClient
proc_?: cp.ChildProcessWithoutNullStreams | NeovimClient
) {
// Stop all (proc + client).
if (!proc_) {
if (proc) {
stopNvim(proc);
}
if (nvim) {
stopNvim(nvim);
}
return;
} else if (proc_ instanceof NeovimClient) {
}

if (proc_ instanceof NeovimClient) {
proc_.quit();
} else if (proc_ && proc_.connected) {
proc_.disconnect();

Check warning on line 69 in packages/neovim/src/testUtil.ts

View check run for this annotation

Codecov / codecov/patch

packages/neovim/src/testUtil.ts#L69

Added line #L69 was not covered by tests
}
}

export function findNvimOrFail() {
const minVersion = '0.9.5';
const found = findNvim({ minVersion });
if (found.matches.length === 0) {
throw new Error(`nvim ${minVersion} not found`);
}
return found.matches[0].path;
}
// jest.beforeAll(async () => {
// [proc, nvim] = startNvim();
// });
// jest.afterAll(() => {
// stopNvim();
// });
27 changes: 15 additions & 12 deletions packages/neovim/src/utils/logger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,21 @@ function setupWinstonLogger(): Logger {
filename: process.env.NVIM_NODE_LOG_FILE,
level,
format: winston.format.combine(
winston.format.splat(),
winston.format.timestamp({
format: 'YYYY-MM-DD HH:mm:ss',
}),
winston.format.errors({ stack: true }),
winston.format.printf(info => {
if (info.raw) {
return info.message
}
const lvl = info.level === 'debug' ? 'DBG' : info.level.slice(0, 3).toUpperCase();
return `${info.timestamp} ${lvl} ${info.message}`
})
winston.format.splat(),
winston.format.timestamp({
format: 'YYYY-MM-DD HH:mm:ss',
}),
winston.format.errors({ stack: true }),
winston.format.printf(info => {
if (info.raw) {
return info.message;

Check warning on line 25 in packages/neovim/src/utils/logger.ts

View check run for this annotation

Codecov / codecov/patch

packages/neovim/src/utils/logger.ts#L25

Added line #L25 was not covered by tests
}
const lvl =
info.level === 'debug'
? 'DBG'
: info.level.slice(0, 3).toUpperCase();
return `${info.timestamp} ${lvl} ${info.message}`;
})
),
})
);
Expand Down

0 comments on commit 865abe8

Please sign in to comment.