diff --git a/frontend/src/components/App/App.tsx b/frontend/src/components/App/App.tsx index 87613ffc2..b44d3b379 100644 --- a/frontend/src/components/App/App.tsx +++ b/frontend/src/components/App/App.tsx @@ -2,7 +2,7 @@ import { useEffect } from "react"; import { BrowserRouter as Router, Route, - Routes + Routes, } from "react-router-dom"; import axios from "axios"; diff --git a/frontend/src/components/InternalRedirect/InternalRedirect.test.tsx b/frontend/src/components/InternalRedirect/InternalRedirect.test.tsx new file mode 100644 index 000000000..7d45b0308 --- /dev/null +++ b/frontend/src/components/InternalRedirect/InternalRedirect.test.tsx @@ -0,0 +1,47 @@ +import { render, screen } from '@testing-library/react' +import { MemoryRouter, Route, Routes } from 'react-router-dom' +import { describe, it, expect, vi } from 'vitest' +import { InternalRedirect } from './InternalRedirect' +import { URLS } from '@/config' + +// Mock the Redirect component +vi.mock('@/components/Redirect/Redirect', () => ({ + default: vi.fn(({ to }) =>
{to}
) +})) + +describe('InternalRedirect', () => { + const renderComponent = (path: string) => { + render( + + + } />= + + + ) + } + + it('redirects to the correct path without search params', () => { + renderComponent('/redirect/dashboard') + expect(screen.getByTestId('mock-redirect').textContent).toBe('/dashboard') + }) + + it('redirects to the correct path with search params', () => { + renderComponent('/redirect/profile?id=123&tab=settings') + expect(screen.getByTestId('mock-redirect').textContent).toBe('/profile?id=123&tab=settings') + }) + + it('handles paths with multiple segments', () => { + renderComponent('/redirect/users/edit/42') + expect(screen.getByTestId('mock-redirect').textContent).toBe('/users/edit/42') + }) + + it('preserves complex search params', () => { + renderComponent('/redirect/search?q=test%20query&filter[]=a&filter[]=b') + expect(screen.getByTestId('mock-redirect').textContent).toBe('/search?q=test%20query&filter[]=a&filter[]=b') + }) + + it('handles redirect with empty path', () => { + renderComponent('/redirect/') + expect(screen.getByTestId('mock-redirect').textContent).toBe('/') + }) +}) diff --git a/frontend/src/components/InternalRedirect/InternalRedirect.tsx b/frontend/src/components/InternalRedirect/InternalRedirect.tsx index 90a42270c..5c44dd2c8 100644 --- a/frontend/src/components/InternalRedirect/InternalRedirect.tsx +++ b/frontend/src/components/InternalRedirect/InternalRedirect.tsx @@ -1,13 +1,12 @@ import React from 'react'; -import { RouteComponentProps } from 'react-router-dom'; +import { useLocation, } from 'react-router-dom'; import Redirect from '@/components/Redirect/Redirect'; -// this component is a route, so it will receive the route props -interface InternalRedirectProps extends RouteComponentProps { } +export const InternalRedirect: React.FC = () => { -export const InternalRedirect: React.FC = (props) => { - const { path } = props.match.params as { path: string }; - const { search } = props.location; + const location = useLocation(); + const { pathname, search } = location; + const path = pathname.replace(/^\/redirect\/?/, ''); // Redirect to the experiment path return ; diff --git a/frontend/src/config.ts b/frontend/src/config.ts index 1f315399d..e728a176c 100644 --- a/frontend/src/config.ts +++ b/frontend/src/config.ts @@ -31,7 +31,7 @@ export const URLS = { block: "/block/:slug", experimentAbout: "/:slug/about", experiment: "/:slug/*", - internalRedirect: "/redirect/:path", + internalRedirect: "/redirect/*", reloadParticipant: "/participant/reload/:id/:hash", theme: "/theme/:id", AMLHome: