{"id":15960676,"url":"https://github.com/emilyjspencer/testing-react","last_synced_at":"2026-01-15T23:52:07.512Z","repository":{"id":39084885,"uuid":"274175732","full_name":"emilyjspencer/Testing-React","owner":"emilyjspencer","description":null,"archived":false,"fork":false,"pushed_at":"2023-01-05T21:50:39.000Z","size":4534,"stargazers_count":0,"open_issues_count":20,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-02-07T22:30:36.136Z","etag":null,"topics":["enzyme","jest","testing"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/emilyjspencer.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-06-22T15:31:09.000Z","updated_at":"2020-06-24T20:58:38.000Z","dependencies_parsed_at":"2023-02-04T18:17:20.736Z","dependency_job_id":null,"html_url":"https://github.com/emilyjspencer/Testing-React","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/emilyjspencer%2FTesting-React","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/emilyjspencer%2FTesting-React/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/emilyjspencer%2FTesting-React/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/emilyjspencer%2FTesting-React/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/emilyjspencer","download_url":"https://codeload.github.com/emilyjspencer/Testing-React/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246771950,"owners_count":20831134,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["enzyme","jest","testing"],"created_at":"2024-10-07T15:21:12.699Z","updated_at":"2026-01-15T23:52:07.474Z","avatar_url":"https://github.com/emilyjspencer.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Testing React\n\n# Jest and Jest Watch Mode\n\n* Enter jest watch mode by running:\n```html\nnpm test\n```\n* Exit jest watch mode by entering:\n```html\nq\n```\n\n* What is Jest watch mode?\nJest watch mode watches for changes and then reruns the tests based on any changes to the code\nBy default, watch mode only watches for changes since the last commit\n\n* If we want to run all of our tests, we can run them even if there haven't been any changes since the last commit, by running \n```html\na\n```\n\n\u003chr\u003e\n\n**Jest tests**\n\nBy default, Jest looks for files in the src directory with the extension .test.js\n\n\nExample test\n\nApp.test.js\n```html\nimport React from 'react';\nimport { render } from '@testing-library/react';\nimport App from './App';\n\ntest('renders learn react link', () =\u003e {\n  const { getByText } = render(\u003cApp /\u003e);\n  const linkElement = getByText(/learn react!!!/i);\n  expect(linkElement).toBeInTheDocument();\n});\n```\n\nApp.js\n\n```html\nimport React from 'react';\nimport './App.css';\n\nconst App = () =\u003e {\n  \n  return (\n    \u003cdiv className=\"App\"\u003e\n      \u003ch1\u003elearn react!!!\u003c/h1\u003e\n    \u003c/div\u003e\n  );\n}\n\nexport default App;\n```\nThis test passes.\n\nBy default, Create-React-App uses the React Testing Library \n\nJust as is the case with RSpec and Jasmine, an expect() method is used to make assertions.\nThe test() method is called, which has two arguments:\n1 - the name of the test/description\n2 - an anonymous function run by Jest. \nIf any errors are thrown, the test will fail\n\n\n## Enzyme\n\nEnzyme isn't shipped with Create-React-App so it needs to be installed.\nThree packages need to be installed:\n\n```html\nnpm install --save-dev enzyme jest-enzyme enzyme-adapter-react-16\n```\n\nSaved as dependencies for testing purposes and not production\nJest-enzyme - so Jest and Enzyme can talk to one another\nenzyme-adapter-react-16 - or whichever version of React that a developer is using. Used to tell Enzyme what type of code to expect\n\n\u003chr\u003e\n\n## What is Enzyme?\n\n* Enzyme is a tool that creates a Virtual DOM, which is needed when testing React without a browser.\n\n* Create-React-App uses REACT-DOM for this and so does Enzyme(under the hood)\n\n* Enzyme's extensive toolkit allows developers to search through the DOM using jQuery-type and CSS-type selectors\n\n* Events can also be simulated on the DOM\n\n\u003chr\u003e\n\n## Setting up Enzyme\n\n* The setup involves configuring Enzyme to use the adapter specified by the developer.\n\n* The adapter tells Enzyme what type of code to expect\n* The following code should be added to the test file:\n\n```html\nimport Enzyme from ‘enzyme’;\nimport EnzymeAdapter from ‘enzyme-adapter-react-16’;\n```\n\n* Enzyme also needs to be configured with an object that specifies an adapter. This object is an instance of the Enzyme Adapter base class.\nThus, the following code also needs to be added to the test file:\n```html\n\nEnzyme.configure({ adapter: new EnzymeAdapter() });\n\n```\n\nRemove the test code and run npm test to check that the setup has been successful.\n\n\u003chr\u003e\n\n## Using Enzyme in tests\n\n### Shallow Rendering\n\nThe shallow function needs to be required i.e.\n```html\nimport Enzyme, { shallow } from 'enzyme';\n```\n\n* Enzyme's shallow() function is used to render components\n\n* shallow() takes JSX as an argument and returns a shallow wrapper. \n\n* When writing unit tests for React, shallow rendering can be helpful Shallow rendering allows developers to render elements that are only one level deep i.e.\nfor a given parent component with various child components, those child components won't be rendered.\n*  Instead placeholders will take their place, and only the parent component will be rendered, therefore allowing for quicker testing.\n\n\n\u003chr\u003e\n\n\n## Debugging with Enzyme\n\n* debug can used to debug React applications\n\n```html\ntest('renders correctly', () =\u003e {\n  const wrapper = shallow(\u003cApp /\u003e);\n  console.log(wrapper.debug());\n  \n});\n```\n\noutputs the following in the command line:\n\n```html\nPASS  src/App.test.js\n  ✓ renders correctly (4ms)\n\n  console.log src/App.test.js:12\n    \u003cdiv className=\"App\"\u003e\n      \u003ch1\u003e\n        Learning to test React!!!\n      \u003c/h1\u003e\n    \u003c/div\u003e\n```\n\nAllows us to get visibility because it returns the DOM as a string\n\n\u003chr\u003e\n\n## Using assertions\n\n```html\n  test('it renders correctly', () =\u003e {\n  const wrapper = shallow(\u003cApp /\u003e);\n  expect(wrapper).toBeFalsy();\n});\n```\n\nThis test fails\n\n```html\ntest('it renders correctly', () =\u003e {\n  const wrapper = shallow(\u003cApp /\u003e);\n  expect(wrapper.toBeTruthy())=;\n}\n```\n\nThis test passes \n\n\u003chr\u003e\n\n## Removing data-test attributes from the production code\n\nInstall the following package\n\n```html\nnpm install —save-dev babel-plugin-react-remove-properties\n```\nRun npm run eject:\n\n```html\nnpm run eject\n```\nwhich takes the configuration files that had been hidden by Create-React-App and makes them configurable to the developer.\nThe package.json will now list all of the dependencies, not just the ones that the developer installed.\n\nUpdate the babel cofiguraiton by copying the following to the 'babel' script in package.json:\n\n```html\nAdd to the package.json - copy under the babel line\n\n\n“babel”: {\n  \"env\": {\n    \"production\": {\n      \"plugins\": [\n        [\"react-remove-properties\", {\"properties\": [\"data-test\"]}\n      ]\n    }, “presents”:[\n      “react-app”\n  }\n}\n```\nCreate a production build:\n\n```html\nnpm run build\n```\n\nRun a static server:\n```html\nnpm install -g server or sudo npm install -g server\n```\n\nRun the command to serve the static app:\n\n```html\nserve -s build\n```\n\nGo to localhost:5000\n\n\u003chr\u003e\n\n## DRYing up tests\n\nFunctions can be used to avoid duplication and repetition in tests, similar to the use of before hooks in rspec and beforeEach() functions in JavaScript.\n\n```html\nconst setup = (props={}, state=null) =\u003e {\n  return shallow(\u003cApp {...props} /\u003e)\n}\n``` \nThis setup method can then replace some of the code in each test e.g.\n\n```html\ntest('it renders without an error', () =\u003e {\n  const wrapper = setup();\n  const appComponent = findByTestAttribute(wrapper, 'component-app');\n  expect(appComponent.length).toBe(1);\n});\n```\n\n```html\nconst wrapper - setup();\n```\ninstead of:\n```html\nconst wrapper = shallow(\u003cApp /\u003e);\n```\n\nAnother example of a function to DRY up test code:\n\n```html\nconst findByTestAttribute = (wrapper, val) =\u003e {\n   return wrapper.find(`[data-test=\"${val}\"]`);\n }\n``` \n\nThen the findByTestAttribute() function can be used to replace some code in each test - thereby avoiding unecessary duplication.\n```html\nconst counterDisplay = findByTestAttribute(wrapper, 'counterDisplay');\n```\ninstead of:\n```html\nconst counterDisplay = wrapper.find(\"[data-test='counterDisplay']\")\n```\n\n\u003chr\u003e\n\n**Side Note - JS Docs**\n\nAn example of a JS doc for the setup() function\n /** \n * Factory function to create a ShallowWrapper for the App component.\n * @function setup\n * @param {object} props \n * @param {any} state  - Initial state for setup\n * @returns {ShallowWrapper}\n */\n\nJS docs explain what particular functions do and can be placed just above functions\n\n\u003chr\u003e\n\n## Testing state\n\n### Class-based components\n\nThe methods setState() and state() can be used to test state (for classical /class-based components)\n\nApp.js\n\n```html\n// code omitted for brevity\n\n render() {\n  return (\n    \u003cdiv data-test=\"component-app\"\u003e\n      \u003ch1\u003eApp\u003c/h1\u003e\n      \u003cbutton onClick={() =\u003e this.setState({ counter: this.state.counter + 1})} data-test=\"increment-button\"\u003eI am a button\u003c/button\u003e\n      \u003ch2 data-test=\"counterDisplay\"\u003e{this.state.counter}\u003c/h2\u003e\n    \u003c/div\u003e\n  );\n```\n\nApp.test.js\n\n```html\n\ntest('the counter starts at 0', () =\u003e {\n  const wrapper = setup();\n  const initialCounterState = wrapper.state('counter');\n  expect(initialCounterState).toBe(0);\n})\n\ntest('the counter display is incremented by 1 on each button click', () =\u003e {\n  const counter = 7;\n  const wrapper = setup(null, { counter });\n  const button = findByTestAttribute(wrapper, 'increment-button'); // used to find the button\n  button.simulate('click'); // used to simulate a button click\n  const counterDisplay = findByTestAttribute(wrapper, 'counterDisplay'); // used to find the counterDisplay\n  expect(counterDisplay.text()).toContain(counter + 1) // checks //that the counter has been incremented by 1 (each time)\n})\n\n\n```\n\n\u003chr\u003e\n\n**simulate()** - This method can be used to interact with a rendered element, for example, a button click can be simulated in a test with the following: \n```html\nbutton.simulate('click');\n``` \n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Femilyjspencer%2Ftesting-react","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Femilyjspencer%2Ftesting-react","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Femilyjspencer%2Ftesting-react/lists"}