diff --git a/lib/modules/manager/git-submodules/extract.spec.ts b/lib/modules/manager/git-submodules/extract.spec.ts index 0f6df2f7737732d10460eb226fd4fa6dccdbe45d..6850f30f1930f47bd3cc04f231f349b0b3e67d1b 100644 --- a/lib/modules/manager/git-submodules/extract.spec.ts +++ b/lib/modules/manager/git-submodules/extract.spec.ts @@ -1,69 +1,83 @@ import is from '@sindresorhus/is'; import { mock } from 'jest-mock-extended'; -import _simpleGit, { - Response, - SimpleGit, - SimpleGitFactory, - TaskOptions, -} from 'simple-git'; +import { Response, SimpleGit, SimpleGitFactory, simpleGit } from 'simple-git'; import { GlobalConfig } from '../../../config/global'; import * as hostRules from '../../../util/host-rules'; -import type { PackageFileContent } from '../types'; import { extractPackageFile } from '.'; jest.mock('simple-git'); -const simpleGit: jest.Mock<Partial<SimpleGit>> = _simpleGit as never; +const simpleGitFactoryMock = simpleGit as jest.Mock<Partial<SimpleGit>>; // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion const Git = jest.requireActual('simple-git') as SimpleGitFactory; +const gitMock = mock<SimpleGit>(); + describe('modules/manager/git-submodules/extract', () => { - // flaky ci tests - // jest.setTimeout(10 * 1000); + beforeEach(() => { + GlobalConfig.set({ localDir: `${__dirname}/__fixtures__` }); + // clear host rules + hostRules.clear(); + // clear environment variables + process.env = {}; - beforeAll(() => { - simpleGit.mockImplementation((basePath: string) => { + simpleGitFactoryMock.mockImplementation((basePath: string) => { const git = Git(basePath); - const lsRemote: Record<string, string> = { - 'https://abc@domain.test/some/other.git': '', - 'https://gitlab-ci-token:xyz@gitlab.com/some/repo.git': - 'ref: refs/heads/dev HEAD\n', - }; - return { - subModule(): Response<string> { - return Promise.resolve( - '4b825dc642cb6eb9a060e54bf8d69288fbee4904' - ) as Response<string>; - }, - raw(options: string | string[] | TaskOptions): Response<string> { - if ( - (is.string(options) || is.array(options, is.string)) && - options.includes('remote.origin.url') - ) { - return Promise.resolve( - 'https://github.com/renovatebot/renovate.git' - ) as Response<string>; - } - return git.raw(options); - }, - listRemote(options: TaskOptions): Response<string> { - if ( - is.array(options, is.string) && - lsRemote[options[1]] !== undefined - ) { - return Promise.resolve(lsRemote[options[1]]) as Response<string>; - } + + gitMock.env.mockImplementation(() => gitMock); + gitMock.subModule.mockResolvedValue( + '4b825dc642cb6eb9a060e54bf8d69288fbee4904' + ); + + gitMock.raw.mockImplementation((options) => { + if ( + (is.string(options) || is.array(options, is.string)) && + options.includes('remote.origin.url') + ) { return Promise.resolve( - 'ref: refs/heads/main HEAD\n5701164b9f5edba1f6ca114c491a564ffb55a964 HEAD' + 'https://github.com/renovatebot/renovate.git' ) as Response<string>; - }, - ...mock<Omit<SimpleGit, 'subModule' | 'raw' | 'listRemote'>>(), - }; + } + return git.raw(options); + }); + return gitMock; }); }); describe('extractPackageFile()', () => { - it('extracts submodules', async () => { - GlobalConfig.set({ localDir: `${__dirname}/__fixtures__` }); + it('empty submodule returns null', async () => { + expect(await extractPackageFile('', '.gitmodules.1', {})).toBeNull(); + }); + + it('default branch is detected when no branch is specified', async () => { + gitMock.listRemote.mockResolvedValueOnce( + 'ref: refs/heads/main HEAD\n5701164b9f5edba1f6ca114c491a564ffb55a964 HEAD' + ); + const res = await extractPackageFile('', '.gitmodules.2', {}); + expect(res?.deps).toHaveLength(1); + expect(res?.deps[0].currentValue).toBe('main'); + }); + + it('default to master if no branch can be detected', async () => { + const res = await extractPackageFile('', '.gitmodules.2', {}); + expect(res?.deps).toHaveLength(1); + expect(res?.deps[0].currentValue).toBe('master'); + }); + + it('given branch is used when branch is specified', async () => { + const res = await extractPackageFile('', '.gitmodules.3', {}); + expect(res?.deps).toHaveLength(1); + expect(res?.deps[0].currentValue).toBe('staging'); + }); + + it('submodule packageName is constructed from relative path', async () => { + const res = await extractPackageFile('', '.gitmodules.4', {}); + expect(res?.deps).toHaveLength(1); + expect(res?.deps[0].packageName).toBe( + 'https://github.com/PowerShell/PowerShell-Docs' + ); + }); + + it('extracts multiple submodules', async () => { hostRules.add({ matchHost: 'github.com', token: '123test' }); hostRules.add({ matchHost: 'domain.test', @@ -75,16 +89,22 @@ describe('modules/manager/git-submodules/extract', () => { token: 'xyz', hostType: 'gitlab', }); - let res: PackageFileContent | null; - expect(await extractPackageFile('', '.gitmodules.1', {})).toBeNull(); - res = await extractPackageFile('', '.gitmodules.2', {}); - expect(res?.deps).toHaveLength(1); - expect(res?.deps[0].currentValue).toBe('main'); - res = await extractPackageFile('', '.gitmodules.3', {}); - expect(res?.deps).toHaveLength(1); - res = await extractPackageFile('', '.gitmodules.4', {}); - expect(res?.deps).toHaveLength(1); - res = await extractPackageFile('', '.gitmodules.5', {}); + gitMock.listRemote.mockResolvedValueOnce( + 'ref: refs/heads/main HEAD\n5701164b9f5edba1f6ca114c491a564ffb55a964 HEAD' + ); + gitMock.listRemote.mockResolvedValueOnce( + 'ref: refs/heads/main HEAD\n5701164b9f5edba1f6ca114c491a564ffb55a964 HEAD' + ); + gitMock.listRemote.mockResolvedValueOnce( + 'ref: refs/heads/main HEAD\n5701164b9f5edba1f6ca114c491a564ffb55a964 HEAD' + ); + gitMock.listRemote.mockResolvedValueOnce( + 'ref: refs/heads/master HEAD\n5701164b9f5edba1f6ca114c491a564ffb55a964 HEAD' + ); + gitMock.listRemote.mockResolvedValueOnce( + 'ref: refs/heads/dev HEAD\n5701164b9f5edba1f6ca114c491a564ffb55a964 HEAD' + ); + const res = await extractPackageFile('', '.gitmodules.5', {}); expect(res).toEqual({ datasource: 'git-refs', deps: [ diff --git a/lib/modules/manager/git-submodules/update.spec.ts b/lib/modules/manager/git-submodules/update.spec.ts index a9ef0700134f89bd504904914995be4de04c9ba2..6b5111ed5cea27cb4a6e099e1c989dbad7430fd2 100644 --- a/lib/modules/manager/git-submodules/update.spec.ts +++ b/lib/modules/manager/git-submodules/update.spec.ts @@ -1,15 +1,29 @@ -import _simpleGit, { Response, SimpleGit } from 'simple-git'; +import { mock } from 'jest-mock-extended'; +import { SimpleGit, simpleGit } from 'simple-git'; import { DirectoryResult, dir } from 'tmp-promise'; import { join } from 'upath'; import { GlobalConfig } from '../../../config/global'; import type { RepoGlobalConfig } from '../../../config/types'; +import * as hostRules from '../../../util/host-rules'; import type { Upgrade } from '../types'; import { updateDependency } from '.'; jest.mock('simple-git'); -const simpleGit: jest.Mock<Partial<SimpleGit>> = _simpleGit as never; +const simpleGitFactoryMock = simpleGit as jest.Mock<Partial<SimpleGit>>; +const gitMock = mock<SimpleGit>(); describe('modules/manager/git-submodules/update', () => { + beforeEach(() => { + GlobalConfig.set({ localDir: `${__dirname}/__fixtures__` }); + // clear host rules + hostRules.clear(); + // clear environment variables + process.env = {}; + + simpleGitFactoryMock.mockReturnValue(gitMock); + gitMock.env.mockImplementation(() => gitMock); + }); + describe('updateDependency', () => { let upgrade: Upgrade; let adminConfig: RepoGlobalConfig; @@ -29,11 +43,8 @@ describe('modules/manager/git-submodules/update', () => { }); it('returns null on error', async () => { - simpleGit.mockReturnValue({ - submoduleUpdate() { - throw new Error(); - }, - }); + gitMock.submoduleUpdate.mockRejectedValue(new Error()); + const update = await updateDependency({ fileContent: '', upgrade, @@ -42,14 +53,9 @@ describe('modules/manager/git-submodules/update', () => { }); it('returns content on update', async () => { - simpleGit.mockReturnValue({ - submoduleUpdate() { - return Promise.resolve('') as Response<string>; - }, - checkout() { - return Promise.resolve('') as Response<string>; - }, - }); + gitMock.submoduleUpdate.mockResolvedValue(''); + gitMock.checkout.mockResolvedValue(''); + const update = await updateDependency({ fileContent: '', upgrade,