Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
bd4e943
feat: add sliding container infrastructure to playgroundComponent
Nov 30, 2025
8536303
chore: add formatting changes to codeAreaModalComponent test
Nov 30, 2025
1d59383
style: add border-radius to flow canvas and update Share button styling
Nov 30, 2025
82a8fcf
fix: add sessionStorage fallback and update types (any -> unknown)
Nov 30, 2025
9969cd6
feat: add chat-header feature to sliding container
Nov 30, 2025
289a190
refactor: simplify FlowPageSlidingContainerContent by extracting sess…
Nov 30, 2025
e45a57d
fix: restore session rename persistence logic from slide-chat-header …
Nov 30, 2025
617624a
chore: revert formatting-only files to main (moved to infrastructure …
Nov 30, 2025
7b30e46
chore: sync formatting files with infrastructure branch
Nov 30, 2025
41970b8
rebase conflicts
Nov 30, 2025
391970c
removed unecessary comment
Dec 1, 2025
a49364a
fix: update messages store when renaming session to prevent content s…
Dec 1, 2025
aa611ff
Refactor playground messages component
Dec 1, 2025
4b9c008
Add Messages component to FlowPageSlidingContainerContent
Dec 1, 2025
bcceaac
Fix message filtering logic to handle default session correctly
Dec 1, 2025
d845a21
Fetch messages in useChatHistory using useGetMessagesQuery
Dec 1, 2025
cf7cb96
Fix API params: do not send session_id if it matches flow_id (default…
Dec 1, 2025
e3a7090
Remove max-width constraints on messages for 100% width
Dec 1, 2025
faf5a32
Align chat header title to the left in fullscreen mode and add padding
Dec 1, 2025
cb14665
Fix fullscreen sidebar layout using flex instead of absolute positioning
Dec 1, 2025
79177ac
Restructure layout: move ChatHeader inside flex column to match messa…
Dec 1, 2025
339abdf
Remove SessionMoreMenu from fullscreen header
Dec 1, 2025
7c780e6
Add tests for ChatMessage component
Dec 1, 2025
3de866a
Update chat message design: remove sender name, update avatars
Dec 1, 2025
6b9db37
refactor: split chat-message into separate bot-message and user-messa…
Dec 1, 2025
4ac9f5a
refactor(ui): remove Sessions icon and adjust padding when playground…
Dec 3, 2025
44e0d03
test: add ChatSidebar component tests
Dec 3, 2025
2e29e3a
refactor: rename content-view.tsx to error-message.tsx
Dec 3, 2025
6508df8
refactor: rename chat-logo-icon.tsx to bot-message-logo.tsx
Dec 3, 2025
9a1b1c7
fix: replace any types with proper TypeScript types in error-message.tsx
Dec 3, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ export default function PublishDropdown({
<Button
variant="ghost"
size="md"
className="!px-2.5 font-normal"
className="!px-2.5 font-normal !bg-white !text-black hover:!bg-gray-100"
data-testid="publish-button"
>
Share
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import ForwardedIconComponent from "@/components/common/genericIconComponent";
import ShadTooltip from "@/components/common/shadTooltipComponent";
import { PlaygroundButtonSliding } from "@/components/core/playgroundComponent/sliding-container/components";
import { PLAYGROUND_BUTTON_NAME } from "@/constants/constants";
import { CustomIOModal } from "@/customization/components/custom-new-modal";
// Will be reverted before merging this PR - IOModal commented out to test sliding container
// import { CustomIOModal } from "@/customization/components/custom-new-modal";
import { ENABLE_PUBLISH } from "@/customization/feature-flags";

interface PlaygroundButtonProps {
Expand Down Expand Up @@ -49,22 +51,26 @@ const PlaygroundButton = ({
setOpen,
canvasOpen,
}: PlaygroundButtonProps) => {
return hasIO ? (
<CustomIOModal
open={open}
setOpen={setOpen}
disable={!hasIO}
canvasOpen={canvasOpen}
>
<ActiveButton />
</CustomIOModal>
) : (
<ShadTooltip content="Add a Chat Input or Chat Output to use the playground">
<div>
<DisabledButton />
</div>
</ShadTooltip>
);
// Will be reverted before merging this PR - IOModal commented out to test sliding container
// return hasIO ? (
// <CustomIOModal
// open={open}
// setOpen={setOpen}
// disable={!hasIO}
// canvasOpen={canvasOpen}
// >
// <ActiveButton />
// </CustomIOModal>
// ) : (
// <ShadTooltip content="Add a Chat Input or Chat Output to use the playground">
// <div>
// <DisabledButton />
// </div>
// </ShadTooltip>
// );

// New sliding container implementation for testing
return <PlaygroundButtonSliding hasIO={hasIO} />;
};

export default PlaygroundButton;
Original file line number Diff line number Diff line change
@@ -0,0 +1,221 @@
import { render, screen } from "@testing-library/react";
import { ChatHeader } from "../chat-header";

// Mock dependencies
jest.mock("@/components/common/genericIconComponent", () => ({
__esModule: true,
default: ({ name, className }: { name: string; className?: string }) => (
<div data-testid={`icon-${name}`} className={className} />
),
}));

jest.mock("@/components/common/shadTooltipComponent", () => ({
__esModule: true,
default: ({
children,
content,
}: {
children: React.ReactNode;
content: string;
}) => <div data-testid={`tooltip-${content}`}>{children}</div>,
}));

jest.mock("@/components/ui/select-custom", () => ({
Select: ({
children,
value,
onValueChange,
}: {
children: React.ReactNode;
value: string;
onValueChange?: (value: string) => void;
}) => (
<div data-testid="select" data-value={value}>
{children}
</div>
),
SelectTrigger: ({
children,
onClick,
...props
}: {
children: React.ReactNode;
onClick?: (e: React.MouseEvent) => void;
} & Record<string, unknown>) => (
<button data-testid="select-trigger" onClick={onClick} {...props}>
{children}
</button>
),
SelectContent: ({ children }: { children: React.ReactNode }) => (
<div data-testid="select-content">{children}</div>
),
SelectItem: ({
children,
value,
onClick,
}: {
children: React.ReactNode;
value: string;
onClick?: () => void;
}) => (
<div data-testid={`select-item-${value}`} onClick={() => onClick?.()}>
{children}
</div>
),
}));

jest.mock("@/controllers/API/queries/messages/use-rename-session", () => ({
useUpdateSessionName: () => ({
mutate: jest.fn(),
}),
}));

jest.mock("../chat-sessions-dropdown", () => ({
ChatSessionsDropdown: ({
onNewChat,
onSessionSelect,
currentSessionId,
}: {
onNewChat?: () => void;
onSessionSelect?: (sessionId: string) => void;
currentSessionId?: string;
}) => (
<div
data-testid="chat-sessions-dropdown"
data-current-session={currentSessionId}
>
<button data-testid="dropdown-new-chat" onClick={onNewChat}>
New Chat
</button>
<button
data-testid="dropdown-select-session"
onClick={() => onSessionSelect?.("session-1")}
>
Select Session
</button>
</div>
),
}));

jest.mock("../session-logs-modal", () => ({
SessionLogsModal: ({
open,
sessionId,
}: {
open: boolean;
sessionId: string;
}) =>
open ? (
<div data-testid="session-logs-modal" data-session-id={sessionId} />
) : null,
}));

jest.mock("../session-rename", () => ({
SessionRename: ({
sessionId,
onSave,
}: {
sessionId?: string;
onSave?: (value: string) => void;
}) => (
<div data-testid="session-rename">
<input
data-testid="rename-input"
defaultValue={sessionId}
onBlur={(e) => onSave?.(e.target.value)}
/>
</div>
),
}));

describe("ChatHeader", () => {
const defaultProps = {
currentSessionId: "session-1",
currentFlowId: "flow-1",
onNewChat: jest.fn(),
onSessionSelect: jest.fn(),
onToggleFullscreen: jest.fn(),
onDeleteSession: jest.fn(),
onClose: jest.fn(),
};

beforeEach(() => {
jest.clearAllMocks();
});

it("renders the component", () => {
render(<ChatHeader {...defaultProps} />);
expect(screen.getByText("session-1")).toBeInTheDocument();
});

it("displays 'Chat' when no session is selected", () => {
render(<ChatHeader {...defaultProps} currentSessionId={undefined} />);
expect(screen.getByText("Chat")).toBeInTheDocument();
});

it("displays 'Default Session' when currentSessionId equals currentFlowId", () => {
render(
<ChatHeader
{...defaultProps}
currentSessionId="flow-1"
currentFlowId="flow-1"
/>,
);
expect(screen.getByText("Default Session")).toBeInTheDocument();
});

it("displays the session ID as title when it's not the default session", () => {
render(<ChatHeader {...defaultProps} />);
expect(screen.getByText("session-1")).toBeInTheDocument();
});

it("shows sessions dropdown when not in fullscreen", () => {
render(<ChatHeader {...defaultProps} isFullscreen={false} />);
expect(screen.getByTestId("chat-sessions-dropdown")).toBeInTheDocument();
});

it("shows fullscreen toggle button", () => {
render(<ChatHeader {...defaultProps} />);
const toggleButton = screen.getByLabelText("Enter fullscreen");
expect(toggleButton).toBeInTheDocument();
});

it("shows exit fullscreen button when in fullscreen", () => {
render(<ChatHeader {...defaultProps} isFullscreen={true} />);
const toggleButton = screen.getByLabelText("Exit fullscreen");
expect(toggleButton).toBeInTheDocument();
});

it("shows close button when in fullscreen", () => {
render(<ChatHeader {...defaultProps} isFullscreen={true} />);
const closeButton = screen.getByLabelText("Close and go back to flow");
expect(closeButton).toBeInTheDocument();
});

it("calls onToggleFullscreen when toggle button is clicked", () => {
const onToggleFullscreen = jest.fn();
render(
<ChatHeader {...defaultProps} onToggleFullscreen={onToggleFullscreen} />,
);
const toggleButton = screen.getByLabelText("Enter fullscreen");
toggleButton.click();
expect(onToggleFullscreen).toHaveBeenCalledTimes(1);
});

it("calls onClose when close button is clicked in fullscreen", () => {
const onClose = jest.fn();
render(
<ChatHeader {...defaultProps} isFullscreen={true} onClose={onClose} />,
);
const closeButton = screen.getByLabelText("Close and go back to flow");
closeButton.click();
expect(onClose).toHaveBeenCalledTimes(1);
});

it("applies custom className", () => {
const { container } = render(
<ChatHeader {...defaultProps} className="custom-class" />,
);
expect(container.firstChild).toHaveClass("custom-class");
});
});
Loading