forked from anti-work/shortest
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
3 changed files
with
339 additions
and
0 deletions.
There are no files selected for viewing
This file contains 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,84 @@ | ||
import React from 'react'; | ||
import { describe, it, expect, vi } from 'vitest'; | ||
import { render, screen, fireEvent } from '@testing-library/react'; | ||
import DashboardPage from './page'; | ||
import { useToast } from '@/hooks/use-toast'; | ||
import { getConnectedProjects } from '@/lib/github'; | ||
|
||
vi.mock('@/hooks/use-toast', () => ({ | ||
useToast: vi.fn(() => ({ | ||
toast: vi.fn(), | ||
})), | ||
})); | ||
|
||
vi.mock('@/lib/github', () => ({ | ||
getConnectedProjects: vi.fn(), | ||
})); | ||
|
||
vi.mock('./project-card', () => ({ | ||
ProjectCard: ({ project }) => <div data-testid={`project-card-${project.id}`}>{project.name}</div>, | ||
})); | ||
|
||
vi.mock('./repo-selector', () => ({ | ||
RepoSelector: ({ onRepoSelected, onClose }) => ( | ||
<div data-testid='repo-selector'> | ||
<button onClick={() => onRepoSelected({ id: 999, name: 'New Repo' })}>Select Repo</button> | ||
<button onClick={onClose}>Close</button> | ||
</div> | ||
), | ||
})); | ||
|
||
describe('DashboardPage', () => { | ||
it('renders loading state', () => { | ||
vi.mocked(getConnectedProjects).mockReturnValue(new Promise(() => {})); | ||
render(<DashboardPage />); | ||
expect(screen.getByText('Loading...')).toBeInTheDocument(); | ||
}); | ||
|
||
it('renders error state', async () => { | ||
vi.mocked(getConnectedProjects).mockRejectedValue(new Error('Test error')); | ||
render(<DashboardPage />); | ||
await screen.findByText('Failed to fetch connected projects. Please try again.'); | ||
}); | ||
|
||
it('renders connected projects', async () => { | ||
const mockProjects = [ | ||
{ id: 1, name: 'Project 1' }, | ||
{ id: 2, name: 'Project 2' }, | ||
]; | ||
vi.mocked(getConnectedProjects).mockResolvedValue(mockProjects); | ||
render(<DashboardPage />); | ||
await screen.findByText('Connected Projects'); | ||
expect(screen.getByTestId('project-card-1')).toBeInTheDocument(); | ||
expect(screen.getByTestId('project-card-2')).toBeInTheDocument(); | ||
}); | ||
|
||
it('opens and closes repo selector', async () => { | ||
vi.mocked(getConnectedProjects).mockResolvedValue([]); | ||
render(<DashboardPage />); | ||
await screen.findByText('Connected Projects'); | ||
|
||
fireEvent.click(screen.getByText('Add New Repository')); | ||
expect(screen.getByTestId('repo-selector')).toBeInTheDocument(); | ||
|
||
fireEvent.click(screen.getByText('Close')); | ||
expect(screen.queryByTestId('repo-selector')).not.toBeInTheDocument(); | ||
}); | ||
|
||
it('adds a new repository', async () => { | ||
const mockProjects = [{ id: 1, name: 'Project 1' }]; | ||
vi.mocked(getConnectedProjects).mockResolvedValue(mockProjects); | ||
const { toast } = useToast(); | ||
render(<DashboardPage />); | ||
await screen.findByText('Connected Projects'); | ||
|
||
fireEvent.click(screen.getByText('Add New Repository')); | ||
fireEvent.click(screen.getByText('Select Repo')); | ||
|
||
expect(screen.getByTestId('project-card-999')).toBeInTheDocument(); | ||
expect(toast).toHaveBeenCalledWith({ | ||
title: 'Success', | ||
description: 'New repository connected successfully.', | ||
}); | ||
}); | ||
}); |
This file contains 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,110 @@ | ||
import React from 'react'; | ||
import { describe, it, expect, vi } from 'vitest'; | ||
import { render, screen, fireEvent, waitFor } from '@testing-library/react'; | ||
import ProjectPage from './page'; | ||
import { useParams } from 'next/navigation'; | ||
import { getProjectPullRequests, getProjectDetails, updateProjectSettings } from '@/lib/github'; | ||
import { useToast } from '@/hooks/use-toast'; | ||
|
||
vi.mock('next/navigation', () => ({ | ||
useParams: vi.fn(), | ||
})); | ||
|
||
vi.mock('@/lib/github', () => ({ | ||
getProjectPullRequests: vi.fn(), | ||
getProjectDetails: vi.fn(), | ||
updateProjectSettings: vi.fn(), | ||
})); | ||
|
||
vi.mock('@/hooks/use-toast', () => ({ | ||
useToast: vi.fn(() => ({ | ||
toast: vi.fn(), | ||
})), | ||
})); | ||
|
||
vi.mock('../../pull-request', () => ({ | ||
PullRequestItem: ({ pullRequest }) => <div data-testid={`pr-${pullRequest.id}`}>{pullRequest.title}</div>, | ||
})); | ||
|
||
describe('ProjectPage', () => { | ||
beforeEach(() => { | ||
vi.mocked(useParams).mockReturnValue({ id: '1' }); | ||
vi.mocked(getProjectPullRequests).mockResolvedValue([]); | ||
vi.mocked(getProjectDetails).mockResolvedValue({ | ||
id: 1, | ||
name: 'Test Project', | ||
environments: [], | ||
}); | ||
}); | ||
|
||
it('renders loading state', () => { | ||
render(<ProjectPage />); | ||
expect(screen.getByText('Loading...')).toBeInTheDocument(); | ||
}); | ||
|
||
it('renders project details and pull requests', async () => { | ||
vi.mocked(getProjectPullRequests).mockResolvedValue([ | ||
{ id: 1, title: 'PR 1' }, | ||
{ id: 2, title: 'PR 2' }, | ||
]); | ||
render(<ProjectPage />); | ||
await screen.findByText('Test Project'); | ||
expect(screen.getByTestId('pr-1')).toBeInTheDocument(); | ||
expect(screen.getByTestId('pr-2')).toBeInTheDocument(); | ||
}); | ||
|
||
it('switches between tabs', async () => { | ||
render(<ProjectPage />); | ||
await screen.findByText('Test Project'); | ||
|
||
fireEvent.click(screen.getByText('Project Settings')); | ||
expect(screen.getByText('Project Environments')).toBeInTheDocument(); | ||
|
||
fireEvent.click(screen.getByText('Open PRs')); | ||
expect(screen.getByText('No open pull requests found for this project.')).toBeInTheDocument(); | ||
}); | ||
|
||
it('adds and updates environments', async () => { | ||
render(<ProjectPage />); | ||
await screen.findByText('Test Project'); | ||
fireEvent.click(screen.getByText('Project Settings')); | ||
|
||
fireEvent.click(screen.getByText('Add Environment')); | ||
const envInputs = screen.getAllByPlaceholderText('Environment Name'); | ||
fireEvent.change(envInputs[envInputs.length - 1], { target: { value: 'New Env' } }); | ||
|
||
fireEvent.click(screen.getByText('Add Test Account')); | ||
const usernameInputs = screen.getAllByPlaceholderText('Username'); | ||
fireEvent.change(usernameInputs[usernameInputs.length - 1], { target: { value: 'testuser' } }); | ||
|
||
fireEvent.click(screen.getByText('Save Settings')); | ||
await waitFor(() => { | ||
expect(updateProjectSettings).toHaveBeenCalledWith(1, expect.objectContaining({ | ||
environments: [expect.objectContaining({ name: 'New Env' })], | ||
})); | ||
}); | ||
|
||
const { toast } = useToast(); | ||
expect(toast).toHaveBeenCalledWith({ | ||
title: 'Settings saved', | ||
description: 'Project settings have been updated successfully.', | ||
}); | ||
}); | ||
|
||
it('handles errors when saving settings', async () => { | ||
vi.mocked(updateProjectSettings).mockRejectedValue(new Error('Test error')); | ||
render(<ProjectPage />); | ||
await screen.findByText('Test Project'); | ||
fireEvent.click(screen.getByText('Project Settings')); | ||
fireEvent.click(screen.getByText('Save Settings')); | ||
|
||
const { toast } = useToast(); | ||
await waitFor(() => { | ||
expect(toast).toHaveBeenCalledWith({ | ||
title: 'Error', | ||
description: 'Failed to save project settings. Please try again.', | ||
variant: 'destructive', | ||
}); | ||
}); | ||
}); | ||
}); |
This file contains 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,145 @@ | ||
import React from 'react'; | ||
import { render, screen, fireEvent, waitFor } from '@testing-library/react'; | ||
import { PullRequestItem } from './pull-request'; | ||
import { vi, describe, it, expect, beforeEach } from 'vitest'; | ||
import { PullRequest } from './types'; | ||
import useSWR from 'swr'; | ||
import { fetchBuildStatus, generateUITestScenarios } from '@/lib/github'; | ||
import { experimental_useObject as useObject } from 'ai/react'; | ||
import { act } from 'react'; | ||
|
||
vi.mock('@/lib/github', async () => { | ||
const actual = await vi.importActual('@/lib/github'); | ||
return { | ||
...(actual as object), | ||
getPullRequestInfo: vi.fn(), | ||
commitChangesToPullRequest: vi.fn(), | ||
getFailingTests: vi.fn(), | ||
fetchBuildStatus: vi.fn(), | ||
getLatestRunId: vi.fn(), | ||
generateUITestScenarios: vi.fn(), | ||
}; | ||
}); | ||
|
||
vi.mock('@/hooks/use-toast', () => ({ | ||
useToast: vi.fn(() => ({ | ||
toast: vi.fn(), | ||
})), | ||
})); | ||
|
||
vi.mock('next/link', () => ({ | ||
default: ({ | ||
children, | ||
href, | ||
}: { | ||
children: React.ReactNode; | ||
href: string; | ||
}) => <a href={href}>{children}</a>, | ||
})); | ||
|
||
vi.mock('react-diff-viewer', () => ({ | ||
default: () => <div data-testid='react-diff-viewer'>Mocked Diff Viewer</div>, | ||
})); | ||
|
||
vi.mock('swr', () => ({ | ||
default: vi.fn(), | ||
})); | ||
|
||
vi.mock('./log-view', () => ({ | ||
LogView: () => <div data-testid='log-view'>Mocked Log View</div>, | ||
})); | ||
|
||
vi.mock('ai/react', () => ({ | ||
experimental_useObject: vi.fn(), | ||
})); | ||
|
||
describe('PullRequestItem', () => { | ||
const mockPullRequest: PullRequest = { | ||
id: 1, | ||
title: 'Test PR', | ||
number: 123, | ||
buildStatus: 'success', | ||
isDraft: false, | ||
branchName: 'feature-branch', | ||
repository: { | ||
id: 1, | ||
name: 'test-repo', | ||
full_name: 'owner/test-repo', | ||
owner: { | ||
login: 'owner', | ||
}, | ||
}, | ||
}; | ||
|
||
beforeEach(() => { | ||
vi.clearAllMocks(); | ||
global.fetch = vi.fn(); | ||
vi.mocked(useSWR).mockReturnValue({ | ||
data: mockPullRequest, | ||
mutate: vi.fn(), | ||
error: undefined, | ||
isValidating: false, | ||
isLoading: false, | ||
}); | ||
vi.mocked(useObject).mockReturnValue({ | ||
object: null, | ||
submit: vi.fn(), | ||
isLoading: false, | ||
}); | ||
}); | ||
|
||
// ... (previous tests remain unchanged) | ||
|
||
it('generates UI test scenarios', async () => { | ||
const { generateUITestScenarios } = await import('@/lib/github'); | ||
vi.mocked(generateUITestScenarios).mockResolvedValue([ | ||
'Verify login button is clickable', | ||
'Validate form submission', | ||
]); | ||
|
||
render(<PullRequestItem pullRequest={mockPullRequest} />); | ||
|
||
const generateUITestButton = screen.getByText('Generate UI Test'); | ||
fireEvent.click(generateUITestButton); | ||
|
||
await waitFor(() => { | ||
expect(screen.getByText('Verify login button is clickable')).toBeInTheDocument(); | ||
expect(screen.getByText('Validate form submission')).toBeInTheDocument(); | ||
}); | ||
|
||
expect(generateUITestScenarios).toHaveBeenCalledWith(mockPullRequest.id, expect.any(String)); | ||
}); | ||
|
||
it('handles errors when generating UI test scenarios', async () => { | ||
const { generateUITestScenarios } = await import('@/lib/github'); | ||
vi.mocked(generateUITestScenarios).mockRejectedValue(new Error('Test error')); | ||
|
||
const { toast } = await import('@/hooks/use-toast'); | ||
render(<PullRequestItem pullRequest={mockPullRequest} />); | ||
|
||
const generateUITestButton = screen.getByText('Generate UI Test'); | ||
fireEvent.click(generateUITestButton); | ||
|
||
await waitFor(() => { | ||
expect(toast).toHaveBeenCalledWith({ | ||
title: 'Error', | ||
description: 'Failed to generate UI test scenarios. Please try again.', | ||
variant: 'destructive', | ||
}); | ||
}); | ||
}); | ||
|
||
it('changes button text after generating UI test scenarios', async () => { | ||
const { generateUITestScenarios } = await import('@/lib/github'); | ||
vi.mocked(generateUITestScenarios).mockResolvedValue(['Test scenario']); | ||
|
||
render(<PullRequestItem pullRequest={mockPullRequest} />); | ||
|
||
const generateUITestButton = screen.getByText('Generate UI Test'); | ||
fireEvent.click(generateUITestButton); | ||
|
||
await waitFor(() => { | ||
expect(screen.getByText('Execute Tests')).toBeInTheDocument(); | ||
}); | ||
}); | ||
}); |