test: add unit test for ChatMessageDisplay
This commit is contained in:
parent
bc95fb10fc
commit
744854fe0d
5 changed files with 1024 additions and 9 deletions
|
|
@ -1,13 +1,21 @@
|
||||||
{
|
{
|
||||||
"name": "react-ts",
|
"name": "simple-chat-client",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "0.0.0",
|
"version": "1.0.0",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
|
"author": {
|
||||||
|
"email": "git@daichendt.one",
|
||||||
|
"name": "Alexander Daichendt",
|
||||||
|
"url": "https://daichendt.one"
|
||||||
|
},
|
||||||
|
"packageManager": "pnpm@10.3.0",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"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",
|
||||||
|
"coverage": "vitest run --coverage"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@tailwindcss/vite": "^4.0.6",
|
"@tailwindcss/vite": "^4.0.6",
|
||||||
|
|
@ -18,6 +26,8 @@
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@eslint/js": "^9.19.0",
|
"@eslint/js": "^9.19.0",
|
||||||
|
"@testing-library/jest-dom": "^6.6.3",
|
||||||
|
"@testing-library/react": "^16.2.0",
|
||||||
"@types/react": "^19.0.8",
|
"@types/react": "^19.0.8",
|
||||||
"@types/react-dom": "^19.0.3",
|
"@types/react-dom": "^19.0.3",
|
||||||
"@vitejs/plugin-react": "^4.3.4",
|
"@vitejs/plugin-react": "^4.3.4",
|
||||||
|
|
@ -27,6 +37,7 @@
|
||||||
"globals": "^15.14.0",
|
"globals": "^15.14.0",
|
||||||
"typescript": "~5.7.2",
|
"typescript": "~5.7.2",
|
||||||
"typescript-eslint": "^8.22.0",
|
"typescript-eslint": "^8.22.0",
|
||||||
"vite": "^6.1.0"
|
"vite": "^6.1.0",
|
||||||
|
"vitest": "^3.0.5"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
871
client/pnpm-lock.yaml
generated
871
client/pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load diff
133
client/src/__tests__/ChatMessageDisplay.test.tsx
Normal file
133
client/src/__tests__/ChatMessageDisplay.test.tsx
Normal file
|
|
@ -0,0 +1,133 @@
|
||||||
|
import { render, screen, fireEvent } from "@testing-library/react";
|
||||||
|
import { describe, it, expect, vi } from "vitest";
|
||||||
|
import ChatMessageDisplay from "../components/ChatMessage/ChatMessageDisplay";
|
||||||
|
import { ChatMessage } from "../../../shared";
|
||||||
|
import "@testing-library/jest-dom/vitest";
|
||||||
|
|
||||||
|
describe("ChatMessageDisplay", () => {
|
||||||
|
const mockMessage: ChatMessage = {
|
||||||
|
id: "1",
|
||||||
|
content: "Test message",
|
||||||
|
author: {
|
||||||
|
userId: "user1",
|
||||||
|
name: "Test User",
|
||||||
|
},
|
||||||
|
timestamp: Date.now(),
|
||||||
|
};
|
||||||
|
|
||||||
|
const mockHandlers = {
|
||||||
|
onDelete: vi.fn(),
|
||||||
|
onEdit: vi.fn(),
|
||||||
|
};
|
||||||
|
|
||||||
|
it("renders message content correctly", () => {
|
||||||
|
render(
|
||||||
|
<ChatMessageDisplay
|
||||||
|
message={mockMessage}
|
||||||
|
userId="user1"
|
||||||
|
onDelete={mockHandlers.onDelete}
|
||||||
|
onEdit={mockHandlers.onEdit}
|
||||||
|
/>,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(screen.getByText("Test message")).toBeInTheDocument();
|
||||||
|
expect(screen.getByText("Test User")).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("shows edit/delete buttons for own messages", () => {
|
||||||
|
render(
|
||||||
|
<ChatMessageDisplay
|
||||||
|
message={mockMessage}
|
||||||
|
userId="user1"
|
||||||
|
onDelete={mockHandlers.onDelete}
|
||||||
|
onEdit={mockHandlers.onEdit}
|
||||||
|
/>,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(screen.getByRole("button", { name: /edit/i })).toBeInTheDocument();
|
||||||
|
expect(screen.getByRole("button", { name: /delete/i })).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("does not show edit/delete buttons for other users messages", () => {
|
||||||
|
render(
|
||||||
|
<ChatMessageDisplay
|
||||||
|
message={mockMessage}
|
||||||
|
userId="user2"
|
||||||
|
onDelete={mockHandlers.onDelete}
|
||||||
|
onEdit={mockHandlers.onEdit}
|
||||||
|
/>,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(
|
||||||
|
screen.queryByRole("button", { name: /edit/i }),
|
||||||
|
).not.toBeInTheDocument();
|
||||||
|
expect(
|
||||||
|
screen.queryByRole("button", { name: /delete/i }),
|
||||||
|
).not.toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("enters edit mode when edit button is clicked", () => {
|
||||||
|
render(
|
||||||
|
<ChatMessageDisplay
|
||||||
|
message={mockMessage}
|
||||||
|
userId="user1"
|
||||||
|
onDelete={mockHandlers.onDelete}
|
||||||
|
onEdit={mockHandlers.onEdit}
|
||||||
|
/>,
|
||||||
|
);
|
||||||
|
|
||||||
|
fireEvent.click(screen.getByRole("button", { name: /edit/i }));
|
||||||
|
|
||||||
|
expect(screen.getByRole("textbox")).toBeInTheDocument();
|
||||||
|
expect(screen.getByRole("button", { name: /save/i })).toBeInTheDocument();
|
||||||
|
expect(screen.getByRole("button", { name: /cancel/i })).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("calls onEdit when saving edited message", () => {
|
||||||
|
render(
|
||||||
|
<ChatMessageDisplay
|
||||||
|
message={mockMessage}
|
||||||
|
userId="user1"
|
||||||
|
onDelete={mockHandlers.onDelete}
|
||||||
|
onEdit={mockHandlers.onEdit}
|
||||||
|
/>,
|
||||||
|
);
|
||||||
|
|
||||||
|
fireEvent.click(screen.getByRole("button", { name: /edit/i }));
|
||||||
|
const textarea = screen.getByRole("textbox");
|
||||||
|
fireEvent.change(textarea, { target: { value: "Edited message" } });
|
||||||
|
fireEvent.click(screen.getByRole("button", { name: /save/i }));
|
||||||
|
expect(mockHandlers.onEdit).toHaveBeenCalledWith("1", "Edited message");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("calls onDelete when delete button is clicked", () => {
|
||||||
|
render(
|
||||||
|
<ChatMessageDisplay
|
||||||
|
message={mockMessage}
|
||||||
|
userId="user1"
|
||||||
|
onDelete={mockHandlers.onDelete}
|
||||||
|
onEdit={mockHandlers.onEdit}
|
||||||
|
/>,
|
||||||
|
);
|
||||||
|
|
||||||
|
fireEvent.click(screen.getByRole("button", { name: /delete/i }));
|
||||||
|
expect(mockHandlers.onDelete).toHaveBeenCalledWith("1");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("has correct accessibility attributes", () => {
|
||||||
|
render(
|
||||||
|
<ChatMessageDisplay
|
||||||
|
message={mockMessage}
|
||||||
|
userId="user1"
|
||||||
|
onDelete={mockHandlers.onDelete}
|
||||||
|
onEdit={mockHandlers.onEdit}
|
||||||
|
/>,
|
||||||
|
);
|
||||||
|
|
||||||
|
const article = screen.getByRole("article");
|
||||||
|
expect(article).toHaveAttribute(
|
||||||
|
"aria-label",
|
||||||
|
expect.stringContaining("Message from Test User"),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
@ -54,8 +54,3 @@ export const useChatState = () => {
|
||||||
}
|
}
|
||||||
return context;
|
return context;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const useCurrentUser = () => {
|
|
||||||
const { state } = useChatState();
|
|
||||||
return state.currentUser;
|
|
||||||
};
|
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
/// <reference types="vitest/config" />
|
||||||
import { defineConfig } from "vite";
|
import { defineConfig } from "vite";
|
||||||
import react from "@vitejs/plugin-react";
|
import react from "@vitejs/plugin-react";
|
||||||
import tailwindcss from "@tailwindcss/vite";
|
import tailwindcss from "@tailwindcss/vite";
|
||||||
|
|
@ -5,6 +6,10 @@ import tailwindcss from "@tailwindcss/vite";
|
||||||
// https://vite.dev/config/
|
// https://vite.dev/config/
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
plugins: [react(), tailwindcss()],
|
plugins: [react(), tailwindcss()],
|
||||||
|
test: {
|
||||||
|
globals: true,
|
||||||
|
environment: "jsdom",
|
||||||
|
},
|
||||||
server: {
|
server: {
|
||||||
proxy: {
|
proxy: {
|
||||||
"/ws": {
|
"/ws": {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue