test: cron jobs

This commit is contained in:
Nicolas Meienberger 2022-09-24 16:02:33 +02:00
parent 7a444698b8
commit 9d4cdf6f77
10 changed files with 99 additions and 8 deletions

View file

View file

@ -0,0 +1,11 @@
const cron: {
schedule: typeof schedule;
} = jest.genMockFromModule('node-cron');
const schedule = (scd: string, cb: () => void) => {
cb();
};
cron.schedule = schedule;
module.exports = cron;

View file

@ -12,4 +12,10 @@ module.exports = {
transform: {
'^.+\\.graphql$': 'graphql-import-node/jest',
},
globals: {
// NODE_ENV: 'test',
'ts-jest': {
isolatedModules: true,
},
},
};

View file

@ -0,0 +1,32 @@
import cron from 'node-cron';
import * as repoHelpers from '../../../helpers/repo-helpers';
import { getConfig } from '../../config/TipiConfig';
import startJobs from '../jobs';
jest.mock('node-cron');
jest.mock('child_process');
beforeEach(async () => {
jest.resetModules();
jest.resetAllMocks();
});
describe('Test: startJobs', () => {
it('Should start cron jobs', () => {
const spy = jest.spyOn(cron, 'schedule');
startJobs();
expect(spy).toHaveBeenCalled();
expect(spy).toHaveBeenCalledWith('0 * * * *', expect.any(Function));
spy.mockRestore();
});
it('Should update apps repo on cron trigger', () => {
const spy = jest.spyOn(repoHelpers, 'updateRepo');
startJobs();
expect(spy).toHaveBeenCalledWith(getConfig().appsRepoUrl);
spy.mockRestore();
});
});

View file

@ -7,7 +7,7 @@ const startJobs = () => {
logger.info('Starting cron jobs...');
cron.schedule('0 * * * *', () => {
logger.info('Cloning apps repo...');
logger.info('Updating apps repo...');
updateRepo(getConfig().appsRepoUrl);
});
};

View file

@ -1,10 +1,10 @@
import datasource from '../../config/datasource';
import { DataSource } from 'typeorm';
import logger from '../../config/logger/logger';
import App from '../../modules/apps/app.entity';
import User from '../../modules/auth/user.entity';
import Update from '../../modules/system/update.entity';
const recover = async () => {
const recover = async (datasource: DataSource) => {
logger.info('Recovering broken database');
const queryRunner = datasource.createQueryRunner();
@ -33,9 +33,10 @@ const recover = async () => {
await Update.create(update).save();
}
logger.info('Users recovered', users.length);
logger.info('Apps recovered', apps.length);
logger.info('Database recovered');
logger.info(`Users recovered ${users.length}`);
logger.info(`Apps recovered ${apps.length}`);
logger.info(`Updates recovered ${updates.length}`);
logger.info('Database fully recovered');
};
export default recover;

View file

@ -28,6 +28,7 @@ describe('Test: updateRepo', () => {
expect(spy).toHaveBeenCalledWith(`${getConfig().rootFolder}/scripts/git.sh`, ['update', url], {}, expect.any(Function));
expect(log).toHaveBeenCalledWith(`Update result: ${stdout}`);
spy.mockRestore();
});
it('Should throw and log error if script failed', async () => {
@ -50,6 +51,7 @@ describe('Test: updateRepo', () => {
expect(e).toBe(randomWord);
expect(log).toHaveBeenCalledWith(`Error updating repo: ${randomWord}`);
}
spy.mockRestore();
});
});
@ -70,6 +72,7 @@ describe('Test: cloneRepo', () => {
expect(spy).toHaveBeenCalledWith(`${getConfig().rootFolder}/scripts/git.sh`, ['clone', url], {}, expect.any(Function));
expect(log).toHaveBeenCalledWith(`Clone result ${stdout}`);
spy.mockRestore();
});
it('Should throw and log error if script failed', async () => {
@ -92,5 +95,6 @@ describe('Test: cloneRepo', () => {
expect(e).toBe(randomWord);
expect(log).toHaveBeenCalledWith(`Error cloning repo: ${randomWord}`);
}
spy.mockRestore();
});
});

View file

@ -2,6 +2,7 @@ import childProcess from 'child_process';
import { getAbsolutePath, readJsonFile, readFile, readdirSync, fileExists, writeFile, createFolder, deleteFolder, runScript, getSeed, ensureAppFolder } from '../fs.helpers';
import fs from 'fs-extra';
import { getConfig } from '../../../core/config/TipiConfig';
import { faker } from '@faker-js/faker';
jest.mock('fs-extra');
@ -36,6 +37,22 @@ describe('Test: readJsonFile', () => {
it('should return null if the file does not exist', () => {
expect(readJsonFile('/test')).toBeNull();
});
it('Should return null if fs.readFile throws an error', () => {
// Arrange
// @ts-ignore
const spy = jest.spyOn(fs, 'readFileSync');
spy.mockImplementation(() => {
throw new Error('Error');
});
// Act
const file = readJsonFile('/test');
// Assert
expect(file).toBeNull();
spy.mockRestore();
});
});
describe('Test: readFile', () => {
@ -197,4 +214,23 @@ describe('Test: ensureAppFolder', () => {
const files = fs.readdirSync(`${getConfig().rootFolder}/apps/test`);
expect(files).toEqual(['test.yml']);
});
it('Should delete folder if it exists but has no docker-compose.yml file', () => {
// Arrange
const randomFileName = `${faker.random.word()}.yml`;
const mockFiles = {
[`${getConfig().rootFolder}/repos/${getConfig().appsRepoId}/apps/test`]: [randomFileName],
[`${getConfig().rootFolder}/apps/test`]: ['test.yml'],
};
// @ts-ignore
fs.__createMockFiles(mockFiles);
// Act
ensureAppFolder('test');
// Assert
const files = fs.readdirSync(`${getConfig().rootFolder}/apps/test`);
expect(files).toEqual([randomFileName]);
});
});

View file

@ -84,7 +84,7 @@ const main = async () => {
await datasource.runMigrations();
} catch (e) {
logger.error(e);
await recover();
await recover(datasource);
}
// Run migrations

View file

@ -38,7 +38,8 @@ export const setupConnection = async (testsuite: string): Promise<DataSource> =>
entities: [App, User, Update],
});
return AppDataSource.initialize();
await AppDataSource.initialize();
return AppDataSource;
};
export const teardownConnection = async (testsuite: string): Promise<void> => {