Skip to content

Commit fd7a177

Browse files
committed
test: add feedback coverage for MessageLog, Overview, FeedbackModal, and FeedbackCell
1 parent b3f5d29 commit fd7a177

File tree

2 files changed

+159
-0
lines changed

2 files changed

+159
-0
lines changed

packages/frontend/tests/pages/MessageLog.test.tsx

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,15 @@ const mockGetMessages = vi.fn();
1818
const mockGetCustomProviders = vi.fn();
1919
const mockGetMessageDetails = vi.fn();
2020
const mockGetRoutingStatus = vi.fn();
21+
const mockSetMessageFeedback = vi.fn();
22+
const mockClearMessageFeedback = vi.fn();
2123
vi.mock("../../src/services/api.js", () => ({
2224
getMessages: (...args: unknown[]) => mockGetMessages(...args),
2325
getCustomProviders: (...args: unknown[]) => mockGetCustomProviders(...args),
2426
getMessageDetails: (...args: unknown[]) => mockGetMessageDetails(...args),
2527
getRoutingStatus: (...args: unknown[]) => mockGetRoutingStatus(...args),
28+
setMessageFeedback: (...args: unknown[]) => mockSetMessageFeedback(...args),
29+
clearMessageFeedback: (...args: unknown[]) => mockClearMessageFeedback(...args),
2630
}));
2731

2832
vi.mock("../../src/services/sse.js", () => ({
@@ -52,6 +56,15 @@ vi.mock("../../src/components/SetupModal.jsx", () => ({
5256
),
5357
}));
5458

59+
vi.mock("../../src/components/FeedbackModal.jsx", () => ({
60+
default: (props: any) => (
61+
<div data-testid="feedback-modal" data-open={props.open ? "true" : "false"}>
62+
<button data-testid="feedback-submit" onClick={() => props.onSubmit?.(['Too slow'], 'test')}>Submit</button>
63+
<button data-testid="feedback-close" onClick={() => props.onClose?.()}>Close</button>
64+
</div>
65+
),
66+
}));
67+
5568
vi.mock("../../src/components/InfoTooltip.jsx", () => ({
5669
default: () => <span data-testid="info-tooltip" />,
5770
}));
@@ -857,4 +870,79 @@ describe("MessageLog", () => {
857870
fireEvent.click(badge);
858871
expect(scrollSpy).toHaveBeenCalled();
859872
});
873+
874+
describe("feedback", () => {
875+
it("calls setMessageFeedback with like when thumb up is clicked", async () => {
876+
mockSetMessageFeedback.mockResolvedValue(undefined);
877+
mockGetMessages.mockResolvedValue(messagesData);
878+
const { container } = render(() => <MessageLog />);
879+
await vi.waitFor(() => {
880+
expect(container.querySelector(".feedback-btn")).not.toBeNull();
881+
});
882+
const likeBtn = container.querySelector(".feedback-btn") as HTMLElement;
883+
fireEvent.click(likeBtn);
884+
expect(mockSetMessageFeedback).toHaveBeenCalledWith("msg-12345678", { rating: "like" });
885+
});
886+
887+
it("calls setMessageFeedback with dislike and opens modal when thumb down is clicked", async () => {
888+
mockSetMessageFeedback.mockResolvedValue(undefined);
889+
mockGetMessages.mockResolvedValue(messagesData);
890+
const { container } = render(() => <MessageLog />);
891+
await vi.waitFor(() => {
892+
expect(container.querySelector(".feedback-btn")).not.toBeNull();
893+
});
894+
const dislikeBtn = container.querySelectorAll(".feedback-btn")[1] as HTMLElement;
895+
fireEvent.click(dislikeBtn);
896+
expect(mockSetMessageFeedback).toHaveBeenCalledWith("msg-12345678", { rating: "dislike" });
897+
const modal = container.querySelector('[data-testid="feedback-modal"]');
898+
expect(modal?.getAttribute("data-open")).toBe("true");
899+
});
900+
901+
it("calls clearMessageFeedback when active like is clicked", async () => {
902+
mockClearMessageFeedback.mockResolvedValue(undefined);
903+
const dataWithFeedback = {
904+
...messagesData,
905+
items: [{ ...messagesData.items[0], feedback_rating: "like" }, messagesData.items[1]],
906+
};
907+
mockGetMessages.mockResolvedValue(dataWithFeedback);
908+
const { container } = render(() => <MessageLog />);
909+
await vi.waitFor(() => {
910+
expect(container.querySelector(".feedback-btn--active-like")).not.toBeNull();
911+
});
912+
const likeBtn = container.querySelector(".feedback-btn--active-like") as HTMLElement;
913+
fireEvent.click(likeBtn);
914+
expect(mockClearMessageFeedback).toHaveBeenCalledWith("msg-12345678");
915+
});
916+
917+
it("submits feedback details from modal", async () => {
918+
mockSetMessageFeedback.mockResolvedValue(undefined);
919+
mockGetMessages.mockResolvedValue(messagesData);
920+
const { container } = render(() => <MessageLog />);
921+
await vi.waitFor(() => {
922+
expect(container.querySelector(".feedback-btn")).not.toBeNull();
923+
});
924+
// Click dislike to open modal
925+
const dislikeBtn = container.querySelectorAll(".feedback-btn")[1] as HTMLElement;
926+
fireEvent.click(dislikeBtn);
927+
// Submit via modal
928+
const submitBtn = container.querySelector('[data-testid="feedback-submit"]') as HTMLElement;
929+
fireEvent.click(submitBtn);
930+
expect(mockSetMessageFeedback).toHaveBeenCalledWith("msg-12345678", { rating: "dislike", tags: ["Too slow"], details: "test" });
931+
});
932+
933+
it("closes feedback modal without submitting", async () => {
934+
mockSetMessageFeedback.mockResolvedValue(undefined);
935+
mockGetMessages.mockResolvedValue(messagesData);
936+
const { container } = render(() => <MessageLog />);
937+
await vi.waitFor(() => {
938+
expect(container.querySelector(".feedback-btn")).not.toBeNull();
939+
});
940+
const dislikeBtn = container.querySelectorAll(".feedback-btn")[1] as HTMLElement;
941+
fireEvent.click(dislikeBtn);
942+
const closeBtn = container.querySelector('[data-testid="feedback-close"]') as HTMLElement;
943+
fireEvent.click(closeBtn);
944+
const modal = container.querySelector('[data-testid="feedback-modal"]');
945+
expect(modal?.getAttribute("data-open")).toBe("false");
946+
});
947+
});
860948
});

packages/frontend/tests/pages/Overview.test.tsx

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,13 @@ vi.mock("@solidjs/meta", () => ({
1818

1919
const mockGetOverview = vi.fn();
2020
const mockGetCustomProviders = vi.fn();
21+
const mockSetMessageFeedback = vi.fn();
22+
const mockClearMessageFeedback = vi.fn();
2123
vi.mock("../../src/services/api.js", () => ({
2224
getOverview: (...args: unknown[]) => mockGetOverview(...args),
2325
getCustomProviders: (...args: unknown[]) => mockGetCustomProviders(...args),
26+
setMessageFeedback: (...args: unknown[]) => mockSetMessageFeedback(...args),
27+
clearMessageFeedback: (...args: unknown[]) => mockClearMessageFeedback(...args),
2428
}));
2529

2630
vi.mock("../../src/services/sse.js", () => ({
@@ -53,6 +57,15 @@ vi.mock("../../src/components/SingleTokenChart.jsx", () => ({
5357
default: () => <div data-testid="single-token-chart" />,
5458
}));
5559

60+
vi.mock("../../src/components/FeedbackModal.jsx", () => ({
61+
default: (props: any) => (
62+
<div data-testid="feedback-modal" data-open={props.open ? "true" : "false"}>
63+
<button data-testid="feedback-submit" onClick={() => props.onSubmit?.(['Too slow'], 'test')}>Submit</button>
64+
<button data-testid="feedback-close" onClick={() => props.onClose?.()}>Close</button>
65+
</div>
66+
),
67+
}));
68+
5669
vi.mock("../../src/components/SetupModal.jsx", () => ({
5770
default: (props: any) => (
5871
<div data-testid="setup-modal" data-open={props.open ? "true" : "false"} data-agent={props.agentName ?? ""} data-api-key={props.apiKey ?? ""}>
@@ -793,4 +806,62 @@ describe("Overview", () => {
793806
expect(badge!.textContent).toBe("fallback_error");
794807
});
795808
});
809+
810+
describe("feedback", () => {
811+
it("calls setMessageFeedback with like when thumb up is clicked", async () => {
812+
mockSetMessageFeedback.mockResolvedValue(undefined);
813+
mockGetOverview.mockResolvedValue(overviewData);
814+
const { container } = render(() => <Overview />);
815+
await vi.waitFor(() => {
816+
expect(container.querySelector(".feedback-btn")).not.toBeNull();
817+
});
818+
const likeBtn = container.querySelector(".feedback-btn") as HTMLElement;
819+
fireEvent.click(likeBtn);
820+
expect(mockSetMessageFeedback).toHaveBeenCalledWith("msg-12345678", { rating: "like" });
821+
});
822+
823+
it("calls setMessageFeedback with dislike and opens modal", async () => {
824+
mockSetMessageFeedback.mockResolvedValue(undefined);
825+
mockGetOverview.mockResolvedValue(overviewData);
826+
const { container } = render(() => <Overview />);
827+
await vi.waitFor(() => {
828+
expect(container.querySelector(".feedback-btn")).not.toBeNull();
829+
});
830+
const dislikeBtn = container.querySelectorAll(".feedback-btn")[1] as HTMLElement;
831+
fireEvent.click(dislikeBtn);
832+
expect(mockSetMessageFeedback).toHaveBeenCalledWith("msg-12345678", { rating: "dislike" });
833+
const modal = container.querySelector('[data-testid="feedback-modal"]');
834+
expect(modal?.getAttribute("data-open")).toBe("true");
835+
});
836+
837+
it("calls clearMessageFeedback when active like is clicked", async () => {
838+
mockClearMessageFeedback.mockResolvedValue(undefined);
839+
const dataWithFeedback = {
840+
...overviewData,
841+
recent_activity: [{ ...overviewData.recent_activity[0], feedback_rating: "like" }],
842+
};
843+
mockGetOverview.mockResolvedValue(dataWithFeedback);
844+
const { container } = render(() => <Overview />);
845+
await vi.waitFor(() => {
846+
expect(container.querySelector(".feedback-btn--active-like")).not.toBeNull();
847+
});
848+
const likeBtn = container.querySelector(".feedback-btn--active-like") as HTMLElement;
849+
fireEvent.click(likeBtn);
850+
expect(mockClearMessageFeedback).toHaveBeenCalledWith("msg-12345678");
851+
});
852+
853+
it("submits feedback details from modal", async () => {
854+
mockSetMessageFeedback.mockResolvedValue(undefined);
855+
mockGetOverview.mockResolvedValue(overviewData);
856+
const { container } = render(() => <Overview />);
857+
await vi.waitFor(() => {
858+
expect(container.querySelector(".feedback-btn")).not.toBeNull();
859+
});
860+
const dislikeBtn = container.querySelectorAll(".feedback-btn")[1] as HTMLElement;
861+
fireEvent.click(dislikeBtn);
862+
const submitBtn = container.querySelector('[data-testid="feedback-submit"]') as HTMLElement;
863+
fireEvent.click(submitBtn);
864+
expect(mockSetMessageFeedback).toHaveBeenCalledWith("msg-12345678", { rating: "dislike", tags: ["Too slow"], details: "test" });
865+
});
866+
});
796867
});

0 commit comments

Comments
 (0)