- {!!user ? (
+ {user ? (
Welcome {user.name}
diff --git a/src/pages/DashboardPage/__tests__/DashboardPage.test.tsx b/src/pages/DashboardPage/__tests__/DashboardPage.test.tsx
index a8d6421..f851aa7 100644
--- a/src/pages/DashboardPage/__tests__/DashboardPage.test.tsx
+++ b/src/pages/DashboardPage/__tests__/DashboardPage.test.tsx
@@ -1,3 +1,4 @@
+import { beforeEach, describe, expect, it, vi } from 'vitest';
import { render, screen } from 'test/test-utils';
import { UseQueryResult } from '@tanstack/react-query';
@@ -7,7 +8,7 @@ import * as UseGetUser from 'api/useGetUser';
import DashboardPage from '../DashboardPage';
describe('DashboardPage', () => {
- const useGetUserSpy = jest.spyOn(UseGetUser, 'useGetUser');
+ const useGetUserSpy = vi.spyOn(UseGetUser, 'useGetUser');
beforeEach(() => {
useGetUserSpy.mockReturnValue({
diff --git a/src/pages/ErrorPage/__tests__/ErrorPage.test.tsx b/src/pages/ErrorPage/__tests__/ErrorPage.test.tsx
index 33cfaaa..92ffa31 100644
--- a/src/pages/ErrorPage/__tests__/ErrorPage.test.tsx
+++ b/src/pages/ErrorPage/__tests__/ErrorPage.test.tsx
@@ -1,3 +1,4 @@
+import { describe, expect, it } from 'vitest';
import { render, screen } from 'test/test-utils';
import ErrorPage from '../ErrorPage';
diff --git a/src/pages/LandingPage/LandingPage.tsx b/src/pages/LandingPage/LandingPage.tsx
index 474dcdc..3d04be6 100644
--- a/src/pages/LandingPage/LandingPage.tsx
+++ b/src/pages/LandingPage/LandingPage.tsx
@@ -1,6 +1,6 @@
import { Navigate } from 'react-router-dom';
-import { useAuthContext } from 'providers/AuthProvider';
+import { useAuth } from 'hooks/useAuth';
import Page from 'components/Page/Page';
/**
@@ -12,7 +12,7 @@ import Page from 'components/Page/Page';
* @returns {JSX.Element} JSX
*/
const LandingPage = (): JSX.Element => {
- const authContext = useAuthContext();
+ const authContext = useAuth();
if (authContext.isAuthenticated) {
return
;
diff --git a/src/pages/LandingPage/__tests__/LandingPage.test.tsx b/src/pages/LandingPage/__tests__/LandingPage.test.tsx
index 1c1a2ae..95251ba 100644
--- a/src/pages/LandingPage/__tests__/LandingPage.test.tsx
+++ b/src/pages/LandingPage/__tests__/LandingPage.test.tsx
@@ -1,15 +1,16 @@
+import { beforeEach, describe, expect, it, vi } from 'vitest';
import { render, screen } from 'test/test-utils';
-import * as UseAuthContext from '../../../providers/AuthProvider';
+import * as UseAuth from 'hooks/useAuth';
import LandingPage from '../LandingPage';
import { Route, Routes } from 'react-router-dom';
describe('LandingPage', () => {
- const useAuthContextSpy = jest.spyOn(UseAuthContext, 'useAuthContext');
+ const useAuthSpy = vi.spyOn(UseAuth, 'useAuth');
beforeEach(() => {
- useAuthContextSpy.mockReturnValue({
+ useAuthSpy.mockReturnValue({
isAuthenticated: false,
});
});
@@ -34,7 +35,7 @@ describe('LandingPage', () => {
it('should navigate when authenticated', async () => {
// ARRANGE
- useAuthContextSpy.mockReturnValueOnce({
+ useAuthSpy.mockReturnValueOnce({
isAuthenticated: true,
});
render(
diff --git a/src/pages/SettingsPage/__tests__/SettingsPage.test.tsx b/src/pages/SettingsPage/__tests__/SettingsPage.test.tsx
index c8a4d60..72b827d 100644
--- a/src/pages/SettingsPage/__tests__/SettingsPage.test.tsx
+++ b/src/pages/SettingsPage/__tests__/SettingsPage.test.tsx
@@ -1,3 +1,4 @@
+import { beforeEach, describe, expect, it, vi } from 'vitest';
import { UseQueryResult } from '@tanstack/react-query';
import { render, screen } from 'test/test-utils';
@@ -8,7 +9,7 @@ import { userFixture1 } from '__fixtures__/users';
import SettingsPage from '../SettingsPage';
describe('SettingsPage', () => {
- const useGetUserSpy = jest.spyOn(UseGetUser, 'useGetUser');
+ const useGetUserSpy = vi.spyOn(UseGetUser, 'useGetUser');
beforeEach(() => {
useGetUserSpy.mockReturnValue({
diff --git a/src/pages/SettingsPage/components/AppearanceSettings.tsx b/src/pages/SettingsPage/components/AppearanceSettings.tsx
index 020c5ee..f702998 100644
--- a/src/pages/SettingsPage/components/AppearanceSettings.tsx
+++ b/src/pages/SettingsPage/components/AppearanceSettings.tsx
@@ -1,7 +1,7 @@
import { PropsWithTestId } from '@leanstacks/react-common';
import classNames from 'classnames';
-import { useSettings } from 'providers/SettingsProvider';
+import { useSettings } from 'hooks/useSettings';
import { useSetSettings } from 'api/useSetSettings';
import SettingsHeading from './SettingsHeading';
diff --git a/src/pages/SettingsPage/components/__tests__/AppearanceSettings.test.tsx b/src/pages/SettingsPage/components/__tests__/AppearanceSettings.test.tsx
index 8485a46..b0fd69f 100644
--- a/src/pages/SettingsPage/components/__tests__/AppearanceSettings.test.tsx
+++ b/src/pages/SettingsPage/components/__tests__/AppearanceSettings.test.tsx
@@ -1,18 +1,19 @@
+import { beforeEach, describe, expect, it, vi } from 'vitest';
import { UseMutationResult } from '@tanstack/react-query';
import userEvent from '@testing-library/user-event';
import { render, screen } from 'test/test-utils';
import { Settings } from 'api/useGetSettings';
import { DEFAULT_SETTINGS } from 'utils/constants';
-import * as SettingsProvider from 'providers/SettingsProvider';
+import * as UseSettings from 'hooks/useSettings';
import * as UseSetSettings from 'api/useSetSettings';
import AppearanceSettings from '../AppearanceSettings';
describe('AppearanceSettings', () => {
- const useSettingsSpy = jest.spyOn(SettingsProvider, 'useSettings');
- const useSetSettingsSpy = jest.spyOn(UseSetSettings, 'useSetSettings');
- const mockSetSettings = jest.fn();
+ const useSettingsSpy = vi.spyOn(UseSettings, 'useSettings');
+ const useSetSettingsSpy = vi.spyOn(UseSetSettings, 'useSetSettings');
+ const mockSetSettings = vi.fn();
beforeEach(() => {
useSettingsSpy.mockReturnValue(DEFAULT_SETTINGS);
diff --git a/src/pages/SettingsPage/components/__tests__/SettingsHeading.test.tsx b/src/pages/SettingsPage/components/__tests__/SettingsHeading.test.tsx
index 377bb1b..302d88e 100644
--- a/src/pages/SettingsPage/components/__tests__/SettingsHeading.test.tsx
+++ b/src/pages/SettingsPage/components/__tests__/SettingsHeading.test.tsx
@@ -1,3 +1,4 @@
+import { describe, expect, it } from 'vitest';
import { render, screen } from '@testing-library/react';
import SettingsHeading from '../SettingsHeading';
diff --git a/src/pages/UsersPage/__tests__/UsersPage.test.tsx b/src/pages/UsersPage/__tests__/UsersPage.test.tsx
index 47d45ef..6af5f73 100644
--- a/src/pages/UsersPage/__tests__/UsersPage.test.tsx
+++ b/src/pages/UsersPage/__tests__/UsersPage.test.tsx
@@ -1,3 +1,4 @@
+import { describe, expect, it } from 'vitest';
import { render, screen } from 'test/test-utils';
import UsersPage from '../UsersPage';
diff --git a/src/pages/UsersPage/api/__tests__/useGetUser.test.ts b/src/pages/UsersPage/api/__tests__/useGetUser.test.ts
index 49d0c91..b5fe474 100644
--- a/src/pages/UsersPage/api/__tests__/useGetUser.test.ts
+++ b/src/pages/UsersPage/api/__tests__/useGetUser.test.ts
@@ -1,3 +1,4 @@
+import { describe, expect, it } from 'vitest';
import { renderHook, waitFor } from 'test/test-utils';
import { useGetUsers } from '../useGetUsers';
diff --git a/src/pages/UsersPage/api/__tests__/useGetUserTasks.test.ts b/src/pages/UsersPage/api/__tests__/useGetUserTasks.test.ts
index 68d9b17..b9f8cad 100644
--- a/src/pages/UsersPage/api/__tests__/useGetUserTasks.test.ts
+++ b/src/pages/UsersPage/api/__tests__/useGetUserTasks.test.ts
@@ -1,3 +1,4 @@
+import { describe, expect, it } from 'vitest';
import { renderHook, waitFor } from 'test/test-utils';
import { useGetUserTasks } from '../useGetUserTasks';
diff --git a/src/pages/UsersPage/api/useGetUserTasks.ts b/src/pages/UsersPage/api/useGetUserTasks.ts
index 9b0c205..6ab8b6b 100644
--- a/src/pages/UsersPage/api/useGetUserTasks.ts
+++ b/src/pages/UsersPage/api/useGetUserTasks.ts
@@ -1,7 +1,7 @@
import { UseQueryResult, useQuery } from '@tanstack/react-query';
-import { useAxios } from 'providers/AxiosProvider';
-import { useConfig } from 'providers/ConfigProvider';
+import { useAxios } from 'hooks/useAxios';
+import { useConfig } from 'hooks/useConfig';
import { QueryKeys } from 'utils/constants';
/**
@@ -35,7 +35,7 @@ export const useGetUserTasks = ({
const getUserTasks = async (): Promise
=> {
const response = await axios.request({
- url: `${config.REACT_APP_BASE_URL_API}/users/${userId}/todos`,
+ url: `${config.VITE_BASE_URL_API}/users/${userId}/todos`,
});
return response.data;
};
diff --git a/src/pages/UsersPage/api/useGetUsers.ts b/src/pages/UsersPage/api/useGetUsers.ts
index 6d4f454..64329b7 100644
--- a/src/pages/UsersPage/api/useGetUsers.ts
+++ b/src/pages/UsersPage/api/useGetUsers.ts
@@ -1,8 +1,8 @@
import { UseQueryResult, useQuery } from '@tanstack/react-query';
import { User } from 'api/useGetUser';
-import { useAxios } from 'providers/AxiosProvider';
-import { useConfig } from 'providers/ConfigProvider';
+import { useAxios } from 'hooks/useAxios';
+import { useConfig } from 'hooks/useConfig';
import { QueryKeys } from 'utils/constants';
/**
@@ -15,7 +15,7 @@ export const useGetUsers = (): UseQueryResult => {
const getUsers = async (): Promise => {
const response = await axios.request({
- url: `${config.REACT_APP_BASE_URL_API}/users`,
+ url: `${config.VITE_BASE_URL_API}/users`,
});
return response.data;
};
diff --git a/src/pages/UsersPage/components/UserTasks.tsx b/src/pages/UsersPage/components/UserTasks.tsx
index a60eeb7..a4a4131 100644
--- a/src/pages/UsersPage/components/UserTasks.tsx
+++ b/src/pages/UsersPage/components/UserTasks.tsx
@@ -49,7 +49,7 @@ const UserTasks = ({ className, testId = 'user-tasks', userId }: UserTasksProps)
>
)}
{!!tasks &&
- tasks.slice(0, 3).map((task, index) => (
+ tasks.slice(0, 3).map((task) => (
({
- ...jest.requireActual('react-router-dom'),
- useParams: () => ({
- userId: '1',
- }),
-}));
+vi.mock('react-router-dom', async () => {
+ const original = await vi.importActual('react-router-dom');
+ return {
+ ...original,
+ useParams: () => ({
+ userId: '1',
+ }),
+ };
+});
describe('UserDetail', () => {
it('should render successfully', async () => {
@@ -52,7 +56,7 @@ describe('UserDetail', () => {
it('should render loading state', async () => {
// ARRANGE
- const useGetUserSpy = jest.spyOn(UseGetUser, 'useGetUser');
+ const useGetUserSpy = vi.spyOn(UseGetUser, 'useGetUser');
useGetUserSpy.mockReturnValue({
data: undefined,
error: undefined,
@@ -67,7 +71,7 @@ describe('UserDetail', () => {
it('should render error state', async () => {
// ARRANGE
- const useGetUserSpy = jest.spyOn(UseGetUser, 'useGetUser');
+ const useGetUserSpy = vi.spyOn(UseGetUser, 'useGetUser');
useGetUserSpy.mockReturnValue({
data: undefined,
error: new AxiosError(),
diff --git a/src/pages/UsersPage/components/__tests__/UserDetailEmpty.test.tsx b/src/pages/UsersPage/components/__tests__/UserDetailEmpty.test.tsx
index 8a28f64..b02b6d4 100644
--- a/src/pages/UsersPage/components/__tests__/UserDetailEmpty.test.tsx
+++ b/src/pages/UsersPage/components/__tests__/UserDetailEmpty.test.tsx
@@ -1,3 +1,4 @@
+import { describe, expect, it } from 'vitest';
import { render, screen } from 'test/test-utils';
import UserDetailEmpty from '../UserDetailEmpty';
diff --git a/src/pages/UsersPage/components/__tests__/UserDetailLayout.test.tsx b/src/pages/UsersPage/components/__tests__/UserDetailLayout.test.tsx
index 4a1c85b..5054043 100644
--- a/src/pages/UsersPage/components/__tests__/UserDetailLayout.test.tsx
+++ b/src/pages/UsersPage/components/__tests__/UserDetailLayout.test.tsx
@@ -1,3 +1,4 @@
+import { describe, expect, it, vi } from 'vitest';
import { UseQueryResult } from '@tanstack/react-query';
import { AxiosError } from 'axios';
import { render, screen } from 'test/test-utils';
@@ -6,12 +7,15 @@ import * as UseGetUser from 'api/useGetUser';
import UserDetailLayout from '../UserDetailLayout';
// mock select functions from react-router-dom
-jest.mock('react-router-dom', () => ({
- ...jest.requireActual('react-router-dom'),
- useParams: () => ({
- userId: '1',
- }),
-}));
+vi.mock('react-router-dom', async () => {
+ const original = await vi.importActual('react-router-dom');
+ return {
+ ...original,
+ useParams: () => ({
+ userId: '1',
+ }),
+ };
+});
describe('UserDetailLayout', () => {
it('should render successfully', async () => {
@@ -52,7 +56,7 @@ describe('UserDetailLayout', () => {
it('should render loading state', async () => {
// ARRANGE
- const useGetUserSpy = jest.spyOn(UseGetUser, 'useGetUser');
+ const useGetUserSpy = vi.spyOn(UseGetUser, 'useGetUser');
useGetUserSpy.mockReturnValue({
data: undefined,
error: undefined,
@@ -67,7 +71,7 @@ describe('UserDetailLayout', () => {
it('should render error state', async () => {
// ARRANGE
- const useGetUserSpy = jest.spyOn(UseGetUser, 'useGetUser');
+ const useGetUserSpy = vi.spyOn(UseGetUser, 'useGetUser');
useGetUserSpy.mockReturnValue({
data: undefined,
error: new AxiosError(),
diff --git a/src/pages/UsersPage/components/__tests__/UserList.test.tsx b/src/pages/UsersPage/components/__tests__/UserList.test.tsx
index 4ba76c5..1ba68e2 100644
--- a/src/pages/UsersPage/components/__tests__/UserList.test.tsx
+++ b/src/pages/UsersPage/components/__tests__/UserList.test.tsx
@@ -1,3 +1,4 @@
+import { describe, expect, it, vi } from 'vitest';
import { render, screen } from 'test/test-utils';
import * as UseGetUser from 'api/useGetUser';
@@ -7,12 +8,15 @@ import { UseQueryResult } from '@tanstack/react-query';
import { AxiosError } from 'axios';
// mock select functions from react-router-dom
-jest.mock('react-router-dom', () => ({
- ...jest.requireActual('react-router-dom'),
- useParams: () => ({
- userId: '1',
- }),
-}));
+vi.mock('react-router-dom', async () => {
+ const original = await vi.importActual('react-router-dom');
+ return {
+ ...original,
+ useParams: () => ({
+ userId: '1',
+ }),
+ };
+});
describe('UserList', () => {
it('should render successfully', async () => {
@@ -53,7 +57,7 @@ describe('UserList', () => {
it('should render loading state', async () => {
// ARRANGE
- const useGetUsersSpy = jest.spyOn(UseGetUsers, 'useGetUsers');
+ const useGetUsersSpy = vi.spyOn(UseGetUsers, 'useGetUsers');
useGetUsersSpy.mockReturnValue({
data: undefined,
error: undefined,
@@ -68,7 +72,7 @@ describe('UserList', () => {
it('should render error state', async () => {
// ARRANGE
- const useGetUsersSpy = jest.spyOn(UseGetUsers, 'useGetUsers');
+ const useGetUsersSpy = vi.spyOn(UseGetUsers, 'useGetUsers');
useGetUsersSpy.mockReturnValue({
data: undefined,
error: new AxiosError(),
diff --git a/src/pages/UsersPage/components/__tests__/UserListItem.test.tsx b/src/pages/UsersPage/components/__tests__/UserListItem.test.tsx
index 34703de..3639523 100644
--- a/src/pages/UsersPage/components/__tests__/UserListItem.test.tsx
+++ b/src/pages/UsersPage/components/__tests__/UserListItem.test.tsx
@@ -1,14 +1,18 @@
+import { describe, expect, it, vi } from 'vitest';
import { render, screen } from 'test/test-utils';
import UserListItem from '../UserListItem';
import { userFixture1 } from '__fixtures__/users';
import userEvent from '@testing-library/user-event';
// mock select functions from react-router-dom
-const mockNavigate = jest.fn();
-jest.mock('react-router-dom', () => ({
- ...jest.requireActual('react-router-dom'),
- useNavigate: () => mockNavigate,
-}));
+const mockNavigate = vi.fn();
+vi.mock('react-router-dom', async () => {
+ const original = await vi.importActual('react-router-dom');
+ return {
+ ...original,
+ useNavigate: () => mockNavigate,
+ };
+});
describe('UserListItem', () => {
it('should render successfully', async () => {
diff --git a/src/pages/UsersPage/components/__tests__/UserTaskList.test.tsx b/src/pages/UsersPage/components/__tests__/UserTaskList.test.tsx
index 1120e79..cafb96d 100644
--- a/src/pages/UsersPage/components/__tests__/UserTaskList.test.tsx
+++ b/src/pages/UsersPage/components/__tests__/UserTaskList.test.tsx
@@ -1,3 +1,4 @@
+import { describe, expect, it, vi } from 'vitest';
import { render, screen } from 'test/test-utils';
import * as UseGetUserTasks from '../../api/useGetUserTasks';
@@ -6,12 +7,15 @@ import { UseQueryResult } from '@tanstack/react-query';
import { AxiosError } from 'axios';
// mock select functions from react-router-dom
-jest.mock('react-router-dom', () => ({
- ...jest.requireActual('react-router-dom'),
- useParams: () => ({
- userId: '1',
- }),
-}));
+vi.mock('react-router-dom', async () => {
+ const original = await vi.importActual('react-router-dom');
+ return {
+ ...original,
+ useParams: () => ({
+ userId: '1',
+ }),
+ };
+});
describe('UserTaskList', () => {
it('should render successfully', async () => {
@@ -55,7 +59,7 @@ describe('UserTaskList', () => {
it('should render loading state', async () => {
// ARRANGE
- const useGetUserTasksSpy = jest.spyOn(UseGetUserTasks, 'useGetUserTasks');
+ const useGetUserTasksSpy = vi.spyOn(UseGetUserTasks, 'useGetUserTasks');
useGetUserTasksSpy.mockReturnValue({
data: undefined,
error: undefined,
@@ -70,7 +74,7 @@ describe('UserTaskList', () => {
it('should render error state', async () => {
// ARRANGE
- const useGetUserTasksSpy = jest.spyOn(UseGetUserTasks, 'useGetUserTasks');
+ const useGetUserTasksSpy = vi.spyOn(UseGetUserTasks, 'useGetUserTasks');
useGetUserTasksSpy.mockReturnValue({
data: undefined,
error: new AxiosError(),
diff --git a/src/pages/UsersPage/components/__tests__/UserTaskListItem.test.tsx b/src/pages/UsersPage/components/__tests__/UserTaskListItem.test.tsx
index d0e6202..c1560ad 100644
--- a/src/pages/UsersPage/components/__tests__/UserTaskListItem.test.tsx
+++ b/src/pages/UsersPage/components/__tests__/UserTaskListItem.test.tsx
@@ -1,3 +1,4 @@
+import { describe, expect, it } from 'vitest';
import { render, screen } from 'test/test-utils';
import { todosFixture } from '__fixtures__/todos';
@@ -42,6 +43,6 @@ describe('UserTaskListItem', () => {
await screen.findByTestId('user-task-list-item');
// ASSERT
- expect(screen.getByTestId('user-task-list-item-icon')).toHaveTextContent('task_alt');
+ expect(screen.getByTestId('user-task-list-item-icon').textContent).toBe('task_alt');
});
});
diff --git a/src/pages/UsersPage/components/__tests__/UserTasks.test.tsx b/src/pages/UsersPage/components/__tests__/UserTasks.test.tsx
index fa237d4..23b947d 100644
--- a/src/pages/UsersPage/components/__tests__/UserTasks.test.tsx
+++ b/src/pages/UsersPage/components/__tests__/UserTasks.test.tsx
@@ -1,3 +1,4 @@
+import { describe, expect, it, vi } from 'vitest';
import { render, screen } from 'test/test-utils';
import * as UseGetUserTasks from '../../api/useGetUserTasks';
@@ -45,7 +46,7 @@ describe('UserTasks', () => {
it('should render loading state', async () => {
// ARRANGE
- const useGetUserTasksSpy = jest.spyOn(UseGetUserTasks, 'useGetUserTasks');
+ const useGetUserTasksSpy = vi.spyOn(UseGetUserTasks, 'useGetUserTasks');
useGetUserTasksSpy.mockReturnValue({
data: undefined,
error: undefined,
@@ -60,7 +61,7 @@ describe('UserTasks', () => {
it('should render error state', async () => {
// ARRANGE
- const useGetUserTasksSpy = jest.spyOn(UseGetUserTasks, 'useGetUserTasks');
+ const useGetUserTasksSpy = vi.spyOn(UseGetUserTasks, 'useGetUserTasks');
useGetUserTasksSpy.mockReturnValue({
data: undefined,
error: new AxiosError(),
diff --git a/src/providers/AuthProvider.tsx b/src/providers/AuthProvider.tsx
index c87e4fb..1e132d7 100644
--- a/src/providers/AuthProvider.tsx
+++ b/src/providers/AuthProvider.tsx
@@ -1,7 +1,8 @@
-import React, { PropsWithChildren, useContext } from 'react';
+import React, { PropsWithChildren } from 'react';
import { UserTokens, useGetUserTokens } from 'api/useGetUserTokens';
import LoaderSpinner from 'components/Loader/LoaderSpinner';
+import { QueryObserverBaseResult } from '@tanstack/react-query';
/**
* The `value` provided by the `AuthContext`.
@@ -9,7 +10,7 @@ import LoaderSpinner from 'components/Loader/LoaderSpinner';
export interface AuthContextValue {
isAuthenticated: boolean;
userToken?: UserTokens;
- refetchUserTokens?: () => any;
+ refetchUserTokens?: () => Promise>;
}
/**
@@ -22,7 +23,7 @@ const DEFAULT_CONTEXT_VALUE: AuthContextValue = {
/**
* The `AuthContext` instance.
*/
-const AuthContext = React.createContext(DEFAULT_CONTEXT_VALUE);
+export const AuthContext = React.createContext(DEFAULT_CONTEXT_VALUE);
/**
* The `AuthContextProvider` React component creates, maintains, and provides
@@ -56,12 +57,4 @@ const AuthContextProvider = ({ children }: PropsWithChildren): JSX.Element => {
);
};
-/**
- * The `useAuthContext` hook returns the current `AuthContext` value.
- * @returns {AuthContextValue} The current `AuthContext` value, `AuthContextValue`.
- */
-export const useAuthContext = (): AuthContextValue => {
- return useContext(AuthContext);
-};
-
export default AuthContextProvider;
diff --git a/src/providers/AxiosProvider.tsx b/src/providers/AxiosProvider.tsx
index 5319187..5562617 100644
--- a/src/providers/AxiosProvider.tsx
+++ b/src/providers/AxiosProvider.tsx
@@ -1,7 +1,8 @@
-import React, { PropsWithChildren, useContext, useEffect, useState } from 'react';
+import React, { PropsWithChildren, useEffect, useState } from 'react';
import axios, { AxiosError, AxiosInstance, InternalAxiosRequestConfig } from 'axios';
-import { AuthContextValue, useAuthContext } from './AuthProvider';
+import { AuthContextValue } from './AuthProvider';
+import { useAuth } from 'hooks/useAuth';
/**
* An Axios request interceptor that adds user authentication headers to
@@ -44,8 +45,8 @@ const notAuthenticatedErrorInterceptor = async (
...config,
headers: {
...config?.headers,
- Authorization: `Bearer ${data.id_token}`,
- 'X-Access-Token': data.access_token,
+ Authorization: `Bearer ${data?.id_token}`,
+ 'X-Access-Token': data?.access_token,
},
});
}
@@ -67,7 +68,7 @@ const customAxios = axios.create({
/**
* The `AxiosContext` instance.
*/
-const AxiosContext = React.createContext(customAxios);
+export const AxiosContext = React.createContext(customAxios);
/**
* The `AxiosContextProvider` React component creates, maintains, and provides
@@ -77,7 +78,7 @@ const AxiosContext = React.createContext(customAxios);
*/
const AxiosContextProvider = ({ children }: PropsWithChildren) => {
const [isReady, setIsReady] = useState(false);
- const authContext = useAuthContext();
+ const authContext = useAuth();
useEffect(() => {
const authRequestInterceptorId = customAxios.interceptors.request.use(async (config) =>
@@ -102,12 +103,4 @@ const AxiosContextProvider = ({ children }: PropsWithChildren) => {
);
};
-/**
- * The `useAxios` hook returns the current `AxiosContext` value.
- * @returns {AxiosInstance} The current `AxiosContext` value, an `AxiosInstance`.
- */
-export const useAxios = (): AxiosInstance => {
- return useContext(AxiosContext);
-};
-
export default AxiosContextProvider;
diff --git a/src/providers/ConfigProvider.tsx b/src/providers/ConfigProvider.tsx
index d03815a..c472f3e 100644
--- a/src/providers/ConfigProvider.tsx
+++ b/src/providers/ConfigProvider.tsx
@@ -1,4 +1,4 @@
-import React, { PropsWithChildren, useContext, useEffect, useState } from 'react';
+import React, { PropsWithChildren, useEffect, useState } from 'react';
import * as Yup from 'yup';
import { ObjectSchema } from 'yup';
@@ -6,16 +6,16 @@ import { ObjectSchema } from 'yup';
* The application configuration. The `value` provided by the `ConfigContext`.
*/
export interface Config {
- REACT_APP_BASE_URL_API: string;
- REACT_APP_BUILD_DATE: string;
- REACT_APP_BUILD_TIME: string;
- REACT_APP_BUILD_TS: string;
- REACT_APP_BUILD_COMMIT_SHA: string;
- REACT_APP_BUILD_ENV_CODE: string;
- REACT_APP_BUILD_WORKFLOW_NAME: string;
- REACT_APP_BUILD_WORKFLOW_RUN_NUMBER: number;
- REACT_APP_BUILD_WORKFLOW_RUN_ATTEMPT: number;
- REACT_APP_TOAST_AUTO_DISMISS_MILLIS: number;
+ VITE_BASE_URL_API: string;
+ VITE_BUILD_DATE: string;
+ VITE_BUILD_TIME: string;
+ VITE_BUILD_TS: string;
+ VITE_BUILD_COMMIT_SHA: string;
+ VITE_BUILD_ENV_CODE: string;
+ VITE_BUILD_WORKFLOW_NAME: string;
+ VITE_BUILD_WORKFLOW_RUN_NUMBER: number;
+ VITE_BUILD_WORKFLOW_RUN_ATTEMPT: number;
+ VITE_TOAST_AUTO_DISMISS_MILLIS: number;
}
/**
@@ -23,22 +23,22 @@ export interface Config {
* @see {@link https://github.com/jquense/yup | Yup}
*/
const configSchema: ObjectSchema = Yup.object({
- REACT_APP_BASE_URL_API: Yup.string().url().required(),
- REACT_APP_BUILD_DATE: Yup.string().default('1970-01-01'),
- REACT_APP_BUILD_TIME: Yup.string().default('00:00:00'),
- REACT_APP_BUILD_TS: Yup.string().default('1970-01-01T00:00:00+0000'),
- REACT_APP_BUILD_COMMIT_SHA: Yup.string().default('local'),
- REACT_APP_BUILD_ENV_CODE: Yup.string().default('local'),
- REACT_APP_BUILD_WORKFLOW_NAME: Yup.string().default('local'),
- REACT_APP_BUILD_WORKFLOW_RUN_NUMBER: Yup.number().default(1),
- REACT_APP_BUILD_WORKFLOW_RUN_ATTEMPT: Yup.number().default(1),
- REACT_APP_TOAST_AUTO_DISMISS_MILLIS: Yup.number().default(5000),
+ VITE_BASE_URL_API: Yup.string().url().required(),
+ VITE_BUILD_DATE: Yup.string().default('1970-01-01'),
+ VITE_BUILD_TIME: Yup.string().default('00:00:00'),
+ VITE_BUILD_TS: Yup.string().default('1970-01-01T00:00:00+0000'),
+ VITE_BUILD_COMMIT_SHA: Yup.string().default('local'),
+ VITE_BUILD_ENV_CODE: Yup.string().default('local'),
+ VITE_BUILD_WORKFLOW_NAME: Yup.string().default('local'),
+ VITE_BUILD_WORKFLOW_RUN_NUMBER: Yup.number().default(1),
+ VITE_BUILD_WORKFLOW_RUN_ATTEMPT: Yup.number().default(1),
+ VITE_TOAST_AUTO_DISMISS_MILLIS: Yup.number().default(5000),
});
/**
* The `ConfigContext` instance.
*/
-const ConfigContext = React.createContext(undefined);
+export const ConfigContext = React.createContext(undefined);
/**
* The `ConfigContextProvider` React component creates, maintains, and provides
@@ -55,7 +55,7 @@ const ConfigContextProvider = ({ children }: PropsWithChildren) => {
useEffect(() => {
try {
- const validatedConfig = configSchema.validateSync(process.env, {
+ const validatedConfig = configSchema.validateSync(import.meta.env, {
abortEarly: false,
stripUnknown: true,
});
@@ -73,17 +73,4 @@ const ConfigContextProvider = ({ children }: PropsWithChildren) => {
);
};
-/**
- * The `useConfig` hook returns the current `ConfigContext` value.
- * @returns {Config} The current `ConfigContext` value, `Config`.
- */
-export const useConfig = (): Config => {
- const context = useContext(ConfigContext);
- if (!context) {
- throw new Error('useConfig hook must be used within a ConfigContextProvider');
- }
-
- return context;
-};
-
export default ConfigContextProvider;
diff --git a/src/providers/SettingsProvider.tsx b/src/providers/SettingsProvider.tsx
index 8a81e5e..8799bf2 100644
--- a/src/providers/SettingsProvider.tsx
+++ b/src/providers/SettingsProvider.tsx
@@ -1,11 +1,11 @@
-import React, { PropsWithChildren, useContext, useMemo } from 'react';
+import React, { PropsWithChildren, useMemo } from 'react';
import { Settings, useGetSettings } from 'api/useGetSettings';
/**
* The `SettingsContext` instance.
*/
-const SettingsContext = React.createContext(undefined);
+export const SettingsContext = React.createContext(undefined);
/**
* The `SettingsContextProvider` React component creates, maintains, and provides
@@ -25,18 +25,4 @@ const SettingsContextProvider = ({ children }: PropsWithChildren) => {
);
};
-/**
- * The `useSettings` hook returns the current `SettingsContext` value.
- * @returns {Settings} The current `SettingsContext` value, `Settings`.
- * @see {@link Settings}
- */
-export const useSettings = (): Settings => {
- const context = useContext(SettingsContext);
- if (!context) {
- throw new Error('useSettings hook must be used within a SettingsContextProvider');
- }
-
- return context;
-};
-
export default SettingsContextProvider;
diff --git a/src/providers/ToastsProvider.tsx b/src/providers/ToastsProvider.tsx
index 0c5d95a..c6be52a 100644
--- a/src/providers/ToastsProvider.tsx
+++ b/src/providers/ToastsProvider.tsx
@@ -1,4 +1,4 @@
-import React, { Dispatch, PropsWithChildren, useContext, useMemo, useReducer } from 'react';
+import React, { Dispatch, PropsWithChildren, useMemo, useReducer } from 'react';
import { v4 as uuid } from 'uuid';
import dayjs from 'dayjs';
@@ -119,7 +119,7 @@ const actions = (dispatch: Dispatch) => {
/**
* The `ToastsContext` instance.
*/
-const ToastsContext = React.createContext(undefined);
+export const ToastsContext = React.createContext(undefined);
/**
* The `ToastsProvider` React component creates, maintains, and provides
@@ -143,16 +143,3 @@ const ToastsProvider = ({ children }: PropsWithChildren): JSX.Element => {
};
export default ToastsProvider;
-
-/**
- * The `useToasts` hook returns the current `ToastsContext` value.
- * @returns {ToastsContextValue} The current `ToastContext` value, `ToastsContextValue`.
- */
-export const useToasts = (): ToastsContextValue => {
- const context = useContext(ToastsContext);
- if (!context) {
- throw new Error('useToasts hook must be used within a ToastsProvider');
- }
-
- return context;
-};
diff --git a/src/providers/__tests__/AuthProvider.test.tsx b/src/providers/__tests__/AuthProvider.test.tsx
index deed308..949b5ee 100644
--- a/src/providers/__tests__/AuthProvider.test.tsx
+++ b/src/providers/__tests__/AuthProvider.test.tsx
@@ -1,14 +1,15 @@
+import { beforeEach, describe, expect, it, vi } from 'vitest';
import { UseQueryResult } from '@tanstack/react-query';
-import { render, renderHook, screen, waitFor } from 'test/test-utils';
+import { render, screen } from 'test/test-utils';
import { userTokensFixture } from '__fixtures__/tokens';
import * as UseGetUserTokens from 'api/useGetUserTokens';
-import AuthContextProvider, { useAuthContext } from 'providers/AuthProvider';
+import AuthContextProvider from 'providers/AuthProvider';
describe('AuthProvider', () => {
- const useGetUserTokensSpy = jest.spyOn(UseGetUserTokens, 'useGetUserTokens');
+ const useGetUserTokensSpy = vi.spyOn(UseGetUserTokens, 'useGetUserTokens');
beforeEach(() => {
useGetUserTokensSpy.mockReturnValue({
@@ -62,25 +63,3 @@ describe('AuthProvider', () => {
expect(screen.getByTestId('provider-auth')).toBeDefined();
});
});
-
-describe('useAuthContext', () => {
- const useGetUserTokensSpy = jest.spyOn(UseGetUserTokens, 'useGetUserTokens');
-
- beforeEach(() => {
- useGetUserTokensSpy.mockReturnValue({
- data: userTokensFixture,
- isSuccess: true,
- isPending: false,
- } as unknown as UseQueryResult);
- });
-
- it('should return the context', async () => {
- // ARRANGE
- const { result } = renderHook(() => useAuthContext());
- await waitFor(() => expect(result.current.isAuthenticated).toBeDefined());
-
- // ASSERT
- expect(result.current).toBeDefined();
- expect(result.current.isAuthenticated).toBe(true);
- });
-});
diff --git a/src/providers/__tests__/AxiosProvider.test.tsx b/src/providers/__tests__/AxiosProvider.test.tsx
index d06e8cb..e5ef75e 100644
--- a/src/providers/__tests__/AxiosProvider.test.tsx
+++ b/src/providers/__tests__/AxiosProvider.test.tsx
@@ -1,21 +1,23 @@
-import { render, renderHook, screen, waitFor } from 'test/test-utils';
-
-import * as AuthProvider from '../AuthProvider';
-
-import AxiosContextProvider, { useAxios } from 'providers/AxiosProvider';
+import { beforeEach, describe, expect, it, vi } from 'vitest';
import { useEffect, useState } from 'react';
import { InternalAxiosRequestConfig } from 'axios';
+import { render, screen } from 'test/test-utils';
+
+import { useAxios } from 'hooks/useAxios';
+import * as UseAuth from 'hooks/useAuth';
import { userTokensFixture } from '__fixtures__/tokens';
+import AxiosContextProvider from 'providers/AxiosProvider';
+
describe('AxiosProvider', () => {
- const useAuthContextSpy = jest.spyOn(AuthProvider, 'useAuthContext');
- const refetchUserTokensMock = jest.fn();
+ const useAuthSpy = vi.spyOn(UseAuth, 'useAuth');
+ const refetchUserTokensMock = vi.fn();
beforeEach(() => {
refetchUserTokensMock.mockReturnValue({
data: userTokensFixture,
});
- useAuthContextSpy.mockReturnValue({
+ useAuthSpy.mockReturnValue({
isAuthenticated: true,
userToken: userTokensFixture,
refetchUserTokens: refetchUserTokensMock,
@@ -74,26 +76,3 @@ describe('AxiosProvider', () => {
expect(refetchUserTokensMock).not.toHaveBeenCalled();
});
});
-
-describe('useAxios', () => {
- const useAuthContextSpy = jest.spyOn(AuthProvider, 'useAuthContext');
- const refetchUserTokensMock = jest.fn();
-
- beforeEach(() => {
- useAuthContextSpy.mockReturnValue({
- isAuthenticated: true,
- userToken: userTokensFixture,
- refetchUserTokens: refetchUserTokensMock,
- });
- });
-
- it('should return context', async () => {
- // ARRANGE
- const { result } = renderHook(() => useAxios());
- await waitFor(() => expect(result.current).not.toBeNull());
-
- // ASSERT
- expect(result.current).toBeDefined();
- expect(result.current.request).toBeDefined();
- });
-});
diff --git a/src/providers/__tests__/ConfigProvider.test.tsx b/src/providers/__tests__/ConfigProvider.test.tsx
index c9c6b33..0c9bdfe 100644
--- a/src/providers/__tests__/ConfigProvider.test.tsx
+++ b/src/providers/__tests__/ConfigProvider.test.tsx
@@ -1,8 +1,8 @@
-import { renderHook as renderHookWithoutWrapper } from '@testing-library/react';
+import { afterAll, beforeAll, describe, expect, it } from 'vitest';
-import { render, renderHook, screen, waitFor } from 'test/test-utils';
+import { render, screen } from 'test/test-utils';
-import ConfigContextProvider, { useConfig } from 'providers/ConfigProvider';
+import ConfigContextProvider from 'providers/ConfigProvider';
describe('ConfigProvider', () => {
it('should render successfully', async () => {
@@ -44,20 +44,3 @@ describe.skip('ConfigProvider error', () => {
expect(renderContextProvider).toThrow(/is a required field/);
});
});
-
-describe('useConfig', () => {
- it('should return the context', async () => {
- // ARRANGE
- const { result } = renderHook(() => useConfig());
- await waitFor(() => expect(result.current).not.toBeNull());
-
- // ASSERT
- expect(result.current).toBeDefined();
- expect(result.current.REACT_APP_BUILD_ENV_CODE).toBe('test');
- });
-
- it('should throw error when not within provider', () => {
- // ASSERT
- expect(() => renderHookWithoutWrapper(() => useConfig())).toThrow(/hook must be used within/);
- });
-});
diff --git a/src/providers/__tests__/SettingsProvider.test.tsx b/src/providers/__tests__/SettingsProvider.test.tsx
index 71861e1..ca5c026 100644
--- a/src/providers/__tests__/SettingsProvider.test.tsx
+++ b/src/providers/__tests__/SettingsProvider.test.tsx
@@ -1,16 +1,14 @@
-import {
- render as renderWithoutWrapper,
- renderHook as renderHookWithoutWrapper,
-} from '@testing-library/react';
+import { beforeEach, describe, expect, it, vi } from 'vitest';
+import { render as renderWithoutWrapper } from '@testing-library/react';
-import { renderHook, screen, waitFor } from 'test/test-utils';
+import { screen } from 'test/test-utils';
-import SettingsContextProvider, { useSettings } from 'providers/SettingsProvider';
-import * as UseGetSettings from 'api/useGetSettings';
+import SettingsContextProvider from 'providers/SettingsProvider';
import { settingsFixture } from '__fixtures__/settings';
+import * as UseGetSettings from 'api/useGetSettings';
import { UseQueryResult } from '@tanstack/react-query';
-const useGetSettingsSpy = jest.spyOn(UseGetSettings, 'useGetSettings');
+const useGetSettingsSpy = vi.spyOn(UseGetSettings, 'useGetSettings');
describe('SettingsProvider', () => {
beforeEach(() => {
@@ -33,27 +31,3 @@ describe('SettingsProvider', () => {
expect(screen.getByTestId('provider-settings')).toBeDefined();
});
});
-
-describe('useSettings', () => {
- beforeEach(() => {
- useGetSettingsSpy.mockReturnValue({
- data: settingsFixture,
- isSuccess: true,
- } as unknown as UseQueryResult);
- });
-
- it('should return default value', async () => {
- // ARRANGE
- const { result } = renderHook(() => UseGetSettings.useGetSettings());
- await waitFor(() => expect(result.current.isSuccess).toBe(true));
-
- // ASSERT
- expect(result.current.data).toBeDefined();
- expect(result.current.data?.theme).toBe(settingsFixture.theme);
- });
-
- it('should throw error when not within provider', () => {
- // ASSERT
- expect(() => renderHookWithoutWrapper(() => useSettings())).toThrow(/hook must be used within/);
- });
-});
diff --git a/src/providers/__tests__/ToastsProvider.test.tsx b/src/providers/__tests__/ToastsProvider.test.tsx
index 416f711..df874b0 100644
--- a/src/providers/__tests__/ToastsProvider.test.tsx
+++ b/src/providers/__tests__/ToastsProvider.test.tsx
@@ -1,11 +1,9 @@
-import {
- render as renderWithoutWrapper,
- renderHook as renderHookWithoutWrapper,
-} from '@testing-library/react';
+import { describe, expect, it } from 'vitest';
+import { render as renderWithoutWrapper } from '@testing-library/react';
-import { act, renderHook, screen, waitFor } from 'test/test-utils';
+import { screen } from 'test/test-utils';
-import ToastsProvider, { useToasts } from 'providers/ToastsProvider';
+import ToastsProvider from 'providers/ToastsProvider';
describe('ToastsProvider', () => {
it('should render successfully', async () => {
@@ -21,53 +19,3 @@ describe('ToastsProvider', () => {
expect(screen.getByTestId('provider-toasts')).toBeDefined();
});
});
-
-describe('useToasts', () => {
- it('should return the context', async () => {
- // ARRANGE
- const { result } = renderHook(() => useToasts());
- await waitFor(() => expect(result.current).not.toBeNull());
-
- // ASSERT
- expect(result.current).not.toBeNull();
- expect(Array.isArray(result.current.toasts)).toBe(true);
- expect(result.current.toasts.length).toBe(0);
- expect(typeof result.current.createToast).toBe('function');
- expect(typeof result.current.removeToast).toBe('function');
- });
-
- it('should create a toast', async () => {
- // ARRANGE
- const { result } = renderHook(() => useToasts());
- await waitFor(() => expect(result.current).not.toBeNull());
- expect(result.current.toasts.length).toBe(0);
-
- // ACT
- act(() => result.current.createToast({ text: 'toast', isAutoDismiss: false }));
-
- // ASSERT
- await waitFor(() => expect(result.current.toasts.length).toBe(1));
- });
-
- it('should remove a toast', async () => {
- // ARRANGE
- const { result } = renderHook(() => useToasts());
- await waitFor(() => expect(result.current).not.toBeNull());
- expect(result.current.toasts.length).toBe(0);
-
- // ACT
- act(() => result.current.createToast({ text: 'toast', isAutoDismiss: false }));
- await waitFor(() => expect(result.current.toasts.length).toBe(1));
- act(() => result.current.removeToast(result.current.toasts[0].id));
-
- // ASSERT
- await waitFor(() => expect(result.current.toasts.length).toBe(0));
- });
-
- it('should throw error when not within provider', async () => {
- // ASSERT
- expect(() => renderHookWithoutWrapper(() => useToasts())).toThrow(
- /useToasts hook must be used within/,
- );
- });
-});
diff --git a/src/react-app-env.d.ts b/src/react-app-env.d.ts
deleted file mode 100644
index 6431bc5..0000000
--- a/src/react-app-env.d.ts
+++ /dev/null
@@ -1 +0,0 @@
-///
diff --git a/src/reportWebVitals.ts b/src/reportWebVitals.ts
deleted file mode 100644
index 49a2a16..0000000
--- a/src/reportWebVitals.ts
+++ /dev/null
@@ -1,15 +0,0 @@
-import { ReportHandler } from 'web-vitals';
-
-const reportWebVitals = (onPerfEntry?: ReportHandler) => {
- if (onPerfEntry && onPerfEntry instanceof Function) {
- import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {
- getCLS(onPerfEntry);
- getFID(onPerfEntry);
- getFCP(onPerfEntry);
- getLCP(onPerfEntry);
- getTTFB(onPerfEntry);
- });
- }
-};
-
-export default reportWebVitals;
diff --git a/src/setupTests.ts b/src/setupTests.ts
deleted file mode 100644
index 44fe52e..0000000
--- a/src/setupTests.ts
+++ /dev/null
@@ -1,24 +0,0 @@
-// runs after test framework installation and before each test file
-// see: https://jestjs.io/docs/configuration#setupfilesafterenv-array
-
-// jest-dom adds custom jest matchers for asserting on DOM nodes.
-// allows you to do things like:
-// expect(element).toHaveTextContent(/react/i)
-// learn more: https://github.com/testing-library/jest-dom
-import '@testing-library/jest-dom';
-
-import { server } from 'test/mocks/server';
-import { queryClient } from 'test/test-utils';
-
-beforeAll(() => {
- server.listen();
-});
-
-afterEach(() => {
- server.resetHandlers();
- queryClient.clear();
-});
-
-afterAll(() => {
- server.close();
-});
diff --git a/src/setupTestsGlobal.ts b/src/setupTestsGlobal.ts
deleted file mode 100644
index c23be20..0000000
--- a/src/setupTestsGlobal.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-// runs before all test suites
-// see: https://jestjs.io/docs/configuration#globalsetup-string
-
-export {};
-
-module.exports = async () => {
- process.env.TZ = 'UTC';
-};
diff --git a/src/test/AllProvidersExceptRouter.tsx b/src/test/AllProvidersExceptRouter.tsx
new file mode 100644
index 0000000..91a534c
--- /dev/null
+++ b/src/test/AllProvidersExceptRouter.tsx
@@ -0,0 +1,25 @@
+import { PropsWithChildren } from 'react';
+import { QueryClientProvider } from '@tanstack/react-query';
+
+import ConfigContextProvider from 'providers/ConfigProvider';
+import SettingsContextProvider from 'providers/SettingsProvider';
+import AuthContextProvider from 'providers/AuthProvider';
+import ToastsProvider from 'providers/ToastsProvider';
+
+import { queryClient } from './query-client';
+
+const AllProvidersExceptRouter = ({ children }: PropsWithChildren): JSX.Element => {
+ return (
+
+
+
+
+ {children}
+
+
+
+
+ );
+};
+
+export default AllProvidersExceptRouter;
diff --git a/src/test/WithAllProviders.tsx b/src/test/WithAllProviders.tsx
new file mode 100644
index 0000000..c465b98
--- /dev/null
+++ b/src/test/WithAllProviders.tsx
@@ -0,0 +1,28 @@
+import { PropsWithChildren } from 'react';
+import { MemoryRouter } from 'react-router-dom';
+import { QueryClientProvider } from '@tanstack/react-query';
+
+import ConfigContextProvider from 'providers/ConfigProvider';
+import SettingsContextProvider from 'providers/SettingsProvider';
+import AuthContextProvider from 'providers/AuthProvider';
+import ToastsProvider from 'providers/ToastsProvider';
+
+import { queryClient } from './query-client';
+
+const WithAllProviders = ({ children }: PropsWithChildren): JSX.Element => {
+ return (
+
+
+
+
+
+ {children}
+
+
+
+
+
+ );
+};
+
+export default WithAllProviders;
diff --git a/src/test/mocks/handlers.ts b/src/test/mocks/handlers.ts
index a623aac..80519f6 100644
--- a/src/test/mocks/handlers.ts
+++ b/src/test/mocks/handlers.ts
@@ -6,13 +6,13 @@ import { usersFixture } from '__fixtures__/users';
import { todosFixture } from '__fixtures__/todos';
export const handlers = [
- rest.get('https://jsonplaceholder.typicode.com/users', (req, res, ctx) => {
+ rest.get('https://jsonplaceholder.typicode.com/users', (_req, res, ctx) => {
return res(ctx.json(usersFixture));
}),
rest.get('https://jsonplaceholder.typicode.com/users/:userId', (req, res, ctx) => {
const { userId } = req.params;
const user = find(usersFixture, { id: Number(userId) });
- if (!!user) {
+ if (user) {
return res(ctx.json(user));
}
return res(ctx.status(404));
diff --git a/src/test/query-client.ts b/src/test/query-client.ts
new file mode 100644
index 0000000..dafe7d4
--- /dev/null
+++ b/src/test/query-client.ts
@@ -0,0 +1,9 @@
+import { QueryClient } from '@tanstack/react-query';
+
+export const queryClient = new QueryClient({
+ defaultOptions: {
+ queries: {
+ retry: false,
+ },
+ },
+});
diff --git a/src/test/test-utils.tsx b/src/test/test-utils.tsx
index 29b9399..a3936b0 100644
--- a/src/test/test-utils.tsx
+++ b/src/test/test-utils.tsx
@@ -6,58 +6,9 @@ import {
RenderHookOptions,
RenderOptions,
} from '@testing-library/react';
-import { PropsWithChildren } from 'react';
-import { MemoryRouter } from 'react-router-dom';
-import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
+import WithAllProviders from './WithAllProviders';
-import ConfigContextProvider from 'providers/ConfigProvider';
-import SettingsContextProvider from 'providers/SettingsProvider';
-import AuthContextProvider from 'providers/AuthProvider';
-import ToastsProvider from 'providers/ToastsProvider';
-
-export const queryClient = new QueryClient({
- defaultOptions: {
- queries: {
- retry: false,
- },
- },
-});
-
-const WithAllProviders = ({ children }: PropsWithChildren): JSX.Element => {
- return (
-
-
-
-
-
- {children}
-
-
-
-
-
- );
-};
-
-export const AllProvidersExceptRouter = ({ children }: PropsWithChildren): JSX.Element => {
- return (
-
-
-
-
- {children}
-
-
-
-
- );
-};
-
-const customRender = (
- ui: React.ReactElement,
- options?: RenderOptions,
- { route = '/' }: any = {},
-) => {
+const customRender = (ui: React.ReactElement, options?: RenderOptions, { route = '/' } = {}) => {
window.history.pushState({}, 'Test page', route);
return render(ui, { wrapper: WithAllProviders, ...options });
@@ -77,6 +28,7 @@ function customRenderHook<
}
// re-export @testing-library/react
+// eslint-disable-next-line
export * from '@testing-library/react';
// override the render function
diff --git a/src/utils/__tests__/storage.test.ts b/src/utils/__tests__/storage.test.ts
index 62aa452..6ecdeae 100644
--- a/src/utils/__tests__/storage.test.ts
+++ b/src/utils/__tests__/storage.test.ts
@@ -1,10 +1,11 @@
+import { afterAll, beforeAll, describe, expect, it, vi } from 'vitest';
import storage from 'utils/storage';
describe('storage', () => {
const originalLocalStorage = global.localStorage;
- const mockGetItem = jest.fn();
- const mockSetItem = jest.fn();
- const mockRemoveItem = jest.fn();
+ const mockGetItem = vi.fn();
+ const mockSetItem = vi.fn();
+ const mockRemoveItem = vi.fn();
beforeAll(() => {
Object.defineProperty(global, 'localStorage', {
diff --git a/src/vite-env.d.ts b/src/vite-env.d.ts
new file mode 100644
index 0000000..11f02fe
--- /dev/null
+++ b/src/vite-env.d.ts
@@ -0,0 +1 @@
+///
diff --git a/tailwind.config.js b/tailwind.config.js
index 628150e..12e03f2 100644
--- a/tailwind.config.js
+++ b/tailwind.config.js
@@ -1,9 +1,13 @@
-const colors = require('tailwindcss/colors');
-const defaultTheme = require('tailwindcss/defaultTheme');
+import colors from 'tailwindcss/colors';
+import defaultTheme from 'tailwindcss/defaultTheme';
/** @type {import('tailwindcss').Config} */
-module.exports = {
- content: ['./src/**/*.{js,jsx,ts,tsx}', './node_modules/@leanstacks/**/*.{js,jsx,ts,tsx}'],
+export default {
+ content: [
+ './index.html',
+ './src/**/*.{js,jsx,ts,tsx}',
+ './node_modules/@leanstacks/**/*.{js,jsx,ts,tsx}',
+ ],
darkMode: 'class',
theme: {
extend: {
diff --git a/tsconfig.json b/tsconfig.json
index 972b640..26fd866 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -1,27 +1,39 @@
{
"compilerOptions": {
- "baseUrl": "./src",
- "target": "es5",
- "lib": [
- "dom",
- "dom.iterable",
- "esnext"
- ],
- "allowJs": true,
+ "target": "ES2020",
+ "useDefineForClassFields": true,
+ "lib": ["ES2020", "DOM", "DOM.Iterable"],
+ "module": "ESNext",
"skipLibCheck": true,
- "esModuleInterop": true,
- "allowSyntheticDefaultImports": true,
- "strict": true,
- "forceConsistentCasingInFileNames": true,
- "noFallthroughCasesInSwitch": true,
- "module": "esnext",
- "moduleResolution": "node",
+
+ /* Bundler mode */
+ "moduleResolution": "bundler",
+ "allowImportingTsExtensions": true,
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
- "jsx": "react-jsx"
+ "jsx": "react-jsx",
+
+ /* Linting */
+ "strict": true,
+ "noUnusedLocals": true,
+ "noUnusedParameters": true,
+ "noFallthroughCasesInSwitch": true,
+
+ /* Absolute imports */
+ "baseUrl": ".",
+ "paths": {
+ "__fixtures__/*": ["./src/__fixtures__/*"],
+ "api/*": ["./src/api/*"],
+ "assets/*": ["./src/assets/*"],
+ "components/*": ["./src/components/*"],
+ "hooks/*": ["./src/hooks/*"],
+ "pages/*": ["./src/pages/*"],
+ "providers/*": ["./src/providers/*"],
+ "test/*": ["./src/test/*"],
+ "utils/*": ["./src/utils/*"]
+ }
},
- "include": [
- "src"
- ]
+ "include": ["src"],
+ "references": [{ "path": "./tsconfig.node.json" }]
}
diff --git a/tsconfig.node.json b/tsconfig.node.json
new file mode 100644
index 0000000..97ede7e
--- /dev/null
+++ b/tsconfig.node.json
@@ -0,0 +1,11 @@
+{
+ "compilerOptions": {
+ "composite": true,
+ "skipLibCheck": true,
+ "module": "ESNext",
+ "moduleResolution": "bundler",
+ "allowSyntheticDefaultImports": true,
+ "strict": true
+ },
+ "include": ["vite.config.ts"]
+}
diff --git a/vite.config.ts b/vite.config.ts
new file mode 100644
index 0000000..9242a2e
--- /dev/null
+++ b/vite.config.ts
@@ -0,0 +1,38 @@
+///
+import { defineConfig } from 'vite';
+import { coverageConfigDefaults } from 'vitest/config';
+import react from '@vitejs/plugin-react';
+
+// https://vitejs.dev/config/
+export default defineConfig({
+ plugins: [react()],
+ resolve: {
+ alias: {
+ __fixtures__: '/src/__fixtures__',
+ api: '/src/api',
+ assets: '/src/assets',
+ components: '/src/components',
+ hooks: '/src/hooks',
+ pages: '/src/pages',
+ providers: '/src/providers',
+ test: '/src/test',
+ utils: '/src/utils',
+ },
+ },
+ test: {
+ coverage: {
+ exclude: [
+ '**/__fixtures__/**',
+ '**/__mocks__/**',
+ 'src/main.tsx',
+ 'src/test',
+ '**/postcss.config.js',
+ '**/tailwind.config.js',
+ ...coverageConfigDefaults.exclude,
+ ],
+ },
+ environment: 'jsdom',
+ globals: true,
+ setupFiles: ['./vitest.setup.ts'],
+ },
+});
diff --git a/vitest.setup.ts b/vitest.setup.ts
new file mode 100644
index 0000000..1d42b77
--- /dev/null
+++ b/vitest.setup.ts
@@ -0,0 +1,17 @@
+import { afterAll, afterEach, beforeAll } from 'vitest';
+
+import { server } from './src/test/mocks/server';
+import { queryClient } from './src/test/query-client';
+
+beforeAll(() => {
+ server.listen();
+});
+
+afterEach(() => {
+ server.resetHandlers();
+ queryClient.clear();
+});
+
+afterAll(() => {
+ server.close();
+});