Skip to content

Commit e8984a8

Browse files
committed
chores: write tests for helpers
1 parent da3859d commit e8984a8

13 files changed

+210
-16
lines changed

.vscode/settings.json

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"liveServer.settings.port": 5501
3+
}

jest.config.json

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"preset": "ts-jest",
3+
"testEnvironment": "node",
4+
"collectCoverage": true,
5+
"coverageReporters": ["lcov", "text-summary"],
6+
"collectCoverageFrom": ["src/**/*.ts"],
7+
"coveragePathIgnorePatterns": ["/node_modules/", "/__tests__/"],
8+
"testPathIgnorePatterns": ["/node_modules/"]
9+
}

src/helpers/get-changed-files.test.ts

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { BASE_SHA, HEAD_SHA } from '../constants';
2+
import { getChangedFiles } from '.';
3+
4+
describe('getChangedFiles', () => {
5+
it('should return a string of changed files', async () => {
6+
const changedFiles = await getChangedFiles(BASE_SHA, HEAD_SHA);
7+
expect(typeof changedFiles).toBe('string');
8+
expect(changedFiles).toContain('.ts'); // assuming you have TypeScript files in your project
9+
});
10+
11+
it('should throw an error if there is an issue with the git command', async () => {
12+
const base = 'main';
13+
const head = 'feature-branch';
14+
await expect(getChangedFiles(base, head)).rejects.toThrow();
15+
});
16+
});
+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import { getReviewersEmails } from '.';
2+
3+
describe('getReviewersEmails', () => {
4+
it('should return an array of reviewers emails', async () => {
5+
const changedFiles = 'src/helpers/get-reviewers-emails.ts';
6+
const reviewersEmails = await getReviewersEmails(changedFiles);
7+
expect(Array.isArray(reviewersEmails)).toBe(true);
8+
expect(reviewersEmails.length).toBeGreaterThan(0);
9+
expect(typeof reviewersEmails[0]).toBe('string');
10+
});
11+
});

src/helpers/get-reviewers-emails.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { exec } from 'child_process';
22
import { formatReviewers } from '../utils';
33

44
export const getReviewersEmails = async (changedFiles: string) => {
5-
return new Promise<string[] | undefined>((resolve) => {
5+
return new Promise<string[]>((resolve) => {
66
exec(
77
`git log --pretty=format:"%ae" -- ${changedFiles} | sort -u`,
88
(error, stdout) => {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import { getReviewersUsernames } from '.';
2+
import { TOctokit } from '../types';
3+
4+
describe('getReviewersUsernames', () => {
5+
it('should return an array of unique reviewers usernames', async () => {
6+
const emails = ['user1@example.com', 'user2@example.com'];
7+
const usernames = ['user1'];
8+
const mockSearchUsers = jest.fn().mockResolvedValue({
9+
data: {
10+
items: [{ login: 'user1' }, { login: 'user2' }],
11+
},
12+
});
13+
const mockOctokit = {
14+
rest: {
15+
search: {
16+
users: mockSearchUsers,
17+
},
18+
},
19+
} as unknown as TOctokit;
20+
21+
const result = await getReviewersUsernames(mockOctokit, emails);
22+
expect(result).toEqual(usernames);
23+
expect(mockSearchUsers).toHaveBeenCalledTimes(2);
24+
expect(mockSearchUsers).toHaveBeenCalledWith({ q: 'user1@example.com' });
25+
expect(mockSearchUsers).toHaveBeenCalledWith({ q: 'user2@example.com' });
26+
});
27+
28+
it('should filter out invalid reviewers', async () => {
29+
const emails = ['user1@example.com', 'user2@example.com'];
30+
const usernames: string[] = [];
31+
const mockSearchUsers = jest.fn().mockResolvedValue({
32+
data: {
33+
items: [{ login: undefined }, { login: null }],
34+
},
35+
});
36+
const mockOctokit = {
37+
rest: {
38+
search: {
39+
users: mockSearchUsers,
40+
},
41+
},
42+
} as unknown as TOctokit;
43+
44+
const result = await getReviewersUsernames(mockOctokit, emails);
45+
expect(result).toEqual(usernames);
46+
expect(mockSearchUsers).toHaveBeenCalledTimes(2);
47+
expect(mockSearchUsers).toHaveBeenCalledWith({ q: 'user1@example.com' });
48+
expect(mockSearchUsers).toHaveBeenCalledWith({ q: 'user2@example.com' });
49+
});
50+
});

src/helpers/get-reviewers-usernames.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,9 @@ export const getReviewersUsernames = async (
1414
})
1515
);
1616

17-
return usernames.filter(
17+
const _usernames = usernames.filter(
1818
(username): username is string => !INVALID_REVIEWERS.includes(username)
1919
);
20+
21+
return [...new Set(_usernames)];
2022
};
+76
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
import { INVALID_REVIEWERS } from '../constants';
2+
import { getValidReviewers } from './get-valid-reviewers';
3+
4+
describe('getValidReviewers', () => {
5+
it('should return an empty array if no valid reviewers are found', () => {
6+
const reviewers = [...INVALID_REVIEWERS, 'creator'] as string[];
7+
const creator = 'creator';
8+
const maxReviewers = 2;
9+
const validReviewers = getValidReviewers({
10+
reviewers,
11+
creator,
12+
maxReviewers,
13+
});
14+
expect(validReviewers).toEqual([]);
15+
});
16+
17+
it('should return an array of valid reviewers', () => {
18+
const reviewers = [
19+
...INVALID_REVIEWERS,
20+
'valid1',
21+
'valid2',
22+
'creator',
23+
'valid3',
24+
] as string[];
25+
const creator = 'creator';
26+
const maxReviewers = 3;
27+
const validReviewers = getValidReviewers({
28+
reviewers,
29+
creator,
30+
maxReviewers,
31+
});
32+
expect(validReviewers).toEqual(['valid1', 'valid2', 'valid3']);
33+
});
34+
35+
it('should return all valid reviewers if there are fewer valid reviewers than the max number of reviewers', () => {
36+
const reviewers = [
37+
...INVALID_REVIEWERS,
38+
'valid1',
39+
'valid2',
40+
'creator',
41+
'valid3',
42+
] as string[];
43+
const creator = 'creator';
44+
const maxReviewers = 5;
45+
const validReviewers = getValidReviewers({
46+
reviewers,
47+
creator,
48+
maxReviewers,
49+
});
50+
expect(validReviewers).toEqual(['valid1', 'valid2', 'valid3']);
51+
});
52+
53+
it('should return an empty array if no reviewers are provided', () => {
54+
const reviewers: string[] = [];
55+
const creator = 'creator';
56+
const maxReviewers = 2;
57+
const validReviewers = getValidReviewers({
58+
reviewers,
59+
creator,
60+
maxReviewers,
61+
});
62+
expect(validReviewers).toEqual([]);
63+
});
64+
65+
it('should return an empty array if all reviewers are invalid', () => {
66+
const reviewers = [...INVALID_REVIEWERS, 'creator'] as string[];
67+
const creator = 'creator';
68+
const maxReviewers = 2;
69+
const validReviewers = getValidReviewers({
70+
reviewers,
71+
creator,
72+
maxReviewers,
73+
});
74+
expect(validReviewers).toEqual([]);
75+
});
76+
});

src/helpers/index.ts

+1
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,4 @@ export * from './get-reviewers-usernames';
22
export * from './get-changed-files';
33
export * from './get-reviewers-emails';
44
export * from './send-review-requests';
5+
export * from './get-valid-reviewers';
+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import { Context } from '@actions/github/lib/context';
2+
import { TOctokit } from '../types';
3+
import { sendReviewRequests } from './send-review-requests';
4+
5+
describe('sendReviewRequests', () => {
6+
it('should send review requests to the specified reviewers', async () => {
7+
const Octokit = {
8+
rest: {
9+
pulls: {
10+
requestReviewers: jest.fn(),
11+
},
12+
},
13+
} as unknown as TOctokit;
14+
const reviewers = ['reviewer1', 'reviewer2'];
15+
const context = {
16+
repo: {
17+
owner: 'owner',
18+
repo: 'repo',
19+
},
20+
payload: {
21+
pull_request: {
22+
number: 123,
23+
},
24+
},
25+
} as unknown as Context;
26+
await sendReviewRequests({ Octokit, reviewers, context });
27+
expect(Octokit.rest.pulls.requestReviewers).toHaveBeenCalledWith({
28+
owner: 'owner',
29+
repo: 'repo',
30+
pull_number: 123,
31+
reviewers: ['reviewer1', 'reviewer2'],
32+
});
33+
});
34+
});

src/helpers/send-review-requests.ts

-2
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,6 @@ export const sendReviewRequests = async ({
1111
reviewers,
1212
context,
1313
}: SendReviewRequests) => {
14-
console.log({ reviewers, context, repo: context.repo });
15-
1614
return await Octokit.rest.pulls.requestReviewers({
1715
owner: context.repo.owner,
1816
repo: context.repo.repo,

src/index.ts

+5-9
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,11 @@ import {
55
getChangedFiles,
66
getReviewersEmails,
77
getReviewersUsernames,
8+
getValidReviewers,
89
sendReviewRequests,
910
} from './helpers';
10-
import { getValidReviewers } from './helpers/get-valid-reviewers';
1111

12-
const run = async () => {
12+
export const run = async () => {
1313
try {
1414
const baseSha = context.payload.pull_request?.base.sha || BASE_SHA;
1515
const headSha = context.payload.pull_request?.head.sha || HEAD_SHA;
@@ -18,15 +18,13 @@ const run = async () => {
1818
const maxReviewers = getInput('max-reviewers');
1919
const token = getInput('github-token');
2020

21-
console.log({ maxReviewers, type: typeof maxReviewers });
22-
2321
const Octokit = getOctokit(token);
2422

2523
const changedFiles = await getChangedFiles(baseSha, headSha);
2624
if (!changedFiles) return warning('No changed files found!');
2725

2826
const emails = await getReviewersEmails(changedFiles);
29-
if (!emails?.length) return warning('No reviewers found!');
27+
if (!emails.length) return warning('No reviewers found!');
3028

3129
const usernames = await getReviewersUsernames(Octokit, emails);
3230

@@ -40,15 +38,13 @@ const run = async () => {
4038

4139
if (!validReviewers?.length) return warning('No valid reviewers found!');
4240

43-
console.log({ validReviewers });
44-
45-
const response = sendReviewRequests({
41+
await sendReviewRequests({
4642
Octokit,
4743
reviewers: validReviewers,
4844
context,
4945
});
5046

51-
console.log({ response });
47+
// console.log({ response });
5248
} catch (error) {
5349
console.log({ error });
5450
}

src/utils.ts

+1-3
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,7 @@ export const formatReviewers = (reviewers: string) => {
44
const _reviewers = reviewers
55
.trim()
66
.split('\n')
7-
.filter(
8-
(reviewer) => reviewer !== '' && !INVALID_REVIEWERS.includes(reviewer)
9-
);
7+
.filter((reviewer) => reviewer && !INVALID_REVIEWERS.includes(reviewer));
108

119
return [...new Set(_reviewers)];
1210
};

0 commit comments

Comments
 (0)