Compare commits
2 Commits
create_doc
...
devin/1737
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bb6ab5a85a | ||
|
|
ce7f65b5be |
@@ -18,7 +18,8 @@
|
|||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
"build": "tsc -b && vite build",
|
"build": "tsc -b && vite build",
|
||||||
"lint": "eslint .",
|
"lint": "eslint .",
|
||||||
"preview": "vite preview"
|
"preview": "vite preview",
|
||||||
|
"test": "vitest run"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@modelcontextprotocol/sdk": "^1.0.3",
|
"@modelcontextprotocol/sdk": "^1.0.3",
|
||||||
@@ -40,6 +41,8 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@eslint/js": "^9.11.1",
|
"@eslint/js": "^9.11.1",
|
||||||
|
"@testing-library/jest-dom": "^6.6.3",
|
||||||
|
"@testing-library/react": "^16.2.0",
|
||||||
"@types/node": "^22.7.5",
|
"@types/node": "^22.7.5",
|
||||||
"@types/react": "^18.3.10",
|
"@types/react": "^18.3.10",
|
||||||
"@types/react-dom": "^18.3.0",
|
"@types/react-dom": "^18.3.0",
|
||||||
@@ -50,10 +53,12 @@
|
|||||||
"eslint-plugin-react-hooks": "^5.1.0-rc.0",
|
"eslint-plugin-react-hooks": "^5.1.0-rc.0",
|
||||||
"eslint-plugin-react-refresh": "^0.4.12",
|
"eslint-plugin-react-refresh": "^0.4.12",
|
||||||
"globals": "^15.9.0",
|
"globals": "^15.9.0",
|
||||||
|
"jsdom": "^26.0.0",
|
||||||
"postcss": "^8.4.47",
|
"postcss": "^8.4.47",
|
||||||
"tailwindcss": "^3.4.13",
|
"tailwindcss": "^3.4.13",
|
||||||
"typescript": "^5.5.3",
|
"typescript": "^5.5.3",
|
||||||
"typescript-eslint": "^8.7.0",
|
"typescript-eslint": "^8.7.0",
|
||||||
"vite": "^5.4.8"
|
"vite": "^5.4.8",
|
||||||
|
"vitest": "^3.0.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
59
client/src/components/ListPane.test.tsx
Normal file
59
client/src/components/ListPane.test.tsx
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
import { render, screen, fireEvent } from "@testing-library/react";
|
||||||
|
import ListPane from "./ListPane";
|
||||||
|
import { describe, it, expect, vi } from "vitest";
|
||||||
|
|
||||||
|
describe("ListPane", () => {
|
||||||
|
const defaultProps = {
|
||||||
|
items: [
|
||||||
|
{ id: 1, name: "Item 1" },
|
||||||
|
{ id: 2, name: "Item 2" },
|
||||||
|
],
|
||||||
|
listItems: vi.fn(),
|
||||||
|
clearItems: vi.fn(),
|
||||||
|
setSelectedItem: vi.fn(),
|
||||||
|
renderItem: (item: { name: string }) => <span>{item.name}</span>,
|
||||||
|
title: "Test List",
|
||||||
|
buttonText: "List Items",
|
||||||
|
};
|
||||||
|
|
||||||
|
it("renders title correctly", () => {
|
||||||
|
render(<ListPane {...defaultProps} />);
|
||||||
|
expect(screen.getByText("Test List")).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("renders list items using renderItem prop", () => {
|
||||||
|
render(<ListPane {...defaultProps} />);
|
||||||
|
expect(screen.getByText("Item 1")).toBeInTheDocument();
|
||||||
|
expect(screen.getByText("Item 2")).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("calls listItems when List Items button is clicked", () => {
|
||||||
|
render(<ListPane {...defaultProps} />);
|
||||||
|
fireEvent.click(screen.getByText("List Items"));
|
||||||
|
expect(defaultProps.listItems).toHaveBeenCalledTimes(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("calls clearItems when Clear button is clicked", () => {
|
||||||
|
render(<ListPane {...defaultProps} />);
|
||||||
|
fireEvent.click(screen.getByText("Clear"));
|
||||||
|
expect(defaultProps.clearItems).toHaveBeenCalledTimes(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("calls setSelectedItem when an item is clicked", () => {
|
||||||
|
render(<ListPane {...defaultProps} />);
|
||||||
|
fireEvent.click(screen.getByText("Item 1"));
|
||||||
|
expect(defaultProps.setSelectedItem).toHaveBeenCalledWith(
|
||||||
|
defaultProps.items[0],
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("disables Clear button when items array is empty", () => {
|
||||||
|
render(<ListPane {...defaultProps} items={[]} />);
|
||||||
|
expect(screen.getByText("Clear")).toBeDisabled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("respects isButtonDisabled prop for List Items button", () => {
|
||||||
|
render(<ListPane {...defaultProps} isButtonDisabled={true} />);
|
||||||
|
expect(screen.getByText("List Items")).toBeDisabled();
|
||||||
|
});
|
||||||
|
});
|
||||||
55
client/src/components/ui/Button.test.tsx
Normal file
55
client/src/components/ui/Button.test.tsx
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
import { render, screen, fireEvent } from "@testing-library/react";
|
||||||
|
import { Button } from "./button";
|
||||||
|
import { describe, it, expect, vi } from "vitest";
|
||||||
|
import { createRef } from "react";
|
||||||
|
|
||||||
|
describe("Button", () => {
|
||||||
|
it("renders children correctly", () => {
|
||||||
|
render(<Button>Click me</Button>);
|
||||||
|
expect(screen.getByText("Click me")).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("handles click events", () => {
|
||||||
|
const handleClick = vi.fn();
|
||||||
|
render(<Button onClick={handleClick}>Click me</Button>);
|
||||||
|
fireEvent.click(screen.getByText("Click me"));
|
||||||
|
expect(handleClick).toHaveBeenCalledTimes(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("applies different variants correctly", () => {
|
||||||
|
const { rerender } = render(<Button variant="default">Default</Button>);
|
||||||
|
expect(screen.getByText("Default")).toHaveClass("bg-primary");
|
||||||
|
|
||||||
|
rerender(<Button variant="outline">Outline</Button>);
|
||||||
|
expect(screen.getByText("Outline")).toHaveClass("border-input");
|
||||||
|
|
||||||
|
rerender(<Button variant="secondary">Secondary</Button>);
|
||||||
|
expect(screen.getByText("Secondary")).toHaveClass("bg-secondary");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("applies different sizes correctly", () => {
|
||||||
|
const { rerender } = render(<Button size="default">Default</Button>);
|
||||||
|
expect(screen.getByText("Default")).toHaveClass("h-9");
|
||||||
|
|
||||||
|
rerender(<Button size="sm">Small</Button>);
|
||||||
|
expect(screen.getByText("Small")).toHaveClass("h-8");
|
||||||
|
|
||||||
|
rerender(<Button size="lg">Large</Button>);
|
||||||
|
expect(screen.getByText("Large")).toHaveClass("h-10");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("forwards ref correctly", () => {
|
||||||
|
const ref = createRef<HTMLButtonElement>();
|
||||||
|
render(<Button ref={ref}>Button with ref</Button>);
|
||||||
|
expect(ref.current).toBeInstanceOf(HTMLButtonElement);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("renders as a different element when asChild is true", () => {
|
||||||
|
render(
|
||||||
|
<Button asChild>
|
||||||
|
<a href="#">Link Button</a>
|
||||||
|
</Button>,
|
||||||
|
);
|
||||||
|
expect(screen.getByText("Link Button").tagName).toBe("A");
|
||||||
|
});
|
||||||
|
});
|
||||||
12
client/src/test.d.ts
vendored
Normal file
12
client/src/test.d.ts
vendored
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
/// <reference types="vitest/globals" />
|
||||||
|
/// <reference types="@testing-library/jest-dom" />
|
||||||
|
|
||||||
|
import "@testing-library/jest-dom";
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
namespace Vi {
|
||||||
|
interface JestAssertion<T = any> extends jest.Matchers<void, T> {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export {};
|
||||||
6
client/test/setupTests.ts
Normal file
6
client/test/setupTests.ts
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
/// <reference types="vitest/globals" />
|
||||||
|
/// <reference types="@testing-library/jest-dom" />
|
||||||
|
import "@testing-library/jest-dom/vitest";
|
||||||
|
|
||||||
|
// Add any additional test setup, custom matchers, or global mocks here
|
||||||
|
// This file runs before each test file
|
||||||
@@ -4,6 +4,7 @@
|
|||||||
"paths": {
|
"paths": {
|
||||||
"@/*": ["./src/*"]
|
"@/*": ["./src/*"]
|
||||||
},
|
},
|
||||||
|
"types": ["vitest/globals", "@testing-library/jest-dom"],
|
||||||
|
|
||||||
"target": "ES2020",
|
"target": "ES2020",
|
||||||
"useDefineForClassFields": true,
|
"useDefineForClassFields": true,
|
||||||
@@ -26,5 +27,5 @@
|
|||||||
"noFallthroughCasesInSwitch": true,
|
"noFallthroughCasesInSwitch": true,
|
||||||
"resolveJsonModule": true
|
"resolveJsonModule": true
|
||||||
},
|
},
|
||||||
"include": ["src"]
|
"include": ["src", "test"]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,8 @@
|
|||||||
"files": [],
|
"files": [],
|
||||||
"references": [
|
"references": [
|
||||||
{ "path": "./tsconfig.app.json" },
|
{ "path": "./tsconfig.app.json" },
|
||||||
{ "path": "./tsconfig.node.json" }
|
{ "path": "./tsconfig.node.json" },
|
||||||
|
{ "path": "./tsconfig.test.json" }
|
||||||
],
|
],
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"baseUrl": ".",
|
"baseUrl": ".",
|
||||||
|
|||||||
7
client/tsconfig.test.json
Normal file
7
client/tsconfig.test.json
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"extends": "./tsconfig.app.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"types": ["vitest/globals", "@testing-library/jest-dom"]
|
||||||
|
},
|
||||||
|
"include": ["src/**/*.test.tsx", "src/**/*.test.ts", "test/**/*.ts"]
|
||||||
|
}
|
||||||
20
client/vitest.config.ts
Normal file
20
client/vitest.config.ts
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
import { defineConfig } from "vitest/config";
|
||||||
|
import react from "@vitejs/plugin-react";
|
||||||
|
import path from "path";
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
plugins: [react()],
|
||||||
|
test: {
|
||||||
|
environment: "jsdom",
|
||||||
|
globals: true,
|
||||||
|
setupFiles: ["./test/setupTests.ts"],
|
||||||
|
typecheck: {
|
||||||
|
tsconfig: "./tsconfig.test.json",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
resolve: {
|
||||||
|
alias: {
|
||||||
|
"@": path.resolve(__dirname, "./src"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user