-
Notifications
You must be signed in to change notification settings - Fork 16
Test/components issue #48
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
Aarya1402
wants to merge
17
commits into
vee1e:master
Choose a base branch
from
Aarya1402:test/components-issue
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
17 commits
Select commit
Hold shift + click to select a range
08a56d1
test(ui): add test coverage for ui components
Aarya1402 5846beb
test(ui): add test coverage for Input component
Aarya1402 551ca41
test(ui): add test coverage for Panel component
Aarya1402 0c59bd4
test(ui): add test coverage for ProgressBar component
Aarya1402 770be7f
test(ui): add test coverage for ScrollArea component
Aarya1402 07ddfe5
test(ui): add test coverage for MarkdownRenderer component
Aarya1402 fdfd964
fix(ui): fix failing ScrollArea test
Aarya1402 bbe3244
test(terminal): add test coverage for TerminalInput component
Aarya1402 08d57fd
fix(types): add jest-dom type reference
Aarya1402 ce5459f
test(issue): add test coverage for IssueMetadata component
Aarya1402 515cad7
test(issue): add test coverage for IssueListItem component
Aarya1402 cef213f
test(issue): add test coverage for IssueList component
Aarya1402 7aba774
test(issue): add test coverage for IssueDetail component
Aarya1402 d1b7ab9
test(issue): fix missing required body property in tests
Aarya1402 1231980
Update src/components/issue/IssueList.test.tsx
Aarya1402 3e9bbbe
Update src/components/ui/Input.test.tsx
Aarya1402 1b9019f
test(issue): resolve PR review feedback and fix pluralization bug
Aarya1402 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,70 @@ | ||
| import { render, screen } from '@testing-library/react'; | ||
| import { IssueDetail } from './IssueDetail'; | ||
| import { describe, it, expect } from 'vitest'; | ||
| import type { RankedIssue } from '../../lib/types'; | ||
| import React from 'react'; | ||
|
|
||
| const mockIssue: RankedIssue = { | ||
| number: 101, | ||
| title: 'Fix styling of buttons', | ||
| body: 'Please fix the styled buttons on the home screen.', | ||
| updated_at: new Date().toISOString(), | ||
| score: 90, | ||
| user: { login: 'github_user', avatar_url: '', html_url: '' }, | ||
| labels: [{ name: 'ui-bug', color: 'ff0000' }], | ||
| assignees: [], | ||
| comments_count: 1, | ||
| created_at: new Date().toISOString(), | ||
| html_url: 'https://github.com/example/repo/issues/101', | ||
| state: 'open', | ||
| analysis: { | ||
| summary: 'Simple styling adjustment.', | ||
| status: 'active', | ||
| progress_estimate: 'early', | ||
| is_actionable_code_change: true, | ||
| not_mergeable_reason: null, | ||
| complexity: 1, | ||
| skills_required: ['CSS'], | ||
| newcomer_friendliness: 5, | ||
| doability_score: 95, | ||
| analysis_notes: 'Notes here.', | ||
| }, | ||
| comments: [ | ||
| { | ||
| id: 1, | ||
| user: { login: 'commenter', avatar_url: '', html_url: '' }, | ||
| body: 'I will take a look.', | ||
| created_at: new Date().toISOString(), | ||
| updated_at: new Date().toISOString(), | ||
| }, | ||
| ], | ||
| }; | ||
|
|
||
| describe('IssueDetail component', () => { | ||
| it('renders select issue placeholder when issue is null', () => { | ||
| render(<IssueDetail issue={null} />); | ||
| expect(screen.getByText('Select an issue to view details')).toBeInTheDocument(); | ||
| }); | ||
|
|
||
| it('renders all details when issue is provided', () => { | ||
| render(<IssueDetail issue={mockIssue} />); | ||
|
|
||
| expect(screen.getByText('#101 — Fix styling of buttons')).toBeInTheDocument(); | ||
| expect(screen.getByText('github_user')).toBeInTheDocument(); | ||
| expect(screen.getByText('1 comment')).toBeInTheDocument(); | ||
| expect(screen.getByText('ui-bug')).toBeInTheDocument(); | ||
|
|
||
| // AI Analysis section | ||
| expect(screen.getByText('Simple styling adjustment.')).toBeInTheDocument(); | ||
| expect(screen.getByText('Notes here.')).toBeInTheDocument(); | ||
|
|
||
| // Comments section | ||
| expect(screen.getByText('@commenter')).toBeInTheDocument(); | ||
| expect(screen.getByText('I will take a look.')).toBeInTheDocument(); | ||
|
|
||
| // Issue Body | ||
| expect( | ||
| screen.getByText('Please fix the styled buttons on the home screen.'), | ||
| ).toBeInTheDocument(); | ||
| }); | ||
| }); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,146 @@ | ||
| import { render, screen, fireEvent } from '@testing-library/react'; | ||
| import { IssueList } from './IssueList'; | ||
| import { describe, it, expect, vi } from 'vitest'; | ||
| import type { RankedIssue } from '../../lib/types'; | ||
| import React from 'react'; | ||
|
|
||
| const mockIssues: RankedIssue[] = [ | ||
| { | ||
| number: 1, | ||
| title: 'Bug in routing', | ||
| body: null, | ||
| updated_at: new Date().toISOString(), | ||
| score: 80, | ||
| user: { login: 'coder1', avatar_url: '', html_url: '' }, | ||
| labels: [{ name: 'bug', color: 'red' }], | ||
| assignees: [], | ||
| comments_count: 0, | ||
| created_at: new Date().toISOString(), | ||
| html_url: '', | ||
| state: 'open', | ||
| }, | ||
| { | ||
| number: 2, | ||
| title: 'Style updates for login page', | ||
| body: null, | ||
| updated_at: new Date().toISOString(), | ||
| score: 60, | ||
| user: { login: 'designer1', avatar_url: '', html_url: '' }, | ||
| labels: [{ name: 'design', color: 'blue' }], | ||
| assignees: [], | ||
| comments_count: 0, | ||
| created_at: new Date().toISOString(), | ||
| html_url: '', | ||
| state: 'open', | ||
| }, | ||
| ]; | ||
|
|
||
| describe('IssueList component', () => { | ||
| it('renders issues correctly', () => { | ||
| render( | ||
| <IssueList | ||
| issues={mockIssues} | ||
| selectedId={1} | ||
| searchQuery="" | ||
| onSearchChange={vi.fn()} | ||
| onSelect={vi.fn()} | ||
| selectedIndex={0} | ||
| />, | ||
| ); | ||
|
|
||
| expect(screen.getByText('Bug in routing')).toBeInTheDocument(); | ||
| expect(screen.getByText('Style updates for login page')).toBeInTheDocument(); | ||
| expect(screen.getByText('2 items')).toBeInTheDocument(); | ||
| }); | ||
|
|
||
| it('triggers onSearchChange when typing in search input', () => { | ||
| const onSearchChange = vi.fn(); | ||
| render( | ||
| <IssueList | ||
| issues={mockIssues} | ||
| selectedId={1} | ||
| searchQuery="" | ||
| onSearchChange={onSearchChange} | ||
| onSelect={vi.fn()} | ||
| selectedIndex={0} | ||
| />, | ||
| ); | ||
|
|
||
| const input = screen.getByPlaceholderText(/Search issues.../); | ||
| fireEvent.change(input, { target: { value: 'routing' } }); | ||
| expect(onSearchChange).toHaveBeenCalledWith('routing'); | ||
| }); | ||
|
|
||
| it('filters issues based on searchQuery prop', () => { | ||
| render( | ||
| <IssueList | ||
| issues={mockIssues} | ||
| selectedId={1} | ||
| searchQuery="routing" | ||
| onSearchChange={vi.fn()} | ||
| onSelect={vi.fn()} | ||
| selectedIndex={0} | ||
| />, | ||
| ); | ||
|
|
||
| expect(screen.getByText('Bug in routing')).toBeInTheDocument(); | ||
| expect(screen.queryByText('Style updates for login page')).not.toBeInTheDocument(); | ||
| expect(screen.getByText('1 items')).toBeInTheDocument(); | ||
| }); | ||
|
|
||
| it('triggers onSelect when an issue item is clicked', () => { | ||
| const onSelect = vi.fn(); | ||
| render( | ||
| <IssueList | ||
| issues={mockIssues} | ||
| selectedId={1} | ||
| searchQuery="" | ||
| onSearchChange={vi.fn()} | ||
| onSelect={onSelect} | ||
| selectedIndex={0} | ||
| />, | ||
| ); | ||
|
|
||
| fireEvent.click(screen.getByText('Style updates for login page')); | ||
| expect(onSelect).toHaveBeenCalledWith(2); | ||
| }); | ||
|
|
||
| it('shows no issues found message when filtered list is empty', () => { | ||
| render( | ||
| <IssueList | ||
| issues={mockIssues} | ||
| selectedId={1} | ||
| searchQuery="xyz" | ||
| onSearchChange={vi.fn()} | ||
| onSelect={vi.fn()} | ||
| selectedIndex={-1} | ||
| />, | ||
| ); | ||
|
|
||
| expect(screen.getByText('No issues match your search.')).toBeInTheDocument(); | ||
| }); | ||
|
|
||
| it('verifies that scrollIntoView is called on the selected item', () => { | ||
| const scrollMock = vi.fn(); | ||
| const originalGetElementById = document.getElementById; | ||
| document.getElementById = vi.fn().mockReturnValue({ | ||
| scrollIntoView: scrollMock, | ||
| }); | ||
|
|
||
| render( | ||
| <IssueList | ||
| issues={mockIssues} | ||
| selectedId={1} | ||
| searchQuery="" | ||
| onSearchChange={vi.fn()} | ||
| onSelect={vi.fn()} | ||
| selectedIndex={0} | ||
| />, | ||
| ); | ||
|
|
||
| expect(document.getElementById).toHaveBeenCalledWith('issue-0'); | ||
| expect(scrollMock).toHaveBeenCalledWith({ block: 'nearest', behavior: 'smooth' }); | ||
|
|
||
| document.getElementById = originalGetElementById; | ||
| }); | ||
| }); | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,73 @@ | ||
| import { render, screen, fireEvent } from '@testing-library/react'; | ||
| import { IssueListItem } from './IssueListItem'; | ||
| import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'; | ||
| import type { RankedIssue } from '../../lib/types'; | ||
| import React from 'react'; | ||
|
|
||
| const getMockIssue = (): RankedIssue => ({ | ||
| number: 101, | ||
| title: 'Optimize database queries', | ||
| body: null, | ||
| updated_at: new Date(Date.now() - 3600000).toISOString(), // 1 hour ago | ||
| score: 95, | ||
| user: { login: 'octocat', avatar_url: '', html_url: '' }, | ||
| labels: [], | ||
| assignees: [], | ||
| comments_count: 0, | ||
| created_at: new Date(Date.now() - 7200000).toISOString(), | ||
| html_url: '', | ||
| state: 'open', | ||
| }); | ||
|
|
||
| describe('IssueListItem component', () => { | ||
| beforeEach(() => { | ||
| vi.useFakeTimers(); | ||
| vi.setSystemTime(new Date('2026-05-18T12:00:00Z')); | ||
| }); | ||
|
|
||
| afterEach(() => { | ||
| vi.useRealTimers(); | ||
| }); | ||
|
|
||
| it('renders standard fields correctly', () => { | ||
| const onClick = vi.fn(); | ||
| render(<IssueListItem issue={getMockIssue()} rank={1} isSelected={false} onClick={onClick} />); | ||
|
|
||
| expect(screen.getByText('1.')).toBeInTheDocument(); | ||
| expect(screen.getByText('#101')).toBeInTheDocument(); | ||
| expect(screen.getByText('Optimize database queries')).toBeInTheDocument(); | ||
| expect(screen.getByText('[95]')).toBeInTheDocument(); | ||
| expect(screen.getByText('1h ago')).toBeInTheDocument(); | ||
|
Aarya1402 marked this conversation as resolved.
|
||
| }); | ||
|
|
||
| it('triggers onClick when clicked', () => { | ||
| const onClick = vi.fn(); | ||
| render(<IssueListItem issue={getMockIssue()} rank={1} isSelected={false} onClick={onClick} />); | ||
|
|
||
| fireEvent.click(screen.getByText('Optimize database queries')); | ||
| expect(onClick).toHaveBeenCalled(); | ||
| }); | ||
|
|
||
| it('renders status prefix tag when analysis exists', () => { | ||
| const issueWithAnalysis: RankedIssue = { | ||
| ...getMockIssue(), | ||
| analysis: { | ||
| summary: 'Discussion required', | ||
| status: 'discussion', | ||
| progress_estimate: 'not_started', | ||
| is_actionable_code_change: false, | ||
| not_mergeable_reason: null, | ||
| complexity: 1, | ||
| skills_required: [], | ||
| newcomer_friendliness: 5, | ||
| doability_score: 50, | ||
| analysis_notes: '', | ||
| }, | ||
| }; | ||
|
|
||
| render( | ||
| <IssueListItem issue={issueWithAnalysis} rank={1} isSelected={false} onClick={vi.fn()} />, | ||
| ); | ||
| expect(screen.getByText('[DISCUSSION]')).toBeInTheDocument(); | ||
| }); | ||
| }); | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,60 @@ | ||
| import { render, screen } from '@testing-library/react'; | ||
| import { IssueMetadata } from './IssueMetadata'; | ||
| import { describe, it, expect } from 'vitest'; | ||
| import type { AnalysisResult } from '../../lib/types'; | ||
| import React from 'react'; | ||
|
|
||
| const mockAnalysis: AnalysisResult = { | ||
| summary: 'This is a summary', | ||
| status: 'active', | ||
| progress_estimate: 'early', | ||
| is_actionable_code_change: true, | ||
| not_mergeable_reason: null, | ||
| complexity: 3, | ||
| skills_required: ['React', 'TypeScript'], | ||
| newcomer_friendliness: 4, | ||
| doability_score: 80, | ||
| analysis_notes: 'Some notes', | ||
| }; | ||
|
|
||
| describe('IssueMetadata component', () => { | ||
| it('renders all analysis metrics correctly', () => { | ||
| render(<IssueMetadata analysis={mockAnalysis} />); | ||
|
|
||
| expect(screen.getByText('Doability')).toBeInTheDocument(); | ||
| expect(screen.getByText('80/100')).toBeInTheDocument(); | ||
|
|
||
| expect(screen.getByText('Status')).toBeInTheDocument(); | ||
| expect(screen.getByText('Active')).toBeInTheDocument(); | ||
|
|
||
| expect(screen.getByText('Complexity')).toBeInTheDocument(); | ||
| expect(screen.getByText(/Moderate/)).toBeInTheDocument(); | ||
|
|
||
| expect(screen.getByText('Friendliness')).toBeInTheDocument(); | ||
| expect(screen.getByText(/Beginner Friendly/)).toBeInTheDocument(); | ||
|
|
||
| expect(screen.getByText('React')).toBeInTheDocument(); | ||
| expect(screen.getByText('TypeScript')).toBeInTheDocument(); | ||
| }); | ||
|
|
||
| it('renders merge blocker when not_mergeable_reason is provided', () => { | ||
| const analysisWithBlocker: AnalysisResult = { | ||
| ...mockAnalysis, | ||
| not_mergeable_reason: 'Missing details', | ||
| }; | ||
| render(<IssueMetadata analysis={analysisWithBlocker} />); | ||
|
|
||
| expect(screen.getByText('Blocker')).toBeInTheDocument(); | ||
| expect(screen.getByText('Missing details')).toBeInTheDocument(); | ||
| }); | ||
|
|
||
| it('renders "none specified" when skills_required is empty', () => { | ||
| const analysisNoSkills: AnalysisResult = { | ||
| ...mockAnalysis, | ||
| skills_required: [], | ||
| }; | ||
| render(<IssueMetadata analysis={analysisNoSkills} />); | ||
|
|
||
| expect(screen.getByText('none specified')).toBeInTheDocument(); | ||
| }); | ||
| }); |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.