Skip to content

Commit

Permalink
test(git-submodules): separate and make tests easier mockable (#23065)
Browse files Browse the repository at this point in the history
  • Loading branch information
Shegox committed Jul 13, 2023
1 parent 3b0bafc commit 714bb27
Show file tree
Hide file tree
Showing 2 changed files with 98 additions and 72 deletions.
134 changes: 77 additions & 57 deletions lib/modules/manager/git-submodules/extract.spec.ts
Original file line number Diff line number Diff line change
@@ -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',
Expand All @@ -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: [
Expand Down
36 changes: 21 additions & 15 deletions lib/modules/manager/git-submodules/update.spec.ts
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -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,
Expand All @@ -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,
Expand Down

0 comments on commit 714bb27

Please sign in to comment.