diff --git a/lib/workers/branch/index.js b/lib/workers/branch/index.js index 5a8384ed9bc3ef1c83b7c8cb095fcefe1f921679..c6fcf2d42f765c75de8016b1db08da22a2220076 100644 --- a/lib/workers/branch/index.js +++ b/lib/workers/branch/index.js @@ -8,7 +8,6 @@ let logger = require('../../logger'); module.exports = { getParentBranch, ensureBranch, - generateConfig, processBranchUpgrades, }; @@ -191,37 +190,10 @@ async function ensureBranch(config) { return true; } -async function generateConfig(branchUpgrades) { - const config = { - upgrades: [], - }; - const hasGroupName = branchUpgrades[0].groupName !== null; - logger.debug(`hasGroupName: ${hasGroupName}`); - // Use group settings only if multiple upgrades or lazy grouping is disabled - const groupEligible = - branchUpgrades.length > 1 || branchUpgrades[0].lazyGrouping === false; - logger.debug(`groupEligible: ${groupEligible}`); - const useGroupSettings = hasGroupName && groupEligible; - logger.debug(`useGroupSettings: ${useGroupSettings}`); - for (const branchUpgrade of branchUpgrades) { - const upgrade = Object.assign({}, branchUpgrade); - if (useGroupSettings) { - // Now overwrite original config with group config - Object.assign(upgrade, upgrade.group); - } - // Delete group config regardless of whether it was applied - delete upgrade.group; - config.upgrades.push(upgrade); - } - // Now assign first upgrade's config as branch config - return Object.assign(config, config.upgrades[0]); -} - async function processBranchUpgrades(branchUpgrades, errors, warnings) { logger.trace({ config: branchUpgrades }, 'processBranchUpgrades'); let createdBranch; - const config = await module.exports.generateConfig(branchUpgrades); - logger.trace({ config }, 'generateConfig'); + const config = Object.assign({}, branchUpgrades); // Delete the semanticPrefix for this branch if feature is not enabled if (config.semanticCommits) { logger.debug('Branch has semantic commits enabled'); @@ -233,7 +205,7 @@ async function processBranchUpgrades(branchUpgrades, errors, warnings) { const branchName = handlebars.compile(config.branchName)(config); const prTitle = handlebars.compile(config.prTitle)(config); - logger = config.logger.child({ + logger = logger.child({ repository: config.repository, branch: branchName, }); diff --git a/lib/workers/repository/index.js b/lib/workers/repository/index.js index 264cb959dfa13cdcd90499b15b812f6c6f83666d..c669f000f99b9d34ddcdbd6228f22bd998af6581 100644 --- a/lib/workers/repository/index.js +++ b/lib/workers/repository/index.js @@ -62,15 +62,13 @@ async function renovateRepository(packageFileConfig) { config.errors = config.errors.concat(res.errors); config.warnings = config.warnings.concat(res.warnings); const branchUpgrades = res.branchUpgrades; - config.logger.debug( - `Updating ${Object.keys(branchUpgrades).length} branch(es)` - ); + config.logger.debug(`Updating ${branchUpgrades.length} branch(es)`); config.logger.trace({ config: branchUpgrades }, 'branchUpgrades'); if (config.repoIsOnboarded) { const branchList = []; - for (const branchName of Object.keys(branchUpgrades)) { + for (const branchUpgrade of branchUpgrades) { const createdBranchName = await branchWorker.processBranchUpgrades( - branchUpgrades[branchName], + branchUpgrade, config.errors, config.warnings ); diff --git a/lib/workers/repository/onboarding.js b/lib/workers/repository/onboarding.js index 574dce997d96bdec97349626c4f1525b5d5e831e..88e177af5be95f995e0fc5e4c9bb8eca40b6960e 100644 --- a/lib/workers/repository/onboarding.js +++ b/lib/workers/repository/onboarding.js @@ -30,7 +30,6 @@ async function createBranch(config) { async function ensurePr(config, branchUpgrades) { const warnings = config.warnings; const errors = config.errors; - const onboardBranchNames = Object.keys(branchUpgrades); let prBody = `Welcome to [Renovate](https://keylocation.sg/our-tech/renovate)! This is an onboarding PR to help you understand and configure Renovate before any changes are made to any \`package.json\` files. Once you close this Pull Request, we will begin keeping your dependencies up-to-date via automated Pull Requests. @@ -89,29 +88,18 @@ Please make any fixes in _this branch_. let prDesc = ` With your current configuration, renovate will initially create the following Pull Requests: -| Pull Requests (${onboardBranchNames.length}) | +| Pull Requests (${branchUpgrades.length}) | | ------ | `; - onboardBranchNames.forEach(branchName => { - const upgrades = branchUpgrades[branchName]; - const upgrade0 = upgrades[0]; - if (!upgrade0.lazyGrouping || (upgrade0.groupName && upgrades.length > 1)) { - Object.assign(upgrade0, upgrade0.group); - } - // Delete the semanticPrefix for this branch if feature is not enabled - if (upgrade0.semanticCommits) { - config.logger.debug('Branch has semantic commits enabled'); - } else { - config.logger.debug('Branch has semantic commits disabled'); - delete upgrade0.semanticPrefix; - } - const prTitle = handlebars.compile(upgrade0.prTitle)(upgrade0); + branchUpgrades.forEach(branch => { + const branchName = handlebars.compile(branch.branchName)(branch); + const prTitle = handlebars.compile(branch.prTitle)(branch); prDesc += `| **${prTitle}**<ul>`; - if (upgrade0.schedule && upgrade0.schedule.length) { - prDesc += `<li>Schedule: ${JSON.stringify(upgrade0.schedule)}</li>`; + if (branch.schedule && branch.schedule.length) { + prDesc += `<li>Schedule: ${JSON.stringify(branch.schedule)}</li>`; } prDesc += `<li>Branch name: \`${branchName}\`</li>`; - upgrades.forEach(upgrade => { + branch.upgrades.forEach(upgrade => { if (upgrade.isPin) { prDesc += '<li>Pins '; } else { @@ -122,7 +110,7 @@ With your current configuration, renovate will initially create the following Pu }); prDesc += '</ul> |\n'; }); - if (onboardBranchNames.length === 0) { + if (branchUpgrades.length === 0) { // Overwrite empty content prDesc = 'It looks like your repository dependencies are already up-to-date and no initial Pull Requests will be necessary.'; diff --git a/lib/workers/repository/upgrades.js b/lib/workers/repository/upgrades.js index 25b35cc3d86705613c0197f145bb0a245f39a21a..9d0dbb4984f07f5671ccc2ce1082909bea0d9219 100644 --- a/lib/workers/repository/upgrades.js +++ b/lib/workers/repository/upgrades.js @@ -2,8 +2,12 @@ const handlebars = require('handlebars'); const configParser = require('../../config'); const packageFileWorker = require('../package-file'); +let logger = require('../../logger'); + module.exports = { determineRepoUpgrades, + groupByBranch, + generateConfig, branchifyUpgrades, getPackageFileConfig, }; @@ -27,8 +31,37 @@ async function determineRepoUpgrades(config) { return upgrades; } -async function branchifyUpgrades(upgrades, logger) { - logger.trace({ config: upgrades }, 'branchifyUpgrades'); +function generateConfig(branchUpgrades) { + const config = { + upgrades: [], + }; + const hasGroupName = branchUpgrades[0].groupName !== null; + logger.debug(`hasGroupName: ${hasGroupName}`); + // Use group settings only if multiple upgrades or lazy grouping is disabled + const groupEligible = + branchUpgrades.length > 1 || branchUpgrades[0].lazyGrouping === false; + logger.debug(`groupEligible: ${groupEligible}`); + const useGroupSettings = hasGroupName && groupEligible; + logger.debug(`useGroupSettings: ${useGroupSettings}`); + for (const branchUpgrade of branchUpgrades) { + const upgrade = Object.assign({}, branchUpgrade); + if (useGroupSettings) { + // Now overwrite original config with group config + Object.assign(upgrade, upgrade.group); + } else { + delete upgrade.groupName; + } + // Delete group config regardless of whether it was applied + delete upgrade.group; + delete upgrade.lazyGrouping; + config.upgrades.push(upgrade); + } + // Now assign first upgrade's config as branch config + return Object.assign(config, config.upgrades[0]); +} + +function groupByBranch(upgrades) { + logger.trace({ config: upgrades }, 'groupUpgrades'); logger.info(`Processing ${upgrades.length} dependency upgrade(s)`); const result = { errors: [], @@ -72,6 +105,22 @@ async function branchifyUpgrades(upgrades, logger) { return result; } +async function branchifyUpgrades(upgrades, parentLogger) { + logger = parentLogger || logger; + logger.debug('branchifyUpgrades'); + logger.trace({ config: upgrades }, 'branchifyUpgrades'); + const branchConfigs = []; + const res = module.exports.groupByBranch(upgrades); + for (const branchName of Object.keys(res.branchUpgrades)) { + logger = logger.child({ branch: branchName }); + const branchUpgrades = res.branchUpgrades[branchName]; + const branchConfig = module.exports.generateConfig(branchUpgrades); + branchConfig.logger = logger; + branchConfigs.push(branchConfig); + } + return branchConfigs; +} + function getPackageFileConfig(repoConfig, index) { let packageFile = repoConfig.packageFiles[index]; if (typeof packageFile === 'string') { diff --git a/test/workers/branch/index.spec.js b/test/workers/branch/index.spec.js index e0ebb682c466d4720df57db6701a131fd60afee7..c68af96f72688bd68dcb4270d43c3f1980fc776c 100644 --- a/test/workers/branch/index.spec.js +++ b/test/workers/branch/index.spec.js @@ -331,58 +331,46 @@ describe('workers/branch', () => { config.logger = logger; branchWorker.ensureBranch = jest.fn(() => true); prWorker.ensurePr = jest.fn(() => true); + config.upgrades = [{ depName: 'a' }]; }); it('returns immediately if closed PR found', async () => { config.api.checkForClosedPr.mockReturnValue(true); - await branchWorker.processBranchUpgrades([config]); + await branchWorker.processBranchUpgrades(config); expect(branchWorker.ensureBranch.mock.calls.length).toBe(0); }); it('does not return immediately if recreateClosed true', async () => { config.api.checkForClosedPr.mockReturnValue(true); config.recreateClosed = true; - await branchWorker.processBranchUpgrades([config]); + await branchWorker.processBranchUpgrades(config); expect(branchWorker.ensureBranch.mock.calls.length).toBe(1); }); it('pins', async () => { config.type = 'pin'; - await branchWorker.processBranchUpgrades([config]); + await branchWorker.processBranchUpgrades(config); expect(branchWorker.ensureBranch.mock.calls.length).toBe(1); }); it('majors', async () => { config.type = 'major'; - await branchWorker.processBranchUpgrades([config]); + await branchWorker.processBranchUpgrades(config); expect(branchWorker.ensureBranch.mock.calls.length).toBe(1); }); it('minors', async () => { config.type = 'minor'; - await branchWorker.processBranchUpgrades([config]); + await branchWorker.processBranchUpgrades(config); expect(branchWorker.ensureBranch.mock.calls.length).toBe(1); }); it('handles semantic commits', async () => { config.type = 'minor'; config.semanticCommits = true; - await branchWorker.processBranchUpgrades([config]); + await branchWorker.processBranchUpgrades(config); expect(branchWorker.ensureBranch.mock.calls.length).toBe(1); }); it('handles errors', async () => { config.api.checkForClosedPr = jest.fn(() => { throw new Error('oops'); }); - await branchWorker.processBranchUpgrades([config]); + await branchWorker.processBranchUpgrades(config); expect(branchWorker.ensureBranch.mock.calls.length).toBe(0); }); }); - describe('generateConfig(branchUpgrades)', () => { - let config; - beforeEach(() => { - config = Object.assign({}, defaultConfig, { logger }); - }); - it('uses group settings', async () => { - config.groupName = 'some-group'; - config.group.branchName = 'some-group-branchname'; - const branchUpgrades = [config, config]; - const res = await branchWorker.generateConfig(branchUpgrades); - expect(res.branchName).toEqual(config.group.branchName); - }); - }); }); diff --git a/test/workers/repository/__snapshots__/upgrades.spec.js.snap b/test/workers/repository/__snapshots__/upgrades.spec.js.snap index 3cc4de3c3f6d2e5cf8e7cf75d2e11c0317cc096e..87019805872d65c06848816027359b1dbaaf1d75 100644 --- a/test/workers/repository/__snapshots__/upgrades.spec.js.snap +++ b/test/workers/repository/__snapshots__/upgrades.spec.js.snap @@ -1,6 +1,34 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`workers/repository/upgrades branchifyUpgrades(upgrades, logger) does not group if different compiled branch names 1`] = ` +exports[`workers/repository/upgrades generateConfig(branchUpgrades) does not group single upgrade 1`] = ` +Object { + "depName": "some-dep", + "foo": 1, + "upgrades": Array [ + Object { + "depName": "some-dep", + "foo": 1, + }, + ], +} +`; + +exports[`workers/repository/upgrades generateConfig(branchUpgrades) groups single upgrade if not lazyGrouping 1`] = ` +Object { + "depName": "some-dep", + "foo": 2, + "groupName": "some-group", + "upgrades": Array [ + Object { + "depName": "some-dep", + "foo": 2, + "groupName": "some-group", + }, + ], +} +`; + +exports[`workers/repository/upgrades groupByBranch(upgrades) does not group if different compiled branch names 1`] = ` Object { "branchUpgrades": Object { "bar-1.1.0": Array [ @@ -27,7 +55,7 @@ Object { } `; -exports[`workers/repository/upgrades branchifyUpgrades(upgrades, logger) groups if same compiled branch names 1`] = ` +exports[`workers/repository/upgrades groupByBranch(upgrades) groups if same compiled branch names 1`] = ` Object { "branchUpgrades": Object { "bar-1.1.0": Array [ @@ -52,7 +80,7 @@ Object { } `; -exports[`workers/repository/upgrades branchifyUpgrades(upgrades, logger) groups if same compiled group name 1`] = ` +exports[`workers/repository/upgrades groupByBranch(upgrades) groups if same compiled group name 1`] = ` Object { "branchUpgrades": Object { "foo": Array [ @@ -87,7 +115,7 @@ Object { } `; -exports[`workers/repository/upgrades branchifyUpgrades(upgrades, logger) mixes errors and warnings 1`] = ` +exports[`workers/repository/upgrades groupByBranch(upgrades) mixes errors and warnings 1`] = ` Object { "branchUpgrades": Object { "bar-1.1.0": Array [ @@ -118,7 +146,7 @@ Object { } `; -exports[`workers/repository/upgrades branchifyUpgrades(upgrades, logger) returns empty object if no input array 1`] = ` +exports[`workers/repository/upgrades groupByBranch(upgrades) returns empty object if no input array 1`] = ` Object { "branchUpgrades": Object {}, "errors": Array [], @@ -126,7 +154,7 @@ Object { } `; -exports[`workers/repository/upgrades branchifyUpgrades(upgrades, logger) returns one branch if one input 1`] = ` +exports[`workers/repository/upgrades groupByBranch(upgrades) returns one branch if one input 1`] = ` Object { "branchUpgrades": Object { "foo-1.1.0": Array [ @@ -140,3 +168,23 @@ Object { "warnings": Array [], } `; + +exports[`workers/repository/upgrades groups multiple upgrades 1`] = ` +Object { + "depName": "some-dep", + "foo": 2, + "groupName": "some-group", + "upgrades": Array [ + Object { + "depName": "some-dep", + "foo": 2, + "groupName": "some-group", + }, + Object { + "depName": "some-other-dep", + "foo": 2, + "groupName": "some-group", + }, + ], +} +`; diff --git a/test/workers/repository/index.spec.js b/test/workers/repository/index.spec.js index 5ce2f9d9fc33a2d93e44d58e9f2924478f399c3e..be9ae49a4c84f30ab61319acb63ad2ad905feb8e 100644 --- a/test/workers/repository/index.spec.js +++ b/test/workers/repository/index.spec.js @@ -83,11 +83,7 @@ describe('workers/repository', () => { config.hasRenovateJson = true; onboarding.getOnboardingStatus.mockReturnValueOnce(true); upgrades.branchifyUpgrades.mockReturnValueOnce({ - branchUpgrades: { - foo: {}, - bar: {}, - baz: {}, - }, + branchUpgrades: [{}, {}, {}], }); await repositoryWorker.renovateRepository(config); expect(branchWorker.processBranchUpgrades.mock.calls.length).toBe(3); diff --git a/test/workers/repository/onboarding.spec.js b/test/workers/repository/onboarding.spec.js index f02eb610835d2e95dd8ac1d056b210918e814777..0ea02ba0b3a7fd5349c363e04136da5bd21b6bb1 100644 --- a/test/workers/repository/onboarding.spec.js +++ b/test/workers/repository/onboarding.spec.js @@ -17,7 +17,7 @@ describe('lib/workers/repository/onboarding', () => { }, logger, }; - branchUpgrades = {}; + branchUpgrades = []; }); it('creates pr', async () => { config.baseBranch = 'next'; @@ -65,85 +65,95 @@ If the default settings are all suitable for you, simply close this Pull Request expect(config.api.updatePr.mock.calls.length).toBe(0); }); it('creates complex pr', async () => { - branchUpgrades = { - 'branch-a': [ - { - prTitle: 'Pin a', - isPin: true, - depName: 'a', - repositoryUrl: 'https://a', - currentVersion: '^1.0.0', - newVersion: '1.1.0', - semanticCommits: true, - }, - ], - 'branch-b': [ - { - prTitle: 'Upgrade b', - depName: 'b', - repositoryUrl: 'https://b', - currentVersion: '1.0.0', - newVersion: '2.0.0', - schedule: 'on monday', - }, - ], - }; + branchUpgrades = [ + { + branchName: 'branch-a', + prTitle: 'Pin a', + upgrades: [ + { + isPin: true, + depName: 'a', + repositoryUrl: 'https://a', + currentVersion: '^1.0.0', + newVersion: '1.1.0', + }, + ], + }, + { + branchName: 'branch-b', + prTitle: 'Upgrade b', + schedule: 'on monday', + upgrades: [ + { + depName: 'b', + repositoryUrl: 'https://b', + currentVersion: '1.0.0', + newVersion: '2.0.0', + }, + ], + }, + ]; await onboarding.ensurePr(config, branchUpgrades); expect(config.api.createPr.mock.calls.length).toBe(1); expect(config.api.updatePr.mock.calls.length).toBe(0); expect(config.api.createPr.mock.calls).toMatchSnapshot(); }); it('handles groups', async () => { - branchUpgrades = { - 'branch-a': [ - { - prTitle: 'Pin a', - isPin: true, - depName: 'a', - repositoryUrl: 'https://a', - currentVersion: '^1.0.0', - newVersion: '1.1.0', - semanticCommits: true, - lazyGrouping: true, - groupName: 'some-group', - }, - { - prTitle: 'Upgrade b', - depName: 'b', - repositoryUrl: 'https://b', - currentVersion: '1.0.0', - newVersion: '2.0.0', - schedule: 'on monday', - }, - ], - }; + branchUpgrades = [ + { + branchName: 'branch-a', + prTitle: 'Pin a', + groupName: 'some-group', + upgrades: [ + { + isPin: true, + depName: 'a', + repositoryUrl: 'https://a', + currentVersion: '^1.0.0', + newVersion: '1.1.0', + }, + { + depName: 'b', + repositoryUrl: 'https://b', + currentVersion: '1.0.0', + newVersion: '2.0.0', + }, + ], + }, + ]; await onboarding.ensurePr(config, branchUpgrades); expect(config.api.createPr.mock.calls.length).toBe(1); expect(config.api.updatePr.mock.calls.length).toBe(0); expect(config.api.createPr.mock.calls).toMatchSnapshot(); }); it('creates shows warnings and errors', async () => { - branchUpgrades = { - 'branch-a': [ - { - prTitle: 'Pin a', - isPin: true, - depName: 'a', - repositoryUrl: 'https://a', - currentVersion: '^1.0.0', - newVersion: '1.1.0', - }, - ], - 'branch-b': [ - { - prTitle: 'Upgrade b', - depName: 'b', - repositoryUrl: 'https://b', - currentVersion: '1.0.0', - newVersion: '2.0.0', - }, - ], - }; + branchUpgrades = [ + { + branchName: 'branch-a', + prTitle: 'Pin a', + upgrades: [ + { + isPin: true, + depName: 'a', + repositoryUrl: 'https://a', + currentVersion: '^1.0.0', + newVersion: '1.1.0', + }, + ], + }, + { + branchName: 'branch-b', + prTitle: 'Upgrade b', + upgrades: [ + { + depName: 'b', + repositoryUrl: 'https://b', + currentVersion: '1.0.0', + newVersion: '2.0.0', + }, + ], + }, + ]; config.errors = [ { depName: 'a', diff --git a/test/workers/repository/upgrades.spec.js b/test/workers/repository/upgrades.spec.js index faf64a50f2d3e693c783594d532509c5d4d99e61..0583efb106023ac9af2927c39111f57c9b703d79 100644 --- a/test/workers/repository/upgrades.spec.js +++ b/test/workers/repository/upgrades.spec.js @@ -44,9 +44,71 @@ describe('workers/repository/upgrades', () => { expect(res.length).toBe(3); }); }); - describe('branchifyUpgrades(upgrades, logger)', () => { + describe('generateConfig(branchUpgrades)', () => { + it('does not group single upgrade', () => { + const branchUpgrades = [ + { + depName: 'some-dep', + groupName: 'some-group', + lazyGrouping: true, + foo: 1, + group: { + foo: 2, + }, + }, + ]; + const res = upgrades.generateConfig(branchUpgrades); + expect(res.foo).toBe(1); + expect(res.groupName).toBeUndefined(); + expect(res).toMatchSnapshot(); + }); + it('groups single upgrade if not lazyGrouping', () => { + const branchUpgrades = [ + { + depName: 'some-dep', + groupName: 'some-group', + lazyGrouping: false, + foo: 1, + group: { + foo: 2, + }, + }, + ]; + const res = upgrades.generateConfig(branchUpgrades); + expect(res.foo).toBe(2); + expect(res.groupName).toBeDefined(); + expect(res).toMatchSnapshot(); + }); + }); + it('groups multiple upgrades', () => { + const branchUpgrades = [ + { + depName: 'some-dep', + groupName: 'some-group', + lazyGrouping: true, + foo: 1, + group: { + foo: 2, + }, + }, + { + depName: 'some-other-dep', + groupName: 'some-group', + lazyGrouping: true, + foo: 1, + group: { + foo: 2, + }, + }, + ]; + const res = upgrades.generateConfig(branchUpgrades); + expect(res.foo).toBe(2); + expect(res.groupName).toBeDefined(); + expect(res).toMatchSnapshot(); + }); + describe('groupByBranch(upgrades)', () => { it('returns empty object if no input array', async () => { - const res = await upgrades.branchifyUpgrades([], logger); + const res = await upgrades.groupByBranch([]); expect(res).toMatchSnapshot(); }); it('returns one branch if one input', async () => { @@ -56,7 +118,7 @@ describe('workers/repository/upgrades', () => { version: '1.1.0', }, ]; - const res = await upgrades.branchifyUpgrades(input, logger); + const res = await upgrades.groupByBranch(input); expect(Object.keys(res.branchUpgrades).length).toBe(1); expect(res).toMatchSnapshot(); }); @@ -75,7 +137,7 @@ describe('workers/repository/upgrades', () => { version: '1.1.0', }, ]; - const res = await upgrades.branchifyUpgrades(input, logger); + const res = await upgrades.groupByBranch(input); expect(Object.keys(res.branchUpgrades).length).toBe(3); expect(res).toMatchSnapshot(); }); @@ -94,7 +156,7 @@ describe('workers/repository/upgrades', () => { version: '1.1.0', }, ]; - const res = await upgrades.branchifyUpgrades(input, logger); + const res = await upgrades.groupByBranch(input); expect(Object.keys(res.branchUpgrades).length).toBe(2); expect(res).toMatchSnapshot(); }); @@ -117,7 +179,7 @@ describe('workers/repository/upgrades', () => { group: { branchName: 'renovate/my-group' }, }, ]; - const res = await upgrades.branchifyUpgrades(input, logger); + const res = await upgrades.groupByBranch(input); expect(Object.keys(res.branchUpgrades).length).toBe(2); expect(res).toMatchSnapshot(); }); @@ -140,11 +202,35 @@ describe('workers/repository/upgrades', () => { version: '1.1.0', }, ]; - const res = await upgrades.branchifyUpgrades(input, logger); + const res = await upgrades.groupByBranch(input); expect(Object.keys(res.branchUpgrades).length).toBe(2); expect(res.errors).toHaveLength(1); expect(res.warnings).toHaveLength(1); expect(res).toMatchSnapshot(); }); }); + describe('branchifyUpgrades(upgrades, parentLogger)', () => { + it('returns empty', async () => { + upgrades.groupByBranch = jest.fn(() => ({ + branchUpgrades: {}, + errors: [], + warnings: [], + })); + const res = await upgrades.branchifyUpgrades({}); + expect(res).toEqual([]); + }); + it('processes multiple branches', async () => { + upgrades.groupByBranch = jest.fn(() => ({ + branchUpgrades: { + a: [], + b: [], + }, + errors: [], + warnings: [], + })); + upgrades.generateConfig = jest.fn(() => ({})); + const res = await upgrades.branchifyUpgrades({}); + expect(res).toHaveLength(2); + }); + }); });