renovate/test/workers/repository/apis.spec.js

311 lines
10 KiB
JavaScript

const jsonValidator = require('json-dup-key-validator');
const apis = require('../../../lib/workers/repository/apis');
const logger = require('../../_fixtures/logger');
const githubApi = require('../../../lib/api/github');
const gitlabApi = require('../../../lib/api/gitlab');
const npmApi = require('../../../lib/api/npm');
const defaultConfig = require('../../../lib/config/defaults').getConfig();
jest.mock('../../../lib/api/github');
jest.mock('../../../lib/api/gitlab');
jest.mock('../../../lib/api/npm');
describe('workers/repository/apis', () => {
describe('setNpmrc(config)', () => {
it('Skips if npmrc not found', async () => {
const config = {
api: {
getFileContent: jest.fn(),
},
};
await apis.setNpmrc(config);
});
it('Parses if npmrc found', async () => {
const config = {
api: {
getFileContent: jest.fn(() => 'a = b'),
},
logger,
};
await apis.setNpmrc(config);
});
it('Catches errors', async () => {
const config = {
api: {
getFileContent: jest.fn(() => {
throw new Error('file error');
}),
},
logger,
};
await apis.setNpmrc(config);
});
});
describe('detectSemanticCommits', () => {
it('disables semantic commits', async () => {
const config = {
api: {
getCommitMessages: jest.fn(() => []),
},
logger,
};
const res = await apis.detectSemanticCommits(config);
expect(res).toEqual(false);
});
it('enables semantic commits', async () => {
const config = {
api: {
getCommitMessages: jest.fn(() => []),
},
logger,
};
config.api.getCommitMessages.mockReturnValueOnce(['fix: something']);
const res = await apis.detectSemanticCommits(config);
expect(res).toEqual(true);
});
});
describe('checkForLerna(config)', () => {
it('swallows lerna 404', async () => {
const config = {
api: {
getFileJson: jest.fn(() => ({})),
getSubDirectories: jest.fn(() => {
throw new Error('some-error');
}),
},
logger,
};
const res = await apis.checkForLerna(config);
expect(res).toMatchSnapshot();
});
it('ignores zero length lerna', async () => {
const config = {
api: {
getFileJson: jest.fn(() => ({ packages: ['packages/*'] })),
getSubDirectories: jest.fn(() => []),
},
logger,
};
const res = await apis.checkForLerna(config);
expect(res).toMatchSnapshot();
});
it('implies lerna package path', async () => {
const config = {
api: {
getFileJson: jest.fn(() => ({})),
getSubDirectories: jest.fn(() => ['a', 'b']),
},
logger,
};
const res = await apis.checkForLerna(config);
expect(res).toMatchSnapshot();
});
it('returns lerna package names', async () => {
const config = {
api: {
getFileJson: jest.fn(() => ({ packages: ['packages/*'] })),
getSubDirectories: jest.fn(() => ['a', 'b']),
},
logger,
};
const res = await apis.checkForLerna(config);
expect(res).toMatchSnapshot();
});
});
describe('initApis(config)', () => {
beforeEach(() => {
jest.resetAllMocks();
});
it('returns github api', async () => {
const config = { logger, platform: 'github', semanticCommits: null };
const res = await apis.initApis(config);
expect(res.platform).toEqual('github');
expect(githubApi.initRepo.mock.calls.length).toBe(1);
expect(gitlabApi.initRepo.mock.calls.length).toBe(0);
expect(npmApi.setNpmrc.mock.calls.length).toBe(1);
});
it('returns gitlab api', async () => {
const config = { logger, platform: 'gitlab' };
const res = await apis.initApis(config);
expect(res.platform).toEqual('gitlab');
expect(githubApi.initRepo.mock.calls.length).toBe(0);
expect(gitlabApi.initRepo.mock.calls.length).toBe(1);
expect(npmApi.setNpmrc.mock.calls.length).toBe(1);
});
it('throws if unknown platform', async () => {
const config = { platform: 'foo' };
let e;
try {
await apis.initApis(config);
} catch (err) {
e = err;
}
expect(e.message).toMatchSnapshot();
expect(githubApi.initRepo.mock.calls.length).toBe(0);
expect(gitlabApi.initRepo.mock.calls.length).toBe(0);
expect(npmApi.setNpmrc.mock.calls.length).toBe(0);
});
});
describe('mergeRenovateJson(config)', () => {
let config;
beforeEach(() => {
config = {
errors: [],
warnings: [],
api: {
getFileContent: jest.fn(),
},
logger,
};
});
it('returns same config if no renovate.json found', async () => {
expect(await apis.mergeRenovateJson(config)).toEqual(config);
});
it('returns extended config if renovate.json found', async () => {
config.api.getFileContent.mockReturnValueOnce('{ "enabled": true }');
const returnConfig = await apis.mergeRenovateJson(config);
expect(returnConfig.enabled).toBe(true);
expect(returnConfig.renovateJsonPresent).toBe(true);
expect(returnConfig.errors).toHaveLength(0);
});
it('returns warning + error plus extended config if unknown keys', async () => {
config.repoIsOnboarded = true;
config.api.getFileContent.mockReturnValueOnce(
'{ "enabled": true, "foo": false, "maintainYarnLock": true, "schedule": "before 5am", "minor": {} }'
);
const returnConfig = await apis.mergeRenovateJson(config);
expect(returnConfig.enabled).toBe(true);
expect(returnConfig.renovateJsonPresent).toBe(true);
expect(returnConfig.errors).toHaveLength(0); // TODO: Update to 1 later
expect(returnConfig.errors).toMatchSnapshot();
});
it('returns error plus extended config if duplicate keys', async () => {
config.repoIsOnboarded = true;
config.api.getFileContent.mockReturnValueOnce(
'{ "enabled": true, "enabled": false }'
);
const returnConfig = await apis.mergeRenovateJson(config);
expect(returnConfig.enabled).toBe(false);
expect(returnConfig.renovateJsonPresent).toBe(true);
expect(returnConfig.errors).toHaveLength(1);
expect(returnConfig.errors).toMatchSnapshot();
});
it('returns error in config if renovate.json cannot be parsed', async () => {
config.api.getFileContent.mockReturnValueOnce('{ enabled: true }');
const returnConfig = await apis.mergeRenovateJson(config);
expect(returnConfig.enabled).toBeUndefined();
expect(returnConfig.renovateJsonPresent).toBeUndefined();
expect(returnConfig.errors).toMatchSnapshot();
});
it('returns error in JSON.parse', async () => {
config.api.getFileContent.mockReturnValueOnce('{ enabled: true }');
jsonValidator.validate = jest.fn();
jsonValidator.validate.mockReturnValueOnce(false);
jsonValidator.validate.mockReturnValueOnce(false);
const returnConfig = await apis.mergeRenovateJson(config);
expect(returnConfig.foo).toBeUndefined();
expect(returnConfig.renovateJsonPresent).toBeUndefined();
expect(returnConfig.errors).toMatchSnapshot();
});
});
describe('detectPackageFiles(config)', () => {
it('adds package files to object', async () => {
const config = {
api: {
findFilePaths: jest.fn(() => [
'package.json',
'backend/package.json',
]),
},
logger,
warnings: [],
};
const res = await apis.detectPackageFiles(config);
expect(res).toMatchObject(config);
expect(res.packageFiles).toMatchSnapshot();
});
it('ignores node modules', async () => {
const config = {
ignoreNodeModules: true,
api: {
findFilePaths: jest.fn(() => [
'package.json',
'node_modules/backend/package.json',
]),
},
logger,
warnings: [],
};
const res = await apis.detectPackageFiles(config);
expect(res.packageFiles).toMatchSnapshot();
expect(res.foundNodeModules).toMatchSnapshot();
expect(res.warnings).toMatchSnapshot();
});
it('defaults to package.json if found', async () => {
const config = {
api: {
findFilePaths: jest.fn(() => []),
getFileJson: jest.fn(() => ({})),
},
logger,
};
const res = await apis.detectPackageFiles(config);
expect(res.packageFiles).toHaveLength(1);
expect(res.packageFiles).toMatchSnapshot();
});
it('returns empty if package.json not found', async () => {
const config = {
api: {
findFilePaths: jest.fn(() => []),
getFileJson: jest.fn(() => null),
},
logger,
};
const res = await apis.detectPackageFiles(config);
expect(res.packageFiles).toEqual([]);
});
});
describe('resolvePackageFiles', () => {
let config;
beforeEach(() => {
config = {
packageFiles: ['package.json', { packageFile: 'a/package.json' }],
api: {
getFileContent: jest.fn(),
getFileJson: jest.fn(),
},
logger,
};
});
it('skips files with no content', async () => {
const res = await apis.resolvePackageFiles(config);
expect(res.packageFiles).toEqual([]);
});
it('includes files with content', async () => {
config.api.getFileJson.mockReturnValueOnce({ renovate: {} });
config.api.getFileJson.mockReturnValueOnce({});
config.api.getFileContent.mockReturnValueOnce(true);
config.api.getFileContent.mockReturnValueOnce(true);
const res = await apis.resolvePackageFiles(config);
expect(res.packageFiles).toHaveLength(2);
expect(res.packageFiles).toMatchSnapshot();
});
});
});
describe('migrateAndValidate', () => {
it('returns empty config', () => {
const renovateJson = {};
const res = apis.migrateAndValidate(defaultConfig, renovateJson);
expect(res).toMatchSnapshot();
});
it('massages string to array', () => {
const renovateJson = {
schedule: 'before 5am',
};
const res = apis.migrateAndValidate(defaultConfig, renovateJson);
expect(Array.isArray(res.schedule)).toBe(true);
});
});