test: cron jobs
This commit is contained in:
parent
7a444698b8
commit
9d4cdf6f77
10 changed files with 99 additions and 8 deletions
0
media/data/music/.gitkeep
Normal file
0
media/data/music/.gitkeep
Normal file
11
packages/system-api/__mocks__/node-cron.ts
Normal file
11
packages/system-api/__mocks__/node-cron.ts
Normal 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;
|
|
@ -12,4 +12,10 @@ module.exports = {
|
|||
transform: {
|
||||
'^.+\\.graphql$': 'graphql-import-node/jest',
|
||||
},
|
||||
globals: {
|
||||
// NODE_ENV: 'test',
|
||||
'ts-jest': {
|
||||
isolatedModules: true,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
|
32
packages/system-api/src/core/jobs/__tests__/jobs.test.ts
Normal file
32
packages/system-api/src/core/jobs/__tests__/jobs.test.ts
Normal 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();
|
||||
});
|
||||
});
|
|
@ -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);
|
||||
});
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
});
|
||||
});
|
||||
|
|
|
@ -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]);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -84,7 +84,7 @@ const main = async () => {
|
|||
await datasource.runMigrations();
|
||||
} catch (e) {
|
||||
logger.error(e);
|
||||
await recover();
|
||||
await recover(datasource);
|
||||
}
|
||||
|
||||
// Run migrations
|
||||
|
|
|
@ -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> => {
|
||||
|
|
Loading…
Reference in a new issue