difit 1.1.0 → 1.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +53 -46
- package/dist/cli/index.js +40 -17
- package/dist/cli/utils.d.ts +5 -0
- package/dist/cli/utils.js +33 -0
- package/dist/cli/utils.test.js +1 -85
- package/dist/client/assets/index-BLEv14wb.js +187 -0
- package/dist/client/assets/index-CmT0VFrk.css +1 -0
- package/dist/client/assets/prism-java-BzVDwsAU.js +1 -0
- package/dist/client/assets/prism-php-CaHq39v2.js +1 -0
- package/dist/client/assets/prism-ruby-ZR-2dwYA.js +1 -0
- package/dist/client/index.html +2 -2
- package/dist/server/git-diff-tui.d.ts +1 -1
- package/dist/server/git-diff-tui.js +31 -23
- package/dist/server/git-diff.d.ts +1 -1
- package/dist/server/git-diff.js +27 -20
- package/dist/server/server.d.ts +2 -1
- package/dist/server/server.js +61 -7
- package/dist/tui/App.d.ts +2 -1
- package/dist/tui/App.js +7 -7
- package/package.json +28 -28
- package/dist/client/assets/index-B67TY4_1.js +0 -178
- package/dist/client/assets/index-BHrhjAlZ.css +0 -1
- package/dist/client/assets/prism-java-Bz0cy7o8.js +0 -1
- package/dist/client/assets/prism-php-Y_bwvUTe.js +0 -1
- package/dist/client/assets/prism-ruby-pgU1Zfy6.js +0 -1
package/README.md
CHANGED
|
@@ -18,59 +18,64 @@ A lightweight command-line tool that spins up a local web server to display Git
|
|
|
18
18
|
- 🎨 **Syntax Highlighting**: Dynamic language loading for Bash, PHP, SQL, Ruby, Java, and more
|
|
19
19
|
- ✨ **100% vibe coding**: Built with pure coding energy and good vibes
|
|
20
20
|
|
|
21
|
-
##
|
|
21
|
+
## ⚡ Quick Start
|
|
22
22
|
|
|
23
23
|
```bash
|
|
24
|
-
#
|
|
25
|
-
npx reviewit <commit-ish>
|
|
26
|
-
|
|
27
|
-
# or Global install
|
|
28
|
-
npm install -g reviewit
|
|
24
|
+
npx reviewit # View HEAD commit changes in a beautiful diff viewer
|
|
29
25
|
```
|
|
30
26
|
|
|
31
27
|
## 🚀 Usage
|
|
32
28
|
|
|
29
|
+
### Basic Usage
|
|
30
|
+
|
|
33
31
|
```bash
|
|
34
|
-
#
|
|
35
|
-
npx reviewit
|
|
32
|
+
npx reviewit <commit-ish> # View single commit diff
|
|
33
|
+
npx reviewit <commit-ish> [compare-with] # Compare two commits/branches
|
|
34
|
+
```
|
|
36
35
|
|
|
37
|
-
|
|
38
|
-
npx reviewit 6f4a9b7
|
|
39
|
-
npx reviewit HEAD^
|
|
40
|
-
npx reviewit HEAD~3
|
|
36
|
+
### Single commit review
|
|
41
37
|
|
|
42
|
-
|
|
43
|
-
npx reviewit
|
|
44
|
-
npx reviewit
|
|
45
|
-
npx reviewit
|
|
38
|
+
```bash
|
|
39
|
+
npx reviewit 6f4a9b7 # Specific commit
|
|
40
|
+
npx reviewit HEAD^ # Previous commit
|
|
41
|
+
npx reviewit feature # Latest commit on branch
|
|
42
|
+
```
|
|
46
43
|
|
|
47
|
-
|
|
48
|
-
npx reviewit 6f4a9b7 --port 4300 --no-open
|
|
44
|
+
### Compare two commits
|
|
49
45
|
|
|
50
|
-
|
|
51
|
-
npx reviewit
|
|
52
|
-
npx reviewit
|
|
46
|
+
```bash
|
|
47
|
+
npx reviewit HEAD main # Compare HEAD with main branch
|
|
48
|
+
npx reviewit feature main # Compare branches
|
|
49
|
+
npx reviewit . origin/main # Compare working directory with remote main
|
|
53
50
|
```
|
|
54
51
|
|
|
55
|
-
###
|
|
52
|
+
### Special Arguments
|
|
56
53
|
|
|
57
|
-
|
|
58
|
-
| -------------- | ------------ | ------------------------------------------------------------------ |
|
|
59
|
-
| `<commit-ish>` | (required) | Any Git reference: hash, tag, HEAD~n, branch, or Special Arguments |
|
|
60
|
-
| `--port` | auto | Preferred port; falls back if occupied |
|
|
61
|
-
| `--no-open` | false | Don't automatically open browser |
|
|
62
|
-
| `--mode` | side-by-side | Diff mode: `inline` or `side-by-side` |
|
|
63
|
-
| `--tui` | false | Use terminal UI mode instead of web interface |
|
|
54
|
+
ReviewIt supports special keywords for common diff scenarios:
|
|
64
55
|
|
|
65
|
-
|
|
56
|
+
```bash
|
|
57
|
+
npx reviewit # HEAD commit changes
|
|
58
|
+
npx reviewit . # All uncommitted changes (staged + unstaged)
|
|
59
|
+
npx reviewit staged # Staged changes ready for commit
|
|
60
|
+
npx reviewit working # Unstaged changes only (cannot use compare-with)
|
|
61
|
+
```
|
|
66
62
|
|
|
67
|
-
|
|
63
|
+
| Keyword | Description | Compare-with Support |
|
|
64
|
+
| --------- | ------------------------------------------------------ | -------------------- |
|
|
65
|
+
| `.` | Shows all uncommitted changes (both staged & unstaged) | ✅ Yes |
|
|
66
|
+
| `staged` | Shows staged changes ready to be committed | ✅ Yes |
|
|
67
|
+
| `working` | Shows unstaged changes in your working directory | ❌ No |
|
|
68
|
+
|
|
69
|
+
### ⚙️ CLI Options
|
|
68
70
|
|
|
69
|
-
|
|
|
70
|
-
|
|
|
71
|
-
|
|
|
72
|
-
| `
|
|
73
|
-
|
|
|
71
|
+
| Flag | Default | Description |
|
|
72
|
+
| ---------------- | ------------ | ------------------------------------------------------------------- |
|
|
73
|
+
| `<commit-ish>` | HEAD | Any Git reference: hash, tag, HEAD~n, branch, or Special Arguments |
|
|
74
|
+
| `[compare-with]` | (optional) | Optional second commit to compare with (shows diff between the two) |
|
|
75
|
+
| `--port` | auto | Preferred port; falls back if occupied |
|
|
76
|
+
| `--no-open` | false | Don't automatically open browser |
|
|
77
|
+
| `--mode` | side-by-side | Diff mode: `inline` or `side-by-side` |
|
|
78
|
+
| `--tui` | false | Use terminal UI mode instead of web interface |
|
|
74
79
|
|
|
75
80
|
## 💬 Comment System
|
|
76
81
|
|
|
@@ -118,15 +123,10 @@ pnpm install
|
|
|
118
123
|
|
|
119
124
|
# Start development server (with hot reload)
|
|
120
125
|
# This runs both Vite dev server and CLI with NODE_ENV=development
|
|
121
|
-
pnpm run dev
|
|
122
|
-
pnpm run dev HEAD~3 # review HEAD~3
|
|
123
|
-
pnpm run dev main # review main branch
|
|
124
|
-
|
|
125
|
-
# For development CLI only (connects to separate Vite server)
|
|
126
|
-
pnpm run dev:cli <commit-ish>
|
|
126
|
+
pnpm run dev
|
|
127
127
|
|
|
128
128
|
# Build and start production server
|
|
129
|
-
pnpm run start
|
|
129
|
+
pnpm run start <commit-ish>
|
|
130
130
|
|
|
131
131
|
# Build for production
|
|
132
132
|
pnpm run build
|
|
@@ -143,20 +143,27 @@ pnpm run typecheck
|
|
|
143
143
|
### Development Workflow
|
|
144
144
|
|
|
145
145
|
- **`pnpm run dev`**: Starts both Vite dev server (with hot reload) and CLI server simultaneously
|
|
146
|
-
- **`pnpm run start <commit>`**: Builds everything and starts production server (for testing final build)
|
|
146
|
+
- **`pnpm run start <commit-ish>`**: Builds everything and starts production server (for testing final build)
|
|
147
147
|
- **Development mode**: Uses Vite's dev server for hot reload and fast development
|
|
148
148
|
- **Production mode**: Serves built static files (used by npx and production builds)
|
|
149
149
|
|
|
150
150
|
## 🏗️ Architecture
|
|
151
151
|
|
|
152
|
-
- **CLI**: Commander.js for argument parsing
|
|
152
|
+
- **CLI**: Commander.js for argument parsing with comprehensive validation
|
|
153
153
|
- **Backend**: Express server with simple-git for diff processing
|
|
154
154
|
- **Frontend**: React 18 + TypeScript + Vite
|
|
155
155
|
- **Styling**: Tailwind CSS v4 with GitHub-like dark theme
|
|
156
156
|
- **Syntax Highlighting**: Prism.js with dynamic language loading
|
|
157
|
-
- **Testing**: Vitest for unit tests
|
|
157
|
+
- **Testing**: Vitest for unit tests with co-located test files
|
|
158
158
|
- **Quality**: ESLint, Prettier, lefthook pre-commit hooks
|
|
159
159
|
|
|
160
|
+
### Key Components
|
|
161
|
+
|
|
162
|
+
- **Validation System**: Unified validation logic for CLI arguments with comprehensive error handling
|
|
163
|
+
- **Dual Parameter System**: Internal refactoring splits commitish into targetCommitish and baseCommitish for flexibility
|
|
164
|
+
- **Special Argument Support**: Working directory, staging area, and uncommitted changes detection
|
|
165
|
+
- **Hash Utilities**: Consistent short hash generation for commit display
|
|
166
|
+
|
|
160
167
|
## 📋 Requirements
|
|
161
168
|
|
|
162
169
|
- Node.js ≥ 18.0.0
|
package/dist/cli/index.js
CHANGED
|
@@ -3,30 +3,38 @@ import { Command } from 'commander';
|
|
|
3
3
|
import React from 'react';
|
|
4
4
|
import pkg from '../../package.json' with { type: 'json' };
|
|
5
5
|
import { startServer } from '../server/server.js';
|
|
6
|
-
import {
|
|
6
|
+
import { validateDiffArguments } from './utils.js';
|
|
7
|
+
function isSpecialArg(arg) {
|
|
8
|
+
return arg === 'working' || arg === 'staged' || arg === '.';
|
|
9
|
+
}
|
|
7
10
|
const program = new Command();
|
|
8
11
|
program
|
|
9
12
|
.name('reviewit')
|
|
10
13
|
.description('A lightweight Git diff viewer with GitHub-like interface')
|
|
11
14
|
.version(pkg.version)
|
|
12
15
|
.argument('[commit-ish]', 'Git commit, tag, branch, HEAD~n reference, or "working"/"staged"/"." (default: HEAD)', 'HEAD')
|
|
16
|
+
.argument('[compare-with]', 'Optional: Compare with this commit/branch (shows diff between commit-ish and compare-with)')
|
|
13
17
|
.option('--port <port>', 'preferred port (auto-assigned if occupied)', parseInt)
|
|
14
18
|
.option('--no-open', 'do not automatically open browser')
|
|
15
19
|
.option('--mode <mode>', 'diff mode (inline only for now)', 'inline')
|
|
16
20
|
.option('--tui', 'use terminal UI instead of web interface')
|
|
17
|
-
.action(async (commitish, options) => {
|
|
21
|
+
.action(async (commitish, compareWith, options) => {
|
|
18
22
|
try {
|
|
19
|
-
// Determine
|
|
23
|
+
// Determine target and base commitish
|
|
20
24
|
let targetCommitish = commitish;
|
|
21
|
-
|
|
22
|
-
if (
|
|
23
|
-
|
|
25
|
+
let baseCommitish;
|
|
26
|
+
if (compareWith) {
|
|
27
|
+
// If compareWith is provided, use it as base
|
|
28
|
+
baseCommitish = compareWith;
|
|
24
29
|
}
|
|
25
|
-
else
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
+
else {
|
|
31
|
+
// Handle special arguments
|
|
32
|
+
if (isSpecialArg(commitish)) {
|
|
33
|
+
baseCommitish = 'HEAD';
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
baseCommitish = commitish + '^';
|
|
37
|
+
}
|
|
30
38
|
}
|
|
31
39
|
if (options.tui) {
|
|
32
40
|
// Check if we're in a TTY environment
|
|
@@ -38,15 +46,17 @@ program
|
|
|
38
46
|
// Dynamic import for TUI mode
|
|
39
47
|
const { render } = await import('ink');
|
|
40
48
|
const { default: TuiApp } = await import('../tui/App.js');
|
|
41
|
-
render(React.createElement(TuiApp, {
|
|
49
|
+
render(React.createElement(TuiApp, { targetCommitish, baseCommitish }));
|
|
42
50
|
return;
|
|
43
51
|
}
|
|
44
|
-
|
|
45
|
-
|
|
52
|
+
const validation = validateDiffArguments(targetCommitish, compareWith);
|
|
53
|
+
if (!validation.valid) {
|
|
54
|
+
console.error(`Error: ${validation.error}`);
|
|
46
55
|
process.exit(1);
|
|
47
56
|
}
|
|
48
|
-
const { url } = await startServer({
|
|
49
|
-
|
|
57
|
+
const { url, port } = await startServer({
|
|
58
|
+
targetCommitish,
|
|
59
|
+
baseCommitish,
|
|
50
60
|
preferredPort: options.port,
|
|
51
61
|
openBrowser: options.open,
|
|
52
62
|
mode: options.mode,
|
|
@@ -59,8 +69,21 @@ program
|
|
|
59
69
|
else {
|
|
60
70
|
console.log('💡 Use --open to automatically open browser\n');
|
|
61
71
|
}
|
|
62
|
-
process.on('SIGINT', () => {
|
|
72
|
+
process.on('SIGINT', async () => {
|
|
63
73
|
console.log('\n👋 Shutting down ReviewIt server...');
|
|
74
|
+
// Try to fetch comments before shutting down
|
|
75
|
+
try {
|
|
76
|
+
const response = await fetch(`http://localhost:${port}/api/comments-output`);
|
|
77
|
+
if (response.ok) {
|
|
78
|
+
const data = await response.text();
|
|
79
|
+
if (data.trim()) {
|
|
80
|
+
console.log(data);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
catch {
|
|
85
|
+
// Silently ignore fetch errors during shutdown
|
|
86
|
+
}
|
|
64
87
|
process.exit(0);
|
|
65
88
|
});
|
|
66
89
|
}
|
package/dist/cli/utils.d.ts
CHANGED
package/dist/cli/utils.js
CHANGED
|
@@ -20,3 +20,36 @@ export function validateCommitish(commitish) {
|
|
|
20
20
|
];
|
|
21
21
|
return validPatterns.some((pattern) => pattern.test(trimmed));
|
|
22
22
|
}
|
|
23
|
+
export function shortHash(hash) {
|
|
24
|
+
return hash.substring(0, 7);
|
|
25
|
+
}
|
|
26
|
+
export function validateDiffArguments(targetCommitish, baseCommitish) {
|
|
27
|
+
// Validate target commitish format
|
|
28
|
+
if (!validateCommitish(targetCommitish)) {
|
|
29
|
+
return { valid: false, error: 'Invalid target commit-ish format' };
|
|
30
|
+
}
|
|
31
|
+
// Validate base commitish format if provided
|
|
32
|
+
if (baseCommitish !== undefined && !validateCommitish(baseCommitish)) {
|
|
33
|
+
return { valid: false, error: 'Invalid base commit-ish format' };
|
|
34
|
+
}
|
|
35
|
+
// Special arguments are only allowed in target, not base
|
|
36
|
+
const specialArgs = ['working', 'staged', '.'];
|
|
37
|
+
if (baseCommitish && specialArgs.includes(baseCommitish)) {
|
|
38
|
+
return {
|
|
39
|
+
valid: false,
|
|
40
|
+
error: `Special arguments (working, staged, .) are only allowed as target, not base. Got base: ${baseCommitish}`,
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
// Cannot compare same values
|
|
44
|
+
if (targetCommitish === baseCommitish) {
|
|
45
|
+
return { valid: false, error: `Cannot compare ${targetCommitish} with itself` };
|
|
46
|
+
}
|
|
47
|
+
// "working" shows unstaged changes and cannot be compared with another commit
|
|
48
|
+
if (targetCommitish === 'working' && baseCommitish) {
|
|
49
|
+
return {
|
|
50
|
+
valid: false,
|
|
51
|
+
error: '"working" shows unstaged changes and cannot be compared with another commit. Use "." instead to compare all uncommitted changes with a specific commit.',
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
return { valid: true };
|
|
55
|
+
}
|
package/dist/cli/utils.test.js
CHANGED
|
@@ -1,23 +1,11 @@
|
|
|
1
1
|
import { describe, it, expect } from 'vitest';
|
|
2
|
-
import { validateCommitish, validateDiffArguments, shortHash
|
|
2
|
+
import { validateCommitish, validateDiffArguments, shortHash } from './utils';
|
|
3
3
|
describe('CLI Utils', () => {
|
|
4
4
|
describe('validateCommitish', () => {
|
|
5
5
|
it('should validate full SHA hashes', () => {
|
|
6
6
|
expect(validateCommitish('a1b2c3d4e5f6789012345678901234567890abcd')).toBe(true);
|
|
7
7
|
expect(validateCommitish('abc123')).toBe(true);
|
|
8
8
|
});
|
|
9
|
-
it('should validate SHA hashes with parent references', () => {
|
|
10
|
-
expect(validateCommitish('a1b2c3d4e5f6789012345678901234567890abcd^')).toBe(true);
|
|
11
|
-
expect(validateCommitish('abc123^')).toBe(true);
|
|
12
|
-
expect(validateCommitish('abc123^^')).toBe(true);
|
|
13
|
-
expect(validateCommitish('bd4b7513e075b5b245284c38fd23427b9bd0f42e^')).toBe(true);
|
|
14
|
-
});
|
|
15
|
-
it('should validate SHA hashes with ancestor references', () => {
|
|
16
|
-
expect(validateCommitish('a1b2c3d4e5f6789012345678901234567890abcd~1')).toBe(true);
|
|
17
|
-
expect(validateCommitish('abc123~5')).toBe(true);
|
|
18
|
-
expect(validateCommitish('abc123~10')).toBe(true);
|
|
19
|
-
expect(validateCommitish('bd4b7513e075b5b245284c38fd23427b9bd0f42e~2')).toBe(true);
|
|
20
|
-
});
|
|
21
9
|
it('should validate HEAD references', () => {
|
|
22
10
|
expect(validateCommitish('HEAD')).toBe(true);
|
|
23
11
|
expect(validateCommitish('HEAD~1')).toBe(true);
|
|
@@ -85,12 +73,6 @@ describe('CLI Utils', () => {
|
|
|
85
73
|
expect(validateDiffArguments('staged', 'HEAD')).toEqual({ valid: true });
|
|
86
74
|
expect(validateDiffArguments('.', 'main')).toEqual({ valid: true });
|
|
87
75
|
});
|
|
88
|
-
it('should allow staged as base only with working target', () => {
|
|
89
|
-
expect(validateDiffArguments('working', 'staged')).toEqual({ valid: true });
|
|
90
|
-
const result = validateDiffArguments('HEAD', 'staged');
|
|
91
|
-
expect(result.valid).toBe(false);
|
|
92
|
-
expect(result.error).toBe('Special arguments (working, staged, .) are only allowed as target, not base. Got base: staged');
|
|
93
|
-
});
|
|
94
76
|
});
|
|
95
77
|
describe('same value comparison', () => {
|
|
96
78
|
it('should reject same target and base values', () => {
|
|
@@ -115,17 +97,6 @@ describe('CLI Utils', () => {
|
|
|
115
97
|
it('should allow working without compareWith', () => {
|
|
116
98
|
expect(validateDiffArguments('working')).toEqual({ valid: true });
|
|
117
99
|
});
|
|
118
|
-
it('should allow working with staged', () => {
|
|
119
|
-
expect(validateDiffArguments('working', 'staged')).toEqual({ valid: true });
|
|
120
|
-
});
|
|
121
|
-
it('should reject working with other commits', () => {
|
|
122
|
-
const result1 = validateDiffArguments('working', 'main');
|
|
123
|
-
expect(result1.valid).toBe(false);
|
|
124
|
-
expect(result1.error).toBe('"working" shows unstaged changes and cannot be compared with another commit. Use "." instead to compare all uncommitted changes with a specific commit.');
|
|
125
|
-
const result2 = validateDiffArguments('working', 'abc123');
|
|
126
|
-
expect(result2.valid).toBe(false);
|
|
127
|
-
expect(result2.error).toBe('"working" shows unstaged changes and cannot be compared with another commit. Use "." instead to compare all uncommitted changes with a specific commit.');
|
|
128
|
-
});
|
|
129
100
|
it('should allow other special args with compareWith', () => {
|
|
130
101
|
expect(validateDiffArguments('staged', 'HEAD')).toEqual({ valid: true });
|
|
131
102
|
expect(validateDiffArguments('.', 'main')).toEqual({ valid: true });
|
|
@@ -143,14 +114,6 @@ describe('CLI Utils', () => {
|
|
|
143
114
|
valid: true,
|
|
144
115
|
});
|
|
145
116
|
});
|
|
146
|
-
it('should handle SHA hashes with parent/ancestor references', () => {
|
|
147
|
-
expect(validateDiffArguments('bd4b7513e075b5b245284c38fd23427b9bd0f42e^', 'abc123')).toEqual({ valid: true });
|
|
148
|
-
expect(validateDiffArguments('abc123', 'def456^')).toEqual({ valid: true });
|
|
149
|
-
expect(validateDiffArguments('abc123~1', 'def456~2')).toEqual({ valid: true });
|
|
150
|
-
expect(validateDiffArguments('a1b2c3d4e5f6789012345678901234567890abcd^', 'HEAD')).toEqual({
|
|
151
|
-
valid: true,
|
|
152
|
-
});
|
|
153
|
-
});
|
|
154
117
|
});
|
|
155
118
|
});
|
|
156
119
|
describe('shortHash', () => {
|
|
@@ -164,51 +127,4 @@ describe('CLI Utils', () => {
|
|
|
164
127
|
expect(shortHash('')).toBe('');
|
|
165
128
|
});
|
|
166
129
|
});
|
|
167
|
-
describe('parseGitHubPrUrl', () => {
|
|
168
|
-
it('should parse valid GitHub PR URLs', () => {
|
|
169
|
-
const result = parseGitHubPrUrl('https://github.com/owner/repo/pull/123');
|
|
170
|
-
expect(result).toEqual({
|
|
171
|
-
owner: 'owner',
|
|
172
|
-
repo: 'repo',
|
|
173
|
-
pullNumber: 123,
|
|
174
|
-
});
|
|
175
|
-
});
|
|
176
|
-
it('should parse GitHub PR URLs with additional path segments', () => {
|
|
177
|
-
const result = parseGitHubPrUrl('https://github.com/owner/repo/pull/456/files');
|
|
178
|
-
expect(result).toEqual({
|
|
179
|
-
owner: 'owner',
|
|
180
|
-
repo: 'repo',
|
|
181
|
-
pullNumber: 456,
|
|
182
|
-
});
|
|
183
|
-
});
|
|
184
|
-
it('should parse GitHub PR URLs with query parameters', () => {
|
|
185
|
-
const result = parseGitHubPrUrl('https://github.com/owner/repo/pull/789?tab=files');
|
|
186
|
-
expect(result).toEqual({
|
|
187
|
-
owner: 'owner',
|
|
188
|
-
repo: 'repo',
|
|
189
|
-
pullNumber: 789,
|
|
190
|
-
});
|
|
191
|
-
});
|
|
192
|
-
it('should handle URLs with hyphens and underscores in owner/repo names', () => {
|
|
193
|
-
const result = parseGitHubPrUrl('https://github.com/owner-name/repo_name/pull/123');
|
|
194
|
-
expect(result).toEqual({
|
|
195
|
-
owner: 'owner-name',
|
|
196
|
-
repo: 'repo_name',
|
|
197
|
-
pullNumber: 123,
|
|
198
|
-
});
|
|
199
|
-
});
|
|
200
|
-
it('should return null for invalid URLs', () => {
|
|
201
|
-
expect(parseGitHubPrUrl('not-a-url')).toBe(null);
|
|
202
|
-
expect(parseGitHubPrUrl('https://example.com/owner/repo/pull/123')).toBe(null);
|
|
203
|
-
expect(parseGitHubPrUrl('https://github.com/owner/repo/issues/123')).toBe(null);
|
|
204
|
-
expect(parseGitHubPrUrl('https://github.com/owner/repo')).toBe(null);
|
|
205
|
-
expect(parseGitHubPrUrl('https://github.com/owner/repo/pull/abc')).toBe(null);
|
|
206
|
-
});
|
|
207
|
-
it('should handle malformed URLs gracefully', () => {
|
|
208
|
-
expect(parseGitHubPrUrl('')).toBe(null);
|
|
209
|
-
expect(parseGitHubPrUrl('https://github.com')).toBe(null);
|
|
210
|
-
expect(parseGitHubPrUrl('https://github.com/owner')).toBe(null);
|
|
211
|
-
expect(parseGitHubPrUrl('https://github.com/owner/repo/pull')).toBe(null);
|
|
212
|
-
});
|
|
213
|
-
});
|
|
214
130
|
});
|