Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
62 changes: 62 additions & 0 deletions src/App.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import { render, screen } from './setupTest';
import { ROUTES } from './routes';
import App from './App';

jest.mock('@edx/frontend-platform', () => ({
getAuthenticatedUser: jest.fn(() => ({ username: 'test-user', roles: [] })),
getConfig: jest.fn(() => ({
LMS_BASE_URL: '',
ENABLE_PROGRAMS: true,
ENABLE_COURSE_DISCOVERY: true,
})),
}));

jest.mock('@edx/frontend-platform/react', () => ({
AppProvider: ({ children }: { children: React.ReactNode }) => <div data-testid="app-provider">{children}</div>,
}));

jest.mock('@openedx/paragon', () => ({
Container: ({ children }: { children: React.ReactNode }) => <div>{children}</div>,
}));

jest.mock('@edx/frontend-component-header', () => function getHeader() {
return <div data-testid="header" />;
});

jest.mock('@edx/frontend-component-footer', () => ({
FooterSlot: () => <div data-testid="footer" />,
}));

describe('App', () => {
beforeEach(() => {
document.body.innerHTML = '';
});

it('renders HomePage on "/" route', () => {
window.testHistory = [ROUTES.HOME];

render(<App />);
expect(screen.getByTestId('home-page')).toBeInTheDocument();
});

it('renders CatalogPage on "/courses" route', () => {
window.testHistory = [ROUTES.COURSES];

render(<App />);
expect(screen.getByTestId('catalog-page')).toBeInTheDocument();
});

it('renders CourseAboutPage on "/courses/some-course-id/about"', () => {
window.testHistory = [ROUTES.COURSE_ABOUT];

render(<App />);
expect(screen.getByTestId('course-about-page')).toBeInTheDocument();
});

it('renders NotFoundPage on unknown route', () => {
window.testHistory = ['/some-unknown-path'];

render(<App />);
expect(screen.getByTestId('not-found-page')).toBeInTheDocument();
});
});
35 changes: 35 additions & 0 deletions src/App.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { AppProvider } from '@edx/frontend-platform/react';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { Route, Routes } from 'react-router-dom';
import { Container } from '@openedx/paragon';
import { FooterSlot } from '@edx/frontend-component-footer';
import Header from '@edx/frontend-component-header';

import HomePage from './home/HomePage';
import CatalogPage from './сatalog/CatalogPage';
import CourseAboutPage from './course-about/CourseAboutPage';
import NotFoundPage from './not-found-page/NotFoundPage';
import { ROUTES } from './routes';

const queryClient = new QueryClient();

const App = () => (
<AppProvider>
<QueryClientProvider client={queryClient}>
<Header />
<main className="d-flex flex-column flex-grow-1">
<Container className="container-xl">
<Routes>
<Route path={ROUTES.HOME} element={<HomePage />} />
<Route path={ROUTES.COURSES} element={<CatalogPage />} />
<Route path={ROUTES.COURSE_ABOUT} element={<CourseAboutPage />} />
<Route path={ROUTES.NOT_FOUND} element={<NotFoundPage />} />
</Routes>
</Container>
</main>
<FooterSlot />
</QueryClientProvider>
</AppProvider>
);

export default App;
7 changes: 7 additions & 0 deletions src/global.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export {}; // make file as module

declare global {
interface Window {
testHistory?: string[];
}
}
66 changes: 0 additions & 66 deletions src/index.test.jsx

This file was deleted.

37 changes: 37 additions & 0 deletions src/index.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { initialize } from '@edx/frontend-platform';

jest.mock('@edx/frontend-platform', () => ({
...jest.requireActual('@edx/frontend-platform'),
APP_READY: 'APP_READY',
APP_INIT_ERROR: 'APP_INIT_ERROR',
subscribe: jest.fn(),
initialize: jest.fn(),
ensureConfig: jest.fn(),
getConfig: jest.fn(() => ({
LMS_BASE_URL: process.env.LMS_BASE_URL,
ENABLE_PROGRAMS: true,
ENABLE_COURSE_DISCOVERY: true,
})),
}));

jest.mock('react-dom/client', () => ({
createRoot: jest.fn(() => ({
render: jest.fn(),
})),
}));

describe('Index', () => {
beforeEach(() => {
jest.clearAllMocks();
document.body.innerHTML = '';
});

it('should initialize the app with correct configuration', async () => {
// Import the module to trigger initialization
await import('./index');

expect(initialize).toHaveBeenCalledWith({
messages: expect.any(Object),
});
});
});
37 changes: 5 additions & 32 deletions src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,46 +4,19 @@ import 'regenerator-runtime/runtime';
import {
APP_INIT_ERROR, APP_READY, subscribe, initialize,
} from '@edx/frontend-platform';
import { AppProvider, ErrorPage } from '@edx/frontend-platform/react';
import { ErrorPage } from '@edx/frontend-platform/react';
import { createRoot } from 'react-dom/client';
import {
QueryClient,
QueryClientProvider,
} from '@tanstack/react-query';
import Header from '@edx/frontend-component-header';
import { FooterSlot } from '@edx/frontend-component-footer';
import { Routes, Route } from 'react-router-dom';
import { Container } from '@openedx/paragon';

import HomePage from './home/HomePage';
import CatalogPage from './сatalog/CatalogPage';
import CourseAboutPage from './course-about/CourseAboutPage';

import App from './App';
import messages from './i18n';

import './index.scss';

const queryClient = new QueryClient();
const container = document.getElementById('root');
const root = createRoot(container!);

const root = createRoot(container!);
subscribe(APP_READY, () => {
root.render(
<AppProvider>
<QueryClientProvider client={queryClient}>
<Header />
<main className="d-flex flex-column flex-grow-1">
<Container className="container-xl">
<Routes>
<Route path="/" element={<HomePage />} />
<Route path="/courses" element={<CatalogPage />} />
<Route path="/courses/:courseId/about" element={<CourseAboutPage />} />
</Routes>
</Container>
</main>
<FooterSlot />
</QueryClientProvider>
</AppProvider>,
);
root.render(<App />);
});

subscribe(APP_INIT_ERROR, (error: { message: any; }) => {
Expand Down
12 changes: 12 additions & 0 deletions src/not-found-page/NotFoundPage.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { render } from '../setupTest';
import NotFoundPage from './NotFoundPage';

import messages from './messages';

describe('<NotFoundPage />', () => {
it('render component correctly', () => {
const { getByText } = render(<NotFoundPage />);

expect(getByText(messages.title.defaultMessage)).toBeInTheDocument();
});
});
18 changes: 18 additions & 0 deletions src/not-found-page/NotFoundPage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { Container } from '@openedx/paragon';
import { useIntl } from '@edx/frontend-platform/i18n';

import messages from './messages';

const NotFoundPage = () => {
const intl = useIntl();

return (
<Container size="sm">
<p className="my-0 py-5 text-muted text-center mx-auto" data-testid="not-found-page">
{intl.formatMessage(messages.title)}
</p>
</Container>
);
};

export default NotFoundPage;
11 changes: 11 additions & 0 deletions src/not-found-page/messages.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { defineMessages } from '@edx/frontend-platform/i18n';

const messages = defineMessages({
title: {
id: 'category.not-found-page.title',
defaultMessage: 'The page you\'re looking for is unavailable or there\'s an error in the URL. Please check the URL and try again.',
description: 'The title text for the not found page.',
},
});

export default messages;
6 changes: 6 additions & 0 deletions src/routes.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export const ROUTES = {
HOME: '/',
COURSES: '/courses',
COURSE_ABOUT: '/courses/:courseId/about',
NOT_FOUND: '*',
} as const;
5 changes: 3 additions & 2 deletions src/setupTest.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import 'core-js/stable';
import 'regenerator-runtime/runtime';
import '@testing-library/jest-dom';
import { IntlProvider } from '@edx/frontend-platform/i18n';
import { render as rtlRender } from '@testing-library/react';
import { render as rtlRender, screen } from '@testing-library/react';
import PropTypes from 'prop-types';
import { MemoryRouter } from 'react-router-dom';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
Expand All @@ -20,7 +20,7 @@ function render(ui) {
// eslint-disable-next-line react/jsx-filename-extension
<QueryClientProvider client={queryClient}>
{/* eslint-disable-next-line no-underscore-dangle */}
<MemoryRouter initialEntries={window._testHistory || ['/']}>
<MemoryRouter initialEntries={window.testHistory || ['/']}>
<IntlProvider locale="en">
{children}
</IntlProvider>
Expand All @@ -37,4 +37,5 @@ function render(ui) {

export {
render,
screen,
};