Skip to content

Commit 64955ae

Browse files
committed
Add unit test
1 parent ac0c4dc commit 64955ae

File tree

5 files changed

+2492
-16
lines changed

5 files changed

+2492
-16
lines changed

create-pull-request.js

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -185,5 +185,19 @@ async function main() {
185185
}
186186
}
187187

188-
// Execute main function
189-
main();
188+
// Export functions for testing
189+
export {
190+
SUPPORTED_BROWSERS,
191+
SUPPORTED_PLATFORMS,
192+
isHelpRequested,
193+
normalizeGitUrl,
194+
getPullRequestUrl,
195+
getBrowser,
196+
displayHelp,
197+
main
198+
};
199+
200+
// Only run main if this file is executed directly
201+
if (import.meta.url === `file://${process.argv[1]}`) {
202+
main();
203+
}

create-pull-request.test.js

Lines changed: 303 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,303 @@
1+
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
2+
import {
3+
SUPPORTED_BROWSERS,
4+
SUPPORTED_PLATFORMS,
5+
isHelpRequested,
6+
normalizeGitUrl,
7+
getPullRequestUrl,
8+
getBrowser,
9+
displayHelp,
10+
} from './create-pull-request.js';
11+
12+
// Mock the dependencies
13+
vi.mock('current-git-branch', () => ({
14+
default: vi.fn(() => 'main'),
15+
}));
16+
17+
vi.mock('git-remote-origin-url', () => ({
18+
default: vi.fn(() => Promise.resolve('https://github.com/user/repo.git')),
19+
}));
20+
21+
vi.mock('open', () => ({
22+
default: vi.fn(() => Promise.resolve()),
23+
}));
24+
25+
vi.mock('chalk', () => ({
26+
default: {
27+
hex: vi.fn(() => vi.fn((text) => text)),
28+
red: vi.fn((text) => text),
29+
green: vi.fn((text) => text),
30+
blue: vi.fn((text) => text),
31+
bold: vi.fn((text) => text),
32+
},
33+
}));
34+
35+
describe('create-pull-request CLI', () => {
36+
let originalArgv;
37+
let consoleSpy;
38+
39+
beforeEach(() => {
40+
// Store original process.argv
41+
originalArgv = process.argv;
42+
// Mock console.log to avoid output during tests
43+
consoleSpy = vi.spyOn(console, 'log').mockImplementation(() => {});
44+
});
45+
46+
afterEach(() => {
47+
// Restore original process.argv
48+
process.argv = originalArgv;
49+
// Restore console.log
50+
consoleSpy.mockRestore();
51+
vi.clearAllMocks();
52+
});
53+
54+
describe('Constants', () => {
55+
it('should have correct supported browsers', () => {
56+
expect(SUPPORTED_BROWSERS).toEqual({
57+
chrome: 'google chrome',
58+
firefox: 'firefox',
59+
'firefox-dev': 'firefox developer edition',
60+
edge: 'microsoft edge',
61+
safari: 'safari',
62+
opera: 'opera',
63+
brave: 'brave browser',
64+
});
65+
});
66+
67+
it('should have correct supported platforms', () => {
68+
expect(Object.keys(SUPPORTED_PLATFORMS)).toEqual([
69+
'github.com',
70+
'bitbucket.org',
71+
'gitlab.com',
72+
]);
73+
});
74+
75+
it('should generate correct GitHub URL', () => {
76+
const githubHandler = SUPPORTED_PLATFORMS['github.com'];
77+
expect(githubHandler('https://github.com/user/repo', 'main')).toBe(
78+
'https://github.com/user/repo/pull/new/main'
79+
);
80+
});
81+
82+
it('should generate correct Bitbucket URL', () => {
83+
const bitbucketHandler = SUPPORTED_PLATFORMS['bitbucket.org'];
84+
expect(bitbucketHandler('https://bitbucket.org/user/repo', 'main')).toBe(
85+
'https://bitbucket.org/user/repo/pull-requests/new?source=main&t=1#diff'
86+
);
87+
});
88+
89+
it('should generate correct GitLab URL', () => {
90+
const gitlabHandler = SUPPORTED_PLATFORMS['gitlab.com'];
91+
expect(gitlabHandler('https://gitlab.com/user/repo', 'main')).toBe(
92+
'https://gitlab.com/user/repo/-/merge_requests/new?merge_request[source_branch]=main'
93+
);
94+
});
95+
});
96+
97+
describe('isHelpRequested', () => {
98+
it('should return true for --help flag', () => {
99+
process.argv = ['node', 'script.js', '--help'];
100+
expect(isHelpRequested()).toBe(true);
101+
});
102+
103+
it('should return true for -h flag', () => {
104+
process.argv = ['node', 'script.js', '-h'];
105+
expect(isHelpRequested()).toBe(true);
106+
});
107+
108+
it('should return false for no flags', () => {
109+
process.argv = ['node', 'script.js'];
110+
expect(isHelpRequested()).toBe(false);
111+
});
112+
113+
it('should return false for other flags', () => {
114+
process.argv = ['node', 'script.js', 'chrome'];
115+
expect(isHelpRequested()).toBe(false);
116+
});
117+
118+
it('should return true when help flag is present with other args', () => {
119+
process.argv = ['node', 'script.js', 'chrome', '--help'];
120+
expect(isHelpRequested()).toBe(true);
121+
});
122+
});
123+
124+
describe('normalizeGitUrl', () => {
125+
it('should convert SSH URL to HTTPS', () => {
126+
const sshUrl = '[email protected]:user/repo.git';
127+
const expected = 'https://github.com/user/repo';
128+
expect(normalizeGitUrl(sshUrl)).toBe(expected);
129+
});
130+
131+
it('should convert SSH URL with .org domain', () => {
132+
const sshUrl = '[email protected]:user/repo.git';
133+
const expected = 'https://bitbucket.org/user/repo';
134+
expect(normalizeGitUrl(sshUrl)).toBe(expected);
135+
});
136+
137+
it('should remove .git suffix from HTTPS URL', () => {
138+
const httpsUrl = 'https://github.com/user/repo.git';
139+
const expected = 'https://github.com/user/repo';
140+
expect(normalizeGitUrl(httpsUrl)).toBe(expected);
141+
});
142+
143+
it('should handle HTTPS URL without .git suffix', () => {
144+
const httpsUrl = 'https://github.com/user/repo';
145+
const expected = 'https://github.com/user/repo';
146+
expect(normalizeGitUrl(httpsUrl)).toBe(expected);
147+
});
148+
149+
it('should handle URL with path', () => {
150+
const url = '[email protected]:group/subgroup/repo.git';
151+
const expected = 'https://gitlab.com/group/subgroup/repo';
152+
expect(normalizeGitUrl(url)).toBe(expected);
153+
});
154+
});
155+
156+
describe('getPullRequestUrl', () => {
157+
it('should generate GitHub pull request URL', () => {
158+
const repoUrl = 'https://github.com/user/repo';
159+
const expected = 'https://github.com/user/repo/pull/new/main';
160+
expect(getPullRequestUrl(repoUrl)).toBe(expected);
161+
});
162+
163+
it('should generate Bitbucket pull request URL', () => {
164+
const repoUrl = 'https://bitbucket.org/user/repo';
165+
const expected = 'https://bitbucket.org/user/repo/pull-requests/new?source=main&t=1#diff';
166+
expect(getPullRequestUrl(repoUrl)).toBe(expected);
167+
});
168+
169+
it('should generate GitLab merge request URL', () => {
170+
const repoUrl = 'https://gitlab.com/user/repo';
171+
const expected = 'https://gitlab.com/user/repo/-/merge_requests/new?merge_request[source_branch]=main';
172+
expect(getPullRequestUrl(repoUrl)).toBe(expected);
173+
});
174+
175+
it('should return empty string for unsupported platform', () => {
176+
const repoUrl = 'https://example.com/user/repo';
177+
expect(getPullRequestUrl(repoUrl)).toBe('');
178+
});
179+
180+
it('should throw error for invalid URL', () => {
181+
const invalidUrl = 'not-a-url';
182+
expect(() => getPullRequestUrl(invalidUrl)).toThrow('Invalid repository URL');
183+
});
184+
185+
it('should handle URLs with paths', () => {
186+
const repoUrl = 'https://github.com/org/team/repo';
187+
const expected = 'https://github.com/org/team/repo/pull/new/main';
188+
expect(getPullRequestUrl(repoUrl)).toBe(expected);
189+
});
190+
});
191+
192+
describe('getBrowser', () => {
193+
it('should return browser name for valid browser', () => {
194+
process.argv = ['node', 'script.js', 'chrome'];
195+
expect(getBrowser()).toBe('google chrome');
196+
});
197+
198+
it('should return firefox developer edition for firefox-dev', () => {
199+
process.argv = ['node', 'script.js', 'firefox-dev'];
200+
expect(getBrowser()).toBe('firefox developer edition');
201+
});
202+
203+
it('should return brave browser for brave', () => {
204+
process.argv = ['node', 'script.js', 'brave'];
205+
expect(getBrowser()).toBe('brave browser');
206+
});
207+
208+
it('should return null for no browser argument', () => {
209+
process.argv = ['node', 'script.js'];
210+
expect(getBrowser()).toBe(null);
211+
});
212+
213+
it('should return null for help flag', () => {
214+
process.argv = ['node', 'script.js', '--help'];
215+
expect(getBrowser()).toBe(null);
216+
});
217+
218+
it('should return null for -h flag', () => {
219+
process.argv = ['node', 'script.js', '-h'];
220+
expect(getBrowser()).toBe(null);
221+
});
222+
223+
it('should return null and log warning for invalid browser', () => {
224+
process.argv = ['node', 'script.js', 'invalid-browser'];
225+
const result = getBrowser();
226+
227+
expect(result).toBe(null);
228+
expect(consoleSpy).toHaveBeenCalledWith(
229+
expect.stringContaining('Browser "invalid-browser" is not supported')
230+
);
231+
});
232+
233+
it('should handle all supported browsers', () => {
234+
const browserTests = [
235+
['chrome', 'google chrome'],
236+
['firefox', 'firefox'],
237+
['firefox-dev', 'firefox developer edition'],
238+
['edge', 'microsoft edge'],
239+
['safari', 'safari'],
240+
['opera', 'opera'],
241+
['brave', 'brave browser'],
242+
];
243+
244+
browserTests.forEach(([input, expected]) => {
245+
process.argv = ['node', 'script.js', input];
246+
expect(getBrowser()).toBe(expected);
247+
});
248+
});
249+
});
250+
251+
describe('displayHelp', () => {
252+
it('should display help information', () => {
253+
displayHelp();
254+
255+
expect(consoleSpy).toHaveBeenCalledWith(
256+
expect.stringContaining('Create Pull Request CLI')
257+
);
258+
expect(consoleSpy).toHaveBeenCalledWith(
259+
expect.stringContaining('Usage:')
260+
);
261+
expect(consoleSpy).toHaveBeenCalledWith(
262+
expect.stringContaining('chrome, firefox, firefox-dev, edge, safari, opera, brave')
263+
);
264+
expect(consoleSpy).toHaveBeenCalledWith(
265+
expect.stringContaining('github.com, bitbucket.org, gitlab.com')
266+
);
267+
});
268+
});
269+
270+
describe('Integration tests', () => {
271+
it('should handle complete workflow for GitHub repo', () => {
272+
const sshUrl = '[email protected]:user/repo.git';
273+
const normalizedUrl = normalizeGitUrl(sshUrl);
274+
const pullRequestUrl = getPullRequestUrl(normalizedUrl);
275+
276+
expect(normalizedUrl).toBe('https://github.com/user/repo');
277+
expect(pullRequestUrl).toBe('https://github.com/user/repo/pull/new/main');
278+
});
279+
280+
it('should handle complete workflow for GitLab repo', () => {
281+
const httpsUrl = 'https://gitlab.com/group/project.git';
282+
const normalizedUrl = normalizeGitUrl(httpsUrl);
283+
const pullRequestUrl = getPullRequestUrl(normalizedUrl);
284+
285+
expect(normalizedUrl).toBe('https://gitlab.com/group/project');
286+
expect(pullRequestUrl).toBe('https://gitlab.com/group/project/-/merge_requests/new?merge_request[source_branch]=main');
287+
});
288+
289+
it('should handle browser selection with help flag', () => {
290+
process.argv = ['node', 'script.js', '--help'];
291+
292+
expect(isHelpRequested()).toBe(true);
293+
expect(getBrowser()).toBe(null);
294+
});
295+
296+
it('should handle browser selection without help flag', () => {
297+
process.argv = ['node', 'script.js', 'firefox'];
298+
299+
expect(isHelpRequested()).toBe(false);
300+
expect(getBrowser()).toBe('firefox');
301+
});
302+
});
303+
});

0 commit comments

Comments
 (0)