diff --git a/frontend-new/src/_test_utilities/VisualMock.tsx b/frontend-new/src/_test_utilities/VisualMock.tsx index 686b2a38b..136bb9e00 100644 --- a/frontend-new/src/_test_utilities/VisualMock.tsx +++ b/frontend-new/src/_test_utilities/VisualMock.tsx @@ -17,6 +17,7 @@ interface VisualMockProps { | "button" | "overline"; text: string; + maxWidth?: string; } export const VisualMock = (props: VisualMockProps) => { @@ -37,6 +38,7 @@ export const VisualMock = (props: VisualMockProps) => { // otherwise the component will overflow // e.g. height: //`calc(100% - ${2 * borderWidth}px)`, height: "100%", + maxWidth: props.maxWidth ?? "100%", position: "relative", }} > diff --git a/frontend-new/src/chat/chatMessage/basicChatMessage/BasicChatMessage.stories.tsx b/frontend-new/src/chat/chatMessage/basicChatMessage/BasicChatMessage.stories.tsx index 1ebb2e1db..4c616d696 100644 --- a/frontend-new/src/chat/chatMessage/basicChatMessage/BasicChatMessage.stories.tsx +++ b/frontend-new/src/chat/chatMessage/basicChatMessage/BasicChatMessage.stories.tsx @@ -5,7 +5,6 @@ import { nanoid } from "nanoid"; import { ChatMessageType } from "src/chat/Chat.types"; const meta: Meta = { - // REVIEW: Chat/ChatMessage/Basic title: "Chat/ChatMessage/Basic", component: BasicChatMessage, tags: ["autodocs"], diff --git a/frontend-new/src/chat/chatMessage/basicChatMessage/BasicChatMessage.test.tsx b/frontend-new/src/chat/chatMessage/basicChatMessage/BasicChatMessage.test.tsx index 373fec804..f22992678 100644 --- a/frontend-new/src/chat/chatMessage/basicChatMessage/BasicChatMessage.test.tsx +++ b/frontend-new/src/chat/chatMessage/basicChatMessage/BasicChatMessage.test.tsx @@ -2,19 +2,20 @@ import "src/_test_utilities/consoleMock"; import BasicChatMessage, { DATA_TEST_ID } from "./BasicChatMessage"; -import ChatMessageFooter, { DATA_TEST_ID as CHAT_MESSAGE_FOOTER_DATA_TEST_ID } from "src/chat/chatMessage/components/chatMessageFooter/ChatMessageFooter"; +import ChatMessageFooter, { DATA_TEST_ID as CHAT_MESSAGE_FOOTER_DATA_TEST_ID } from "src/chat/chatMessage/components/chatMessageFooter/ChatMessageFooterLayout"; import ChatBubble, { DATA_TEST_ID as CHAT_BUBBLE_DATA_TEST_ID } from "src/chat/chatMessage/components/chatBubble/ChatBubble"; import { render, screen } from "src/_test_utilities/test-utils"; import { ConversationMessageSender } from "src/chat/ChatService/ChatService.types"; import { nanoid } from "nanoid"; import { ChatMessageType, IChatMessage } from "src/chat/Chat.types"; +import Timestamp from "../components/chatMessageFooter/components/timestamp/Timestamp"; -jest.mock("src/chat/chatMessage/components/chatMessageFooter/ChatMessageFooter", () => { - const originalModule = jest.requireActual("src/chat/chatMessage/components/chatMessageFooter/ChatMessageFooter"); +jest.mock("src/chat/chatMessage/components/chatMessageFooter/ChatMessageFooterLayout", () => { + const originalModule = jest.requireActual("src/chat/chatMessage/components/chatMessageFooter/ChatMessageFooterLayout"); return { __esModule: true, ...originalModule, - default: jest.fn(() =>
), + default: jest.fn(() =>
), } }) @@ -27,6 +28,15 @@ jest.mock("src/chat/chatMessage/components/chatBubble/ChatBubble", () => { } }) +jest.mock("src/chat/chatMessage/components/chatMessageFooter/components/timestamp/Timestamp", () => { + const originalModule = jest.requireActual("src/chat/chatMessage/components/chatMessageFooter/components/timestamp/Timestamp"); + return { + __esModule: true, + ...originalModule, + default: jest.fn(() =>
), + } +}) + describe("render tests", () => { beforeAll(() => { jest.useFakeTimers(); @@ -55,17 +65,14 @@ describe("render tests", () => { expect(screen.getByTestId(DATA_TEST_ID.CHAT_MESSAGE_CONTAINER)).toBeInTheDocument(); // AND expect the message bubble to be visible expect(screen.getByTestId(CHAT_BUBBLE_DATA_TEST_ID.CHAT_MESSAGE_BUBBLE_CONTAINER)).toBeInTheDocument(); - // AND expect the timestamp to be visible - expect(screen.getByTestId(CHAT_MESSAGE_FOOTER_DATA_TEST_ID.CHAT_MESSAGE_TIMESTAMP)).toBeInTheDocument(); + // AND expect the footer to be visible + expect(screen.getByTestId(CHAT_MESSAGE_FOOTER_DATA_TEST_ID.CHAT_MESSAGE_FOOTER_LAYOUT_CONTAINER)).toBeInTheDocument(); + + // AND the footer to have been called with a timestamp component + const footerCall = (ChatMessageFooter as jest.Mock).mock.calls[0][0]; + expect(footerCall.children.type).toBe(Timestamp); + expect(footerCall.children.props).toEqual({ sentAt: givenDate }); - // AND the correct date to have been displayed - expect(ChatMessageFooter).toHaveBeenNthCalledWith( - 1, - { - sentAt: givenDate - }, - {} - ) // AND expect the Chat bubble to have been rendered with the expected message expect(ChatBubble).toHaveBeenNthCalledWith( 1, diff --git a/frontend-new/src/chat/chatMessage/basicChatMessage/BasicChatMessage.tsx b/frontend-new/src/chat/chatMessage/basicChatMessage/BasicChatMessage.tsx index e8fab016d..e92faf027 100644 --- a/frontend-new/src/chat/chatMessage/basicChatMessage/BasicChatMessage.tsx +++ b/frontend-new/src/chat/chatMessage/basicChatMessage/BasicChatMessage.tsx @@ -2,8 +2,9 @@ import React from "react"; import { Box, styled } from "@mui/material"; import { IChatMessage } from "src/chat/Chat.types"; import { ConversationMessageSender } from "src/chat/ChatService/ChatService.types"; -import ChatMessageFooter from "src/chat/chatMessage/components/chatMessageFooter/ChatMessageFooter"; +import ChatMessageFooter from "src/chat/chatMessage/components/chatMessageFooter/ChatMessageFooterLayout"; import ChatBubble from "src/chat/chatMessage/components/chatBubble/ChatBubble"; +import Timestamp from "src/chat/chatMessage/components/chatMessageFooter/components/timestamp/Timestamp"; const uniqueId = "2fbaf2ef-9eab-485a-bd28-b4a164e18b06"; @@ -26,8 +27,21 @@ type BasicChatMessageProps = { const BasicChatMessage: React.FC = ({ chatMessage }) => { return ( - - + + + + + + + + ); }; diff --git a/frontend-new/src/chat/chatMessage/basicChatMessage/__snapshots__/BasicChatMessage.test.tsx.snap b/frontend-new/src/chat/chatMessage/basicChatMessage/__snapshots__/BasicChatMessage.test.tsx.snap index d19116e4a..ab742d6dc 100644 --- a/frontend-new/src/chat/chatMessage/basicChatMessage/__snapshots__/BasicChatMessage.test.tsx.snap +++ b/frontend-new/src/chat/chatMessage/basicChatMessage/__snapshots__/BasicChatMessage.test.tsx.snap @@ -7,10 +7,18 @@ exports[`render tests should render the Chat message with a timestamp 1`] = ` origin="COMPASS" >
-
+ class="MuiBox-root css-14jedwi" + > +
+
+
+
+
`; diff --git a/frontend-new/src/chat/chatMessage/components/chatBubble/ChatBubble.stories.tsx b/frontend-new/src/chat/chatMessage/components/chatBubble/ChatBubble.stories.tsx index b3b9f4c20..c8008afed 100644 --- a/frontend-new/src/chat/chatMessage/components/chatBubble/ChatBubble.stories.tsx +++ b/frontend-new/src/chat/chatMessage/components/chatBubble/ChatBubble.stories.tsx @@ -32,6 +32,6 @@ export const ShownWithFooter: Story = { args: { message: "Hello, how can I help you?", sender: ConversationMessageSender.COMPASS, - footer: + children: } } \ No newline at end of file diff --git a/frontend-new/src/chat/chatMessage/components/chatBubble/ChatBubble.test.tsx b/frontend-new/src/chat/chatMessage/components/chatBubble/ChatBubble.test.tsx index dcd1eca75..e5e654b31 100644 --- a/frontend-new/src/chat/chatMessage/components/chatBubble/ChatBubble.test.tsx +++ b/frontend-new/src/chat/chatMessage/components/chatBubble/ChatBubble.test.tsx @@ -25,7 +25,7 @@ describe("render tests", () => { expect(screen.getByTestId(DATA_TEST_ID.CHAT_MESSAGE_BUBBLE_CONTAINER)).toMatchSnapshot(); }); - test("should render the Chat Bubble with a footer if one is passed", () => { + test("should render the Chat Bubble with a child if one is passed", () => { // GIVEN a message const givenMessage: string = "Hello, I'm Compass"; // AND a sender @@ -34,14 +34,16 @@ describe("render tests", () => { const givenFooter =
foo child
// WHEN the chat bubble is rendered - render(); + render( + + {givenFooter} + + ); // THEN expect the message container to be visible expect(screen.getByTestId(DATA_TEST_ID.CHAT_MESSAGE_BUBBLE_CONTAINER)).toBeInTheDocument(); // AND expect the message text to be visible expect(screen.getByTestId(DATA_TEST_ID.CHAT_MESSAGE_BUBBLE_MESSAGE_TEXT)).toBeInTheDocument(); - // AND expect the divider to be visible - expect(screen.getByTestId(DATA_TEST_ID.CHAT_MESSAGE_BUBBLE_MESSAGE_DIVIDER)).toBeInTheDocument(); // AND expect the child container to be visible expect(screen.getByTestId(DATA_TEST_ID.CHAT_MESSAGE_BUBBLE_MESSAGE_FOOTER_CONTAINER)).toBeInTheDocument(); // AND expect the child to be visible diff --git a/frontend-new/src/chat/chatMessage/components/chatBubble/ChatBubble.tsx b/frontend-new/src/chat/chatMessage/components/chatBubble/ChatBubble.tsx index 2e9b8bead..bbf9e07a1 100644 --- a/frontend-new/src/chat/chatMessage/components/chatBubble/ChatBubble.tsx +++ b/frontend-new/src/chat/chatMessage/components/chatBubble/ChatBubble.tsx @@ -1,10 +1,11 @@ +import React from "react"; import { ConversationMessageSender } from "src/chat/ChatService/ChatService.types"; -import { Box, Typography, styled, alpha, Divider, useTheme } from "@mui/material"; +import { Box, Typography, styled, alpha } from "@mui/material"; export interface ChatBubbleProps { message: string, sender: ConversationMessageSender, - footer?: React.ReactNode + children?: React.ReactNode, } const uniqueId = "6e685eeb-2b54-432a-8b66-8a81633b3981"; @@ -12,13 +13,10 @@ const uniqueId = "6e685eeb-2b54-432a-8b66-8a81633b3981"; export const DATA_TEST_ID = { CHAT_MESSAGE_BUBBLE_CONTAINER: `chat-message-bubble-container-${uniqueId}`, CHAT_MESSAGE_BUBBLE_MESSAGE_TEXT: `chat-message-bubble-message-text-${uniqueId}`, - CHAT_MESSAGE_BUBBLE_MESSAGE_DIVIDER: `chat-message-bubble-message-divider-${uniqueId}`, CHAT_MESSAGE_BUBBLE_MESSAGE_FOOTER_CONTAINER: `chat-message-bubble-message-footer-container-${uniqueId}`, } const MessageBubble = styled(Box)<{ origin: ConversationMessageSender }>(({ theme, origin }) => ({ - maxWidth: "80%", - minWidth: "30%", variants: "outlined", wordWrap: "break-word", padding: theme.fixedSpacing(theme.tabiyaSpacing.sm), @@ -33,25 +31,13 @@ const MessageBubble = styled(Box)<{ origin: ConversationMessageSender }>(({ them flexDirection: "column", })); -const ChatBubble: React.FC = ({ message, sender, footer }) => { - const theme = useTheme(); +const ChatBubble: React.FC = ({ message, sender, children }) => { return ( {message} - { - footer && ( - <> - - - {footer} - - - ) - } + + {children} + ) } diff --git a/frontend-new/src/chat/chatMessage/components/chatBubble/__snapshots__/ChatBubble.test.tsx.snap b/frontend-new/src/chat/chatMessage/components/chatBubble/__snapshots__/ChatBubble.test.tsx.snap index c6f164dab..0be70e15c 100644 --- a/frontend-new/src/chat/chatMessage/components/chatBubble/__snapshots__/ChatBubble.test.tsx.snap +++ b/frontend-new/src/chat/chatMessage/components/chatBubble/__snapshots__/ChatBubble.test.tsx.snap @@ -1,8 +1,8 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`render tests should render the Chat Bubble with a footer if one is passed 1`] = ` +exports[`render tests should render the Chat Bubble with a child if one is passed 1`] = `
@@ -12,11 +12,6 @@ exports[`render tests should render the Chat Bubble with a footer if one is pass > Hello, I'm Compass

-
@@ -42,5 +37,9 @@ exports[`render tests should render the Chat Bubble without a child if none is p > Hello, I'm Compass

+
`; diff --git a/frontend-new/src/chat/chatMessage/components/chatMessageFooter/ChatMessageFooter.stories.tsx b/frontend-new/src/chat/chatMessage/components/chatMessageFooter/ChatMessageFooter.stories.tsx deleted file mode 100644 index c8523d87c..000000000 --- a/frontend-new/src/chat/chatMessage/components/chatMessageFooter/ChatMessageFooter.stories.tsx +++ /dev/null @@ -1,19 +0,0 @@ -import type { Meta, StoryObj } from "@storybook/react"; -import ChatMessageFooter from "./ChatMessageFooter"; - -const meta: Meta = { - title: "Chat/ChatMessageFooter", - component: ChatMessageFooter, - tags: ["autodocs"], - argTypes: {}, -}; - -export default meta; - -type Story = StoryObj; - -export const Shown: Story = { - args: { - sentAt: new Date().toISOString() - }, -}; \ No newline at end of file diff --git a/frontend-new/src/chat/chatMessage/components/chatMessageFooter/ChatMessageFooterLayout.stories.tsx b/frontend-new/src/chat/chatMessage/components/chatMessageFooter/ChatMessageFooterLayout.stories.tsx new file mode 100644 index 000000000..0d9d29ce4 --- /dev/null +++ b/frontend-new/src/chat/chatMessage/components/chatMessageFooter/ChatMessageFooterLayout.stories.tsx @@ -0,0 +1,57 @@ +import type { Meta, StoryObj } from "@storybook/react"; +import ChatMessageFooter from "./ChatMessageFooterLayout"; +import Timestamp from "./components/timestamp/Timestamp"; +import { VisualMock } from "src/_test_utilities/VisualMock"; +import { ConversationMessageSender } from "src/chat/ChatService/ChatService.types"; + +const meta: Meta = { + title: "Chat/ChatMessageFooter/Layout", + component: ChatMessageFooter, + tags: ["autodocs"], +}; + +export default meta; + +type Story = StoryObj; + +export const ShownWithTimestampCompassSender: Story = { + args: { + sender: ConversationMessageSender.COMPASS, + children: , + }, +} +export const ShownWithTimestampUserSender: Story = { + args: { + sender: ConversationMessageSender.USER, + children: , + }, +} + +export const OneFullWidthChild: Story = { + args: { + children: , + }, +}; +export const OneFixedWidthChild: Story = { + args: { + children: , + }, +} + +export const MultipleFullWidthChildren: Story = { + args: { + children: [ + , + , + ], + }, +}; + +export const MultipleFixedWidthChildren: Story = { + args: { + children: [ + , + , + ], + }, +}; \ No newline at end of file diff --git a/frontend-new/src/chat/chatMessage/components/chatMessageFooter/ChatMessageFooterLayout.test.tsx b/frontend-new/src/chat/chatMessage/components/chatMessageFooter/ChatMessageFooterLayout.test.tsx new file mode 100644 index 000000000..d27e3e5ec --- /dev/null +++ b/frontend-new/src/chat/chatMessage/components/chatMessageFooter/ChatMessageFooterLayout.test.tsx @@ -0,0 +1,86 @@ +// mute the console +import "src/_test_utilities/consoleMock"; + +import ChatMessageFooter, { DATA_TEST_ID } from "src/chat/chatMessage/components/chatMessageFooter/ChatMessageFooterLayout"; +import { render, screen } from "src/_test_utilities/test-utils"; +import { Box } from "@mui/material"; +import { ConversationMessageSender } from "src/chat/ChatService/ChatService.types"; + +describe("render tests", () => { + // GIVEN some test children components + const Child = (id: string) => Child; + + test.each([ + { + name: "without children", + children: [], + expectedTestIds: [] + }, + { + name: "with a single child", + children: [Child("foo-child-1")], + expectedTestIds: ["foo-child-1"] + }, + { + name: "with multiple children", + children: [Child("foo-child-1"), Child("foo-child-2")], + expectedTestIds: ["foo-child-1", "foo-child-2"] + } + ])("should render a compass chat message footer %s", ({ children, expectedTestIds }) => { + // WHEN the component is rendered + render({children}); + + // THEN expect the container to be in the document + const container = screen.getByTestId(DATA_TEST_ID.CHAT_MESSAGE_FOOTER_LAYOUT_CONTAINER); + expect(container).toBeInTheDocument(); + + // AND expect all children to be rendered if any + expectedTestIds.forEach(testId => { + expect(screen.getByTestId(testId)).toBeInTheDocument(); + }); + + // AND expect no errors or warnings + expect(console.error).not.toHaveBeenCalled(); + expect(console.warn).not.toHaveBeenCalled(); + + // AND expect the component to match snapshot + expect(container).toMatchSnapshot(); + }); + + test.each([ + { + name: "without children", + children: [], + expectedTestIds: [] + }, + { + name: "with a single child", + children: [Child("foo-child-1")], + expectedTestIds: ["foo-child-1"] + }, + { + name: "with multiple children", + children: [Child("foo-child-1"), Child("foo-child-2")], + expectedTestIds: ["foo-child-1", "foo-child-2"] + } + ])("should render a user chat message footer %s", ({ children, expectedTestIds }) => { + // WHEN the component is rendered + render({children}); + + // THEN expect the container to be in the document + const container = screen.getByTestId(DATA_TEST_ID.CHAT_MESSAGE_FOOTER_LAYOUT_CONTAINER); + expect(container).toBeInTheDocument(); + + // AND expect all children to be rendered if any + expectedTestIds.forEach(testId => { + expect(screen.getByTestId(testId)).toBeInTheDocument(); + }); + + // AND expect no errors or warnings + expect(console.error).not.toHaveBeenCalled(); + expect(console.warn).not.toHaveBeenCalled(); + + // AND expect the component to match snapshot + expect(container).toMatchSnapshot(); + }); +}); \ No newline at end of file diff --git a/frontend-new/src/chat/chatMessage/components/chatMessageFooter/ChatMessageFooterLayout.tsx b/frontend-new/src/chat/chatMessage/components/chatMessageFooter/ChatMessageFooterLayout.tsx new file mode 100644 index 000000000..63b30fb8b --- /dev/null +++ b/frontend-new/src/chat/chatMessage/components/chatMessageFooter/ChatMessageFooterLayout.tsx @@ -0,0 +1,33 @@ +import React from "react"; +import { Box } from "@mui/material"; +import { ConversationMessageSender } from "src/chat/ChatService/ChatService.types"; + +const uniqueId = "7772f20a-9d0c-4072-b24f-97eca2f43d7b"; + +export const DATA_TEST_ID = { + CHAT_MESSAGE_FOOTER_LAYOUT_CONTAINER: `chat-message-footer-layout-container-${uniqueId}`, +}; + +export interface ChatMessageFooterLayoutProps { + sender: ConversationMessageSender; + children: React.ReactNode; +} + +const ChatMessageFooterLayout: React.FC = ({ sender, children }) => { + return ( + theme.fixedSpacing(theme.tabiyaSpacing.xs)} + justifyContent={"space-between"} + gap={(theme) => theme.fixedSpacing(theme.tabiyaSpacing.sm)} + > + {children} + + + ); +}; + +export default ChatMessageFooterLayout; diff --git a/frontend-new/src/chat/chatMessage/components/chatMessageFooter/__snapshots__/ChatMessageFooter.test.tsx.snap b/frontend-new/src/chat/chatMessage/components/chatMessageFooter/__snapshots__/ChatMessageFooter.test.tsx.snap deleted file mode 100644 index 5130305a6..000000000 --- a/frontend-new/src/chat/chatMessage/components/chatMessageFooter/__snapshots__/ChatMessageFooter.test.tsx.snap +++ /dev/null @@ -1,11 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`render tests should render the Chat Message Footer without a child if none is passed 1`] = ` - - sent - a foo years ago - -`; diff --git a/frontend-new/src/chat/chatMessage/components/chatMessageFooter/__snapshots__/ChatMessageFooterLayout.test.tsx.snap b/frontend-new/src/chat/chatMessage/components/chatMessageFooter/__snapshots__/ChatMessageFooterLayout.test.tsx.snap new file mode 100644 index 000000000..bf929723d --- /dev/null +++ b/frontend-new/src/chat/chatMessage/components/chatMessageFooter/__snapshots__/ChatMessageFooterLayout.test.tsx.snap @@ -0,0 +1,99 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`render tests should render a compass chat message footer { + name: 'with a single child', + children: [Array], + expectedTestIds: [Array] +} 1`] = ` +
+
+ Child +
+
+`; + +exports[`render tests should render a compass chat message footer { + name: 'with multiple children', + children: [Array], + expectedTestIds: [Array] +} 1`] = ` +
+
+ Child +
+
+ Child +
+
+`; + +exports[`render tests should render a compass chat message footer { name: 'without children', children: [], expectedTestIds: [] } 1`] = ` +
+`; + +exports[`render tests should render a user chat message footer { + name: 'with a single child', + children: [Array], + expectedTestIds: [Array] +} 1`] = ` +
+
+ Child +
+
+`; + +exports[`render tests should render a user chat message footer { + name: 'with multiple children', + children: [Array], + expectedTestIds: [Array] +} 1`] = ` +
+
+ Child +
+
+ Child +
+
+`; + +exports[`render tests should render a user chat message footer { name: 'without children', children: [], expectedTestIds: [] } 1`] = ` +
+`; diff --git a/frontend-new/src/chat/chatMessage/components/chatMessageFooter/components/timestamp/Timestamp.stories.tsx b/frontend-new/src/chat/chatMessage/components/chatMessageFooter/components/timestamp/Timestamp.stories.tsx new file mode 100644 index 000000000..da9ab699d --- /dev/null +++ b/frontend-new/src/chat/chatMessage/components/chatMessageFooter/components/timestamp/Timestamp.stories.tsx @@ -0,0 +1,19 @@ +import type { Meta, StoryObj } from "@storybook/react"; +import Timestamp from "./Timestamp"; + +const meta: Meta = { + title: "Chat/ChatMessageFooter/Timestamp", + component: Timestamp, + tags: ["autodocs"], + argTypes: {}, +}; + +export default meta; + +type Story = StoryObj; + +export const Shown: Story = { + args: { + sentAt: new Date().toISOString() + }, +}; \ No newline at end of file diff --git a/frontend-new/src/chat/chatMessage/components/chatMessageFooter/ChatMessageFooter.test.tsx b/frontend-new/src/chat/chatMessage/components/chatMessageFooter/components/timestamp/Timestamp.test.tsx similarity index 50% rename from frontend-new/src/chat/chatMessage/components/chatMessageFooter/ChatMessageFooter.test.tsx rename to frontend-new/src/chat/chatMessage/components/chatMessageFooter/components/timestamp/Timestamp.test.tsx index 5e8982d56..09f1877d4 100644 --- a/frontend-new/src/chat/chatMessage/components/chatMessageFooter/ChatMessageFooter.test.tsx +++ b/frontend-new/src/chat/chatMessage/components/chatMessageFooter/components/timestamp/Timestamp.test.tsx @@ -1,18 +1,18 @@ // mute the console import "src/_test_utilities/consoleMock"; -import ChatMessageFooter , { DATA_TEST_ID } from "src/chat/chatMessage/components/chatMessageFooter/ChatMessageFooter"; +import Timestamp , { DATA_TEST_ID } from "src/chat/chatMessage/components/chatMessageFooter/components/timestamp/Timestamp"; import { render, screen } from "src/_test_utilities/test-utils"; -import { getDurationFromNow } from "src/utils/getDurationFromNow/getDurationFromNow"; +import { getDurationFromNow } from "src/chat/chatMessage/components/chatMessageFooter/components/timestamp/getDurationFromNow/getDurationFromNow"; -jest.mock("src/utils/getDurationFromNow/getDurationFromNow", () => { +jest.mock("src/chat/chatMessage/components/chatMessageFooter/components/timestamp/getDurationFromNow/getDurationFromNow", () => { return { getDurationFromNow: jest.fn() } }) describe("render tests", () => { - test("should render the Chat Message Footer without a child if none is passed", () => { + test("should render the Chat Message Timestamp without a child if none is passed", () => { // GIVEN a sent at time const givenSentAt: string = new Date().toISOString() @@ -20,17 +20,17 @@ describe("render tests", () => { const givenDuration = "a foo years ago"; (getDurationFromNow as jest.Mock).mockReturnValueOnce(givenDuration); - // WHEN the Chat Message Footer is rendered - render(); + // WHEN the Chat Message Timestamp is rendered + render(); // THEN expect the timestamp to be visible - expect(screen.getByTestId(DATA_TEST_ID.CHAT_MESSAGE_TIMESTAMP)).toBeInTheDocument(); + expect(screen.getByTestId(DATA_TEST_ID.TIMESTAMP)).toBeInTheDocument(); // AND expect the getDurationFromNow method to have been called with the given sentAt as a Date object expect(getDurationFromNow).toHaveBeenCalledWith(new Date(givenSentAt)); // AND expect the given duration to be shown - expect(screen.getByTestId(DATA_TEST_ID.CHAT_MESSAGE_TIMESTAMP)).toHaveTextContent(givenDuration); + expect(screen.getByTestId(DATA_TEST_ID.TIMESTAMP)).toHaveTextContent(givenDuration); // AND expect the component to match the snapshot - expect(screen.getByTestId(DATA_TEST_ID.CHAT_MESSAGE_TIMESTAMP)).toMatchSnapshot(); + expect(screen.getByTestId(DATA_TEST_ID.TIMESTAMP)).toMatchSnapshot(); }); }); \ No newline at end of file diff --git a/frontend-new/src/chat/chatMessage/components/chatMessageFooter/ChatMessageFooter.tsx b/frontend-new/src/chat/chatMessage/components/chatMessageFooter/components/timestamp/Timestamp.tsx similarity index 57% rename from frontend-new/src/chat/chatMessage/components/chatMessageFooter/ChatMessageFooter.tsx rename to frontend-new/src/chat/chatMessage/components/chatMessageFooter/components/timestamp/Timestamp.tsx index 3b80bad74..b503ef9d9 100644 --- a/frontend-new/src/chat/chatMessage/components/chatMessageFooter/ChatMessageFooter.tsx +++ b/frontend-new/src/chat/chatMessage/components/chatMessageFooter/components/timestamp/Timestamp.tsx @@ -1,10 +1,10 @@ import { Typography, styled } from "@mui/material"; -import { getDurationFromNow } from "src/utils/getDurationFromNow/getDurationFromNow"; +import { getDurationFromNow } from "src/chat/chatMessage/components/chatMessageFooter/components/timestamp/getDurationFromNow/getDurationFromNow"; -const uniqueId = "7772f20a-9d0c-4072-b24f-97eca2f43d7b"; +const uniqueId = "c9253326-05ee-4bff-9d43-7852ca78a033"; export const DATA_TEST_ID = { - CHAT_MESSAGE_TIMESTAMP: `chat-message-sent_at-${uniqueId}`, + TIMESTAMP: `chat-message-timestamp-${uniqueId}`, }; export interface ChatMessageFooterProps { @@ -18,7 +18,7 @@ const TimeStamp = styled(Typography)(({ theme }) => ({ })); -const ChatMessageFooter: React.FC = ({ sentAt }) => { +const Timestamp: React.FC = ({ sentAt }) => { let duration; try { duration = getDurationFromNow(new Date(sentAt)); @@ -27,10 +27,10 @@ const ChatMessageFooter: React.FC = ({ sentAt }) => { } return ( - + sent {duration} ) } -export default ChatMessageFooter; \ No newline at end of file +export default Timestamp; \ No newline at end of file diff --git a/frontend-new/src/chat/chatMessage/components/chatMessageFooter/components/timestamp/__snapshots__/Timestamp.test.tsx.snap b/frontend-new/src/chat/chatMessage/components/chatMessageFooter/components/timestamp/__snapshots__/Timestamp.test.tsx.snap new file mode 100644 index 000000000..9da4f3be5 --- /dev/null +++ b/frontend-new/src/chat/chatMessage/components/chatMessageFooter/components/timestamp/__snapshots__/Timestamp.test.tsx.snap @@ -0,0 +1,11 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`render tests should render the Chat Message Timestamp without a child if none is passed 1`] = ` + + sent + a foo years ago + +`; diff --git a/frontend-new/src/utils/getDurationFromNow/getDurationFromNow.test.ts b/frontend-new/src/chat/chatMessage/components/chatMessageFooter/components/timestamp/getDurationFromNow/getDurationFromNow.test.ts similarity index 100% rename from frontend-new/src/utils/getDurationFromNow/getDurationFromNow.test.ts rename to frontend-new/src/chat/chatMessage/components/chatMessageFooter/components/timestamp/getDurationFromNow/getDurationFromNow.test.ts diff --git a/frontend-new/src/utils/getDurationFromNow/getDurationFromNow.ts b/frontend-new/src/chat/chatMessage/components/chatMessageFooter/components/timestamp/getDurationFromNow/getDurationFromNow.ts similarity index 100% rename from frontend-new/src/utils/getDurationFromNow/getDurationFromNow.ts rename to frontend-new/src/chat/chatMessage/components/chatMessageFooter/components/timestamp/getDurationFromNow/getDurationFromNow.ts diff --git a/frontend-new/src/chat/chatMessage/conversationConclusionChatMessage/ConversationConclusionChatMessage.test.tsx b/frontend-new/src/chat/chatMessage/conversationConclusionChatMessage/ConversationConclusionChatMessage.test.tsx index e4badc304..c7c66fc5a 100644 --- a/frontend-new/src/chat/chatMessage/conversationConclusionChatMessage/ConversationConclusionChatMessage.test.tsx +++ b/frontend-new/src/chat/chatMessage/conversationConclusionChatMessage/ConversationConclusionChatMessage.test.tsx @@ -8,6 +8,7 @@ import { render, screen } from "src/_test_utilities/test-utils"; import { ConversationMessageSender } from "src/chat/ChatService/ChatService.types"; import { nanoid } from "nanoid"; import { ChatMessageType, IChatMessage } from "src/chat/Chat.types"; +import { Divider } from "@mui/material"; jest.mock("src/chat/chatMessage/components/chatBubble/ChatBubble", () => { const originalModule = jest.requireActual("src/chat/chatMessage/components/chatBubble/ChatBubble"); @@ -51,13 +52,18 @@ describe("render tests", () => { // AND expect the conversation conclusion footer to be visible const call = (ChatBubble as jest.Mock).mock.calls.at(-1)[0]; - expect(call.footer).toEqual( - expect.objectContaining({ + expect(call.children).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + type: Divider, + }), + expect.objectContaining({ type: ConversationConclusionFooter, props: expect.objectContaining({ notifyOnFeedbackFormOpened: givenNotifyOnFeedbackFormOpened, }), - }) + }), + ]) ); // AND expect the Chat bubble to have been rendered with the expected message diff --git a/frontend-new/src/chat/chatMessage/conversationConclusionChatMessage/ConversationConclusionChatMessage.tsx b/frontend-new/src/chat/chatMessage/conversationConclusionChatMessage/ConversationConclusionChatMessage.tsx index c7bea673c..68a7be62e 100644 --- a/frontend-new/src/chat/chatMessage/conversationConclusionChatMessage/ConversationConclusionChatMessage.tsx +++ b/frontend-new/src/chat/chatMessage/conversationConclusionChatMessage/ConversationConclusionChatMessage.tsx @@ -4,11 +4,12 @@ import { MessageContainer } from "src/chat/chatMessage/basicChatMessage/BasicCha import ConversationConclusionFooter from "src/chat/chatMessage/conversationConclusionChatMessage/conversationConclusionFooter/ConversationConclusionFooter"; import ChatBubble from "src/chat/chatMessage/components/chatBubble/ChatBubble"; +import { Divider, useTheme } from "@mui/material" const uniqueId = "2fbaf2ef-9eab-485a-bd28-b4a164e18b06"; export const DATA_TEST_ID = { - CONVERSATION_CONCLUSION_CHAT_MESSAGE_CONTAINER: `conversation_conclusion_chat-message-container-${uniqueId}`, + CONVERSATION_CONCLUSION_CHAT_MESSAGE_CONTAINER: `conversation_conclusion_chat-message-container-${uniqueId}` }; type ConversationConclusionChatMessageProps = { @@ -17,9 +18,16 @@ type ConversationConclusionChatMessageProps = { }; const ConversationConclusionChatMessage: React.FC = ({ chatMessage, notifyOnFeedbackFormOpened }) => { + const theme = useTheme() return ( - }/> + + + + ); };