mirror of https://github.com/renovatebot/renovate
529 lines
16 KiB
TypeScript
529 lines
16 KiB
TypeScript
import * as httpMock from '../../../../test/http-mock';
|
|
import { partial } from '../../../../test/util';
|
|
import { REPOSITORY_ARCHIVED } from '../../../constants/error-messages';
|
|
import { setBaseUrl } from '../../../util/http/gerrit';
|
|
import type { FindPRConfig } from '../types';
|
|
import { client } from './client';
|
|
import type {
|
|
GerritChange,
|
|
GerritChangeMessageInfo,
|
|
GerritFindPRConfig,
|
|
GerritMergeableInfo,
|
|
} from './types';
|
|
|
|
const gerritEndpointUrl = 'https://dev.gerrit.com/renovate/';
|
|
const jsonResultHeader = { 'content-type': 'application/json;charset=utf-8' };
|
|
|
|
describe('modules/platform/gerrit/client', () => {
|
|
beforeAll(() => {
|
|
setBaseUrl(gerritEndpointUrl);
|
|
});
|
|
|
|
describe('getRepos()', () => {
|
|
it('returns repos', async () => {
|
|
httpMock
|
|
.scope(gerritEndpointUrl)
|
|
.get('/a/projects/?type=CODE&state=ACTIVE')
|
|
.reply(
|
|
200,
|
|
gerritRestResponse({
|
|
repo1: { id: 'repo1', state: 'ACTIVE' },
|
|
repo2: { id: 'repo2', state: 'ACTIVE' },
|
|
}),
|
|
jsonResultHeader,
|
|
);
|
|
expect(await client.getRepos()).toEqual(['repo1', 'repo2']);
|
|
});
|
|
});
|
|
|
|
describe('getProjectInfo()', () => {
|
|
it('inactive', async () => {
|
|
httpMock
|
|
.scope(gerritEndpointUrl)
|
|
.get('/a/projects/test%2Frepo')
|
|
.reply(
|
|
200,
|
|
gerritRestResponse({
|
|
id: 'repo1',
|
|
name: 'test-repo',
|
|
state: 'READ_ONLY',
|
|
}),
|
|
jsonResultHeader,
|
|
);
|
|
await expect(client.getProjectInfo('test/repo')).rejects.toThrow(
|
|
REPOSITORY_ARCHIVED,
|
|
);
|
|
});
|
|
|
|
it('active', async () => {
|
|
httpMock
|
|
.scope(gerritEndpointUrl)
|
|
.get('/a/projects/test%2Frepo')
|
|
.reply(
|
|
200,
|
|
gerritRestResponse({
|
|
id: 'repo1',
|
|
name: 'test-repo',
|
|
state: 'ACTIVE',
|
|
}),
|
|
jsonResultHeader,
|
|
);
|
|
await expect(client.getProjectInfo('test/repo')).resolves.toEqual({
|
|
id: 'repo1',
|
|
name: 'test-repo',
|
|
state: 'ACTIVE',
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('getBranchInfo()', () => {
|
|
it('info', async () => {
|
|
httpMock
|
|
.scope(gerritEndpointUrl)
|
|
.get('/a/projects/test%2Frepo/branches/HEAD')
|
|
.reply(
|
|
200,
|
|
gerritRestResponse({ ref: 'sha-hash....', revision: 'main' }),
|
|
jsonResultHeader,
|
|
);
|
|
await expect(client.getBranchInfo('test/repo')).resolves.toEqual({
|
|
ref: 'sha-hash....',
|
|
revision: 'main',
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('findChanges()', () => {
|
|
it.each([
|
|
['owner:self', { branchName: 'dependency-xyz' }],
|
|
['project:repo', { branchName: 'dependency-xyz' }],
|
|
['-is:wip', { branchName: 'dependency-xyz' }],
|
|
[
|
|
'footer:Renovate-Branch=dependency-xyz',
|
|
{ branchName: 'dependency-xyz' },
|
|
],
|
|
['hashtag:sourceBranch-dependency-xyz', { branchName: 'dependency-xyz' }], // for backwards compatibility
|
|
['label:Code-Review=-2', { branchName: 'dependency-xyz', label: '-2' }],
|
|
[
|
|
'branch:otherTarget',
|
|
{ branchName: 'dependency-xyz', targetBranch: 'otherTarget' },
|
|
],
|
|
[
|
|
'status:closed',
|
|
{
|
|
branchName: 'dependency-xyz',
|
|
state: 'closed' as FindPRConfig['state'],
|
|
},
|
|
],
|
|
[
|
|
'message:"fix(deps): update dependency react-router-dom to v6.21.2"',
|
|
{
|
|
branchName: 'dependency-xyz',
|
|
prTitle: 'fix(deps): update dependency react-router-dom to v6.21.2',
|
|
},
|
|
],
|
|
[
|
|
'message:"fix(deps): update dependency react-router-dom to ~> v6.21.2"',
|
|
{
|
|
branchName: 'dependency-xyz',
|
|
prTitle:
|
|
'fix(deps): update dependency react-router-dom to ~> "v6.21.2"',
|
|
},
|
|
],
|
|
[
|
|
'message:"fix(deps): update dependency react-router-dom to ~> v6.21.2"',
|
|
{
|
|
branchName: 'dependency-xyz',
|
|
prTitle:
|
|
'fix(deps): "update dependency react-router-dom to ~> "v6.21.2""',
|
|
},
|
|
],
|
|
])(
|
|
'query contains %p',
|
|
async (expectedQueryPart: string, config: GerritFindPRConfig) => {
|
|
httpMock
|
|
.scope(gerritEndpointUrl)
|
|
.get('/a/changes/')
|
|
.query((query) => query?.q?.includes(expectedQueryPart) ?? false)
|
|
.reply(
|
|
200,
|
|
gerritRestResponse([{ _number: 1 }, { _number: 2 }]),
|
|
jsonResultHeader,
|
|
);
|
|
await expect(client.findChanges('repo', config)).resolves.toEqual([
|
|
{ _number: 1 },
|
|
{ _number: 2 },
|
|
]);
|
|
},
|
|
);
|
|
});
|
|
|
|
describe('getChange()', () => {
|
|
it('get', async () => {
|
|
const change = partial<GerritChange>({});
|
|
httpMock
|
|
.scope(gerritEndpointUrl)
|
|
.get(
|
|
'/a/changes/123456?o=SUBMITTABLE&o=CHECK&o=MESSAGES&o=DETAILED_ACCOUNTS&o=LABELS&o=CURRENT_ACTIONS&o=CURRENT_REVISION&o=CURRENT_COMMIT',
|
|
)
|
|
.reply(200, gerritRestResponse(change), jsonResultHeader);
|
|
await expect(client.getChange(123456)).resolves.toEqual(change);
|
|
});
|
|
});
|
|
|
|
describe('getMergeableInfo()', () => {
|
|
it('get', async () => {
|
|
const mergeInfo: GerritMergeableInfo = {
|
|
mergeable: true,
|
|
submit_type: 'MERGE_IF_NECESSARY',
|
|
};
|
|
httpMock
|
|
.scope(gerritEndpointUrl)
|
|
.get('/a/changes/123456/revisions/current/mergeable')
|
|
.reply(200, gerritRestResponse(mergeInfo), jsonResultHeader);
|
|
await expect(
|
|
client.getMergeableInfo(partial<GerritChange>({ _number: 123456 })),
|
|
).resolves.toEqual(mergeInfo);
|
|
});
|
|
});
|
|
|
|
describe('abandonChange()', () => {
|
|
it('abandon', async () => {
|
|
httpMock
|
|
.scope(gerritEndpointUrl)
|
|
.post('/a/changes/123456/abandon')
|
|
.reply(200, gerritRestResponse({}), jsonResultHeader);
|
|
await expect(client.abandonChange(123456)).toResolve();
|
|
});
|
|
});
|
|
|
|
describe('submitChange()', () => {
|
|
it('submit', async () => {
|
|
const change = partial<GerritChange>({});
|
|
httpMock
|
|
.scope(gerritEndpointUrl)
|
|
.post('/a/changes/123456/submit')
|
|
.reply(200, gerritRestResponse(change), jsonResultHeader);
|
|
await expect(client.submitChange(123456)).resolves.toEqual(change);
|
|
});
|
|
});
|
|
|
|
describe('setCommitMessage()', () => {
|
|
it('setCommitMessage', async () => {
|
|
const change = partial<GerritChange>({});
|
|
httpMock
|
|
.scope(gerritEndpointUrl)
|
|
.put('/a/changes/123456/message', { message: 'new message' })
|
|
.reply(200, gerritRestResponse(change), jsonResultHeader);
|
|
await expect(client.setCommitMessage(123456, 'new message')).toResolve();
|
|
});
|
|
});
|
|
|
|
describe('updateChangeSubject', () => {
|
|
it('updateChangeSubject - success', async () => {
|
|
const change = partial<GerritChange>({});
|
|
const newSubject = 'new subject';
|
|
const previousSubject = 'some subject';
|
|
const previousBody = `some body\n\nChange-Id: some-change-id\n`;
|
|
httpMock
|
|
.scope(gerritEndpointUrl)
|
|
.put('/a/changes/123456/message', {
|
|
message: `${newSubject}\n\n${previousBody}`,
|
|
})
|
|
.reply(200, gerritRestResponse(change), jsonResultHeader);
|
|
await expect(
|
|
client.updateChangeSubject(
|
|
123456,
|
|
`${previousSubject}\n\n${previousBody}`,
|
|
'new subject',
|
|
),
|
|
).toResolve();
|
|
});
|
|
});
|
|
|
|
describe('getMessages()', () => {
|
|
it('no messages', async () => {
|
|
httpMock
|
|
.scope(gerritEndpointUrl)
|
|
.get('/a/changes/123456/messages')
|
|
.reply(200, gerritRestResponse([]), jsonResultHeader);
|
|
await expect(client.getMessages(123456)).resolves.toEqual([]);
|
|
});
|
|
|
|
it('with messages', async () => {
|
|
httpMock
|
|
.scope(gerritEndpointUrl)
|
|
.get('/a/changes/123456/messages')
|
|
.reply(
|
|
200,
|
|
gerritRestResponse([
|
|
partial<GerritChangeMessageInfo>({ message: 'msg1' }),
|
|
partial<GerritChangeMessageInfo>({ message: 'msg2' }),
|
|
]),
|
|
jsonResultHeader,
|
|
);
|
|
await expect(client.getMessages(123456)).resolves.toEqual([
|
|
{ message: 'msg1' },
|
|
{ message: 'msg2' },
|
|
]);
|
|
});
|
|
});
|
|
|
|
describe('addMessage()', () => {
|
|
it('add with tag', async () => {
|
|
httpMock
|
|
.scope(gerritEndpointUrl)
|
|
.post('/a/changes/123456/revisions/current/review', {
|
|
message: 'message',
|
|
tag: 'tag',
|
|
})
|
|
.reply(200, gerritRestResponse([]), jsonResultHeader);
|
|
await expect(client.addMessage(123456, 'message', 'tag')).toResolve();
|
|
});
|
|
|
|
it('add without tag', async () => {
|
|
httpMock
|
|
.scope(gerritEndpointUrl)
|
|
.post('/a/changes/123456/revisions/current/review', {
|
|
message: 'message',
|
|
})
|
|
.reply(200, gerritRestResponse([]), jsonResultHeader);
|
|
await expect(client.addMessage(123456, 'message')).toResolve();
|
|
});
|
|
|
|
it('add too big message', async () => {
|
|
const okMessage = 'a'.repeat(0x4000);
|
|
const tooBigMessage = okMessage + 'b';
|
|
httpMock
|
|
.scope(gerritEndpointUrl)
|
|
.post('/a/changes/123456/revisions/current/review', {
|
|
message: okMessage,
|
|
})
|
|
.reply(200, gerritRestResponse([]), jsonResultHeader);
|
|
await expect(client.addMessage(123456, tooBigMessage)).toResolve();
|
|
});
|
|
});
|
|
|
|
describe('checkForExistingMessage()', () => {
|
|
it('msg not found', async () => {
|
|
httpMock
|
|
.scope(gerritEndpointUrl)
|
|
.get('/a/changes/123456/messages')
|
|
.reply(200, gerritRestResponse([]), jsonResultHeader);
|
|
await expect(
|
|
client.checkForExistingMessage(123456, ' the message '),
|
|
).resolves.toBeFalse();
|
|
});
|
|
|
|
it('msg found', async () => {
|
|
httpMock
|
|
.scope(gerritEndpointUrl)
|
|
.get('/a/changes/123456/messages')
|
|
.reply(
|
|
200,
|
|
gerritRestResponse([
|
|
partial<GerritChangeMessageInfo>({ message: 'msg1' }),
|
|
partial<GerritChangeMessageInfo>({ message: 'the message' }),
|
|
]),
|
|
jsonResultHeader,
|
|
);
|
|
await expect(
|
|
client.checkForExistingMessage(123456, 'the message'),
|
|
).resolves.toBeTrue();
|
|
});
|
|
});
|
|
|
|
describe('addMessageIfNotAlreadyExists()', () => {
|
|
it('msg not found', async () => {
|
|
httpMock
|
|
.scope(gerritEndpointUrl)
|
|
.get('/a/changes/123456/messages')
|
|
.reply(200, gerritRestResponse([]), jsonResultHeader);
|
|
httpMock
|
|
.scope(gerritEndpointUrl)
|
|
.post('/a/changes/123456/revisions/current/review', {
|
|
message: 'new trimmed message',
|
|
tag: 'TAG',
|
|
})
|
|
.reply(200, gerritRestResponse([]), jsonResultHeader);
|
|
|
|
await expect(
|
|
client.addMessageIfNotAlreadyExists(
|
|
123456,
|
|
' new trimmed message\n',
|
|
'TAG',
|
|
),
|
|
).toResolve();
|
|
});
|
|
|
|
it('msg already exists', async () => {
|
|
httpMock
|
|
.scope(gerritEndpointUrl)
|
|
.get('/a/changes/123456/messages')
|
|
.reply(
|
|
200,
|
|
gerritRestResponse([
|
|
partial<GerritChangeMessageInfo>({ message: 'msg1', tag: 'TAG' }),
|
|
]),
|
|
jsonResultHeader,
|
|
);
|
|
|
|
await expect(
|
|
client.addMessageIfNotAlreadyExists(123456, 'msg1\n', 'TAG'),
|
|
).toResolve();
|
|
});
|
|
});
|
|
|
|
describe('setLabel()', () => {
|
|
it('setLabel', async () => {
|
|
httpMock
|
|
.scope(gerritEndpointUrl)
|
|
.post('/a/changes/123456/revisions/current/review', {
|
|
labels: { 'Code-Review': 2 },
|
|
})
|
|
.reply(200, gerritRestResponse([]), jsonResultHeader);
|
|
await expect(client.setLabel(123456, 'Code-Review', +2)).toResolve();
|
|
});
|
|
});
|
|
|
|
describe('addReviewer()', () => {
|
|
it('add', async () => {
|
|
httpMock
|
|
.scope(gerritEndpointUrl)
|
|
.post('/a/changes/123456/reviewers', {
|
|
reviewer: 'username',
|
|
})
|
|
.reply(200, gerritRestResponse([]), jsonResultHeader);
|
|
await expect(client.addReviewer(123456, 'username')).toResolve();
|
|
});
|
|
});
|
|
|
|
describe('addAssignee()', () => {
|
|
it('add', async () => {
|
|
httpMock
|
|
.scope(gerritEndpointUrl)
|
|
.put('/a/changes/123456/assignee', {
|
|
assignee: 'username',
|
|
})
|
|
.reply(200, gerritRestResponse([]), jsonResultHeader);
|
|
await expect(client.addAssignee(123456, 'username')).toResolve();
|
|
});
|
|
});
|
|
|
|
describe('getFile()', () => {
|
|
it('getFile() - repo and branch', async () => {
|
|
httpMock
|
|
.scope(gerritEndpointUrl)
|
|
.get(
|
|
'/a/projects/test%2Frepo/branches/base%2Fbranch/files/renovate.json/content',
|
|
)
|
|
.reply(200, gerritFileResponse('{}'));
|
|
await expect(
|
|
client.getFile('test/repo', 'base/branch', 'renovate.json'),
|
|
).resolves.toBe('{}');
|
|
});
|
|
});
|
|
|
|
describe('approveChange()', () => {
|
|
it('already approved - do nothing', async () => {
|
|
const change = partial<GerritChange>({});
|
|
httpMock
|
|
.scope(gerritEndpointUrl)
|
|
.get((url) => url.includes('/a/changes/123456?o='))
|
|
.reply(200, gerritRestResponse(change), jsonResultHeader);
|
|
await expect(client.approveChange(123456)).toResolve();
|
|
});
|
|
|
|
it('label not available - do nothing', async () => {
|
|
const change = partial<GerritChange>({ labels: {} });
|
|
httpMock
|
|
.scope(gerritEndpointUrl)
|
|
.get((url) => url.includes('/a/changes/123456?o='))
|
|
.reply(200, gerritRestResponse(change), jsonResultHeader);
|
|
|
|
await expect(client.approveChange(123456)).toResolve();
|
|
});
|
|
|
|
it('not already approved - approve now', async () => {
|
|
const change = partial<GerritChange>({ labels: { 'Code-Review': {} } });
|
|
httpMock
|
|
.scope(gerritEndpointUrl)
|
|
.get((url) => url.includes('/a/changes/123456?o='))
|
|
.reply(200, gerritRestResponse(change), jsonResultHeader);
|
|
const approveMock = httpMock
|
|
.scope(gerritEndpointUrl)
|
|
.post('/a/changes/123456/revisions/current/review', {
|
|
labels: { 'Code-Review': +2 },
|
|
})
|
|
.reply(200, gerritRestResponse(''), jsonResultHeader);
|
|
await expect(client.approveChange(123456)).toResolve();
|
|
expect(approveMock.isDone()).toBeTrue();
|
|
});
|
|
});
|
|
|
|
describe('wasApprovedBy()', () => {
|
|
it('label not exists', () => {
|
|
expect(
|
|
client.wasApprovedBy(partial<GerritChange>({}), 'user'),
|
|
).toBeUndefined();
|
|
});
|
|
|
|
it('not approved by anyone', () => {
|
|
expect(
|
|
client.wasApprovedBy(
|
|
partial<GerritChange>({
|
|
labels: {
|
|
'Code-Review': {},
|
|
},
|
|
}),
|
|
'user',
|
|
),
|
|
).toBeUndefined();
|
|
});
|
|
|
|
it('approved by given user', () => {
|
|
expect(
|
|
client.wasApprovedBy(
|
|
partial<GerritChange>({
|
|
labels: {
|
|
'Code-Review': {
|
|
approved: {
|
|
_account_id: 1,
|
|
username: 'user',
|
|
},
|
|
},
|
|
},
|
|
}),
|
|
'user',
|
|
),
|
|
).toBeTrue();
|
|
});
|
|
|
|
it('approved by given other', () => {
|
|
expect(
|
|
client.wasApprovedBy(
|
|
partial<GerritChange>({
|
|
labels: {
|
|
'Code-Review': {
|
|
approved: {
|
|
_account_id: 1,
|
|
username: 'other',
|
|
},
|
|
},
|
|
},
|
|
}),
|
|
'user',
|
|
),
|
|
).toBeFalse();
|
|
});
|
|
});
|
|
});
|
|
|
|
function gerritRestResponse(body: any): any {
|
|
return `)]}'\n${JSON.stringify(body)}`;
|
|
}
|
|
|
|
function gerritFileResponse(content: string): any {
|
|
return Buffer.from(content).toString('base64');
|
|
}
|