diff --git a/src/taxonomy/TaxonomyLayout.test.jsx b/src/taxonomy/TaxonomyLayout.test.jsx
new file mode 100644
index 0000000000..924e7465e9
--- /dev/null
+++ b/src/taxonomy/TaxonomyLayout.test.jsx
@@ -0,0 +1,48 @@
+import React from 'react';
+import { IntlProvider } from '@edx/frontend-platform/i18n';
+import { initializeMockApp } from '@edx/frontend-platform';
+import { AppProvider } from '@edx/frontend-platform/react';
+import { render } from '@testing-library/react';
+
+import initializeStore from '../store';
+import TaxonomyLayout from './TaxonomyLayout';
+
+let store;
+
+jest.mock('../header', () => jest.fn(() => <div data-testid="mock-header" />));
+jest.mock('@edx/frontend-component-footer', () => ({
+  StudioFooter: jest.fn(() => <div data-testid="mock-footer" />),
+}));
+jest.mock('react-router-dom', () => ({
+  ...jest.requireActual('react-router-dom'),
+  Outlet: jest.fn(() => <div data-testid="mock-content" />),
+}));
+
+const RootWrapper = () => (
+  <AppProvider store={store}>
+    <IntlProvider locale="en" messages={{}}>
+      <TaxonomyLayout />
+    </IntlProvider>
+  </AppProvider>
+);
+
+describe('<TaxonomyLayout />', async () => {
+  beforeEach(async () => {
+    initializeMockApp({
+      authenticatedUser: {
+        userId: 3,
+        username: 'abc123',
+        administrator: true,
+        roles: [],
+      },
+    });
+    store = initializeStore();
+  });
+
+  it('should render page correctly', async () => {
+    const { getByTestId } = render(<RootWrapper />);
+    expect(getByTestId('mock-header')).toBeInTheDocument();
+    expect(getByTestId('mock-content')).toBeInTheDocument();
+    expect(getByTestId('mock-footer')).toBeInTheDocument();
+  });
+});
diff --git a/src/taxonomy/taxonomy-detail/TagListTable.test.jsx b/src/taxonomy/taxonomy-detail/TagListTable.test.jsx
new file mode 100644
index 0000000000..1128deced9
--- /dev/null
+++ b/src/taxonomy/taxonomy-detail/TagListTable.test.jsx
@@ -0,0 +1,67 @@
+import React from 'react';
+import { IntlProvider, injectIntl } from '@edx/frontend-platform/i18n';
+import { initializeMockApp } from '@edx/frontend-platform';
+import { AppProvider } from '@edx/frontend-platform/react';
+import { render } from '@testing-library/react';
+
+import { useTagListData } from '../api/hooks/api';
+import initializeStore from '../../store';
+import TagListTable from './TagListTable';
+
+let store;
+
+jest.mock('../api/hooks/api', () => ({
+  useTagListData: jest.fn(),
+}));
+
+const RootWrapper = () => (
+  <AppProvider store={store}>
+    <IntlProvider locale="en" messages={{}}>
+      <TagListTable intl={injectIntl} taxonomyId="1" />
+    </IntlProvider>
+  </AppProvider>
+);
+
+describe('<TagListPage />', async () => {
+  beforeEach(async () => {
+    initializeMockApp({
+      authenticatedUser: {
+        userId: 3,
+        username: 'abc123',
+        administrator: true,
+        roles: [],
+      },
+    });
+    store = initializeStore();
+  });
+
+  it('shows the spinner before the query is complete', async () => {
+    useTagListData.mockReturnValue({
+      isLoading: true,
+      isFetched: false,
+    });
+    const { getByRole } = render(<RootWrapper />);
+    const spinner = getByRole('status');
+    expect(spinner.textContent).toEqual('loading');
+  });
+
+  it('should render page correctly', async () => {
+    useTagListData.mockReturnValue({
+      isSuccess: true,
+      isFetched: true,
+      isError: false,
+      data: {
+        count: 3,
+        numPages: 1,
+        results: [
+          { value: 'Tag 1' },
+          { value: 'Tag 2' },
+          { value: 'Tag 3' },
+        ],
+      },
+    });
+    const { getAllByRole } = render(<RootWrapper />);
+    const rows = getAllByRole('row');
+    expect(rows.length).toBe(3 + 1); // 3 items plus header
+  });
+});
diff --git a/src/taxonomy/taxonomy-detail/TaxonomyDetailPage.jsx b/src/taxonomy/taxonomy-detail/TaxonomyDetailPage.jsx
index d1a981f292..385a3f797b 100644
--- a/src/taxonomy/taxonomy-detail/TaxonomyDetailPage.jsx
+++ b/src/taxonomy/taxonomy-detail/TaxonomyDetailPage.jsx
@@ -28,15 +28,15 @@ const TaxonomyDetailPage = () => {
 
   const [isExportModalOpen, setIsExportModalOpen] = useState(false);
 
-  if (isError) {
+  if (!isFetched) {
     return (
-      <ConnectionErrorAlert />
+      <Loading />
     );
   }
 
-  if (!isFetched) {
+  if (isError || !taxonomy) {
     return (
-      <Loading />
+      <ConnectionErrorAlert />
     );
   }
 
@@ -47,7 +47,7 @@ const TaxonomyDetailPage = () => {
         <ExportModal
           isOpen={isExportModalOpen}
           onClose={() => setIsExportModalOpen(false)}
-          taxonomyId={taxonomyId}
+          taxonomyId={taxonomy.id}
           taxonomyName={taxonomy.name}
         />
       )}
@@ -80,49 +80,45 @@ const TaxonomyDetailPage = () => {
     />
   );
 
-  if (taxonomy) {
-    return (
-      <>
-        <div className="pt-4.5 pr-4.5 pl-4.5 pb-2 bg-light-100 box-shadow-down-2">
-          <Container size="xl">
-            <Breadcrumb
-              links={[
-                { label: 'Taxonomies', to: '/taxonomy-list/' },
-              ]}
-              activeLabel={taxonomy.name}
-              linkAs={Link}
-            />
-            <SubHeader
-              title={taxonomy.name}
-              hideBorder
-              headerActions={getHeaderActions()}
-            />
-          </Container>
-        </div>
-        <div className="bg-light-400 m-4">
-          <Container size="xl">
-            <Layout
-              lg={[{ span: 9 }, { span: 3 }]}
-              md={[{ span: 9 }, { span: 3 }]}
-              sm={[{ span: 9 }, { span: 3 }]}
-              xs={[{ span: 9 }, { span: 3 }]}
-              xl={[{ span: 9 }, { span: 3 }]}
-            >
-              <Layout.Element>
-                <TagListTable taxonomyId={taxonomyId} />
-              </Layout.Element>
-              <Layout.Element>
-                <TaxonomyDetailSideCard taxonomy={taxonomy} />
-              </Layout.Element>
-            </Layout>
-          </Container>
-        </div>
-        {renderModals()}
-      </>
-    );
-  }
-
-  return undefined;
+  return (
+    <>
+      <div className="pt-4.5 pr-4.5 pl-4.5 pb-2 bg-light-100 box-shadow-down-2">
+        <Container size="xl">
+          <Breadcrumb
+            links={[
+              { label: 'Taxonomies', to: '/taxonomy-list/' },
+            ]}
+            activeLabel={taxonomy.name}
+            linkAs={Link}
+          />
+          <SubHeader
+            title={taxonomy.name}
+            hideBorder
+            headerActions={getHeaderActions()}
+          />
+        </Container>
+      </div>
+      <div className="bg-light-400 m-4">
+        <Container size="xl">
+          <Layout
+            lg={[{ span: 9 }, { span: 3 }]}
+            md={[{ span: 9 }, { span: 3 }]}
+            sm={[{ span: 9 }, { span: 3 }]}
+            xs={[{ span: 9 }, { span: 3 }]}
+            xl={[{ span: 9 }, { span: 3 }]}
+          >
+            <Layout.Element>
+              <TagListTable taxonomyId={taxonomyId} />
+            </Layout.Element>
+            <Layout.Element>
+              <TaxonomyDetailSideCard taxonomy={taxonomy} />
+            </Layout.Element>
+          </Layout>
+        </Container>
+      </div>
+      {renderModals()}
+    </>
+  );
 };
 
 export default TaxonomyDetailPage;
diff --git a/src/taxonomy/taxonomy-detail/TaxonomyDetailPage.test.jsx b/src/taxonomy/taxonomy-detail/TaxonomyDetailPage.test.jsx
new file mode 100644
index 0000000000..ab832bc9c8
--- /dev/null
+++ b/src/taxonomy/taxonomy-detail/TaxonomyDetailPage.test.jsx
@@ -0,0 +1,111 @@
+import React from 'react';
+import { IntlProvider, injectIntl } from '@edx/frontend-platform/i18n';
+import { initializeMockApp } from '@edx/frontend-platform';
+import { AppProvider } from '@edx/frontend-platform/react';
+import { fireEvent, render } from '@testing-library/react';
+
+import { useTaxonomyDetailData } from '../api/hooks/api';
+import initializeStore from '../../store';
+import TaxonomyDetailPage from './TaxonomyDetailPage';
+
+let store;
+
+jest.mock('../api/hooks/api', () => ({
+  useTaxonomyDetailData: jest.fn(),
+}));
+jest.mock('react-router-dom', () => ({
+  ...jest.requireActual('react-router-dom'), // use actual for all non-hook parts
+  useParams: () => ({
+    taxonomyId: '1',
+  }),
+}));
+
+jest.mock('./TaxonomyDetailSideCard', () => jest.fn(() => <>Mock TaxonomyDetailSideCard</>));
+jest.mock('./TagListTable', () => jest.fn(() => <>Mock TagListTable</>));
+
+const RootWrapper = () => (
+  <AppProvider store={store}>
+    <IntlProvider locale="en" messages={{}}>
+      <TaxonomyDetailPage intl={injectIntl} />
+    </IntlProvider>
+  </AppProvider>
+);
+
+describe('<TaxonomyDetailPage />', async () => {
+  beforeEach(async () => {
+    initializeMockApp({
+      authenticatedUser: {
+        userId: 3,
+        username: 'abc123',
+        administrator: true,
+        roles: [],
+      },
+    });
+    store = initializeStore();
+  });
+
+  it('shows the spinner before the query is complete', async () => {
+    useTaxonomyDetailData.mockReturnValue({
+      isFetched: false,
+    });
+    const { getByRole } = render(<RootWrapper />);
+    const spinner = getByRole('status');
+    expect(spinner.textContent).toEqual('Loading...');
+  });
+
+  it('shows the connector error component if got some error', async () => {
+    useTaxonomyDetailData.mockReturnValue({
+      isFetched: true,
+      isError: true,
+    });
+    const { getByTestId } = render(<RootWrapper />);
+    expect(getByTestId('connectionErrorAlert')).toBeInTheDocument();
+  });
+
+  it('should render page and page title correctly', async () => {
+    useTaxonomyDetailData.mockReturnValue({
+      isSuccess: true,
+      isFetched: true,
+      isError: false,
+      data: {
+        id: 1,
+        name: 'Test taxonomy',
+        description: 'This is a description',
+        systemDefined: false,
+      },
+    });
+    const { getByRole } = render(<RootWrapper />);
+    expect(getByRole('heading')).toHaveTextContent('Test taxonomy');
+  });
+
+  it('should open export modal on export menu click', () => {
+    useTaxonomyDetailData.mockReturnValue({
+      isSuccess: true,
+      isFetched: true,
+      isError: false,
+      data: {
+        id: 1,
+        name: 'Test taxonomy',
+        description: 'This is a description',
+      },
+    });
+
+    const { getByRole, getByText } = render(<RootWrapper />);
+
+    // Modal closed
+    expect(() => getByText('Select format to export')).toThrow();
+
+    // Click on export menu
+    fireEvent.click(getByRole('button'));
+    fireEvent.click(getByText('Export'));
+
+    // Modal opened
+    expect(getByText('Select format to export')).toBeInTheDocument();
+
+    // Click on cancel button
+    fireEvent.click(getByText('Cancel'));
+
+    // Modal closed
+    expect(() => getByText('Select format to export')).toThrow();
+  });
+});