test: add tests for MCPAddRedirect and useMCPDeepLink

This commit is contained in:
Danny Avila 2026-03-17 01:36:57 -04:00
parent d67669768a
commit c17cb9a85d
2 changed files with 182 additions and 0 deletions

View file

@ -0,0 +1,108 @@
import React from 'react';
import { renderHook, act } from '@testing-library/react';
import { createMemoryRouter, RouterProvider } from 'react-router-dom';
import useMCPDeepLink from '../useMCPDeepLink';
if (typeof Request === 'undefined') {
global.Request = class Request {
constructor(
public url: string,
public init?: RequestInit,
) {}
} as any;
}
function TestWrapper({ router }: { router: ReturnType<typeof createMemoryRouter> }) {
return <RouterProvider router={router} />;
}
function renderDeepLinkHook(state?: Record<string, unknown>) {
let hookResult: { current: ReturnType<typeof useMCPDeepLink> };
function HookConsumer() {
hookResult = { current: useMCPDeepLink() };
return null;
}
const router = createMemoryRouter(
[
{
path: 'c/:conversationId',
element: <HookConsumer />,
},
],
{
initialEntries: [{ pathname: '/c/new', state }],
},
);
const renderResult = renderHook(() => hookResult!.current, {
wrapper: ({ children }) => (
<>
<TestWrapper router={router} />
{children}
</>
),
});
return { ...renderResult, router, getHook: () => hookResult!.current };
}
describe('useMCPDeepLink', () => {
it('should open dialog with initialValues from route state including valid transport', async () => {
const { getHook } = renderDeepLinkHook({
mcpName: 'My Server',
mcpUrl: 'https://example.com/mcp',
mcpTransport: 'sse',
});
await act(async () => {});
const result = getHook();
expect(result.isOpen).toBe(true);
expect(result.initialValues).toEqual({
title: 'My Server',
url: 'https://example.com/mcp',
type: 'sse',
});
});
it('should ignore an invalid mcpTransport value', async () => {
const { getHook } = renderDeepLinkHook({
mcpName: 'Server',
mcpTransport: 'websocket',
});
await act(async () => {});
const result = getHook();
expect(result.isOpen).toBe(true);
expect(result.initialValues).toEqual({ title: 'Server' });
expect(result.initialValues).not.toHaveProperty('type');
});
it('should not open the dialog when route state has no MCP params', async () => {
const { getHook } = renderDeepLinkHook(undefined);
await act(async () => {});
const result = getHook();
expect(result.isOpen).toBe(false);
expect(result.initialValues).toBeUndefined();
});
it('should clear initialValues when dialog is closed via onOpenChange', async () => {
const { getHook } = renderDeepLinkHook({ mcpName: 'Server' });
await act(async () => {});
expect(getHook().isOpen).toBe(true);
expect(getHook().initialValues).toEqual({ title: 'Server' });
act(() => {
getHook().onOpenChange(false);
});
expect(getHook().isOpen).toBe(false);
expect(getHook().initialValues).toBeUndefined();
});
});

View file

@ -0,0 +1,74 @@
import React from 'react';
import { render, waitFor } from '@testing-library/react';
import { createMemoryRouter, RouterProvider, useLocation } from 'react-router-dom';
import MCPAddRedirect from '../MCPAddRedirect';
if (typeof Request === 'undefined') {
global.Request = class Request {
constructor(
public url: string,
public init?: RequestInit,
) {}
} as any;
}
function CaptureState() {
const location = useLocation();
(window as any).__capturedState = location.state;
// eslint-disable-next-line i18next/no-literal-string
return <div data-testid="chat-page">Chat</div>;
}
const createTestRouter = (initialEntry: string) =>
createMemoryRouter(
[
{
path: 'mcps/add',
element: <MCPAddRedirect />,
},
{
path: 'c/:conversationId',
element: <CaptureState />,
},
],
{ initialEntries: [initialEntry] },
);
describe('MCPAddRedirect', () => {
afterEach(() => {
(window as any).__capturedState = undefined;
});
it('should redirect to /c/new forwarding all params via route state', async () => {
const router = createTestRouter(
'/mcps/add?name=My+Server&url=https://example.com/mcp&transport=sse',
);
render(<RouterProvider router={router} />);
await waitFor(() => {
expect(router.state.location.pathname).toBe('/c/new');
});
expect(router.state.historyAction).toBe('REPLACE');
expect((window as any).__capturedState).toEqual({
mcpName: 'My Server',
mcpUrl: 'https://example.com/mcp',
mcpTransport: 'sse',
});
});
it('should redirect to /c/new even when no query params are provided', async () => {
const router = createTestRouter('/mcps/add');
render(<RouterProvider router={router} />);
await waitFor(() => {
expect(router.state.location.pathname).toBe('/c/new');
});
expect((window as any).__capturedState).toEqual({
mcpName: undefined,
mcpUrl: undefined,
mcpTransport: undefined,
});
});
});