diff --git a/frontend/src/App/app.test.tsx b/frontend/src/App/app.test.tsx
index b5aea7e63..f6236cdc9 100644
--- a/frontend/src/App/app.test.tsx
+++ b/frontend/src/App/app.test.tsx
@@ -1,14 +1,9 @@
import { render } from "@/tests";
-import { StrictMode } from "react";
import { describe, it } from "vitest";
import App from ".";
describe("App", () => {
it("should render without crash", () => {
- render(
-
-
-
- );
+ render();
});
});
diff --git a/frontend/src/App/index.tsx b/frontend/src/App/index.tsx
index e5c974240..374505be1 100644
--- a/frontend/src/App/index.tsx
+++ b/frontend/src/App/index.tsx
@@ -4,7 +4,7 @@ import { Layout } from "@/constants";
import NavbarProvider from "@/contexts/Navbar";
import OnlineProvider from "@/contexts/Online";
import { notification } from "@/modules/task";
-import CriticalError from "@/pages/CriticalError";
+import CriticalError from "@/pages/errors/CriticalError";
import { RouterNames } from "@/Router/RouterNames";
import { Environment } from "@/utilities";
import { AppShell } from "@mantine/core";
diff --git a/frontend/src/Router/index.tsx b/frontend/src/Router/index.tsx
index 3c3ab8a4a..5e90290c8 100644
--- a/frontend/src/Router/index.tsx
+++ b/frontend/src/Router/index.tsx
@@ -6,12 +6,12 @@ import Authentication from "@/pages/Authentication";
import BlacklistMoviesView from "@/pages/Blacklist/Movies";
import BlacklistSeriesView from "@/pages/Blacklist/Series";
import Episodes from "@/pages/Episodes";
+import NotFound from "@/pages/errors/NotFound";
import MoviesHistoryView from "@/pages/History/Movies";
import SeriesHistoryView from "@/pages/History/Series";
import MovieView from "@/pages/Movies";
import MovieDetailView from "@/pages/Movies/Details";
import MovieMassEditor from "@/pages/Movies/Editor";
-import NotFound from "@/pages/NotFound";
import SeriesView from "@/pages/Series";
import SeriesMassEditor from "@/pages/Series/Editor";
import SettingsGeneralView from "@/pages/Settings/General";
diff --git a/frontend/src/components/ErrorBoundary.tsx b/frontend/src/components/ErrorBoundary.tsx
index b7b7494fb..9f6228e34 100644
--- a/frontend/src/components/ErrorBoundary.tsx
+++ b/frontend/src/components/ErrorBoundary.tsx
@@ -1,4 +1,4 @@
-import UIError from "@/pages/UIError";
+import UIError from "@/pages/errors/UIError";
import { Component } from "react";
interface State {
diff --git a/frontend/src/modules/socketio/index.ts b/frontend/src/modules/socketio/index.ts
index 18934b39a..fe9536bbc 100644
--- a/frontend/src/modules/socketio/index.ts
+++ b/frontend/src/modules/socketio/index.ts
@@ -1,7 +1,7 @@
import { debounce, forIn, remove, uniq } from "lodash";
import { onlineManager } from "react-query";
import { io, Socket } from "socket.io-client";
-import { Environment, isDevEnv } from "../../utilities";
+import { Environment, isDevEnv, isTestEnv } from "../../utilities";
import { ENSURE, GROUP, LOG } from "../../utilities/console";
import { createDefaultReducer } from "./reducer";
@@ -51,6 +51,10 @@ class SocketIOClient {
}
initialize() {
+ if (isTestEnv) {
+ return;
+ }
+
LOG("info", "Initializing Socket.IO client...");
this.reducers.push(...createDefaultReducer());
diff --git a/frontend/src/pages/Blacklist/blacklist.test.tsx b/frontend/src/pages/Blacklist/blacklist.test.tsx
new file mode 100644
index 000000000..4360c473c
--- /dev/null
+++ b/frontend/src/pages/Blacklist/blacklist.test.tsx
@@ -0,0 +1,16 @@
+import { renderTest, RenderTestCase } from "@/tests/render";
+import BlacklistMoviesView from "./Movies";
+import BlacklistSeriesView from "./Series";
+
+const cases: RenderTestCase[] = [
+ {
+ name: "movie page",
+ ui: BlacklistMoviesView,
+ },
+ {
+ name: "series page",
+ ui: BlacklistSeriesView,
+ },
+];
+
+renderTest("Blacklist", cases);
diff --git a/frontend/src/pages/History/history.test.tsx b/frontend/src/pages/History/history.test.tsx
new file mode 100644
index 000000000..1de1e6c5d
--- /dev/null
+++ b/frontend/src/pages/History/history.test.tsx
@@ -0,0 +1,21 @@
+import { renderTest, RenderTestCase } from "@/tests/render";
+import MoviesHistoryView from "./Movies";
+import SeriesHistoryView from "./Series";
+import HistoryStats from "./Statistics";
+
+const cases: RenderTestCase[] = [
+ {
+ name: "movie page",
+ ui: MoviesHistoryView,
+ },
+ {
+ name: "series page",
+ ui: SeriesHistoryView,
+ },
+ {
+ name: "statistics page",
+ ui: HistoryStats,
+ },
+];
+
+renderTest("History", cases);
diff --git a/frontend/src/pages/Movies/movies.test.tsx b/frontend/src/pages/Movies/movies.test.tsx
new file mode 100644
index 000000000..fe5691a15
--- /dev/null
+++ b/frontend/src/pages/Movies/movies.test.tsx
@@ -0,0 +1,16 @@
+import { render } from "@/tests";
+import { describe } from "vitest";
+import MovieView from ".";
+import MovieMassEditor from "./Editor";
+
+describe("Movies page", () => {
+ it("should render", () => {
+ render();
+ });
+});
+
+describe("Movies editor page", () => {
+ it("should render", () => {
+ render();
+ });
+});
diff --git a/frontend/src/pages/Series/series.test.tsx b/frontend/src/pages/Series/series.test.tsx
new file mode 100644
index 000000000..6813c6e19
--- /dev/null
+++ b/frontend/src/pages/Series/series.test.tsx
@@ -0,0 +1,16 @@
+import { render } from "@/tests";
+import { describe } from "vitest";
+import SeriesView from ".";
+import SeriesMassEditor from "./Editor";
+
+describe("Series page", () => {
+ it("should render", () => {
+ render();
+ });
+});
+
+describe("Series editor page", () => {
+ it("should render", () => {
+ render();
+ });
+});
diff --git a/frontend/src/pages/Settings/settings.test.tsx b/frontend/src/pages/Settings/settings.test.tsx
new file mode 100644
index 000000000..71aa74158
--- /dev/null
+++ b/frontend/src/pages/Settings/settings.test.tsx
@@ -0,0 +1,51 @@
+import { renderTest, RenderTestCase } from "@/tests/render";
+import SettingsGeneralView from "./General";
+import SettingsLanguagesView from "./Languages";
+import SettingsNotificationsView from "./Notifications";
+import SettingsProvidersView from "./Providers";
+import SettingsRadarrView from "./Radarr";
+import SettingsSchedulerView from "./Scheduler";
+import SettingsSonarrView from "./Sonarr";
+import SettingsSubtitlesView from "./Subtitles";
+import SettingsUIView from "./UI";
+
+const cases: RenderTestCase[] = [
+ {
+ name: "general page",
+ ui: SettingsGeneralView,
+ },
+ {
+ name: "languages page",
+ ui: SettingsLanguagesView,
+ },
+ {
+ name: "notifications page",
+ ui: SettingsNotificationsView,
+ },
+ {
+ name: "providers page",
+ ui: SettingsProvidersView,
+ },
+ {
+ name: "radarr page",
+ ui: SettingsRadarrView,
+ },
+ {
+ name: "scheduler page",
+ ui: SettingsSchedulerView,
+ },
+ {
+ name: "sonarr page",
+ ui: SettingsSonarrView,
+ },
+ {
+ name: "subtitles page",
+ ui: SettingsSubtitlesView,
+ },
+ {
+ name: "ui page",
+ ui: SettingsUIView,
+ },
+];
+
+renderTest("Settings", cases);
diff --git a/frontend/src/pages/System/system.test.tsx b/frontend/src/pages/System/system.test.tsx
new file mode 100644
index 000000000..f9c0b5dad
--- /dev/null
+++ b/frontend/src/pages/System/system.test.tsx
@@ -0,0 +1,36 @@
+import { renderTest, RenderTestCase } from "@/tests/render";
+import SystemBackupsView from "./Backups";
+import SystemLogsView from "./Logs";
+import SystemProvidersView from "./Providers";
+import SystemReleasesView from "./Releases";
+import SystemStatusView from "./Status";
+import SystemTasksView from "./Tasks";
+
+const cases: RenderTestCase[] = [
+ {
+ name: "backups page",
+ ui: SystemBackupsView,
+ },
+ {
+ name: "logs page",
+ ui: SystemLogsView,
+ },
+ {
+ name: "providers page",
+ ui: SystemProvidersView,
+ },
+ {
+ name: "releases page",
+ ui: SystemReleasesView,
+ },
+ {
+ name: "status page",
+ ui: SystemStatusView,
+ },
+ {
+ name: "tasks page",
+ ui: SystemTasksView,
+ },
+];
+
+renderTest("System", cases);
diff --git a/frontend/src/pages/Wanted/wanted.test.tsx b/frontend/src/pages/Wanted/wanted.test.tsx
new file mode 100644
index 000000000..36e72c4bb
--- /dev/null
+++ b/frontend/src/pages/Wanted/wanted.test.tsx
@@ -0,0 +1,16 @@
+import { renderTest, RenderTestCase } from "@/tests/render";
+import WantedMoviesView from "./Movies";
+import WantedSeriesView from "./Series";
+
+const cases: RenderTestCase[] = [
+ {
+ name: "movie page",
+ ui: WantedMoviesView,
+ },
+ {
+ name: "series page",
+ ui: WantedSeriesView,
+ },
+];
+
+renderTest("Wanted", cases);
diff --git a/frontend/src/pages/CriticalError.tsx b/frontend/src/pages/errors/CriticalError.tsx
similarity index 100%
rename from frontend/src/pages/CriticalError.tsx
rename to frontend/src/pages/errors/CriticalError.tsx
diff --git a/frontend/src/pages/NotFound.tsx b/frontend/src/pages/errors/NotFound.tsx
similarity index 100%
rename from frontend/src/pages/NotFound.tsx
rename to frontend/src/pages/errors/NotFound.tsx
diff --git a/frontend/src/pages/UIError.tsx b/frontend/src/pages/errors/UIError.tsx
similarity index 100%
rename from frontend/src/pages/UIError.tsx
rename to frontend/src/pages/errors/UIError.tsx
diff --git a/frontend/src/pages/errors/errors.test.tsx b/frontend/src/pages/errors/errors.test.tsx
new file mode 100644
index 000000000..eeacfd631
--- /dev/null
+++ b/frontend/src/pages/errors/errors.test.tsx
@@ -0,0 +1,22 @@
+import { render } from "@/tests";
+import CriticalError from "./CriticalError";
+import NotFound from "./NotFound";
+import UIError from "./UIError";
+
+describe("Not found page", () => {
+ it("should display message", () => {
+ render();
+ });
+});
+
+describe("Critical error page", () => {
+ it("should disable error", () => {
+ render();
+ });
+});
+
+describe("UI error page", () => {
+ it("should disable error", () => {
+ render();
+ });
+});
diff --git a/frontend/src/tests/index.tsx b/frontend/src/tests/index.tsx
index 8239af064..9053be909 100644
--- a/frontend/src/tests/index.tsx
+++ b/frontend/src/tests/index.tsx
@@ -1,11 +1,19 @@
import { AllProviders } from "@/providers";
import { render, RenderOptions } from "@testing-library/react";
-import { ReactElement } from "react";
+import { FunctionComponent, ReactElement, StrictMode } from "react";
+
+const AllProvidersWithStrictMode: FunctionComponent = ({ children }) => {
+ return (
+
+ {children}
+
+ );
+};
const customRender = (
ui: ReactElement,
options?: Omit
-) => render(ui, { wrapper: AllProviders, ...options });
+) => render(ui, { wrapper: AllProvidersWithStrictMode, ...options });
// re-export everything
export * from "@testing-library/react";
diff --git a/frontend/src/tests/render.tsx b/frontend/src/tests/render.tsx
new file mode 100644
index 000000000..e0031e903
--- /dev/null
+++ b/frontend/src/tests/render.tsx
@@ -0,0 +1,17 @@
+import { FunctionComponent } from "react";
+import { render } from ".";
+
+export interface RenderTestCase {
+ name: string;
+ ui: FunctionComponent;
+}
+
+export function renderTest(name: string, cases: RenderTestCase[]) {
+ describe(name, () => {
+ cases.forEach((element) => {
+ it(`${element.name.toLowerCase()} should render`, () => {
+ render();
+ });
+ });
+ });
+}
diff --git a/frontend/test/setup.ts b/frontend/test/setup.ts
index 858b64791..2b3bf3672 100644
--- a/frontend/test/setup.ts
+++ b/frontend/test/setup.ts
@@ -26,3 +26,5 @@ class ResizeObserver {
}
window.ResizeObserver = ResizeObserver;
+
+window.scrollTo = () => {};