Add clean deleted responses task on startup, and add tests (#1292)

* Add clean deleted responses task on startup, and add tests

* Bump version

* Add hookDatabaseInit() call to perform ops on DB startup

* Refactor clean responses function to fetch all from db instead of batching, move the call to db init hook, and refactor tests to use spyOn
This commit is contained in:
Ricky Chandra 2018-12-05 10:26:18 +07:00 committed by Gregory Schier
parent 8eb494dfe8
commit f88d961748
2 changed files with 114 additions and 0 deletions

View File

@ -12,6 +12,11 @@ describe('migrate()', () => {
jest.useFakeTimers();
});
afterEach(async () => {
// Reset to real timers so that other test suites don't fail.
jest.useRealTimers();
});
it('migrates utf8 body correctly', async () => {
const initialModel = { body: 'hello world!', encoding: 'utf8' };
@ -134,3 +139,89 @@ describe('migrate()', () => {
).toBe('zip');
});
});
describe('cleanDeletedResponses()', function() {
beforeEach(globalBeforeEach);
afterEach(function() {
jest.restoreAllMocks();
});
it('deletes nothing if there is no files in directory', async function() {
const mockReaddirSync = jest.spyOn(fs, 'readdirSync');
const mockUnlinkSync = jest.spyOn(fs, 'unlinkSync');
mockReaddirSync.mockReturnValueOnce([]);
mockUnlinkSync.mockImplementation();
await models.response.cleanDeletedResponses();
expect(fs.unlinkSync.mock.calls.length).toBe(0);
});
it('only deletes response files that are not in db', async function() {
const responsesDir = path.join(getDataDirectory(), 'responses');
let dbResponseIds = await createModels(responsesDir, 10);
let notDbResponseIds = [];
for (let index = 100; index < 110; index++) {
notDbResponseIds.push('res_' + index);
}
const mockReaddirSync = jest.spyOn(fs, 'readdirSync');
const mockUnlinkSync = jest.spyOn(fs, 'unlinkSync');
mockReaddirSync.mockReturnValueOnce([...dbResponseIds, ...notDbResponseIds]);
mockUnlinkSync.mockImplementation();
await models.response.cleanDeletedResponses();
expect(fs.unlinkSync.mock.calls.length).toBe(notDbResponseIds.length);
Object.keys(notDbResponseIds).map(index => {
const resId = notDbResponseIds[index];
const bodyPath = path.join(responsesDir, resId);
expect(fs.unlinkSync.mock.calls[index][0]).toBe(bodyPath);
});
});
});
/**
* Create mock workspaces, requests, and responses as many as {@code count}.
* @param responsesDir
* @param count
* @returns {Promise<string[]>} the created response ids
*/
async function createModels(responsesDir, count) {
if (count < 1) {
return [];
}
let responseIds = [];
for (let index = 0; index < count; index++) {
const workspaceId = 'wrk_' + index;
const requestId = 'req_' + index;
const responseId = 'res_' + index;
await models.workspace.create({
_id: workspaceId,
created: 111,
modified: 222
});
await models.request.create({
_id: requestId,
parentId: workspaceId,
created: 111,
modified: 222,
metaSortKey: 0,
url: 'https://insomnia.rest'
});
await models.response.create({
_id: responseId,
parentId: requestId,
statusCode: 200,
body: 'foo',
bodyPath: path.join(responsesDir, responseId)
});
responseIds.push(responseId);
}
return responseIds;
}

View File

@ -80,6 +80,8 @@ export async function migrate(doc: Object) {
}
export async function hookDatabaseInit() {
await models.response.cleanDeletedResponses();
console.log('Init responses DB');
}
@ -236,3 +238,24 @@ function migrateBodyCompression(doc: Object) {
return doc;
}
export async function cleanDeletedResponses() {
const responsesDir = path.join(getDataDirectory(), 'responses');
mkdirp.sync(responsesDir);
let files = fs.readdirSync(responsesDir);
if (files.length === 0) {
return;
}
let whitelistFiles = (await db.all(type)).map(res => {
return res.bodyPath.slice(responsesDir.length + 1);
});
for (let index = 0; index < files.length; index++) {
if (whitelistFiles.indexOf(files[index]) === -1) {
const bodyPath = path.join(responsesDir, files[index]);
fs.unlinkSync(bodyPath);
}
}
}