const repositoryWorker = require('../../../lib/workers/repository/index'); const branchWorker = require('../../../lib/workers/branch'); const apis = require('../../../lib/workers/repository/apis'); const manager = require('../../../lib/manager'); const onboarding = require('../../../lib/workers/repository/onboarding'); const upgrades = require('../../../lib/workers/repository/upgrades'); const logger = require('../../_fixtures/logger'); const onboardingPr = require('../../../lib/workers/repository/onboarding/pr'); jest.mock('../../../lib/workers/repository/onboarding/pr'); describe('workers/repository', () => { describe('renovateRepository', () => { let config; beforeEach(() => { jest.resetAllMocks(); apis.initApis = jest.fn(input => input); apis.mergeRenovateJson = jest.fn(input => input); manager.detectPackageFiles = jest.fn(); apis.resolvePackageFiles = jest.fn(input => input); apis.checkMonorepos = jest.fn(input => input); onboarding.getOnboardingStatus = jest.fn(input => input); upgrades.determineRepoUpgrades = jest.fn(() => []); upgrades.branchifyUpgrades = jest.fn(() => ({ branchUpgrades: {} })); branchWorker.processBranch = jest.fn(() => 'done'); config = { lockFileMaintenance: true, api: { getFileJson: jest.fn(), setBaseBranch: jest.fn(), branchExists: jest.fn(), }, logger, packageFiles: [], }; }); it('skips repository if config is disabled', async () => { config.enabled = false; await repositoryWorker.renovateRepository(config); expect(manager.detectPackageFiles.mock.calls.length).toBe(0); }); it('skips repository if its unconfigured fork', async () => { config.isFork = true; config.renovateJsonPresent = false; await repositoryWorker.renovateRepository(config); expect(manager.detectPackageFiles.mock.calls.length).toBe(0); }); it('does not skip repository if its a configured fork', async () => { config.isFork = true; config.renovateFork = true; manager.detectPackageFiles.mockReturnValueOnce([]); await repositoryWorker.renovateRepository(config); }); it('sets custom base branch', async () => { config.baseBranch = 'some-branch'; config.api.branchExists.mockReturnValueOnce(true); manager.detectPackageFiles.mockReturnValueOnce([]); await repositoryWorker.renovateRepository(config); expect(config.api.setBaseBranch.mock.calls).toHaveLength(1); }); it('errors when missing custom base branch', async () => { config.baseBranch = 'some-branch'; config.api.branchExists.mockReturnValueOnce(false); manager.detectPackageFiles.mockReturnValueOnce([]); await repositoryWorker.renovateRepository(config); expect(config.api.setBaseBranch.mock.calls).toHaveLength(0); }); it('skips repository if no package.json', async () => { manager.detectPackageFiles.mockReturnValueOnce([]); await repositoryWorker.renovateRepository(config); expect(apis.resolvePackageFiles.mock.calls.length).toBe(0); expect(config.logger.error.mock.calls.length).toBe(0); }); it('does not skip repository if package.json', async () => { manager.detectPackageFiles.mockReturnValueOnce(['package.json']); config.api.getFileJson = jest.fn(() => ({ a: 1 })); apis.mergeRenovateJson.mockImplementationOnce(input => ({ ...input, ...{ packageFiles: ['package.json'] }, })); apis.mergeRenovateJson.mockImplementationOnce(input => ({ ...input, ...{ packageFiles: ['package.json'] }, })); upgrades.branchifyUpgrades.mockReturnValueOnce({ upgrades: [{}, {}, {}], }); await repositoryWorker.renovateRepository(config); expect(onboarding.getOnboardingStatus.mock.calls.length).toBe(1); expect(branchWorker.processBranch.mock.calls.length).toBe(0); expect(onboardingPr.ensureOnboardingPr.mock.calls.length).toBe(1); expect(config.logger.error.mock.calls.length).toBe(0); }); it('uses onboarding custom baseBranch', async () => { manager.detectPackageFiles.mockReturnValueOnce(['package.json']); config.api.getFileJson = jest.fn(() => ({ a: 1 })); manager.detectPackageFiles.mockReturnValueOnce(['package.json']); apis.mergeRenovateJson.mockImplementationOnce(input => ({ ...input, ...{ packageFiles: ['package.json'], baseBranch: 'next' }, })); config.api.branchExists.mockReturnValueOnce(true); upgrades.branchifyUpgrades.mockReturnValueOnce({ upgrades: [{}, {}, {}], }); await repositoryWorker.renovateRepository(config); expect(onboarding.getOnboardingStatus.mock.calls.length).toBe(1); expect(branchWorker.processBranch.mock.calls.length).toBe(0); expect(onboardingPr.ensureOnboardingPr.mock.calls.length).toBe(1); expect(config.logger.error.mock.calls.length).toBe(0); }); it('errors onboarding custom baseBranch', async () => { manager.detectPackageFiles.mockReturnValueOnce(['package.json']); config.api.getFileJson = jest.fn(() => ({ a: 1 })); apis.mergeRenovateJson.mockImplementationOnce(input => ({ ...input, ...{ packageFiles: [] }, })); apis.mergeRenovateJson.mockImplementationOnce(input => ({ ...input, ...{ packageFiles: [], baseBranch: 'next' }, })); upgrades.branchifyUpgrades.mockReturnValueOnce({ upgrades: [{}, {}, {}], }); await repositoryWorker.renovateRepository(config); expect(onboarding.getOnboardingStatus.mock.calls.length).toBe(1); expect(branchWorker.processBranch.mock.calls.length).toBe(0); expect(onboardingPr.ensureOnboardingPr.mock.calls.length).toBe(1); expect(config.logger.error.mock.calls.length).toBe(0); }); it('calls branchWorker', async () => { config.packageFiles = ['package.json']; config.hasRenovateJson = true; onboarding.getOnboardingStatus.mockImplementation(input => ({ ...input, repoIsOnboarded: true, })); upgrades.branchifyUpgrades.mockReturnValueOnce({ upgrades: [{}, {}, {}], }); await repositoryWorker.renovateRepository(config); expect(branchWorker.processBranch.mock.calls.length).toBe(3); expect(config.logger.error.mock.calls.length).toBe(0); }); it('skips branchWorker after automerging', async () => { config.packageFiles = ['package.json']; config.hasRenovateJson = true; onboarding.getOnboardingStatus.mockImplementation(input => ({ ...input, repoIsOnboarded: true, })); upgrades.branchifyUpgrades.mockReturnValueOnce({ upgrades: [{}, {}, {}], }); upgrades.branchifyUpgrades.mockReturnValueOnce({ upgrades: [{}, {}], }); upgrades.branchifyUpgrades.mockReturnValueOnce({ upgrades: [{}], }); upgrades.branchifyUpgrades.mockReturnValueOnce({ upgrades: [], }); branchWorker.processBranch.mockReturnValue('automerged'); await repositoryWorker.renovateRepository(config); expect(upgrades.branchifyUpgrades.mock.calls).toHaveLength(4); expect(branchWorker.processBranch.mock.calls).toHaveLength(3); expect(config.logger.error.mock.calls).toHaveLength(0); }); it('only processes pins first', async () => { config.packageFiles = ['package.json']; config.hasRenovateJson = true; onboarding.getOnboardingStatus.mockImplementation(input => ({ ...input, repoIsOnboarded: true, })); upgrades.branchifyUpgrades.mockReturnValueOnce({ upgrades: [{ isPin: true }, {}, {}], }); branchWorker.processBranch.mockReturnValue('done'); await repositoryWorker.renovateRepository(config); expect(upgrades.branchifyUpgrades.mock.calls).toHaveLength(1); expect(branchWorker.processBranch.mock.calls).toHaveLength(1); expect(config.logger.error.mock.calls).toHaveLength(0); }); it('swallows errors', async () => { apis.initApis.mockImplementationOnce(() => { throw new Error('bad init'); }); await repositoryWorker.renovateRepository(config); expect(config.logger.error.mock.calls.length).toBe(1); }); it('handles special uninitiated error', async () => { apis.initApis.mockImplementationOnce(() => { // Create a new object, that prototypically inherits from the Error constructor function MyError() { this.message = 'uninitiated'; } MyError.prototype = Object.create(Error.prototype); MyError.prototype.constructor = MyError; throw new MyError(); }); await repositoryWorker.renovateRepository(config); expect(config.logger.error.mock.calls.length).toBe(0); }); it('handles special no package files error', async () => { apis.initApis.mockImplementationOnce(() => { // Create a new object, that prototypically inherits from the Error constructor function MyError() { this.message = 'no package files'; } MyError.prototype = Object.create(Error.prototype); MyError.prototype.constructor = MyError; throw new MyError(); }); await repositoryWorker.renovateRepository(config); expect(config.logger.error.mock.calls.length).toBe(0); }); }); });