From 1b98d5019007fb1026146efa4f83083a25129777 Mon Sep 17 00:00:00 2001 From: Sergii Mykolyshyn Date: Fri, 10 Feb 2023 16:35:25 +0000 Subject: [PATCH] unit tests v 0.1 - Configured unit tests with jest and enzyme - added unit tests on screens new job and landing screen --- .gitignore | 1 + jest.config.js | 33 ++++++++++ jest.setup.js | 30 ++++++++++ package.json | 18 ++++-- src/forms/NewJobForm/index.jsx | 4 +- src/layouts/Landing/index.jsx | 4 +- src/screens/jobs/new/index.jsx | 4 +- src/screens/landing/index.jsx | 4 +- src/test/screens/jobs/new/index.test.js | 80 +++++++++++++++++++++++++ src/test/screens/landing/index.test.js | 50 ++++++++++++++++ 10 files changed, 219 insertions(+), 9 deletions(-) create mode 100644 jest.config.js create mode 100644 jest.setup.js create mode 100644 src/test/screens/jobs/new/index.test.js create mode 100644 src/test/screens/landing/index.test.js diff --git a/.gitignore b/.gitignore index dcf6e98..9ba3602 100644 --- a/.gitignore +++ b/.gitignore @@ -27,3 +27,4 @@ yarn-error.log* .idea/ .vscode/ +*.lock diff --git a/jest.config.js b/jest.config.js new file mode 100644 index 0000000..9a63fb6 --- /dev/null +++ b/jest.config.js @@ -0,0 +1,33 @@ +// jest.config.js +const nextJest = require('next/jest') + +const createJestConfig = nextJest({ + // Provide the path to your Next.js app to load next.config.js and .env files in your test environment + dir: './', +}) + +// Add any custom config to be passed to Jest +/** @type {import('jest').Config} */ +const customJestConfig = { + // Add more setup options before each test is run + // setupFilesAfterEnv: ['/jest.setup.js'], + // if using TypeScript with a baseUrl set to the root directory then you need the below for alias' to work + moduleDirectories: ['node_modules', '/'], + transformIgnorePatterns: [ + '(?!(/node_modules/(wagmi)/))(/node_modules/.+.(js|jsx|mjs|cjs|ts|tsx)$)', + '^.+.module.(css|sass|scss)$', + ], + + // If you're using [Module Path Aliases](https://nextjs.org/docs/advanced-features/module-path-aliases), + // you will have to add the moduleNameMapper in order for jest to resolve your absolute paths. + // The paths have to be matching with the paths option within the compilerOptions in the tsconfig.json + // For example: + + moduleNameMapper: { + '@/(.*)$': '/src/$1', + }, + testEnvironment: 'jest-environment-jsdom', +} + +// createJestConfig is exported this way to ensure that next/jest can load the Next.js config which is async +module.exports = createJestConfig(customJestConfig) diff --git a/jest.setup.js b/jest.setup.js new file mode 100644 index 0000000..03778e3 --- /dev/null +++ b/jest.setup.js @@ -0,0 +1,30 @@ +import { setConfig } from 'next/config' +/* import config from './next.config' */ + +const nextConfig = { + poweredByHeader: false, + + // https://nextjs.org/docs/api-reference/next.config.js/react-strict-mode + reactStrictMode: true, + + // https://nextjs.org/docs/api-reference/next.config.js/trailing-slash + trailingSlash: true, + + // This will build the project as a standalone app inside the Docker image + output: 'standalone', + + // output source map for debugging + productionBrowserSourceMaps: true, + + publicRuntimeConfig: { + // Will be available on both server and client + optriSpaceContractAddress: process.env.OPTRISPACE_CONTRACT_ADDRESS, + domain: process.env.DOMAIN, + blockchainNetworkId: process.env.BLOCKCHAIN_NETWORK_ID, + blockchainViewAddressURL: process.env.BLOCKCHAIN_VIEW_ADDRESS_URL, + frontendNodeAddress: process.env.FRONTEND_NODE_ADDRESS, + }, +} + +// Make sure you can use "publicRuntimeConfig" within tests. +setConfig(nextConfig) diff --git a/package.json b/package.json index 0e17c6b..c405eb3 100644 --- a/package.json +++ b/package.json @@ -23,14 +23,20 @@ "homepage": "https://github.com/optriment/optrispace-frontend-v2#readme", "private": true, "dependencies": { + "@cfaester/enzyme-adapter-react-18": "^0.6.0", + "@testing-library/user-event": "^14.4.3", + "@types/react": "^18.0.27", "cross-env": "^7.0.3", + "enzyme": "^3.11.0", "ethers": "^5.7.2", "js-cookie": "^3.0.1", - "next": "=12.3.1", - "react": "^17.0.2", - "react-dom": "^17.0.2", + "next": "^13.1.6", + "node": "^19.6.0", + "react": "^18.0.1", + "react-dom": "^18.0.1", "react-markdown": "^8.0.3", "react-scripts": "^5.0.1", + "react-test-renderer": "^18.2.0", "semantic-ui-css": "=2.5.0", "wagmi": "^0.8.6" }, @@ -38,7 +44,7 @@ "dev": "next dev", "build": "next build", "start": "next start", - "test": "next test", + "test": "NODE_OPTIONS=--experimental-vm-modules jest --verbose", "build-production": "next build && next export", "lint": "next lint --no-cache && npx eslint . --ext .js,.jsx && npx prettier --check .", "lint-fix": "next lint --fix", @@ -58,6 +64,8 @@ }, "devDependencies": { "@next/eslint-plugin-next": "^12.1.5", + "@testing-library/jest-dom": "^5.16.5", + "@testing-library/react": "^13.4.0", "eslint": "^8.32.0", "eslint-config-next": "12.3.1", "eslint-config-prettier": "^8.5.0", @@ -68,6 +76,8 @@ "eslint-plugin-react": "^7.32.1", "eslint-plugin-react-hooks": "^4.4.0", "husky": "^8.0.2", + "jest": "27.0.2", + "jest-environment-jsdom": "^27.0.2", "prettier": "^2.8.3", "semantic-ui-react": "^2.1.4" } diff --git a/src/forms/NewJobForm/index.jsx b/src/forms/NewJobForm/index.jsx index 69623df..82d2d82 100644 --- a/src/forms/NewJobForm/index.jsx +++ b/src/forms/NewJobForm/index.jsx @@ -30,7 +30,7 @@ import gigsAddJobCommandABI from '../../../contracts/GigsAddJobCommand.json' const { publicRuntimeConfig } = getConfig() const { optriSpaceContractAddress, frontendNodeAddress } = publicRuntimeConfig -export const NewJobForm = ({ +const NewJobForm = ({ currentAccount, accountBalance, onJobCreated, @@ -334,3 +334,5 @@ export const NewJobForm = ({ ) } + +export default NewJobForm diff --git a/src/layouts/Landing/index.jsx b/src/layouts/Landing/index.jsx index 90df914..71fb514 100644 --- a/src/layouts/Landing/index.jsx +++ b/src/layouts/Landing/index.jsx @@ -6,8 +6,8 @@ import { Header } from '../../components/Header' import { Footer } from '../../components/Footer' import { Favicon } from '../../components/Favicon' -const { publicRuntimeConfig } = getConfig() -const { domain, frontendNodeAddress } = publicRuntimeConfig +const { publicRuntimeConfig } = getConfig() || {} +const { domain, frontendNodeAddress } = publicRuntimeConfig || {} import 'semantic-ui-css/semantic.min.css' diff --git a/src/screens/jobs/new/index.jsx b/src/screens/jobs/new/index.jsx index 7742bca..b16f59a 100644 --- a/src/screens/jobs/new/index.jsx +++ b/src/screens/jobs/new/index.jsx @@ -16,7 +16,7 @@ import ErrorWrapper from '../../../components/ErrorWrapper' const { publicRuntimeConfig } = getConfig() const { optriSpaceContractAddress } = publicRuntimeConfig -export const NewJobScreen = ({ currentAccount, accountBalance }) => { +const NewJobScreen = ({ currentAccount, accountBalance }) => { const router = useRouter() const onJobCreated = (jobAddress) => { @@ -109,3 +109,5 @@ export const NewJobScreen = ({ currentAccount, accountBalance }) => { ) } + +export default NewJobScreen diff --git a/src/screens/landing/index.jsx b/src/screens/landing/index.jsx index d17d030..4646e69 100644 --- a/src/screens/landing/index.jsx +++ b/src/screens/landing/index.jsx @@ -2,7 +2,7 @@ import React from 'react' import Link from 'next/link' import { Image, Container, Divider, Header, List } from 'semantic-ui-react' -export const LandingScreen = () => { +const LandingScreen = () => { return ( <> @@ -140,3 +140,5 @@ export const LandingScreen = () => { ) } + +export default LandingScreen diff --git a/src/test/screens/jobs/new/index.test.js b/src/test/screens/jobs/new/index.test.js new file mode 100644 index 0000000..7c639c0 --- /dev/null +++ b/src/test/screens/jobs/new/index.test.js @@ -0,0 +1,80 @@ +/* eslint-disable no-undef */ +/* eslint-disable no-unused-vars */ + +/** + * Example of how to call and test React page with components inside it + * Also has some examples of passing props to components + * First we need to import these components with jest mock pointing to component location. + * Then, use regular import from the library. Note: importing several components with {} doesn't work for some reason. + * Before executing each test, mount the component, inside the beforeEach function + * */ + +jest.mock( + '../../../../screens/jobs/new', + () => + ({ children }) => + children +) + +jest.mock( + 'semantic-ui-react', + () => + ({ children }) => + children +) + +jest.mock( + '../../../../components/InsufficientBalance', + () => + ({ children }) => + children +) + +jest.mock( + '../../../../forms/NewJobForm', + () => + ({ children }) => + children +) + +import '@testing-library/jest-dom' + +import NewJobScreen from '../../../../screens/jobs/new' +import Grid from 'semantic-ui-react' +import Enzyme, { mount, shallow } from 'enzyme' +import Adapter from '@cfaester/enzyme-adapter-react-18' +import InsufficientBalance from '../../../../components/InsufficientBalance' +jest.mock('@fluentui/react-component-ref') + +Enzyme.configure({ adapter: new Adapter() }) + +describe('', () => { + let wrapper + + const props = { + currentAccount: 'test', + accountBalance: 4, + } + + it('should render render omponent', () => { + wrapper = mount( + + ) + expect(wrapper).toBeTruthy() + }) + + it('should render render Grid component', () => { + wrapper = mount( + + ) + expect(wrapper.find(Grid)).toBeTruthy() + }) + + it('should render insufficients funds component', () => { + wrapper = mount( + + ) + + expect(wrapper.find(InsufficientBalance)).toBeTruthy() + }) +}) diff --git a/src/test/screens/landing/index.test.js b/src/test/screens/landing/index.test.js new file mode 100644 index 0000000..f752971 --- /dev/null +++ b/src/test/screens/landing/index.test.js @@ -0,0 +1,50 @@ +/* eslint-disable no-undef */ +/* eslint-disable no-unused-vars */ + +/** + * Example of how to call and test React page with components inside it + * First we need to import these components with jest mock pointing to component location. + * Then, use regular import from the library. Note: importing several components with {} doesn't work for some reason. + * Before executing each test, mount the component, inside the beforeEach function + * */ + +jest.mock( + '../../../screens/landing', + () => + ({ children }) => + children +) + +jest.mock( + 'semantic-ui-react', + () => + ({ children }) => + children +) + +import '@testing-library/jest-dom' +import LandingScreen from '../../../screens/landing' +import Container from 'semantic-ui-react' +import Image from 'semantic-ui-react' +import Enzyme, { mount } from 'enzyme' +import Adapter from '@cfaester/enzyme-adapter-react-18' + +jest.mock('@fluentui/react-component-ref') + +Enzyme.configure({ adapter: new Adapter() }) + +describe('', () => { + let wrapper + + beforeEach(() => { + wrapper = mount() + }) + + it('should render render Container component', () => { + expect(wrapper.find(Container)).toBeTruthy() + }) + + it('should render render Image component', () => { + expect(wrapper.find(Image)).toBeTruthy() + }) +})