mirror of
https://github.com/renovatebot/renovate.git
synced 2026-11-01 18:19:51 +00:00
05e1271376
Enables the vitest/prefer-expect-resolves oxlint rule and applies its autofix across the spec suite.
674 lines
19 KiB
TypeScript
674 lines
19 KiB
TypeScript
import { git } from '~test/util.ts';
|
|
import * as httpMock from '../../../../test/http-mock.ts';
|
|
import { GlobalConfig } from '../../../config/global.ts';
|
|
import * as hostRules from '../../../util/host-rules.ts';
|
|
import type { Pr } from '../types.ts';
|
|
import * as util from '../util.ts';
|
|
import * as scmPlatform from './index.ts';
|
|
import { mapPrFromScmToRenovate } from './mapper.ts';
|
|
import type { PullRequest, Repo, User } from './schema.ts';
|
|
import type { PrFilterByState } from './types.ts';
|
|
|
|
vi.mock('../util.ts');
|
|
vi.mock('../../../util/git/index.ts');
|
|
|
|
const endpoint = 'https://localhost:8080/scm/';
|
|
const baseUrl = `${endpoint}api/v2`;
|
|
const token = 'TEST_TOKEN';
|
|
|
|
const user: User = {
|
|
mail: 'test@user.de',
|
|
displayName: 'Test User',
|
|
name: 'testUser1337',
|
|
};
|
|
|
|
const repo: Repo = {
|
|
contact: 'test@test.com',
|
|
creationDate: '2023-08-02T10:48:24.762Z',
|
|
description: 'Default Repo',
|
|
lastModified: '2023-08-10T10:48:24.762Z',
|
|
namespace: 'default',
|
|
name: 'repo',
|
|
type: 'git',
|
|
archived: false,
|
|
exporting: false,
|
|
healthCheckRunning: false,
|
|
_links: {
|
|
protocol: [
|
|
{ name: 'http', href: 'https://localhost:8080/scm/default/repo' },
|
|
],
|
|
defaultBranch: {
|
|
href: 'https://localhost:8080/scm/api/v2/config/git/default/repo/default-branch',
|
|
},
|
|
},
|
|
};
|
|
|
|
const pullRequest: PullRequest = {
|
|
id: '1',
|
|
author: { displayName: 'Thomas Zerr', id: 'tzerr' },
|
|
source: 'feature/test',
|
|
target: 'develop',
|
|
title: 'The PullRequest',
|
|
description: 'Another PullRequest',
|
|
creationDate: '2023-08-02T10:48:24.762Z',
|
|
status: 'OPEN',
|
|
labels: [],
|
|
tasks: { todo: 2, done: 4 },
|
|
_links: {},
|
|
_embedded: {
|
|
defaultConfig: {
|
|
mergeStrategy: 'SQUASH',
|
|
deleteBranchOnMerge: true,
|
|
},
|
|
},
|
|
};
|
|
|
|
const renovatePr = mapPrFromScmToRenovate(pullRequest);
|
|
|
|
describe('modules/platform/scm-manager/index', () => {
|
|
beforeEach(() => {
|
|
GlobalConfig.reset();
|
|
hostRules.add({ token, username: user.name });
|
|
scmPlatform.invalidatePrCache();
|
|
});
|
|
|
|
describe('initPlatform', () => {
|
|
it('should throw error, when endpoint is not configured', async () => {
|
|
await expect(scmPlatform.initPlatform({ token })).rejects.toThrow(
|
|
'SCM-Manager endpoint not configured',
|
|
);
|
|
});
|
|
|
|
it('should throw error, when token is not configured', async () => {
|
|
await expect(scmPlatform.initPlatform({ endpoint })).rejects.toThrow(
|
|
'SCM-Manager API token not configured',
|
|
);
|
|
});
|
|
|
|
it('should throw error, when token is invalid', async () => {
|
|
httpMock.scope(baseUrl).get(`/me`).reply(401);
|
|
|
|
await expect(
|
|
scmPlatform.initPlatform({ endpoint, token: 'invalid' }),
|
|
).rejects.toThrow('Init: Authentication failure');
|
|
});
|
|
|
|
it('should init platform', async () => {
|
|
httpMock.scope(baseUrl).get('/me').reply(200, user);
|
|
await expect(
|
|
scmPlatform.initPlatform({ endpoint, token }),
|
|
).resolves.toEqual({
|
|
endpoint: baseUrl,
|
|
gitAuthor: 'Test User <test@user.de>',
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('initRepo', () => {
|
|
it('should init repo', async () => {
|
|
const repository = `${repo.namespace}/${repo.name}`;
|
|
const expectedFingerprint = 'expectedFingerprint';
|
|
const expectedDefaultBranch = 'expectedDefaultBranch';
|
|
GlobalConfig.set({ ignorePrAuthor: true });
|
|
|
|
httpMock
|
|
.scope(baseUrl)
|
|
.get(`/repositories/${repository}`)
|
|
.reply(200, repo);
|
|
httpMock
|
|
.scope(baseUrl)
|
|
.get(`/config/git/${repository}/default-branch`)
|
|
.reply(200, { defaultBranch: expectedDefaultBranch });
|
|
|
|
vi.mocked(util.repoFingerprint).mockReturnValueOnce(expectedFingerprint);
|
|
|
|
await expect(
|
|
scmPlatform.initRepo({
|
|
repository: `${repo.namespace}/${repo.name}`,
|
|
}),
|
|
).resolves.toEqual({
|
|
defaultBranch: expectedDefaultBranch,
|
|
isFork: false,
|
|
repoFingerprint: expectedFingerprint,
|
|
});
|
|
|
|
expect(git.initRepo).toHaveBeenCalledExactlyOnceWith({
|
|
url: `https://${user.name}:${token}@localhost:8080/scm/default/repo`,
|
|
repository,
|
|
defaultBranch: expectedDefaultBranch,
|
|
ignorePrAuthor: true,
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('getRepos', () => {
|
|
it('should return all available repos', async () => {
|
|
httpMock
|
|
.scope(baseUrl)
|
|
.get(`/repositories?pageSize=1000000`)
|
|
.reply(200, {
|
|
page: 0,
|
|
pageTotal: 1,
|
|
_embedded: {
|
|
repositories: [
|
|
repo,
|
|
{ ...repo, namespace: 'other', name: 'repository' },
|
|
{ ...repo, namespace: 'other', name: 'mercurial', type: 'hg' },
|
|
{ ...repo, namespace: 'other', name: 'subversion', type: 'svn' },
|
|
],
|
|
},
|
|
});
|
|
|
|
await expect(scmPlatform.getRepos()).resolves.toEqual([
|
|
'default/repo',
|
|
'other/repository',
|
|
]);
|
|
});
|
|
});
|
|
|
|
describe('getPrList', () => {
|
|
it('should return empty array, because no PR could be found', async () => {
|
|
httpMock
|
|
.scope(baseUrl)
|
|
.get(
|
|
`/pull-requests/${repo.namespace}/${repo.name}?status=ALL&pageSize=1000000`,
|
|
)
|
|
.reply(200, {
|
|
page: 0,
|
|
pageTotal: 1,
|
|
_embedded: {
|
|
pullRequests: [],
|
|
},
|
|
});
|
|
|
|
await expect(scmPlatform.getPrList()).resolves.toBeEmptyArray();
|
|
});
|
|
|
|
it('should return empty array, because API request failed', async () => {
|
|
httpMock
|
|
.scope(baseUrl)
|
|
.get(
|
|
`/pull-requests/${repo.namespace}/${repo.name}?status=ALL&pageSize=1000000`,
|
|
)
|
|
.reply(400);
|
|
|
|
await expect(scmPlatform.getPrList()).resolves.toBeEmptyArray();
|
|
});
|
|
|
|
it('should return all PRs of a repo', async () => {
|
|
const expectedResult: Pr[] = [
|
|
{
|
|
sourceBranch: pullRequest.source,
|
|
createdAt: pullRequest.creationDate,
|
|
labels: pullRequest.labels,
|
|
number: parseInt(pullRequest.id, 10),
|
|
state: 'open',
|
|
targetBranch: pullRequest.target,
|
|
title: pullRequest.title,
|
|
hasAssignees: false,
|
|
isDraft: false,
|
|
reviewers: [],
|
|
},
|
|
];
|
|
|
|
httpMock
|
|
.scope(baseUrl)
|
|
.get(
|
|
`/pull-requests/${repo.namespace}/${repo.name}?status=ALL&pageSize=1000000`,
|
|
)
|
|
.reply(200, {
|
|
page: 0,
|
|
pageTotal: 1,
|
|
_embedded: {
|
|
pullRequests: [pullRequest],
|
|
},
|
|
});
|
|
|
|
//Fetching from client
|
|
await expect(scmPlatform.getPrList()).resolves.toIncludeAllMembers(
|
|
expectedResult,
|
|
);
|
|
//Fetching from cache
|
|
await expect(scmPlatform.getPrList()).resolves.toIncludeAllMembers(
|
|
expectedResult,
|
|
);
|
|
});
|
|
});
|
|
|
|
describe('findPr', () => {
|
|
it('search in Pull Request without explicitly setting the state as argument', async () => {
|
|
httpMock
|
|
.scope(baseUrl)
|
|
.get(
|
|
`/pull-requests/${repo.namespace}/${repo.name}?status=ALL&pageSize=1000000`,
|
|
)
|
|
.reply(200, {
|
|
page: 0,
|
|
pageTotal: 1,
|
|
_embedded: {
|
|
pullRequests: [pullRequest],
|
|
},
|
|
});
|
|
|
|
await expect(
|
|
scmPlatform.findPr({
|
|
branchName: pullRequest.source,
|
|
prTitle: pullRequest.title,
|
|
}),
|
|
).resolves.toEqual(renovatePr);
|
|
});
|
|
|
|
it.each`
|
|
availablePullRequest | branchName | prTitle | state | result
|
|
${[]} | ${pullRequest.source} | ${pullRequest.title} | ${'all'} | ${null}
|
|
${[pullRequest]} | ${'invalid branchName'} | ${pullRequest.title} | ${'all'} | ${null}
|
|
${[pullRequest]} | ${pullRequest.source} | ${'invalid title'} | ${'all'} | ${null}
|
|
${[pullRequest]} | ${pullRequest.source} | ${null} | ${'all'} | ${renovatePr}
|
|
${[pullRequest]} | ${pullRequest.source} | ${undefined} | ${'all'} | ${renovatePr}
|
|
${[pullRequest]} | ${pullRequest.source} | ${pullRequest.title} | ${'all'} | ${renovatePr}
|
|
${[pullRequest]} | ${pullRequest.source} | ${pullRequest.title} | ${'open'} | ${renovatePr}
|
|
${[pullRequest]} | ${pullRequest.source} | ${pullRequest.title} | ${'!open'} | ${null}
|
|
${[pullRequest]} | ${pullRequest.source} | ${pullRequest.title} | ${'closed'} | ${null}
|
|
`(
|
|
'search within available pull requests for branch name "$branchName", pr title "$prTitle" and state "$state" with result $result',
|
|
async ({
|
|
availablePullRequest,
|
|
branchName,
|
|
prTitle,
|
|
state,
|
|
result,
|
|
}: {
|
|
availablePullRequest: PullRequest[];
|
|
branchName: string;
|
|
prTitle: string | undefined | null;
|
|
state: string;
|
|
result: Pr | null;
|
|
}) => {
|
|
httpMock
|
|
.scope(baseUrl)
|
|
.get(
|
|
`/pull-requests/${repo.namespace}/${repo.name}?status=ALL&pageSize=1000000`,
|
|
)
|
|
.reply(200, {
|
|
page: 0,
|
|
pageTotal: 1,
|
|
_embedded: {
|
|
pullRequests: availablePullRequest,
|
|
},
|
|
});
|
|
|
|
await expect(
|
|
scmPlatform.findPr({
|
|
branchName,
|
|
prTitle,
|
|
state: state as PrFilterByState,
|
|
}),
|
|
).resolves.toEqual(result);
|
|
},
|
|
);
|
|
});
|
|
|
|
describe('getBranchPr', () => {
|
|
it.each`
|
|
availablePullRequest | branchName | result
|
|
${[]} | ${pullRequest.source} | ${null}
|
|
${[pullRequest]} | ${'invalid branchName'} | ${null}
|
|
${[pullRequest]} | ${pullRequest.source} | ${renovatePr}
|
|
`(
|
|
'search within available pull requests for branch name "$branchName" with result $result',
|
|
async ({
|
|
availablePullRequest,
|
|
branchName,
|
|
result,
|
|
}: {
|
|
availablePullRequest: PullRequest[];
|
|
branchName: string;
|
|
result: Pr | null;
|
|
}) => {
|
|
httpMock
|
|
.scope(baseUrl)
|
|
.get(
|
|
`/pull-requests/${repo.namespace}/${repo.name}?status=ALL&pageSize=1000000`,
|
|
)
|
|
.reply(200, {
|
|
page: 0,
|
|
pageTotal: 1,
|
|
_embedded: {
|
|
pullRequests: availablePullRequest,
|
|
},
|
|
});
|
|
|
|
await expect(scmPlatform.getBranchPr(branchName)).resolves.toEqual(
|
|
result,
|
|
);
|
|
},
|
|
);
|
|
});
|
|
|
|
describe('getPr', () => {
|
|
it('should return null, because PR was not found', async () => {
|
|
httpMock
|
|
.scope(baseUrl)
|
|
.get(
|
|
`/pull-requests/${repo.namespace}/${repo.name}?status=ALL&pageSize=1000000`,
|
|
)
|
|
.reply(200, {
|
|
page: 0,
|
|
pageTotal: 1,
|
|
_embedded: {
|
|
pullRequests: [],
|
|
},
|
|
});
|
|
|
|
httpMock
|
|
.scope(baseUrl)
|
|
.get(`/pull-requests/${repo.namespace}/${repo.name}/${pullRequest.id}`)
|
|
.reply(404);
|
|
|
|
await expect(scmPlatform.getPr(1)).resolves.toBeNull();
|
|
});
|
|
|
|
it('should return PR from cache', async () => {
|
|
httpMock
|
|
.scope(baseUrl)
|
|
.get(
|
|
`/pull-requests/${repo.namespace}/${repo.name}?status=ALL&pageSize=1000000`,
|
|
)
|
|
.reply(200, {
|
|
page: 0,
|
|
pageTotal: 1,
|
|
_embedded: {
|
|
pullRequests: [pullRequest],
|
|
},
|
|
});
|
|
|
|
await expect(
|
|
scmPlatform.getPr(parseInt(pullRequest.id, 10)),
|
|
).resolves.toEqual(renovatePr);
|
|
});
|
|
|
|
it('should return fetched pr', async () => {
|
|
httpMock
|
|
.scope(baseUrl)
|
|
.get(
|
|
`/pull-requests/${repo.namespace}/${repo.name}?status=ALL&pageSize=1000000`,
|
|
)
|
|
.reply(200, {
|
|
page: 0,
|
|
pageTotal: 1,
|
|
_embedded: {
|
|
pullRequests: [],
|
|
},
|
|
});
|
|
|
|
httpMock
|
|
.scope(baseUrl)
|
|
.get(`/pull-requests/${repo.namespace}/${repo.name}/${pullRequest.id}`)
|
|
.reply(200, pullRequest);
|
|
|
|
await expect(
|
|
scmPlatform.getPr(parseInt(pullRequest.id, 10)),
|
|
).resolves.toEqual(renovatePr);
|
|
});
|
|
});
|
|
|
|
describe('createPr', () => {
|
|
it.each`
|
|
draftPr | expectedIsDraft
|
|
${undefined} | ${false}
|
|
${false} | ${false}
|
|
${true} | ${true}
|
|
`(
|
|
'should create PR with $draftPR and state $expectedState',
|
|
async ({
|
|
draftPr,
|
|
expectedIsDraft,
|
|
}: {
|
|
draftPr: boolean | undefined;
|
|
expectedState: string;
|
|
expectedIsDraft: boolean;
|
|
}) => {
|
|
httpMock
|
|
.scope(baseUrl)
|
|
.post(`/pull-requests/${repo.namespace}/${repo.name}`)
|
|
.reply(201, undefined, {
|
|
location: `${baseUrl}/pull-requests/${repo.namespace}/${repo.name}/1337`,
|
|
});
|
|
|
|
httpMock
|
|
.scope(baseUrl)
|
|
.get(`/pull-requests/${repo.namespace}/${repo.name}/1337`)
|
|
.reply(200, {
|
|
id: '1337',
|
|
source: 'feature/test',
|
|
target: 'develop',
|
|
title: 'PR Title',
|
|
description: 'PR Body',
|
|
creationDate: '2023-01-01T13:37:00.000Z',
|
|
status: draftPr ? 'DRAFT' : 'OPEN',
|
|
labels: [],
|
|
tasks: { todo: 0, done: 0 },
|
|
_links: {},
|
|
_embedded: {
|
|
defaultConfig: {
|
|
mergeStrategy: 'FAST_FORWARD_IF_POSSIBLE',
|
|
deleteBranchOnMerge: false,
|
|
},
|
|
},
|
|
});
|
|
|
|
await expect(
|
|
scmPlatform.createPr({
|
|
sourceBranch: 'feature/test',
|
|
targetBranch: 'develop',
|
|
prTitle: 'PR Title',
|
|
prBody: 'PR Body',
|
|
draftPR: draftPr,
|
|
}),
|
|
).resolves.toEqual({
|
|
sourceBranch: 'feature/test',
|
|
targetBranch: 'develop',
|
|
title: 'PR Title',
|
|
createdAt: '2023-01-01T13:37:00.000Z',
|
|
hasAssignees: false,
|
|
isDraft: expectedIsDraft,
|
|
labels: [],
|
|
number: 1337,
|
|
reviewers: [],
|
|
state: 'open',
|
|
});
|
|
},
|
|
);
|
|
});
|
|
|
|
describe('updatePr', () => {
|
|
it.each`
|
|
state | body
|
|
${'open'} | ${'prBody'}
|
|
${'closed'} | ${'prBody'}
|
|
${undefined} | ${'prBody'}
|
|
${'open'} | ${undefined}
|
|
`(
|
|
'should update PR with state $state and bdoy $body',
|
|
async ({
|
|
state,
|
|
body,
|
|
}: {
|
|
state: string | undefined;
|
|
body: string | undefined;
|
|
}) => {
|
|
httpMock
|
|
.scope(baseUrl)
|
|
.get(
|
|
`/pull-requests/${repo.namespace}/${repo.name}/${pullRequest.id}`,
|
|
)
|
|
.reply(200, pullRequest);
|
|
|
|
httpMock
|
|
.scope(baseUrl)
|
|
.put(`/pull-requests/${repo.namespace}/${repo.name}/1`)
|
|
.reply(204);
|
|
|
|
await expect(
|
|
scmPlatform.updatePr({
|
|
number: 1,
|
|
prTitle: 'PR Title',
|
|
prBody: body,
|
|
state: state as 'open' | 'closed' | undefined,
|
|
targetBranch: 'Target/Branch',
|
|
}),
|
|
).resolves.not.toThrow();
|
|
},
|
|
);
|
|
});
|
|
|
|
describe('mergePr', () => {
|
|
it('should Not implemented and return false', async () => {
|
|
const result = await scmPlatform.mergePr({ id: 1 });
|
|
expect(result).toBeFalse();
|
|
});
|
|
});
|
|
|
|
describe('getBranchStatus', () => {
|
|
it('should Not implemented and return red', async () => {
|
|
const result = await scmPlatform.getBranchStatus('test/branch', false);
|
|
expect(result).toBe('red');
|
|
});
|
|
});
|
|
|
|
describe('setBranchStatus', () => {
|
|
it('should Not implemented', async () => {
|
|
await expect(
|
|
scmPlatform.setBranchStatus({
|
|
branchName: 'test/branch',
|
|
context: 'context',
|
|
description: 'description',
|
|
state: 'red',
|
|
}),
|
|
).resolves.not.toThrow();
|
|
});
|
|
});
|
|
|
|
describe('getBranchStatusCheck', () => {
|
|
it('should Not implemented and return null', async () => {
|
|
const result = await scmPlatform.getBranchStatusCheck(
|
|
'test/branch',
|
|
null,
|
|
);
|
|
expect(result).toBeNull();
|
|
});
|
|
});
|
|
|
|
describe('addReviewers', () => {
|
|
it('should Not implemented', async () => {
|
|
await expect(
|
|
scmPlatform.addReviewers(1, ['reviewer']),
|
|
).resolves.not.toThrow();
|
|
});
|
|
});
|
|
|
|
describe('addAssignees', () => {
|
|
it('should Not implemented', async () => {
|
|
await expect(
|
|
scmPlatform.addAssignees(1, ['assignee']),
|
|
).resolves.not.toThrow();
|
|
});
|
|
});
|
|
|
|
describe('deleteLabel', () => {
|
|
it('should Not implemented', async () => {
|
|
await expect(scmPlatform.deleteLabel(1, 'label')).resolves.not.toThrow();
|
|
});
|
|
});
|
|
|
|
describe('getIssueList', () => {
|
|
it('should Not implemented and return empty list', async () => {
|
|
const result = await scmPlatform.getIssueList();
|
|
expect(result).toEqual([]);
|
|
});
|
|
});
|
|
|
|
describe('findIssue', () => {
|
|
it('should Not implemented and return null', async () => {
|
|
const result = await scmPlatform.findIssue('issue');
|
|
expect(result).toBeNull();
|
|
});
|
|
});
|
|
|
|
describe('ensureIssue', () => {
|
|
it('should Not implemented and return null', async () => {
|
|
const result = await scmPlatform.ensureIssue({
|
|
title: 'issue',
|
|
body: 'body',
|
|
});
|
|
expect(result).toBeNull();
|
|
});
|
|
});
|
|
|
|
describe('ensureIssueClosing', () => {
|
|
it('should Not implemented', async () => {
|
|
await expect(
|
|
scmPlatform.ensureIssueClosing('issue'),
|
|
).resolves.not.toThrow();
|
|
});
|
|
});
|
|
|
|
describe('ensureCommentRemoval', () => {
|
|
it('should Not implemented', async () => {
|
|
await expect(
|
|
scmPlatform.ensureCommentRemoval({
|
|
type: 'by-content',
|
|
number: 1,
|
|
content: 'content',
|
|
}),
|
|
).resolves.not.toThrow();
|
|
});
|
|
});
|
|
|
|
describe('ensureComment', () => {
|
|
it('should Not implemented', async () => {
|
|
await expect(
|
|
scmPlatform.ensureComment({
|
|
number: 1,
|
|
topic: 'comment',
|
|
content: 'content',
|
|
}),
|
|
).resolves.toBeFalse();
|
|
});
|
|
});
|
|
|
|
describe('massageMarkdown', () => {
|
|
it('should adjust smart link for Pull Requests', () => {
|
|
const result = scmPlatform.massageMarkdown('[PR](../pull/1)');
|
|
expect(result).toBe('[PR](pulls/1)');
|
|
});
|
|
});
|
|
|
|
describe('getRepoForceRebase', () => {
|
|
it('should Not implemented and return false', async () => {
|
|
const result = await scmPlatform.getRepoForceRebase();
|
|
expect(result).toBeFalse();
|
|
});
|
|
});
|
|
|
|
describe('getRawFile', () => {
|
|
it('should Not implemented and return null', async () => {
|
|
const result = await scmPlatform.getRawFile('file');
|
|
expect(result).toBeNull();
|
|
});
|
|
});
|
|
|
|
describe('getJsonFile', () => {
|
|
it('should Not implemented and return undefined', async () => {
|
|
const result = await scmPlatform.getJsonFile('package.json');
|
|
expect(result).toBeNull();
|
|
});
|
|
});
|
|
|
|
describe('maxBodyLength', () => {
|
|
it('should return the max body length allowed for an SCM-Manager request body', () => {
|
|
expect(scmPlatform.maxBodyLength()).toBe(200000);
|
|
});
|
|
});
|
|
});
|