Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,18 @@
},
"devDependencies": {
"@eslint/js": "^10.0.1",
"@testing-library/jest-dom": "^6.9.1",
"@testing-library/react": "^16.3.2",
"@testing-library/user-event": "^14.6.1",
"@types/jsdom": "^21.1.7",
"@types/react": "^19.2.14",
"@types/react-dom": "^19.2.3",
"eslint": "^10.2.1",
"eslint-plugin-react-hooks": "^7.1.1",
"eslint-plugin-react-refresh": "^0.5.2",
"globals": "^17.5.0",
"husky": "^9.1.7",
"jsdom": "^26.0.0",
"lint-staged": "^16.4.0",
"prettier": "^3.8.3",
"typescript-eslint": "^8.58.2",
Expand Down
40 changes: 40 additions & 0 deletions src/components/terminal/TerminalInput.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { render, screen, fireEvent } from '@testing-library/react';
import { TerminalInput } from './TerminalInput';
import { describe, it, expect, vi } from 'vitest';
import React from 'react';

describe('TerminalInput component', () => {
Comment thread
Aarya1402 marked this conversation as resolved.
it('renders correctly', () => {
const onChange = vi.fn();
const onSubmit = vi.fn();
render(<TerminalInput value="" onChange={onChange} onSubmit={onSubmit} />);
expect(screen.getByPlaceholderText('Type here...')).toBeInTheDocument();
});

it('calls onChange when typing', () => {
const onChange = vi.fn();
const onSubmit = vi.fn();
render(<TerminalInput value="" onChange={onChange} onSubmit={onSubmit} />);
const input = screen.getByPlaceholderText('Type here...');
fireEvent.change(input, { target: { value: 'hello' } });
expect(onChange).toHaveBeenCalledWith('hello');
});

it('calls onSubmit when Enter is pressed', () => {
const onChange = vi.fn();
const onSubmit = vi.fn();
render(<TerminalInput value="test" onChange={onChange} onSubmit={onSubmit} />);
const input = screen.getByPlaceholderText('Type here...');
fireEvent.keyDown(input, { key: 'Enter', code: 'Enter' });
expect(onSubmit).toHaveBeenCalled();
});

it('clears input when Escape is pressed', () => {
const onChange = vi.fn();
const onSubmit = vi.fn();
render(<TerminalInput value="test" onChange={onChange} onSubmit={onSubmit} />);
const input = screen.getByPlaceholderText('Type here...');
fireEvent.keyDown(input, { key: 'Escape', code: 'Escape' });
expect(onChange).toHaveBeenCalledWith('');
});
Comment thread
Aarya1402 marked this conversation as resolved.
});
16 changes: 16 additions & 0 deletions src/components/ui/Button.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { render, screen } from '@testing-library/react';
import { Button } from './Button';
import { describe, it, expect } from 'vitest';

describe('Button component', () => {
it('renders children correctly', () => {
render(<Button>Click Me</Button>);
expect(screen.getByText('Click Me')).toBeInTheDocument();
});

it('shows loading state when loading prop is true', () => {
render(<Button loading>Submit</Button>);
expect(screen.getByText('⏳')).toBeInTheDocument();
expect(screen.getByRole('button')).toBeDisabled();
});
});
23 changes: 23 additions & 0 deletions src/components/ui/Input.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { render, screen } from '@testing-library/react';
import { Input } from './Input';
import { describe, it, expect } from 'vitest';
import React from 'react';

describe('Input component', () => {
it('renders correctly', () => {
render(<Input placeholder="Enter text" />);
expect(screen.getByPlaceholderText('Enter text')).toBeInTheDocument();
});

it('passes ref correctly', () => {
const ref = React.createRef<HTMLInputElement>();
render(<Input ref={ref} />);
expect(ref.current).toBeInstanceOf(HTMLInputElement);
});

it('applies error styles when hasError is true', () => {
render(<Input hasError data-testid="error-input" />);
const input = screen.getByTestId('error-input');
expect(input.style.border).toContain('var(--status-error)');
});
});
25 changes: 25 additions & 0 deletions src/components/ui/MarkdownRenderer.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { render, screen } from '@testing-library/react';
import { MarkdownRenderer } from './MarkdownRenderer';
import { describe, it, expect } from 'vitest';
import React from 'react';

describe('MarkdownRenderer component', () => {
it('renders markdown content correctly', () => {
render(<MarkdownRenderer content="# Hello World" />);
// Testing specific output depends on react-markdown, we just test if the component renders the text
expect(screen.getByText('Hello World')).toBeInTheDocument();
});

it('renders code blocks correctly', () => {
render(<MarkdownRenderer content="`inline code`" />);
expect(screen.getByText('inline code')).toBeInTheDocument();
expect(screen.getByText('inline code').tagName).toBe('CODE');
});

it('renders links correctly', () => {
render(<MarkdownRenderer content="[GitHub](https://github.com)" />);
const link = screen.getByRole('link', { name: 'GitHub' });
expect(link).toBeInTheDocument();
expect(link).toHaveAttribute('href', 'https://github.com');
});
});
25 changes: 25 additions & 0 deletions src/components/ui/Panel.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { render, screen } from '@testing-library/react';
import { Panel } from './Panel';
import { describe, it, expect } from 'vitest';
import React from 'react';

describe('Panel component', () => {
it('renders children correctly', () => {
render(<Panel>Panel Content</Panel>);
expect(screen.getByText('Panel Content')).toBeInTheDocument();
});

it('renders title when provided', () => {
render(<Panel title="Test Title">Content</Panel>);
expect(screen.getByText('[ Test Title ]')).toBeInTheDocument();
});

it('renders headerRight when provided', () => {
render(
<Panel title="Title" headerRight={<button>Action</button>}>
Content
</Panel>,
);
expect(screen.getByRole('button', { name: 'Action' })).toBeInTheDocument();
});
});
35 changes: 35 additions & 0 deletions src/components/ui/ProgressBar.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { render, screen } from '@testing-library/react';
import { ProgressBar } from './ProgressBar';
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
import React from 'react';

describe('ProgressBar component', () => {
beforeEach(() => {
vi.useFakeTimers();
});

afterEach(() => {
vi.useRealTimers();
});

it('renders correctly with current and total', () => {
render(<ProgressBar current={5} total={10} />);
expect(screen.getByText(/5\/10 \(50%\)/)).toBeInTheDocument();
});

it('renders label when provided', () => {
render(<ProgressBar current={5} total={10} label="Processing" />);
expect(screen.getByText('Processing')).toBeInTheDocument();
});

it('hides count when showCount is false', () => {
render(<ProgressBar current={5} total={10} showCount={false} />);
expect(screen.queryByText(/5\/10 \(50%\)/)).not.toBeInTheDocument();
});

it('shows ETA when startTime is provided', () => {
const startTime = Date.now();
render(<ProgressBar current={5} total={10} startTime={startTime} />);
expect(screen.getByText(/ETA:/)).toBeInTheDocument();
});
Comment thread
Aarya1402 marked this conversation as resolved.
});
23 changes: 23 additions & 0 deletions src/components/ui/ScrollArea.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { render, screen } from '@testing-library/react';
import { ScrollArea } from './ScrollArea';
import { describe, it, expect } from 'vitest';
import React from 'react';

describe('ScrollArea component', () => {
it('renders children correctly', () => {
render(<ScrollArea>Scrollable Content</ScrollArea>);
expect(screen.getByText('Scrollable Content')).toBeInTheDocument();
});

it('applies maxHeight when provided', () => {
render(<ScrollArea maxHeight="200px">Scroll Area Content</ScrollArea>);
const element = screen.getByText('Scroll Area Content');
expect(element.style.maxHeight).toBe('200px');
});

it('passes innerRef correctly', () => {
const ref = React.createRef<HTMLDivElement>();
render(<ScrollArea innerRef={ref}>Content</ScrollArea>);
expect(ref.current).toBeInstanceOf(HTMLDivElement);
});
});
1 change: 1 addition & 0 deletions src/test/setup.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
import '@testing-library/jest-dom';
1 change: 1 addition & 0 deletions vite-env.d.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
/// <reference types="vite/client" />
/// <reference types="@testing-library/jest-dom" />

interface ImportMetaEnv {
readonly VITE_GITHUB_TOKEN: string;
Expand Down
7 changes: 6 additions & 1 deletion vite.config.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { defineConfig } from 'vite';
import { defineConfig } from 'vitest/config';
import react from '@vitejs/plugin-react';
import tailwindcss from '@tailwindcss/vite';
import path from 'path';
Expand All @@ -14,4 +14,9 @@ export default defineConfig({
port: 5173,
open: true,
},
test: {
environment: 'jsdom',
setupFiles: ['./src/test/setup.ts'],
globals: true,
},
});
Loading