diff --git a/package-lock.json b/package-lock.json index 2319391ba6..69c38d7319 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15607,9 +15607,9 @@ } }, "node_modules/follow-redirects": { - "version": "1.15.5", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.5.tgz", - "integrity": "sha512-vSFWUON1B+yAw1VN4xMfxgn5fTUiaOzAJCKBwIIgT/+7CuGy9+r+5gITvP62j3RmaD5Ph65UaERdOSRGUzZtgw==", + "version": "1.15.6", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", + "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", "dev": true, "funding": [ { @@ -45218,9 +45218,9 @@ "dev": true }, "follow-redirects": { - "version": "1.15.5", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.5.tgz", - "integrity": "sha512-vSFWUON1B+yAw1VN4xMfxgn5fTUiaOzAJCKBwIIgT/+7CuGy9+r+5gITvP62j3RmaD5Ph65UaERdOSRGUzZtgw==", + "version": "1.15.6", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", + "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", "dev": true }, "for-each": { diff --git a/src/App.jsx b/src/App.jsx index 67c92ee41d..ee9903e99c 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -8,6 +8,7 @@ import config from 'config' import { SentryRoute } from 'sentry' import BaseLayout from 'layouts/BaseLayout' +import EnterpriseLoginLayout from 'layouts/EnterpriseLoginLayout' import LoginLayout from 'layouts/LoginLayout' import { useLocationParams } from 'services/navigation' import { ToastNotificationProvider } from 'services/toastNotification' @@ -143,9 +144,9 @@ const MainAppRoutes = () => ( {config.IS_SELF_HOSTED ? ( - + - + ) : ( )} diff --git a/src/layouts/EnterpriseLoginLayout/EnterpriseLoginLayout.spec.tsx b/src/layouts/EnterpriseLoginLayout/EnterpriseLoginLayout.spec.tsx new file mode 100644 index 0000000000..2081809abe --- /dev/null +++ b/src/layouts/EnterpriseLoginLayout/EnterpriseLoginLayout.spec.tsx @@ -0,0 +1,82 @@ +import { QueryClient, QueryClientProvider } from '@tanstack/react-query' +import { render, screen } from '@testing-library/react' +import { MemoryRouter, Route } from 'react-router-dom' + +import EnterpriseLoginLayout from './EnterpriseLoginLayout' + +jest.mock('./Header', () => () => 'Header') +jest.mock('layouts/Footer', () => () => 'Footer') +jest.mock('shared/GlobalBanners', () => () => 'GlobalBanners') +jest.mock('layouts/ToastNotifications', () => () => 'ToastNotifications') +jest.mock('ui/SessionExpiryTracker', () => () => 'SessionExpiryTracker') + +const queryClient = new QueryClient({ + defaultOptions: { + queries: { + retry: false, + }, + }, +}) + +const wrapper = ({ children }: { children: React.ReactNode }) => ( + + + + {children} + + + +) + +describe('EnterpriseLoginLayout', () => { + it('renders children', () => { + render(<>children, { wrapper }) + + const children = screen.getByText(/children/) + expect(children).toBeInTheDocument() + }) + + it('renders global banners', () => { + render(<>children, { wrapper }) + + const globalBanners = screen.getByText(/GlobalBanners/) + expect(globalBanners).toBeInTheDocument() + }) + + it('renders the header', () => { + render(<>children, { wrapper }) + + const header = screen.getByText(/Header/) + expect(header).toBeInTheDocument() + }) + + it('renders the footer', () => { + render(<>children, { wrapper }) + + const footer = screen.getByText(/Footer/) + expect(footer).toBeInTheDocument() + }) + + it('renders toast notifications', () => { + render(<>children, { wrapper }) + + const ToastNotifications = screen.getByText(/ToastNotifications/) + expect(ToastNotifications).toBeInTheDocument() + }) + + it('renders the session expiry tracker if no tracking session found', () => { + render(<>children, { wrapper }) + + const session = screen.getByText(/SessionExpiryTracker/) + expect(session).toBeInTheDocument() + }) + + it('does not render the session expiry tracker if tracking session found', () => { + localStorage.setItem('tracking-session-expiry', 'true') + + render(<>children, { wrapper }) + + const session = screen.queryByText(/SessionExpiryTracker/) + expect(session).not.toBeInTheDocument() + }) +}) diff --git a/src/layouts/EnterpriseLoginLayout/EnterpriseLoginLayout.tsx b/src/layouts/EnterpriseLoginLayout/EnterpriseLoginLayout.tsx new file mode 100644 index 0000000000..50d921e320 --- /dev/null +++ b/src/layouts/EnterpriseLoginLayout/EnterpriseLoginLayout.tsx @@ -0,0 +1,45 @@ +import { Suspense } from 'react' + +import Footer from 'layouts/Footer' +import ErrorBoundary from 'layouts/shared/ErrorBoundary' +import NetworkErrorBoundary from 'layouts/shared/NetworkErrorBoundary' +import ToastNotifications from 'layouts/ToastNotifications' +import GlobalBanners from 'shared/GlobalBanners' +import LoadingLogo from 'ui/LoadingLogo' +import SessionExpiryTracker from 'ui/SessionExpiryTracker' + +import Header from './Header' + +const LOCAL_STORAGE_SESSION_TRACKING_KEY = 'tracking-session-expiry' + +const FullPageLoader = () => ( +
+ +
+) + +function EnterpriseLoginLayout({ children }: { children: React.ReactNode }) { + const isTrackingSession = localStorage.getItem( + LOCAL_STORAGE_SESSION_TRACKING_KEY + ) + return ( + <> +
+ {!isTrackingSession && } + }> + + +
+ + {children} +
+
+
+
+