15d221ae0e
Separate linting from testing as follows: - `yarn jscs`: Run JSCS. - `yarn jshint`: Run JSHint. - `yarn lint`: Run all linters, i.e. ESLint, TSLint, JSHint, and JSHint. - `yarn test-node`: Run Mocha tests in Node.js environment. - `yarn test-electron`: Run tests in Electron environment via Grunt. - `yarn test`: Run all tests. CI - Align Travis and AppVeyor scripts as much as possible. - Run linting before tests to fail fast. - Run Node.js (headless and fast) tests first. - Run Electron tests last (Travis seems to require custom setup in `travis.sh`).
274 lines
8.8 KiB
JavaScript
274 lines
8.8 KiB
JavaScript
// NOTE: Temporarily allow `then` until we convert the entire file to `async` / `await`:
|
|
/* eslint-disable more/no-then */
|
|
|
|
const fs = require('fs');
|
|
const path = require('path');
|
|
|
|
const tmp = require('tmp');
|
|
const { expect } = require('chai');
|
|
|
|
const {
|
|
eliminateOutOfDateFiles,
|
|
eliminateOldEntries,
|
|
isLineAfterDate,
|
|
fetchLog,
|
|
fetch,
|
|
} = require('../../app/logging');
|
|
|
|
describe('app/logging', () => {
|
|
let basePath;
|
|
let tmpDir;
|
|
|
|
beforeEach(() => {
|
|
tmpDir = tmp.dirSync({
|
|
unsafeCleanup: true,
|
|
});
|
|
basePath = tmpDir.name;
|
|
});
|
|
|
|
afterEach((done) => {
|
|
// we need the unsafe option to recursively remove the directory
|
|
tmpDir.removeCallback(done);
|
|
});
|
|
|
|
describe('#isLineAfterDate', () => {
|
|
it('returns false if falsy', () => {
|
|
const actual = isLineAfterDate('', new Date());
|
|
expect(actual).to.equal(false);
|
|
});
|
|
it('returns false if invalid JSON', () => {
|
|
const actual = isLineAfterDate('{{}', new Date());
|
|
expect(actual).to.equal(false);
|
|
});
|
|
it('returns false if date is invalid', () => {
|
|
const line = JSON.stringify({ time: '2018-01-04T19:17:05.014Z' });
|
|
const actual = isLineAfterDate(line, new Date('try6'));
|
|
expect(actual).to.equal(false);
|
|
});
|
|
it('returns false if log time is invalid', () => {
|
|
const line = JSON.stringify({ time: 'try7' });
|
|
const date = new Date('2018-01-04T19:17:00.000Z');
|
|
const actual = isLineAfterDate(line, date);
|
|
expect(actual).to.equal(false);
|
|
});
|
|
it('returns false if date before provided date', () => {
|
|
const line = JSON.stringify({ time: '2018-01-04T19:17:00.000Z' });
|
|
const date = new Date('2018-01-04T19:17:05.014Z');
|
|
const actual = isLineAfterDate(line, date);
|
|
expect(actual).to.equal(false);
|
|
});
|
|
it('returns true if date is after provided date', () => {
|
|
const line = JSON.stringify({ time: '2018-01-04T19:17:05.014Z' });
|
|
const date = new Date('2018-01-04T19:17:00.000Z');
|
|
const actual = isLineAfterDate(line, date);
|
|
expect(actual).to.equal(true);
|
|
});
|
|
});
|
|
|
|
describe('#eliminateOutOfDateFiles', () => {
|
|
it('deletes an empty file', () => {
|
|
const date = new Date();
|
|
const log = '\n';
|
|
const target = path.join(basePath, 'log.log');
|
|
fs.writeFileSync(target, log);
|
|
|
|
return eliminateOutOfDateFiles(basePath, date).then(() => {
|
|
expect(fs.existsSync(target)).to.equal(false);
|
|
});
|
|
});
|
|
it('deletes a file with invalid JSON lines', () => {
|
|
const date = new Date();
|
|
const log = '{{}\n';
|
|
const target = path.join(basePath, 'log.log');
|
|
fs.writeFileSync(target, log);
|
|
|
|
return eliminateOutOfDateFiles(basePath, date).then(() => {
|
|
expect(fs.existsSync(target)).to.equal(false);
|
|
});
|
|
});
|
|
it('deletes a file with all dates before provided date', () => {
|
|
const date = new Date('2018-01-04T19:17:05.014Z');
|
|
const contents = [
|
|
JSON.stringify({ time: '2018-01-04T19:17:00.014Z' }),
|
|
JSON.stringify({ time: '2018-01-04T19:17:01.014Z' }),
|
|
JSON.stringify({ time: '2018-01-04T19:17:02.014Z' }),
|
|
JSON.stringify({ time: '2018-01-04T19:17:03.014Z' }),
|
|
].join('\n');
|
|
const target = path.join(basePath, 'log.log');
|
|
fs.writeFileSync(target, contents);
|
|
|
|
return eliminateOutOfDateFiles(basePath, date).then(() => {
|
|
expect(fs.existsSync(target)).to.equal(false);
|
|
});
|
|
});
|
|
it('keeps a file with first line date before provided date', () => {
|
|
const date = new Date('2018-01-04T19:16:00.000Z');
|
|
const contents = [
|
|
JSON.stringify({ time: '2018-01-04T19:17:00.014Z' }),
|
|
JSON.stringify({ time: '2018-01-04T19:17:01.014Z' }),
|
|
JSON.stringify({ time: '2018-01-04T19:17:02.014Z' }),
|
|
JSON.stringify({ time: '2018-01-04T19:17:03.014Z' }),
|
|
].join('\n');
|
|
const target = path.join(basePath, 'log.log');
|
|
fs.writeFileSync(target, contents);
|
|
|
|
return eliminateOutOfDateFiles(basePath, date).then(() => {
|
|
expect(fs.existsSync(target)).to.equal(true);
|
|
});
|
|
});
|
|
it('keeps a file with last line date before provided date', () => {
|
|
const date = new Date('2018-01-04T19:17:01.000Z');
|
|
const contents = [
|
|
JSON.stringify({ time: '2018-01-04T19:17:00.014Z' }),
|
|
JSON.stringify({ time: '2018-01-04T19:17:01.014Z' }),
|
|
JSON.stringify({ time: '2018-01-04T19:17:02.014Z' }),
|
|
JSON.stringify({ time: '2018-01-04T19:17:03.014Z' }),
|
|
].join('\n');
|
|
const target = path.join(basePath, 'log.log');
|
|
fs.writeFileSync(target, contents);
|
|
|
|
return eliminateOutOfDateFiles(basePath, date).then(() => {
|
|
expect(fs.existsSync(target)).to.equal(true);
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('#eliminateOldEntries', () => {
|
|
it('eliminates all non-parsing entries', () => {
|
|
const date = new Date('2018-01-04T19:17:01.000Z');
|
|
const contents = [
|
|
'random line',
|
|
JSON.stringify({ time: '2018-01-04T19:17:01.014Z' }),
|
|
JSON.stringify({ time: '2018-01-04T19:17:02.014Z' }),
|
|
JSON.stringify({ time: '2018-01-04T19:17:03.014Z' }),
|
|
].join('\n');
|
|
const expected = [
|
|
JSON.stringify({ time: '2018-01-04T19:17:01.014Z' }),
|
|
JSON.stringify({ time: '2018-01-04T19:17:02.014Z' }),
|
|
JSON.stringify({ time: '2018-01-04T19:17:03.014Z' }),
|
|
].join('\n');
|
|
|
|
const target = path.join(basePath, 'log.log');
|
|
const files = [{
|
|
path: target,
|
|
}];
|
|
|
|
fs.writeFileSync(target, contents);
|
|
|
|
return eliminateOldEntries(files, date).then(() => {
|
|
expect(fs.readFileSync(target, 'utf8')).to.equal(`${expected}\n`);
|
|
});
|
|
});
|
|
it('preserves all lines if before target date', () => {
|
|
const date = new Date('2018-01-04T19:17:03.000Z');
|
|
const contents = [
|
|
'random line',
|
|
JSON.stringify({ time: '2018-01-04T19:17:01.014Z' }),
|
|
JSON.stringify({ time: '2018-01-04T19:17:02.014Z' }),
|
|
JSON.stringify({ time: '2018-01-04T19:17:03.014Z' }),
|
|
].join('\n');
|
|
const expected = [
|
|
JSON.stringify({ time: '2018-01-04T19:17:03.014Z' }),
|
|
].join('\n');
|
|
|
|
const target = path.join(basePath, 'log.log');
|
|
const files = [{
|
|
path: target,
|
|
}];
|
|
|
|
fs.writeFileSync(target, contents);
|
|
|
|
return eliminateOldEntries(files, date).then(() => {
|
|
expect(fs.readFileSync(target, 'utf8')).to.equal(`${expected}\n`);
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('#fetchLog', () => {
|
|
it('returns error if file does not exist', () => {
|
|
const target = 'random_file';
|
|
return fetchLog(target).then(() => {
|
|
throw new Error('Expected an error!');
|
|
}, (error) => {
|
|
expect(error).to.have.property('message').that.match(/random_file/);
|
|
});
|
|
});
|
|
it('returns empty array if file has no valid JSON lines', () => {
|
|
const contents = 'line 1\nline2\n';
|
|
const expected = [];
|
|
const target = path.join(basePath, 'test.log');
|
|
|
|
fs.writeFileSync(target, contents);
|
|
|
|
return fetchLog(target).then((result) => {
|
|
expect(result).to.deep.equal(expected);
|
|
});
|
|
});
|
|
it('returns just three fields in each returned line', () => {
|
|
const contents = [
|
|
JSON.stringify({
|
|
one: 1,
|
|
two: 2,
|
|
level: 1,
|
|
time: 2,
|
|
msg: 3,
|
|
}),
|
|
JSON.stringify({
|
|
one: 1,
|
|
two: 2,
|
|
level: 2,
|
|
time: 3,
|
|
msg: 4,
|
|
}),
|
|
'',
|
|
].join('\n');
|
|
const expected = [{
|
|
level: 1,
|
|
time: 2,
|
|
msg: 3,
|
|
}, {
|
|
level: 2,
|
|
time: 3,
|
|
msg: 4,
|
|
}];
|
|
|
|
const target = path.join(basePath, 'test.log');
|
|
|
|
fs.writeFileSync(target, contents);
|
|
|
|
return fetchLog(target).then((result) => {
|
|
expect(result).to.deep.equal(expected);
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('#fetch', () => {
|
|
it('returns single entry if no files', () => {
|
|
return fetch(basePath).then((results) => {
|
|
expect(results).to.have.length(1);
|
|
expect(results[0].msg).to.match(/Loaded this list/);
|
|
});
|
|
});
|
|
it('returns sorted entries from all files', () => {
|
|
const first = [
|
|
JSON.stringify({ msg: 2, time: '2018-01-04T19:17:05.014Z' }),
|
|
'',
|
|
].join('\n');
|
|
const second = [
|
|
JSON.stringify({ msg: 1, time: '2018-01-04T19:17:00.014Z' }),
|
|
JSON.stringify({ msg: 3, time: '2018-01-04T19:18:00.014Z' }),
|
|
'',
|
|
].join('\n');
|
|
|
|
fs.writeFileSync(path.join(basePath, 'first.log'), first);
|
|
fs.writeFileSync(path.join(basePath, 'second.log'), second);
|
|
|
|
return fetch(basePath).then((results) => {
|
|
expect(results).to.have.length(4);
|
|
expect(results[0].msg).to.equal(1);
|
|
expect(results[1].msg).to.equal(2);
|
|
expect(results[2].msg).to.equal(3);
|
|
});
|
|
});
|
|
});
|
|
});
|