Skip to content
Merged
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
14 changes: 7 additions & 7 deletions app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,23 +6,23 @@
"author": "Promptfoo Team",
"license": "MIT",
"dependencies": {
"react": "^19.2.0",
"react-dom": "^19.2.0"
"react": "^19.2.1",
"react-dom": "^19.2.1"
},
"devDependencies": {
"@testing-library/dom": "^10.4.1",
"@testing-library/jest-dom": "^6.9.1",
"@testing-library/react": "^16.3.0",
"@testing-library/user-event": "^14.6.1",
"@types/node": "^24.10.1",
"@types/react": "^19.2.2",
"@types/react": "^19.2.7",
"@types/react-dom": "^19.2.3",
"@vitejs/plugin-react": "^5.1.0",
"@vitejs/plugin-react": "^5.1.1",
"@vitest/ui": "^4.0.13",
"jsdom": "^27.2.0",
"typescript": "^5.9.3",
"vite": "^7.2.2",
"vitest": "^4.0.7"
"vite": "^7.2.6",
"vitest": "^4.0.15"
},
"scripts": {
"dev": "vite",
Expand All @@ -37,6 +37,6 @@
"format:check": "prettier --check ."
},
"engines": {
"node": ">=20"
"node": ">=22"
}
}
162 changes: 112 additions & 50 deletions app/src/App.integration.test.tsx
Original file line number Diff line number Diff line change
@@ -1,95 +1,157 @@
import React from 'react';
import { render } from '@testing-library/react';
import { vi } from 'vitest';
import { render, screen, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { vi, beforeEach, afterEach, describe, it, expect } from 'vitest';
import App from './App';

// Mock fetch
global.fetch = vi.fn(() =>
Promise.resolve({
json: () => Promise.resolve([]),
} as Response)
);
const mockEvaluations = [
{
id: 1,
name: 'Test Eval 1',
results: [
{
id: 1,
evalId: 1,
input: 'test input',
output: 'test output',
passed: true,
},
{
id: 2,
evalId: 1,
input: 'fail input',
output: 'fail output',
passed: false,
},
],
},
{
id: 2,
name: 'Test Eval 2',
results: [
{ id: 3, evalId: 2, input: 'input 2', output: 'output 2', passed: true },
],
},
];

describe('App Integration Tests', () => {
beforeEach(() => {
vi.mocked(fetch).mockClear();
vi.stubGlobal('fetch', vi.fn());
});

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

describe('Data fetching', () => {
it('should fetch evaluations on mount', async () => {
// TODO: Implement test
it('should fetch evaluations on mount and display them', async () => {
vi.mocked(fetch).mockResolvedValueOnce({
json: () => Promise.resolve(mockEvaluations),
} as Response);

render(<App />);
expect(true).toBe(true);

await waitFor(() => {
expect(
screen.getByRole('heading', { name: 'Test Eval 1' })
).toBeInTheDocument();
});

expect(fetch).toHaveBeenCalledWith('http://localhost:8085/evals');
});

it('should handle fetch errors gracefully', async () => {
// TODO: Implement test
vi.mocked(fetch).mockRejectedValueOnce(new Error('Network error'));

render(<App />);
expect(true).toBe(true);

// App should still render without crashing
expect(screen.getByText(/Evaluation Results/i)).toBeInTheDocument();
});

it('should display loading state while fetching', async () => {
// TODO: Implement test
it('should display first evaluation by default when data loads', async () => {
vi.mocked(fetch).mockResolvedValueOnce({
json: () => Promise.resolve(mockEvaluations),
} as Response);

render(<App />);
expect(true).toBe(true);

await waitFor(() => {
expect(
screen.getByRole('heading', { name: 'Test Eval 1' })
).toBeInTheDocument();
});
});
});

describe('Evaluation selection', () => {
it('should select first evaluation by default', async () => {
// TODO: Implement test
render(<App />);
expect(true).toBe(true);
});

it('should change selected evaluation on dropdown change', async () => {
// TODO: Implement test
render(<App />);
expect(true).toBe(true);
});
const user = userEvent.setup();
vi.mocked(fetch).mockResolvedValueOnce({
json: () => Promise.resolve(mockEvaluations),
} as Response);

it('should display selected evaluation results', async () => {
// TODO: Implement test
render(<App />);
expect(true).toBe(true);

await waitFor(() => {
expect(
screen.getByRole('heading', { name: 'Test Eval 1' })
).toBeInTheDocument();
});

const select = screen.getByRole('combobox');
await user.selectOptions(select, '2');

expect(
screen.getByRole('heading', { name: 'Test Eval 2' })
).toBeInTheDocument();
});
});

describe('Results display', () => {
it('should show passed results with correct styling', async () => {
// TODO: Implement test
vi.mocked(fetch).mockResolvedValueOnce({
json: () => Promise.resolve(mockEvaluations),
} as Response);

render(<App />);
expect(true).toBe(true);

await waitFor(() => {
expect(screen.getByText('Passed')).toBeInTheDocument();
});

const passedElement = screen.getByText('Passed');
expect(passedElement).toHaveClass('passed');
});

it('should show failed results with correct styling', async () => {
// TODO: Implement test
render(<App />);
expect(true).toBe(true);
});
vi.mocked(fetch).mockResolvedValueOnce({
json: () => Promise.resolve(mockEvaluations),
} as Response);

it('should handle empty results', async () => {
// TODO: Implement test
render(<App />);
expect(true).toBe(true);
});
});

describe('UI interactions', () => {
it('should be keyboard accessible', async () => {
// TODO: Implement test
render(<App />);
expect(true).toBe(true);
await waitFor(() => {
expect(screen.getByText('Failed')).toBeInTheDocument();
});

const failedElement = screen.getByText('Failed');
expect(failedElement).toHaveClass('failed');
});

it('should have proper ARIA labels', async () => {
// TODO: Implement test
it('should handle empty evaluations list', async () => {
vi.mocked(fetch).mockResolvedValueOnce({
json: () => Promise.resolve([]),
} as Response);

render(<App />);
expect(true).toBe(true);

// Wait for fetch to complete
await waitFor(() => {
expect(fetch).toHaveBeenCalled();
});

// Should show the placeholder option
expect(screen.getByText(/Choose an evaluation.../i)).toBeInTheDocument();
});
});
});
1 change: 0 additions & 1 deletion app/src/App.test.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import React from 'react';
import { render, screen } from '@testing-library/react';
import App from './App';

Expand Down
41 changes: 0 additions & 41 deletions app/src/components/EvaluationDropdown.test.tsx

This file was deleted.

44 changes: 0 additions & 44 deletions app/src/components/ResultsTable.test.tsx

This file was deleted.

50 changes: 0 additions & 50 deletions app/src/hooks/useEvaluations.test.ts

This file was deleted.

Loading