From 33218851b43760af9d39d51783c9e7fabf9d3240 Mon Sep 17 00:00:00 2001 From: Graham Neubig Date: Tue, 10 Dec 2024 01:44:44 -0500 Subject: [PATCH 1/2] Fix issue #13: Add the option to sort PRs --- package-lock.json | 15 ++++++++ package.json | 1 + src/PullRequestViewer.test.tsx | 34 ++++++++++++++++- src/PullRequestViewer.tsx | 67 +++++++++++++++++++++++++++++----- 4 files changed, 107 insertions(+), 10 deletions(-) diff --git a/package-lock.json b/package-lock.json index 2195477..3c58f44 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19,6 +19,7 @@ }, "devDependencies": { "@eslint/js": "^9.8.0", + "@testing-library/user-event": "^14.5.2", "@types/react": "^18.3.3", "@types/react-dom": "^18.3.0", "@vitejs/plugin-react": "^4.3.1", @@ -1692,6 +1693,20 @@ } } }, + "node_modules/@testing-library/user-event": { + "version": "14.5.2", + "resolved": "https://registry.npmjs.org/@testing-library/user-event/-/user-event-14.5.2.tgz", + "integrity": "sha512-YAh82Wh4TIrxYLmfGcixwD18oIjyC1pFQC2Y01F2lzV2HTMiYrI0nze0FD0ocB//CKS/7jIUgae+adPqxK5yCQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12", + "npm": ">=6" + }, + "peerDependencies": { + "@testing-library/dom": ">=7.21.4" + } + }, "node_modules/@types/aria-query": { "version": "5.0.4", "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.4.tgz", diff --git a/package.json b/package.json index 1ee556f..594782c 100644 --- a/package.json +++ b/package.json @@ -22,6 +22,7 @@ }, "devDependencies": { "@eslint/js": "^9.8.0", + "@testing-library/user-event": "^14.5.2", "@types/react": "^18.3.3", "@types/react-dom": "^18.3.0", "@vitejs/plugin-react": "^4.3.1", diff --git a/src/PullRequestViewer.test.tsx b/src/PullRequestViewer.test.tsx index 10f2959..b41b0dd 100644 --- a/src/PullRequestViewer.test.tsx +++ b/src/PullRequestViewer.test.tsx @@ -1,7 +1,8 @@ import React from 'react'; -import { render, screen } from '@testing-library/react'; +import { render, screen, fireEvent } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; import PullRequestViewer from './PullRequestViewer'; describe('PullRequestViewer', () => { @@ -16,4 +17,35 @@ describe('PullRequestViewer', () => { const selectElement = screen.getByRole('combobox', { name: /select a repository/i }); expect(selectElement).toBeInTheDocument(); }); + + it('renders the sort select dropdown', () => { + render(); + const sortSelect = screen.getByRole('combobox', { name: /sort pull requests/i }); + expect(sortSelect).toBeInTheDocument(); + }); + + it('displays default sort option', () => { + render(); + const defaultOption = screen.getByText('Creation Date (Newest)'); + expect(defaultOption).toBeInTheDocument(); + }); + + it('shows all sorting options', async () => { + render(); + const sortSelect = screen.getByRole('combobox', { name: /sort pull requests/i }); + await userEvent.click(sortSelect); + + const expectedOptions = [ + 'Creation Date (Newest)', + 'Creation Date (Oldest)', + 'Last Updated (Newest)', + 'Last Updated (Oldest)', + 'PR Number (Highest)', + 'PR Number (Lowest)', + ]; + + expectedOptions.forEach(option => { + expect(screen.getAllByText(option)[0]).toBeInTheDocument(); + }); + }); }); diff --git a/src/PullRequestViewer.tsx b/src/PullRequestViewer.tsx index c2e9399..065da80 100644 --- a/src/PullRequestViewer.tsx +++ b/src/PullRequestViewer.tsx @@ -14,6 +14,9 @@ interface PullRequest { user: { login: string; }; + created_at: string; + updated_at: string; + number: number; } interface Repo { @@ -21,10 +24,26 @@ interface Repo { label: string; } +interface SortOption { + value: keyof PullRequest | 'number' | 'created_at' | 'updated_at'; + label: string; + direction: 'asc' | 'desc'; +} + +const sortOptions: SortOption[] = [ + { value: 'created_at', label: 'Creation Date (Newest)', direction: 'desc' }, + { value: 'created_at', label: 'Creation Date (Oldest)', direction: 'asc' }, + { value: 'updated_at', label: 'Last Updated (Newest)', direction: 'desc' }, + { value: 'updated_at', label: 'Last Updated (Oldest)', direction: 'asc' }, + { value: 'number', label: 'PR Number (Highest)', direction: 'desc' }, + { value: 'number', label: 'PR Number (Lowest)', direction: 'asc' }, +]; + const PullRequestViewer: React.FC = () => { const [repos, setRepos] = useState([]); const [selectedRepo, setSelectedRepo] = useState(null); const [pullRequests, setPullRequests] = useState([]); + const [selectedSort, setSelectedSort] = useState(sortOptions[0]); useEffect(() => { const fetchRepos = async () => { @@ -80,25 +99,55 @@ const PullRequestViewer: React.FC = () => { fetchPullRequests(); }, [selectedRepo]); + const sortPullRequests = (prs: PullRequest[]) => { + return [...prs].sort((a, b) => { + const aValue = a[selectedSort.value]; + const bValue = b[selectedSort.value]; + + if (selectedSort.direction === 'asc') { + return aValue < bValue ? -1 : aValue > bValue ? 1 : 0; + } else { + return bValue < aValue ? -1 : bValue > aValue ? 1 : 0; + } + }); + }; + + const sortedPullRequests = sortPullRequests(pullRequests); + return (

Pull Request Viewer

- setSelectedRepo(option as Repo)} + placeholder="Select a repository" + aria-label="Select a repository" + /> +
+
+