Skip to content

Commit

Permalink
configure jest as test framework, and add some test code
Browse files Browse the repository at this point in the history
  • Loading branch information
TrumanH committed Feb 8, 2023
1 parent 9e61d0f commit 6d4d21a
Show file tree
Hide file tree
Showing 14 changed files with 1,328 additions and 43 deletions.
195 changes: 195 additions & 0 deletions jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,195 @@
/*
* For a detailed explanation regarding each configuration property, visit:
* https://jestjs.io/docs/configuration
*/

module.exports = {
// All imported modules in your tests should be mocked automatically
// automock: false,

// Stop running tests after `n` failures
// bail: 0,

// The directory where Jest should store its cached dependency information
// cacheDirectory: "C:\\Users\\he\\AppData\\Local\\Temp\\jest",

// Automatically clear mock calls, instances, contexts and results before every test
clearMocks: true,

// Indicates whether the coverage information should be collected while executing the test
collectCoverage: true,

// An array of glob patterns indicating a set of files for which coverage information should be collected
// collectCoverageFrom: undefined,

// The directory where Jest should output its coverage files
coverageDirectory: "coverage",

// An array of regexp pattern strings used to skip coverage collection
// coveragePathIgnorePatterns: [
// "\\\\node_modules\\\\"
// ],

// Indicates which provider should be used to instrument code for coverage
coverageProvider: "v8",

// A list of reporter names that Jest uses when writing coverage reports
// coverageReporters: [
// "json",
// "text",
// "lcov",
// "clover"
// ],

// An object that configures minimum threshold enforcement for coverage results
// coverageThreshold: undefined,

// A path to a custom dependency extractor
// dependencyExtractor: undefined,

// Make calling deprecated APIs throw helpful error messages
// errorOnDeprecated: false,

// The default configuration for fake timers
// fakeTimers: {
// "enableGlobally": false
// },

// Force coverage collection from ignored files using an array of glob patterns
// forceCoverageMatch: [],

// A path to a module which exports an async function that is triggered once before all test suites
// globalSetup: undefined,

// A path to a module which exports an async function that is triggered once after all test suites
// globalTeardown: undefined,

// A set of global variables that need to be available in all test environments
// globals: {},

// The maximum amount of workers used to run your tests. Can be specified as % or a number. E.g. maxWorkers: 10% will use 10% of your CPU amount + 1 as the maximum worker number. maxWorkers: 2 will use a maximum of 2 workers.
// maxWorkers: "50%",

// An array of directory names to be searched recursively up from the requiring module's location
// moduleDirectories: [
// "node_modules"
// ],

// An array of file extensions your modules use
moduleFileExtensions: [
"js",
"mjs",
"cjs",
"jsx",
"ts",
"tsx",
"json",
"node"
],

// A map from regular expressions to module names or to arrays of module names that allow to stub out resources with a single module
// moduleNameMapper: {},

// An array of regexp pattern strings, matched against all module paths before considered 'visible' to the module loader
// modulePathIgnorePatterns: [],

// Activates notifications for test results
// notify: false,

// An enum that specifies notification mode. Requires { notify: true }
// notifyMode: "failure-change",

// A preset that is used as a base for Jest's configuration
preset: "ts-jest",

// Run tests from one or more projects
// projects: undefined,

// Use this configuration option to add custom reporters to Jest
// reporters: undefined,

// Automatically reset mock state before every test
// resetMocks: false,

// Reset the module registry before running each individual test
// resetModules: false,

// A path to a custom resolver
resolver: './src/jest.resolver.js',

// Automatically restore mock state and implementation before every test
// restoreMocks: false,

// The root directory that Jest should scan for tests and modules within
// rootDir: undefined,

// A list of paths to directories that Jest should use to search for files in
// roots: [
// "<rootDir>"
// ],

// Allows you to use a custom runner instead of Jest's default test runner
// runner: "jest-runner",

// The paths to modules that run some code to configure or set up the testing environment before each test
// setupFiles: [],

// A list of paths to modules that run some code to configure or set up the testing framework before each test
// setupFilesAfterEnv: [],

// The number of seconds after which a test is considered as slow and reported as such in the results.
// slowTestThreshold: 5,

// A list of paths to snapshot serializer modules Jest should use for snapshot testing
// snapshotSerializers: [],

// The test environment that will be used for testing
testEnvironment: "jsdom",

// Options that will be passed to the testEnvironment
// testEnvironmentOptions: {},

// Adds a location field to test results
// testLocationInResults: false,

// The glob patterns Jest uses to detect test files
// testMatch: [
// "**/__tests__/**/*.[jt]s?(x)",
// "**/?(*.)+(spec|test).[tj]s?(x)"
// ],

// An array of regexp pattern strings that are matched against all test paths, matched tests are skipped
// testPathIgnorePatterns: [
// "\\\\node_modules\\\\"
// ],

// The regexp pattern or array of patterns that Jest uses to detect test files
// testRegex: [],

// This option allows the use of a custom results processor
// testResultsProcessor: undefined,

// This option allows use of a custom test runner
// testRunner: "jest-circus/runner",

// A map from regular expressions to paths to transformers
// transform: {'^.+\\.ts?$': 'ts-jest'},

// An array of regexp pattern strings that are matched against all source file paths, matched files will skip transformation
// transformIgnorePatterns: [
// "\\\\node_modules\\\\",
// "\\.pnp\\.[^\\\\]+$"
// ],

// An array of regexp pattern strings that are matched against all modules before the module loader will automatically return a mock for them
// unmockedModulePathPatterns: undefined,

// Indicates whether each individual test should be reported during the run
// verbose: undefined,

// An array of regexp patterns that are matched against all source file paths before re-running tests in watch mode
// watchPathIgnorePatterns: [],

// Whether to use watchman for file crawling
// watchman: true,
};
9 changes: 6 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
"@testing-library/jest-dom": "^5.16.5",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^13.5.0",
"@types/jest": "^29.2.5",
"@types/jest": "^29.4.0",
"@types/node": "^18.11.18",
"@types/react": "^18.0.26",
"@types/react-dom": "^18.0.10",
Expand All @@ -34,7 +34,7 @@
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"test": "jest",
"eject": "react-scripts eject"
},
"eslintConfig": {
Expand All @@ -56,6 +56,9 @@
]
},
"devDependencies": {
"babel-plugin-macros": "^3.1.0"
"babel-plugin-macros": "^3.1.0",
"jest": "^29.4.1",
"jest-environment-jsdom": "^29.4.1",
"ts-jest": "^29.0.5"
}
}
8 changes: 0 additions & 8 deletions src/App.test.js

This file was deleted.

7 changes: 4 additions & 3 deletions src/App.js → src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { useDispatch } from 'react-redux';
import { setUser } from './store/user/user.slice';
import Spinner from './components/spinner/spinner.component';
import GlobalStyle from './global.styles';
import { User } from "firebase/auth";

const Home = lazy(()=>import('./routes/home/home.component'));
const Navigation = lazy(()=>import('./routes/navigation/navigation.component'));
Expand All @@ -17,10 +18,10 @@ const App = ()=> {

useEffect(() => {
const unsubscribe = onAuthStateChangeListener((user)=>{
const createUser = async (user) => {
const createUser = async (user: User|null) => {
if (!user) {return;}
// console.log(user); // here can't get displayName from userAuth
const userSnapshot = await createUserDocumentFromAuth(user);
const userSnapshot = await createUserDocumentFromAuth(user, {});
const userDoc = userSnapshot.data()
dispatch(setUser(userDoc));
};
Expand All @@ -34,7 +35,7 @@ const App = ()=> {
return (
<Fragment>
<GlobalStyle />
<Suspense callback={<Spinner />}>
<Suspense fallback={<Spinner />}>
<Routes>
<Route path="/" element={<Navigation />}>
<Route index element={<Home/>} />
Expand Down
16 changes: 16 additions & 0 deletions src/components/button/button.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import {cleanup, fireEvent, render, screen} from '../../utils/test/test.utils';
import Button from './button.component';

// Note: running cleanup afterEach is done automatically for you in @testing-library/[email protected] or higher
// unmount and cleanup DOM after the test is finished.
afterEach(cleanup);

it('button with specific text exit', async () => {
const {getByText} = render(
<Button>TEST</Button>,
);

expect(await screen.findByText("TEST")).toBeTruthy();
fireEvent.click(getByText(/test/i));

});
1 change: 0 additions & 1 deletion src/components/cart-icon/cart-icon.styles.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import styled from 'styled-components';
import { ReactComponent as Svg } from "../../assets/shopping-bag.svg";
// TODO: load svg, migrate to typesript

export const CartIconContainer = styled.div`
width: 45px;
Expand Down
File renamed without changes.
3 changes: 1 addition & 2 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,9 @@ import ReactDOM from 'react-dom/client';
import { BrowserRouter } from 'react-router-dom';
import App from './App';
import reportWebVitals from './reportWebVitals';
import { store } from './store/store';
import { store, persistor } from './store/store';
import { Provider } from 'react-redux';
import { PersistGate } from 'redux-persist/integration/react';
import { persistor } from './store/store';
import { Elements } from '@stripe/react-stripe-js';
import { stripePromise } from './utils/stripe/stripe.utils';
import * as serviceWorkerRegistration from './serviceWorkerRegistration';
Expand Down
34 changes: 34 additions & 0 deletions src/jest.resolver.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// jest.resolver.js
module.exports = (path, options) => {
// Call the defaultResolver, so we leverage its cache, error handling, etc.
return options.defaultResolver(path, {
...options,
// Use packageFilter to process parsed `package.json` before the resolution (see https://www.npmjs.com/package/resolve#resolveid-opts-cb)
packageFilter: (pkg) => {
const pkgNamesToTarget = new Set([
'rxjs',
'@firebase/auth',
'@firebase/storage',
'@firebase/functions',
'@firebase/database',
'@firebase/auth-compat',
'@firebase/database-compat',
'@firebase/app-compat',
'@firebase/firestore',
'@firebase/firestore-compat',
'@firebase/messaging',
'@firebase/util',
'firebase',
'@stripe/stripe-js',
]);

if (pkgNamesToTarget.has(pkg.name)) {
// console.log('>>>', pkg.name)
delete pkg['exports'];
delete pkg['module'];
}

return pkg;
},
});
};
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { selectCategoriesMap } from '../../store/categories/categories.slice';
const CategoriesPreview = ()=> {
const isLoading = useSelector((state: RootState) => state.categories.isLoading);
const categoriesMap = useSelector(selectCategoriesMap);
console.log("categories:", categoriesMap);
// console.log("categories:", categoriesMap);
return (
<Fragment>
{isLoading ? <Spinner /> :
Expand Down
2 changes: 1 addition & 1 deletion src/store/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ export type RootState = ReturnType<typeof store.getState>;
export type AppDispatch = typeof store.dispatch;

// then run the saga
sagaMiddleware.run(rootSaga)
sagaMiddleware.run(rootSaga);

export const persistor = persistStore(store);

Expand Down
2 changes: 1 addition & 1 deletion src/utils/firebase/firebase.utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ provider.setCustomParameters({

export const signInWithGooglePopup = ()=> signInWithPopup(auth, provider);

export const db = getFirestore();
const db = getFirestore();

export type ObjectToAdd = {
title: string;
Expand Down
23 changes: 23 additions & 0 deletions src/utils/test/test.utils.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import React, {ReactElement} from 'react';
import { BrowserRouter } from 'react-router-dom';
import {render, RenderOptions} from '@testing-library/react';
import { store } from '../../store/store';
import { Provider } from 'react-redux';

const AllTheProviders = ({children}: {children: React.ReactNode}) => {
return (
<BrowserRouter>
<Provider store={store}>
{children}
</Provider>
</BrowserRouter>
)
};

const customRender = (
ui: ReactElement,
options?: Omit<RenderOptions, 'wrapper'>,
) => render(ui, {wrapper: AllTheProviders, ...options});

export * from '@testing-library/react';
export {customRender as render};
Loading

0 comments on commit 6d4d21a

Please sign in to comment.