251211:1314 Frontend: reeactor Admin panel
This commit is contained in:
@@ -7,10 +7,11 @@ import { Loader2 } from "lucide-react";
|
||||
|
||||
interface DrawingListProps {
|
||||
type: "CONTRACT" | "SHOP";
|
||||
projectId?: number;
|
||||
}
|
||||
|
||||
export function DrawingList({ type }: DrawingListProps) {
|
||||
const { data: drawings, isLoading, isError } = useDrawings(type, { projectId: 1 });
|
||||
export function DrawingList({ type, projectId }: DrawingListProps) {
|
||||
const { data: drawings, isLoading, isError } = useDrawings(type, { projectId: projectId ?? 1 });
|
||||
|
||||
// Note: The hook handles switching services based on type.
|
||||
// The params { type } might be redundant if getAll doesn't use it, but safe to pass.
|
||||
|
||||
153
frontend/components/ui/__tests__/button.test.tsx
Normal file
153
frontend/components/ui/__tests__/button.test.tsx
Normal file
@@ -0,0 +1,153 @@
|
||||
import { describe, it, expect, vi } from 'vitest';
|
||||
import { render, screen, fireEvent } from '@testing-library/react';
|
||||
import { Button } from '../button';
|
||||
|
||||
describe('Button', () => {
|
||||
describe('rendering', () => {
|
||||
it('should render with default variant and size', () => {
|
||||
render(<Button>Click me</Button>);
|
||||
|
||||
const button = screen.getByRole('button', { name: /click me/i });
|
||||
expect(button).toBeInTheDocument();
|
||||
expect(button).toHaveClass('bg-primary');
|
||||
expect(button).toHaveClass('h-10', 'px-4', 'py-2');
|
||||
});
|
||||
|
||||
it('should render with children text', () => {
|
||||
render(<Button>Submit Form</Button>);
|
||||
|
||||
expect(screen.getByText('Submit Form')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
describe('variants', () => {
|
||||
it('should render destructive variant', () => {
|
||||
render(<Button variant="destructive">Delete</Button>);
|
||||
|
||||
const button = screen.getByRole('button');
|
||||
expect(button).toHaveClass('bg-destructive');
|
||||
});
|
||||
|
||||
it('should render outline variant', () => {
|
||||
render(<Button variant="outline">Cancel</Button>);
|
||||
|
||||
const button = screen.getByRole('button');
|
||||
expect(button).toHaveClass('border', 'border-input');
|
||||
});
|
||||
|
||||
it('should render secondary variant', () => {
|
||||
render(<Button variant="secondary">Secondary</Button>);
|
||||
|
||||
const button = screen.getByRole('button');
|
||||
expect(button).toHaveClass('bg-secondary');
|
||||
});
|
||||
|
||||
it('should render ghost variant', () => {
|
||||
render(<Button variant="ghost">Ghost</Button>);
|
||||
|
||||
const button = screen.getByRole('button');
|
||||
expect(button).toHaveClass('hover:bg-accent');
|
||||
});
|
||||
|
||||
it('should render link variant', () => {
|
||||
render(<Button variant="link">Link</Button>);
|
||||
|
||||
const button = screen.getByRole('button');
|
||||
expect(button).toHaveClass('underline-offset-4');
|
||||
});
|
||||
});
|
||||
|
||||
describe('sizes', () => {
|
||||
it('should render small size', () => {
|
||||
render(<Button size="sm">Small</Button>);
|
||||
|
||||
const button = screen.getByRole('button');
|
||||
expect(button).toHaveClass('h-9', 'px-3');
|
||||
});
|
||||
|
||||
it('should render large size', () => {
|
||||
render(<Button size="lg">Large</Button>);
|
||||
|
||||
const button = screen.getByRole('button');
|
||||
expect(button).toHaveClass('h-11', 'px-8');
|
||||
});
|
||||
|
||||
it('should render icon size', () => {
|
||||
render(<Button size="icon">👍</Button>);
|
||||
|
||||
const button = screen.getByRole('button');
|
||||
expect(button).toHaveClass('h-10', 'w-10');
|
||||
});
|
||||
});
|
||||
|
||||
describe('states', () => {
|
||||
it('should be disabled when disabled prop is passed', () => {
|
||||
render(<Button disabled>Disabled</Button>);
|
||||
|
||||
const button = screen.getByRole('button');
|
||||
expect(button).toBeDisabled();
|
||||
expect(button).toHaveClass('disabled:opacity-50');
|
||||
});
|
||||
|
||||
it('should handle click events', () => {
|
||||
const handleClick = vi.fn();
|
||||
render(<Button onClick={handleClick}>Click</Button>);
|
||||
|
||||
const button = screen.getByRole('button');
|
||||
fireEvent.click(button);
|
||||
|
||||
expect(handleClick).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('should not fire click when disabled', () => {
|
||||
const handleClick = vi.fn();
|
||||
render(<Button disabled onClick={handleClick}>Disabled</Button>);
|
||||
|
||||
const button = screen.getByRole('button');
|
||||
fireEvent.click(button);
|
||||
|
||||
expect(handleClick).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('asChild prop', () => {
|
||||
it('should render as child element when asChild is true', () => {
|
||||
render(
|
||||
<Button asChild>
|
||||
<a href="/test">Link Button</a>
|
||||
</Button>
|
||||
);
|
||||
|
||||
const link = screen.getByRole('link');
|
||||
expect(link).toBeInTheDocument();
|
||||
expect(link).toHaveAttribute('href', '/test');
|
||||
expect(link).toHaveClass('bg-primary');
|
||||
});
|
||||
});
|
||||
|
||||
describe('custom className', () => {
|
||||
it('should apply custom className', () => {
|
||||
render(<Button className="custom-class">Custom</Button>);
|
||||
|
||||
const button = screen.getByRole('button');
|
||||
expect(button).toHaveClass('custom-class');
|
||||
});
|
||||
});
|
||||
|
||||
describe('type attribute', () => {
|
||||
it('should have type button by default', () => {
|
||||
render(<Button>Button</Button>);
|
||||
|
||||
const button = screen.getByRole('button');
|
||||
// Default type in React is undefined (browser defaults to submit in forms)
|
||||
expect(button).not.toHaveAttribute('type', 'submit');
|
||||
});
|
||||
|
||||
it('should accept submit type', () => {
|
||||
render(<Button type="submit">Submit</Button>);
|
||||
|
||||
const button = screen.getByRole('button');
|
||||
expect(button).toHaveAttribute('type', 'submit');
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user