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,
|
||||
"version": "0.0.0",
|
||||
"version": "1.0.0",
|
||||
"type": "module",
|
||||
"author": {
|
||||
"email": "git@daichendt.one",
|
||||
"name": "Alexander Daichendt",
|
||||
"url": "https://daichendt.one"
|
||||
},
|
||||
"packageManager": "pnpm@10.3.0",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "tsc -b && vite build",
|
||||
"lint": "eslint .",
|
||||
"preview": "vite preview"
|
||||
"preview": "vite preview",
|
||||
"test": "vitest",
|
||||
"coverage": "vitest run --coverage"
|
||||
},
|
||||
"dependencies": {
|
||||
"@tailwindcss/vite": "^4.0.6",
|
||||
|
|
@ -18,6 +26,8 @@
|
|||
},
|
||||
"devDependencies": {
|
||||
"@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-dom": "^19.0.3",
|
||||
"@vitejs/plugin-react": "^4.3.4",
|
||||
|
|
@ -27,6 +37,7 @@
|
|||
"globals": "^15.14.0",
|
||||
"typescript": "~5.7.2",
|
||||
"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;
|
||||
};
|
||||
|
||||
export const useCurrentUser = () => {
|
||||
const { state } = useChatState();
|
||||
return state.currentUser;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
/// <reference types="vitest/config" />
|
||||
import { defineConfig } from "vite";
|
||||
import react from "@vitejs/plugin-react";
|
||||
import tailwindcss from "@tailwindcss/vite";
|
||||
|
|
@ -5,6 +6,10 @@ import tailwindcss from "@tailwindcss/vite";
|
|||
// https://vite.dev/config/
|
||||
export default defineConfig({
|
||||
plugins: [react(), tailwindcss()],
|
||||
test: {
|
||||
globals: true,
|
||||
environment: "jsdom",
|
||||
},
|
||||
server: {
|
||||
proxy: {
|
||||
"/ws": {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue