Skip to content

Commit 3321885

Browse files
committed
Fix issue #13: Add the option to sort PRs
1 parent 9d8b0a0 commit 3321885

File tree

4 files changed

+107
-10
lines changed

4 files changed

+107
-10
lines changed

package-lock.json

Lines changed: 15 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
},
2323
"devDependencies": {
2424
"@eslint/js": "^9.8.0",
25+
"@testing-library/user-event": "^14.5.2",
2526
"@types/react": "^18.3.3",
2627
"@types/react-dom": "^18.3.0",
2728
"@vitejs/plugin-react": "^4.3.1",

src/PullRequestViewer.test.tsx

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11

22

33
import React from 'react';
4-
import { render, screen } from '@testing-library/react';
4+
import { render, screen, fireEvent } from '@testing-library/react';
5+
import userEvent from '@testing-library/user-event';
56
import PullRequestViewer from './PullRequestViewer';
67

78
describe('PullRequestViewer', () => {
@@ -16,4 +17,35 @@ describe('PullRequestViewer', () => {
1617
const selectElement = screen.getByRole('combobox', { name: /select a repository/i });
1718
expect(selectElement).toBeInTheDocument();
1819
});
20+
21+
it('renders the sort select dropdown', () => {
22+
render(<PullRequestViewer />);
23+
const sortSelect = screen.getByRole('combobox', { name: /sort pull requests/i });
24+
expect(sortSelect).toBeInTheDocument();
25+
});
26+
27+
it('displays default sort option', () => {
28+
render(<PullRequestViewer />);
29+
const defaultOption = screen.getByText('Creation Date (Newest)');
30+
expect(defaultOption).toBeInTheDocument();
31+
});
32+
33+
it('shows all sorting options', async () => {
34+
render(<PullRequestViewer />);
35+
const sortSelect = screen.getByRole('combobox', { name: /sort pull requests/i });
36+
await userEvent.click(sortSelect);
37+
38+
const expectedOptions = [
39+
'Creation Date (Newest)',
40+
'Creation Date (Oldest)',
41+
'Last Updated (Newest)',
42+
'Last Updated (Oldest)',
43+
'PR Number (Highest)',
44+
'PR Number (Lowest)',
45+
];
46+
47+
expectedOptions.forEach(option => {
48+
expect(screen.getAllByText(option)[0]).toBeInTheDocument();
49+
});
50+
});
1951
});

src/PullRequestViewer.tsx

Lines changed: 58 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,17 +14,36 @@ interface PullRequest {
1414
user: {
1515
login: string;
1616
};
17+
created_at: string;
18+
updated_at: string;
19+
number: number;
1720
}
1821

1922
interface Repo {
2023
value: string;
2124
label: string;
2225
}
2326

27+
interface SortOption {
28+
value: keyof PullRequest | 'number' | 'created_at' | 'updated_at';
29+
label: string;
30+
direction: 'asc' | 'desc';
31+
}
32+
33+
const sortOptions: SortOption[] = [
34+
{ value: 'created_at', label: 'Creation Date (Newest)', direction: 'desc' },
35+
{ value: 'created_at', label: 'Creation Date (Oldest)', direction: 'asc' },
36+
{ value: 'updated_at', label: 'Last Updated (Newest)', direction: 'desc' },
37+
{ value: 'updated_at', label: 'Last Updated (Oldest)', direction: 'asc' },
38+
{ value: 'number', label: 'PR Number (Highest)', direction: 'desc' },
39+
{ value: 'number', label: 'PR Number (Lowest)', direction: 'asc' },
40+
];
41+
2442
const PullRequestViewer: React.FC = () => {
2543
const [repos, setRepos] = useState<Repo[]>([]);
2644
const [selectedRepo, setSelectedRepo] = useState<Repo | null>(null);
2745
const [pullRequests, setPullRequests] = useState<PullRequest[]>([]);
46+
const [selectedSort, setSelectedSort] = useState<SortOption>(sortOptions[0]);
2847

2948
useEffect(() => {
3049
const fetchRepos = async () => {
@@ -80,25 +99,55 @@ const PullRequestViewer: React.FC = () => {
8099
fetchPullRequests();
81100
}, [selectedRepo]);
82101

102+
const sortPullRequests = (prs: PullRequest[]) => {
103+
return [...prs].sort((a, b) => {
104+
const aValue = a[selectedSort.value];
105+
const bValue = b[selectedSort.value];
106+
107+
if (selectedSort.direction === 'asc') {
108+
return aValue < bValue ? -1 : aValue > bValue ? 1 : 0;
109+
} else {
110+
return bValue < aValue ? -1 : bValue > aValue ? 1 : 0;
111+
}
112+
});
113+
};
114+
115+
const sortedPullRequests = sortPullRequests(pullRequests);
116+
83117
return (
84118
<div>
85119
<h1>Pull Request Viewer</h1>
86-
<Select
87-
options={repos}
88-
value={selectedRepo}
89-
onChange={(option) => setSelectedRepo(option as Repo)}
90-
placeholder="Select a repository"
91-
aria-label="Select a repository"
92-
/>
93-
{pullRequests.length > 0 ? (
120+
<div style={{ marginBottom: '1rem' }}>
121+
<Select
122+
options={repos}
123+
value={selectedRepo}
124+
onChange={(option) => setSelectedRepo(option as Repo)}
125+
placeholder="Select a repository"
126+
aria-label="Select a repository"
127+
/>
128+
</div>
129+
<div style={{ marginBottom: '1rem' }}>
130+
<Select
131+
options={sortOptions}
132+
value={selectedSort}
133+
onChange={(option) => setSelectedSort(option as SortOption)}
134+
placeholder="Sort by"
135+
aria-label="Sort pull requests"
136+
/>
137+
</div>
138+
{sortedPullRequests.length > 0 ? (
94139
<ul>
95-
{pullRequests.map((pr) => (
140+
{sortedPullRequests.map((pr) => (
96141
<li key={pr.html_url}>
97142
<a href={pr.html_url} target="_blank" rel="noopener noreferrer">
98143
{pr.title}
99144
</a>
100145
{' by '}
101146
{pr.user.login}
147+
{' - '}
148+
Created: {new Date(pr.created_at).toLocaleDateString()}
149+
{', '}
150+
Last updated: {new Date(pr.updated_at).toLocaleDateString()}
102151
</li>
103152
))}
104153
</ul>

0 commit comments

Comments
 (0)