feat(FN-3906): add Chat Rooms experimental feature with Settings toggle
Added an experimental Chat Rooms feature gated behind a settings toggle in the dashboard. The ChatView rooms UI is now conditionally rendered based on the experimental features setting, controlled via the SettingsModal. Included documentation updates and corresponding test coverage. Fusion-Task-Id: FN-3906
This commit is contained in:
5
.changeset/fn-3906-chat-rooms-experimental.md
Normal file
5
.changeset/fn-3906-chat-rooms-experimental.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@runfusion/fusion": patch
|
||||
---
|
||||
|
||||
Hide Chat Rooms behind the `chatRooms` experimental flag. By default, Chat now shows direct-chat-only UI; re-enable rooms via **Settings → Experimental Features → Chat Rooms**.
|
||||
@@ -99,6 +99,7 @@ Chat view provides project-scoped conversations with agents.
|
||||
|
||||
Chat Rooms are project-scoped group conversations for multiple agents. They are separate from one-on-one direct chat sessions.
|
||||
|
||||
- Chat Rooms are currently gated behind the `chatRooms` experimental feature flag. Enable it in **Settings → Experimental Features → Chat Rooms**.
|
||||
- Use the **Direct / Rooms** toggle in the Chat sidebar to switch scopes. The selected scope is saved and restored the next time you open Chat.
|
||||
- In **Rooms**, click **Create room** to open the room-creation modal.
|
||||
- Room names follow strict validation: a leading `#` is removed automatically, names must be lowercase, up to 80 characters, use only `a-z`, `0-9`, `-`, or `_`, cannot start or end with `-`/`_`, and must be unique in the current project.
|
||||
|
||||
@@ -1220,7 +1220,11 @@ function AppInner() {
|
||||
return (
|
||||
<PageErrorBoundary>
|
||||
<Suspense fallback={null}>
|
||||
<ChatView addToast={addToast} projectId={currentProject?.id} />
|
||||
<ChatView
|
||||
addToast={addToast}
|
||||
projectId={currentProject?.id}
|
||||
experimentalFeatures={experimentalFeatures}
|
||||
/>
|
||||
</Suspense>
|
||||
</PageErrorBoundary>
|
||||
);
|
||||
|
||||
@@ -44,6 +44,7 @@ import { matchesAgentMentionFilter } from "./mentionMatching";
|
||||
export interface ChatViewProps {
|
||||
projectId?: string;
|
||||
addToast: (msg: string, type?: "success" | "error" | "warning") => void;
|
||||
experimentalFeatures?: Record<string, boolean>;
|
||||
}
|
||||
|
||||
function formatRelativeTime(dateStr: string): string {
|
||||
@@ -709,7 +710,7 @@ const ChatMessageItem = memo(function ChatMessageItem({
|
||||
);
|
||||
});
|
||||
|
||||
export function ChatView({ projectId, addToast }: ChatViewProps) {
|
||||
export function ChatView({ projectId, addToast, experimentalFeatures }: ChatViewProps) {
|
||||
const {
|
||||
activeSession,
|
||||
sessionsLoading,
|
||||
@@ -741,6 +742,9 @@ export function ChatView({ projectId, addToast }: ChatViewProps) {
|
||||
const [sidebarWidth, setSidebarWidth] = useState(CHAT_SIDEBAR_DEFAULT_WIDTH);
|
||||
const [chatScope, setChatScope] = useState<"direct" | "rooms">("direct");
|
||||
const [createRoomOpen, setCreateRoomOpen] = useState(false);
|
||||
const chatRoomsEnabled = experimentalFeatures?.chatRooms === true;
|
||||
// Keep this hook unconditional to preserve hook ordering and test stability.
|
||||
// Rooms UI and interactions are fully gated by `chatRoomsEnabled`.
|
||||
const rooms = useChatRooms(projectId, addToast);
|
||||
const [agentsMap, setAgentsMap] = useState<Map<string, Agent>>(new Map());
|
||||
const [discoveredSkills, setDiscoveredSkills] = useState<DiscoveredSkill[]>([]);
|
||||
@@ -813,21 +817,29 @@ export function ChatView({ projectId, addToast }: ChatViewProps) {
|
||||
useEffect(() => {
|
||||
try {
|
||||
const persistedScope = localStorage.getItem(CHAT_SCOPE_STORAGE_KEY);
|
||||
if (persistedScope === "direct" || persistedScope === "rooms") {
|
||||
setChatScope(persistedScope);
|
||||
if (persistedScope === "direct") {
|
||||
setChatScope("direct");
|
||||
return;
|
||||
}
|
||||
if (persistedScope === "rooms" && chatRoomsEnabled) {
|
||||
setChatScope("rooms");
|
||||
}
|
||||
} catch {
|
||||
// Ignore storage errors.
|
||||
}
|
||||
}, []);
|
||||
}, [chatRoomsEnabled]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!chatRoomsEnabled && chatScope === "rooms") {
|
||||
setChatScope("direct");
|
||||
return;
|
||||
}
|
||||
try {
|
||||
localStorage.setItem(CHAT_SCOPE_STORAGE_KEY, chatScope);
|
||||
} catch {
|
||||
// Ignore storage errors.
|
||||
}
|
||||
}, [chatScope]);
|
||||
}, [chatRoomsEnabled, chatScope]);
|
||||
|
||||
const { keyboardOverlap, viewportHeight, viewportOffsetTop, keyboardOpen } = useMobileKeyboard({
|
||||
enabled: isMobile && !!activeSession,
|
||||
@@ -1229,7 +1241,7 @@ export function ChatView({ projectId, addToast }: ChatViewProps) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (chatScope === "rooms") {
|
||||
if (chatRoomsEnabled && chatScope === "rooms") {
|
||||
if (!rooms.activeRoom) {
|
||||
return;
|
||||
}
|
||||
@@ -1239,7 +1251,7 @@ export function ChatView({ projectId, addToast }: ChatViewProps) {
|
||||
}
|
||||
|
||||
handleSend();
|
||||
}, [messageInput, chatScope, rooms, handleSend]);
|
||||
}, [messageInput, chatRoomsEnabled, chatScope, rooms, handleSend]);
|
||||
|
||||
const handleSkillSelect = useCallback(
|
||||
(skill: DiscoveredSkill) => {
|
||||
@@ -1759,29 +1771,31 @@ export function ChatView({ projectId, addToast }: ChatViewProps) {
|
||||
className={`chat-sidebar${!sidebarVisible ? " chat-sidebar--hidden" : ""}`}
|
||||
style={isMobile ? undefined : { width: `${sidebarWidth}px` }}
|
||||
>
|
||||
<div className="chat-sidebar-scope-toggle" role="tablist" data-testid="chat-sidebar-scope-toggle">
|
||||
<button
|
||||
type="button"
|
||||
role="tab"
|
||||
className={`chat-sidebar-scope-btn${chatScope === "direct" ? " chat-sidebar-scope-btn--active" : ""}`}
|
||||
aria-selected={chatScope === "direct"}
|
||||
data-testid="chat-sidebar-scope-direct"
|
||||
onClick={() => setChatScope("direct")}
|
||||
>
|
||||
Direct
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
role="tab"
|
||||
className={`chat-sidebar-scope-btn${chatScope === "rooms" ? " chat-sidebar-scope-btn--active" : ""}`}
|
||||
aria-selected={chatScope === "rooms"}
|
||||
data-testid="chat-sidebar-scope-rooms"
|
||||
onClick={() => setChatScope("rooms")}
|
||||
>
|
||||
Rooms
|
||||
</button>
|
||||
</div>
|
||||
{chatScope === "direct" ? (
|
||||
{chatRoomsEnabled && (
|
||||
<div className="chat-sidebar-scope-toggle" role="tablist" data-testid="chat-sidebar-scope-toggle">
|
||||
<button
|
||||
type="button"
|
||||
role="tab"
|
||||
className={`chat-sidebar-scope-btn${chatScope === "direct" ? " chat-sidebar-scope-btn--active" : ""}`}
|
||||
aria-selected={chatScope === "direct"}
|
||||
data-testid="chat-sidebar-scope-direct"
|
||||
onClick={() => setChatScope("direct")}
|
||||
>
|
||||
Direct
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
role="tab"
|
||||
className={`chat-sidebar-scope-btn${chatScope === "rooms" ? " chat-sidebar-scope-btn--active" : ""}`}
|
||||
aria-selected={chatScope === "rooms"}
|
||||
data-testid="chat-sidebar-scope-rooms"
|
||||
onClick={() => setChatScope("rooms")}
|
||||
>
|
||||
Rooms
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
{!chatRoomsEnabled || chatScope === "direct" ? (
|
||||
<>
|
||||
{/* Search section */}
|
||||
<div className="chat-sidebar-search-container">
|
||||
@@ -1999,7 +2013,7 @@ export function ChatView({ projectId, addToast }: ChatViewProps) {
|
||||
</div>
|
||||
)}
|
||||
|
||||
{confirmDeleteRoomId && (
|
||||
{chatRoomsEnabled && confirmDeleteRoomId && (
|
||||
<div className="chat-new-dialog-backdrop chat-view-dialog-backdrop" onClick={() => setConfirmDeleteRoomId(null)}>
|
||||
<div className="chat-new-dialog chat-view-dialog" onClick={(e) => e.stopPropagation()}>
|
||||
<h3>Delete Room?</h3>
|
||||
@@ -2030,7 +2044,7 @@ export function ChatView({ projectId, addToast }: ChatViewProps) {
|
||||
</div>
|
||||
)}
|
||||
{/* Thread */}
|
||||
{chatScope === "rooms" ? (
|
||||
{chatRoomsEnabled && chatScope === "rooms" ? (
|
||||
<div className="chat-thread">
|
||||
{rooms.activeRoom ? (
|
||||
<>
|
||||
@@ -2460,16 +2474,18 @@ export function ChatView({ projectId, addToast }: ChatViewProps) {
|
||||
</div>
|
||||
)}
|
||||
|
||||
<CreateRoomModal
|
||||
isOpen={createRoomOpen}
|
||||
onClose={() => setCreateRoomOpen(false)}
|
||||
projectId={projectId}
|
||||
existingRoomNames={rooms.rooms.map((room) => room.name)}
|
||||
onCreate={async (draft) => {
|
||||
await rooms.createRoom({ name: draft.name, memberAgentIds: draft.memberAgentIds });
|
||||
setCreateRoomOpen(false);
|
||||
}}
|
||||
/>
|
||||
{chatRoomsEnabled && (
|
||||
<CreateRoomModal
|
||||
isOpen={createRoomOpen}
|
||||
onClose={() => setCreateRoomOpen(false)}
|
||||
projectId={projectId}
|
||||
existingRoomNames={rooms.rooms.map((room) => room.name)}
|
||||
onCreate={async (draft) => {
|
||||
await rooms.createRoom({ name: draft.name, memberAgentIds: draft.memberAgentIds });
|
||||
setCreateRoomOpen(false);
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
|
||||
{/* New Chat Dialog (rendered at root level) */}
|
||||
{showNewDialog && (
|
||||
|
||||
@@ -280,6 +280,7 @@ const KNOWN_EXPERIMENTAL_FEATURES: Record<string, string> = {
|
||||
todoView: "Todo List",
|
||||
researchView: "Research View",
|
||||
evalsView: "Evals View",
|
||||
chatRooms: "Chat Rooms",
|
||||
agentOnboarding: "Planning-style Agent Onboarding",
|
||||
};
|
||||
|
||||
|
||||
@@ -67,7 +67,7 @@ describe("ChatView rooms", () => {
|
||||
});
|
||||
mockUseChatRooms.mockReturnValue(roomsMock);
|
||||
|
||||
render(<ChatView addToast={vi.fn()} projectId="proj-1" />);
|
||||
render(<ChatView addToast={vi.fn()} projectId="proj-1" experimentalFeatures={{ chatRooms: true }} />);
|
||||
await userEvent.click(screen.getByTestId("chat-sidebar-scope-rooms"));
|
||||
await userEvent.click(screen.getByTestId("chat-room-item-engineering"));
|
||||
|
||||
@@ -80,7 +80,7 @@ describe("ChatView rooms", () => {
|
||||
const roomsMock = buildRoomsMock({ rooms: [] });
|
||||
mockUseChatRooms.mockReturnValue(roomsMock);
|
||||
|
||||
render(<ChatView addToast={vi.fn()} projectId="proj-1" />);
|
||||
render(<ChatView addToast={vi.fn()} projectId="proj-1" experimentalFeatures={{ chatRooms: true }} />);
|
||||
await userEvent.click(screen.getByTestId("chat-sidebar-scope-rooms"));
|
||||
await userEvent.click(screen.getByTestId("chat-create-room-btn"));
|
||||
await userEvent.type(screen.getByLabelText("Room name"), "product");
|
||||
@@ -100,7 +100,7 @@ describe("ChatView rooms", () => {
|
||||
});
|
||||
mockUseChatRooms.mockReturnValue(roomsMock);
|
||||
|
||||
render(<ChatView addToast={vi.fn()} projectId="proj-1" />);
|
||||
render(<ChatView addToast={vi.fn()} projectId="proj-1" experimentalFeatures={{ chatRooms: true }} />);
|
||||
await userEvent.click(screen.getByTestId("chat-sidebar-scope-rooms"));
|
||||
await userEvent.click(screen.getByTestId("chat-room-item-engineering"));
|
||||
|
||||
@@ -113,7 +113,7 @@ describe("ChatView rooms", () => {
|
||||
});
|
||||
mockUseChatRooms.mockReturnValue(roomsMock);
|
||||
|
||||
render(<ChatView addToast={vi.fn()} projectId="proj-1" />);
|
||||
render(<ChatView addToast={vi.fn()} projectId="proj-1" experimentalFeatures={{ chatRooms: true }} />);
|
||||
await userEvent.click(screen.getByTestId("chat-sidebar-scope-rooms"));
|
||||
await userEvent.type(screen.getByTestId("chat-input"), "hello room");
|
||||
await userEvent.click(screen.getByTestId("chat-send-btn"));
|
||||
@@ -128,7 +128,7 @@ describe("ChatView rooms", () => {
|
||||
});
|
||||
mockUseChatRooms.mockReturnValue(roomsMock);
|
||||
|
||||
render(<ChatView addToast={vi.fn()} projectId="proj-1" />);
|
||||
render(<ChatView addToast={vi.fn()} projectId="proj-1" experimentalFeatures={{ chatRooms: true }} />);
|
||||
await userEvent.click(screen.getByTestId("chat-sidebar-scope-rooms"));
|
||||
await userEvent.type(screen.getByTestId("chat-input"), " hello room from enter ");
|
||||
await userEvent.keyboard("{Enter}");
|
||||
@@ -144,7 +144,7 @@ describe("ChatView rooms", () => {
|
||||
});
|
||||
mockUseChatRooms.mockReturnValue(roomsMock);
|
||||
|
||||
render(<ChatView addToast={vi.fn()} projectId="proj-1" />);
|
||||
render(<ChatView addToast={vi.fn()} projectId="proj-1" experimentalFeatures={{ chatRooms: true }} />);
|
||||
await userEvent.click(screen.getByTestId("chat-sidebar-scope-rooms"));
|
||||
await userEvent.click(screen.getByTestId("chat-room-delete-engineering"));
|
||||
|
||||
@@ -158,7 +158,7 @@ describe("ChatView rooms", () => {
|
||||
});
|
||||
mockUseChatRooms.mockReturnValue(roomsMock);
|
||||
|
||||
render(<ChatView addToast={vi.fn()} projectId="proj-1" />);
|
||||
render(<ChatView addToast={vi.fn()} projectId="proj-1" experimentalFeatures={{ chatRooms: true }} />);
|
||||
await userEvent.click(screen.getByTestId("chat-sidebar-scope-rooms"));
|
||||
await userEvent.click(screen.getByTestId("chat-room-delete-engineering"));
|
||||
await userEvent.click(screen.getByRole("button", { name: "Delete" }));
|
||||
@@ -173,7 +173,7 @@ describe("ChatView rooms", () => {
|
||||
});
|
||||
mockUseChatRooms.mockReturnValue(roomsMock);
|
||||
|
||||
render(<ChatView addToast={vi.fn()} projectId="proj-1" />);
|
||||
render(<ChatView addToast={vi.fn()} projectId="proj-1" experimentalFeatures={{ chatRooms: true }} />);
|
||||
await userEvent.click(screen.getByTestId("chat-sidebar-scope-rooms"));
|
||||
await userEvent.click(screen.getByTestId("chat-room-delete-engineering"));
|
||||
await userEvent.click(screen.getByRole("button", { name: "Cancel" }));
|
||||
@@ -189,11 +189,11 @@ describe("ChatView rooms", () => {
|
||||
});
|
||||
mockUseChatRooms.mockImplementation(() => state);
|
||||
|
||||
const { rerender } = render(<ChatView addToast={vi.fn()} projectId="proj-1" />);
|
||||
const { rerender } = render(<ChatView addToast={vi.fn()} projectId="proj-1" experimentalFeatures={{ chatRooms: true }} />);
|
||||
await userEvent.click(screen.getByTestId("chat-sidebar-scope-rooms"));
|
||||
|
||||
state.messages = [{ id: "msg-2", roomId: "room-1", role: "assistant", content: "reply", thinkingOutput: null, metadata: null, senderAgentId: "agent-1", mentions: [], createdAt: "2026-05-09T00:00:00.000Z" }];
|
||||
rerender(<ChatView addToast={vi.fn()} projectId="proj-1" />);
|
||||
rerender(<ChatView addToast={vi.fn()} projectId="proj-1" experimentalFeatures={{ chatRooms: true }} />);
|
||||
|
||||
expect(screen.getByText("reply")).toBeInTheDocument();
|
||||
});
|
||||
|
||||
@@ -2436,13 +2436,22 @@ describe("Direct/Rooms scope toggle", () => {
|
||||
localStorage.clear();
|
||||
});
|
||||
|
||||
it("hides rooms UI when chatRooms experimental flag is off", () => {
|
||||
setupMockChat({ sessions: [], filteredSessions: [] });
|
||||
|
||||
render(<ChatView projectId="proj-123" addToast={vi.fn()} experimentalFeatures={{}} />);
|
||||
|
||||
expect(screen.queryByTestId("chat-sidebar-scope-rooms")).not.toBeInTheDocument();
|
||||
expect(screen.queryByTestId("chat-sidebar-rooms")).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("defaults to Direct with sidebar list visible", () => {
|
||||
setupMockChat({
|
||||
sessions: [{ id: "session-001", agentId: "agent-001", status: "active", title: "Test Chat", createdAt: "2026-04-08T00:00:00.000Z", updatedAt: "2026-04-08T00:00:00.000Z" }],
|
||||
filteredSessions: [{ id: "session-001", agentId: "agent-001", status: "active", title: "Test Chat", createdAt: "2026-04-08T00:00:00.000Z", updatedAt: "2026-04-08T00:00:00.000Z" }],
|
||||
});
|
||||
|
||||
render(<ChatView projectId="proj-123" addToast={vi.fn()} />);
|
||||
render(<ChatView projectId="proj-123" addToast={vi.fn()} experimentalFeatures={{ chatRooms: true }} />);
|
||||
|
||||
expect(screen.getByTestId("chat-sidebar-scope-direct")).toHaveAttribute("aria-selected", "true");
|
||||
expect(screen.getByTestId("chat-sidebar-scope-rooms")).toHaveAttribute("aria-selected", "false");
|
||||
@@ -2450,13 +2459,23 @@ describe("Direct/Rooms scope toggle", () => {
|
||||
expect(screen.queryByTestId("chat-sidebar-rooms-empty")).toBeNull();
|
||||
});
|
||||
|
||||
it("shows rooms UI when chatRooms experimental flag is on", async () => {
|
||||
setupMockChat({ sessions: [], filteredSessions: [] });
|
||||
|
||||
render(<ChatView projectId="proj-123" addToast={vi.fn()} experimentalFeatures={{ chatRooms: true }} />);
|
||||
|
||||
expect(screen.getByTestId("chat-sidebar-scope-rooms")).toBeInTheDocument();
|
||||
await userEvent.click(screen.getByTestId("chat-sidebar-scope-rooms"));
|
||||
expect(screen.getByTestId("chat-sidebar-rooms")).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("shows rooms placeholder and hides direct search/list in Rooms scope", async () => {
|
||||
setupMockChat({
|
||||
sessions: [{ id: "session-001", agentId: "agent-001", status: "active", title: "Test Chat", createdAt: "2026-04-08T00:00:00.000Z", updatedAt: "2026-04-08T00:00:00.000Z" }],
|
||||
filteredSessions: [{ id: "session-001", agentId: "agent-001", status: "active", title: "Test Chat", createdAt: "2026-04-08T00:00:00.000Z", updatedAt: "2026-04-08T00:00:00.000Z" }],
|
||||
});
|
||||
|
||||
render(<ChatView projectId="proj-123" addToast={vi.fn()} />);
|
||||
render(<ChatView projectId="proj-123" addToast={vi.fn()} experimentalFeatures={{ chatRooms: true }} />);
|
||||
|
||||
await userEvent.click(screen.getByTestId("chat-sidebar-scope-rooms"));
|
||||
|
||||
@@ -2473,7 +2492,7 @@ describe("Direct/Rooms scope toggle", () => {
|
||||
filteredSessions: [{ id: "session-001", agentId: "agent-001", status: "active", title: "Test Chat", createdAt: "2026-04-08T00:00:00.000Z", updatedAt: "2026-04-08T00:00:00.000Z" }],
|
||||
});
|
||||
|
||||
render(<ChatView projectId="proj-123" addToast={vi.fn()} />);
|
||||
render(<ChatView projectId="proj-123" addToast={vi.fn()} experimentalFeatures={{ chatRooms: true }} />);
|
||||
|
||||
await userEvent.click(screen.getByTestId("chat-sidebar-scope-rooms"));
|
||||
await userEvent.click(screen.getByTestId("chat-sidebar-scope-direct"));
|
||||
@@ -2483,17 +2502,27 @@ describe("Direct/Rooms scope toggle", () => {
|
||||
expect(screen.getByTestId("chat-session-session-001")).toHaveClass("chat-session-item--active");
|
||||
});
|
||||
|
||||
it("forces direct scope when localStorage persisted rooms but chatRooms is off", () => {
|
||||
setupMockChat({ sessions: [], filteredSessions: [] });
|
||||
localStorage.setItem("fusion:chat-scope", "rooms");
|
||||
|
||||
render(<ChatView projectId="proj-123" addToast={vi.fn()} experimentalFeatures={{}} />);
|
||||
|
||||
expect(screen.queryByTestId("chat-sidebar-scope-rooms")).not.toBeInTheDocument();
|
||||
expect(screen.getByTestId("chat-search-input")).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("persists scope in localStorage and restores Rooms on next mount", async () => {
|
||||
setupMockChat({ sessions: [], filteredSessions: [] });
|
||||
|
||||
const { unmount } = render(<ChatView projectId="proj-123" addToast={vi.fn()} />);
|
||||
const { unmount } = render(<ChatView projectId="proj-123" addToast={vi.fn()} experimentalFeatures={{ chatRooms: true }} />);
|
||||
|
||||
await userEvent.click(screen.getByTestId("chat-sidebar-scope-rooms"));
|
||||
expect(localStorage.getItem("fusion:chat-scope")).toBe("rooms");
|
||||
|
||||
unmount();
|
||||
|
||||
render(<ChatView projectId="proj-123" addToast={vi.fn()} />);
|
||||
render(<ChatView projectId="proj-123" addToast={vi.fn()} experimentalFeatures={{ chatRooms: true }} />);
|
||||
|
||||
expect(screen.getByTestId("chat-sidebar-scope-rooms")).toHaveAttribute("aria-selected", "true");
|
||||
expect(screen.getByTestId("chat-sidebar-rooms-empty")).toBeInTheDocument();
|
||||
@@ -3206,7 +3235,9 @@ describe("ChatView mobile behavior", () => {
|
||||
|
||||
await userEvent.click(screen.getByTestId("chat-jump-to-latest"));
|
||||
expect(scrollTopValue).toBe(1000);
|
||||
expect(screen.queryByTestId("chat-jump-to-latest")).not.toBeInTheDocument();
|
||||
await waitFor(() => {
|
||||
expect(screen.queryByTestId("chat-jump-to-latest")).not.toBeInTheDocument();
|
||||
});
|
||||
} finally {
|
||||
restoreMatchMedia.mockRestore();
|
||||
}
|
||||
|
||||
@@ -1933,6 +1933,14 @@ describe("SettingsModal", () => {
|
||||
expect(screen.getByLabelText("Evals View")).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("shows chatRooms in the Experimental Features list", async () => {
|
||||
renderModal();
|
||||
|
||||
await openExperimentalFeaturesSection();
|
||||
|
||||
expect(screen.getByLabelText("Chat Rooms")).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("shows agentOnboarding in the Experimental Features list", async () => {
|
||||
renderModal();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user