Spaces:
Sleeping
Sleeping
Commit ·
ebe1c3d
1
Parent(s): a3fb547
test: add frontend test suite with vitest
Browse files- frontend/package-lock.json +0 -0
- frontend/package.json +9 -3
- frontend/src/test/components.test.tsx +52 -0
- frontend/src/test/helpers.test.ts +55 -0
- frontend/src/test/setup.ts +1 -0
- frontend/tsconfig.tsbuildinfo +1 -0
- frontend/vite.config.ts +5 -0
frontend/package-lock.json
CHANGED
|
The diff for this file is too large to render.
See raw diff
|
|
|
frontend/package.json
CHANGED
|
@@ -7,7 +7,9 @@
|
|
| 7 |
"dev": "vite",
|
| 8 |
"build": "tsc -b && vite build",
|
| 9 |
"lint": "eslint .",
|
| 10 |
-
"preview": "vite preview"
|
|
|
|
|
|
|
| 11 |
},
|
| 12 |
"dependencies": {
|
| 13 |
"@tanstack/react-query": "^5.60.0",
|
|
@@ -19,18 +21,22 @@
|
|
| 19 |
},
|
| 20 |
"devDependencies": {
|
| 21 |
"@eslint/js": "^9.13.0",
|
|
|
|
|
|
|
| 22 |
"@types/react": "^18.3.12",
|
| 23 |
"@types/react-dom": "^18.3.1",
|
| 24 |
-
"@vitejs/plugin-react": "^4.
|
| 25 |
"autoprefixer": "^10.4.20",
|
| 26 |
"eslint": "^9.13.0",
|
| 27 |
"eslint-plugin-react-hooks": "^5.0.0",
|
| 28 |
"eslint-plugin-react-refresh": "^0.4.14",
|
| 29 |
"globals": "^15.11.0",
|
|
|
|
| 30 |
"postcss": "^8.4.47",
|
| 31 |
"tailwindcss": "^3.4.14",
|
| 32 |
"typescript": "~5.6.2",
|
| 33 |
"typescript-eslint": "^8.11.0",
|
| 34 |
-
"vite": "^5.4.10"
|
|
|
|
| 35 |
}
|
| 36 |
}
|
|
|
|
| 7 |
"dev": "vite",
|
| 8 |
"build": "tsc -b && vite build",
|
| 9 |
"lint": "eslint .",
|
| 10 |
+
"preview": "vite preview",
|
| 11 |
+
"test": "vitest run",
|
| 12 |
+
"test:watch": "vitest"
|
| 13 |
},
|
| 14 |
"dependencies": {
|
| 15 |
"@tanstack/react-query": "^5.60.0",
|
|
|
|
| 21 |
},
|
| 22 |
"devDependencies": {
|
| 23 |
"@eslint/js": "^9.13.0",
|
| 24 |
+
"@testing-library/jest-dom": "^6.9.1",
|
| 25 |
+
"@testing-library/react": "^16.3.2",
|
| 26 |
"@types/react": "^18.3.12",
|
| 27 |
"@types/react-dom": "^18.3.1",
|
| 28 |
+
"@vitejs/plugin-react": "^4.7.0",
|
| 29 |
"autoprefixer": "^10.4.20",
|
| 30 |
"eslint": "^9.13.0",
|
| 31 |
"eslint-plugin-react-hooks": "^5.0.0",
|
| 32 |
"eslint-plugin-react-refresh": "^0.4.14",
|
| 33 |
"globals": "^15.11.0",
|
| 34 |
+
"jsdom": "^29.0.1",
|
| 35 |
"postcss": "^8.4.47",
|
| 36 |
"tailwindcss": "^3.4.14",
|
| 37 |
"typescript": "~5.6.2",
|
| 38 |
"typescript-eslint": "^8.11.0",
|
| 39 |
+
"vite": "^5.4.10",
|
| 40 |
+
"vitest": "^4.1.2"
|
| 41 |
}
|
| 42 |
}
|
frontend/src/test/components.test.tsx
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import { describe, it, expect } from 'vitest';
|
| 2 |
+
import { render, screen } from '@testing-library/react';
|
| 3 |
+
import { Button } from '../components/ui/Button';
|
| 4 |
+
import { Badge } from '../components/ui/Badge';
|
| 5 |
+
import { Card, CardHeader, CardContent } from '../components/ui/Card';
|
| 6 |
+
|
| 7 |
+
describe('UI Components', () => {
|
| 8 |
+
describe('Button', () => {
|
| 9 |
+
it('renders with children', () => {
|
| 10 |
+
render(<Button>Click me</Button>);
|
| 11 |
+
expect(screen.getByText('Click me')).toBeInTheDocument();
|
| 12 |
+
});
|
| 13 |
+
|
| 14 |
+
it('applies variant classes', () => {
|
| 15 |
+
render(<Button variant="primary">Primary</Button>);
|
| 16 |
+
const button = screen.getByText('Primary');
|
| 17 |
+
expect(button).toHaveClass('btn-primary');
|
| 18 |
+
});
|
| 19 |
+
|
| 20 |
+
it('is disabled when disabled prop is true', () => {
|
| 21 |
+
render(<Button disabled>Disabled</Button>);
|
| 22 |
+
const button = screen.getByText('Disabled');
|
| 23 |
+
expect(button).toBeDisabled();
|
| 24 |
+
});
|
| 25 |
+
});
|
| 26 |
+
|
| 27 |
+
describe('Badge', () => {
|
| 28 |
+
it('renders with text', () => {
|
| 29 |
+
render(<Badge>Status</Badge>);
|
| 30 |
+
expect(screen.getByText('Status')).toBeInTheDocument();
|
| 31 |
+
});
|
| 32 |
+
|
| 33 |
+
it('applies success variant classes', () => {
|
| 34 |
+
render(<Badge variant="success">Success</Badge>);
|
| 35 |
+
const badge = screen.getByText('Success');
|
| 36 |
+
expect(badge).toHaveClass('text-green-400');
|
| 37 |
+
});
|
| 38 |
+
});
|
| 39 |
+
|
| 40 |
+
describe('Card', () => {
|
| 41 |
+
it('renders card with header and content', () => {
|
| 42 |
+
render(
|
| 43 |
+
<Card>
|
| 44 |
+
<CardHeader title="Test Card" />
|
| 45 |
+
<CardContent>Card content</CardContent>
|
| 46 |
+
</Card>
|
| 47 |
+
);
|
| 48 |
+
expect(screen.getByText('Test Card')).toBeInTheDocument();
|
| 49 |
+
expect(screen.getByText('Card content')).toBeInTheDocument();
|
| 50 |
+
});
|
| 51 |
+
});
|
| 52 |
+
});
|
frontend/src/test/helpers.test.ts
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import { describe, it, expect } from 'vitest';
|
| 2 |
+
import { formatTimestamp, truncateText, classNames, formatDuration } from '../utils/helpers';
|
| 3 |
+
|
| 4 |
+
describe('helpers', () => {
|
| 5 |
+
describe('formatTimestamp', () => {
|
| 6 |
+
it('formats ISO timestamps', () => {
|
| 7 |
+
const result = formatTimestamp('2024-01-15T10:30:00Z');
|
| 8 |
+
expect(result).toBeDefined();
|
| 9 |
+
expect(typeof result).toBe('string');
|
| 10 |
+
});
|
| 11 |
+
|
| 12 |
+
it('handles invalid dates', () => {
|
| 13 |
+
const result = formatTimestamp('invalid');
|
| 14 |
+
expect(result).toBe('Invalid Date');
|
| 15 |
+
});
|
| 16 |
+
});
|
| 17 |
+
|
| 18 |
+
describe('truncateText', () => {
|
| 19 |
+
it('truncates long strings', () => {
|
| 20 |
+
const result = truncateText('This is a long string', 13);
|
| 21 |
+
expect(result).toBe('This is a ...');
|
| 22 |
+
});
|
| 23 |
+
|
| 24 |
+
it('leaves short strings unchanged', () => {
|
| 25 |
+
const result = truncateText('Short', 10);
|
| 26 |
+
expect(result).toBe('Short');
|
| 27 |
+
});
|
| 28 |
+
});
|
| 29 |
+
|
| 30 |
+
describe('classNames', () => {
|
| 31 |
+
it('joins class names', () => {
|
| 32 |
+
const result = classNames('a', 'b', 'c');
|
| 33 |
+
expect(result).toBe('a b c');
|
| 34 |
+
});
|
| 35 |
+
|
| 36 |
+
it('filters falsy values', () => {
|
| 37 |
+
const result = classNames('a', false, undefined, 'b', null, 'c');
|
| 38 |
+
expect(result).toBe('a b c');
|
| 39 |
+
});
|
| 40 |
+
});
|
| 41 |
+
|
| 42 |
+
describe('formatDuration', () => {
|
| 43 |
+
it('formats milliseconds to seconds', () => {
|
| 44 |
+
expect(formatDuration(45000)).toBe('45s');
|
| 45 |
+
});
|
| 46 |
+
|
| 47 |
+
it('formats minutes and seconds', () => {
|
| 48 |
+
expect(formatDuration(125000)).toBe('2m 5s');
|
| 49 |
+
});
|
| 50 |
+
|
| 51 |
+
it('formats hours', () => {
|
| 52 |
+
expect(formatDuration(3665000)).toBe('1h 1m');
|
| 53 |
+
});
|
| 54 |
+
});
|
| 55 |
+
});
|
frontend/src/test/setup.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
import '@testing-library/jest-dom';
|
frontend/tsconfig.tsbuildinfo
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
{"root":["./src/app.tsx","./src/main.tsx","./src/vite-env.d.ts","./src/api/client.ts","./src/components/actionpanel.tsx","./src/components/agentview.tsx","./src/components/dashboard.tsx","./src/components/episodepanel.tsx","./src/components/memorypanel.tsx","./src/components/observationview.tsx","./src/components/rewardchart.tsx","./src/components/settings.tsx","./src/components/toolregistry.tsx","./src/components/ui/badge.tsx","./src/components/ui/button.tsx","./src/components/ui/card.tsx","./src/components/ui/input.tsx","./src/components/ui/select.tsx","./src/hooks/useagents.ts","./src/hooks/useepisode.ts","./src/hooks/usememory.ts","./src/hooks/usewebsocket.ts","./src/types/index.ts","./src/utils/helpers.ts"],"version":"5.6.3"}
|
frontend/vite.config.ts
CHANGED
|
@@ -22,4 +22,9 @@ export default defineConfig({
|
|
| 22 |
},
|
| 23 |
},
|
| 24 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 25 |
});
|
|
|
|
| 22 |
},
|
| 23 |
},
|
| 24 |
},
|
| 25 |
+
test: {
|
| 26 |
+
globals: true,
|
| 27 |
+
environment: 'jsdom',
|
| 28 |
+
setupFiles: ['./src/test/setup.ts'],
|
| 29 |
+
},
|
| 30 |
});
|