{"id":15433953,"url":"https://github.com/abhinaba-ghosh/cypress-react-selector","last_synced_at":"2025-04-12T14:58:52.958Z","repository":{"id":37007833,"uuid":"260916088","full_name":"abhinaba-ghosh/cypress-react-selector","owner":"abhinaba-ghosh","description":":zap: cypress plugin to locate react elements by component, props and state","archived":false,"fork":false,"pushed_at":"2023-07-20T23:55:42.000Z","size":7112,"stargazers_count":275,"open_issues_count":39,"forks_count":28,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-04-12T14:58:47.178Z","etag":null,"topics":["chained-queries","component","cypress","cypress-io","cypress-plugin","cypress-react","e2e","element-filtration","props","react"],"latest_commit_sha":null,"homepage":"https://www.cypress.io/","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/abhinaba-ghosh.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"custom":["https://www.buymeacoffee.com/abhinabaghosh","https://www.paypal.com/paypalme/abhinabaghosh"]}},"created_at":"2020-05-03T12:51:23.000Z","updated_at":"2025-02-20T06:26:07.000Z","dependencies_parsed_at":"2024-06-18T13:36:24.019Z","dependency_job_id":"acdcccee-e9d5-4d94-bf57-38e79fc92af2","html_url":"https://github.com/abhinaba-ghosh/cypress-react-selector","commit_stats":{"total_commits":342,"total_committers":18,"mean_commits":19.0,"dds":0.5350877192982456,"last_synced_commit":"1c552942900f9ce24bf93a5ca996392957ac461f"},"previous_names":[],"tags_count":36,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/abhinaba-ghosh%2Fcypress-react-selector","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/abhinaba-ghosh%2Fcypress-react-selector/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/abhinaba-ghosh%2Fcypress-react-selector/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/abhinaba-ghosh%2Fcypress-react-selector/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/abhinaba-ghosh","download_url":"https://codeload.github.com/abhinaba-ghosh/cypress-react-selector/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248586249,"owners_count":21128997,"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":["chained-queries","component","cypress","cypress-io","cypress-plugin","cypress-react","e2e","element-filtration","props","react"],"created_at":"2024-10-01T18:36:19.320Z","updated_at":"2025-04-12T14:58:52.929Z","avatar_url":"https://github.com/abhinaba-ghosh.png","language":"JavaScript","funding_links":["https://www.buymeacoffee.com/abhinabaghosh","https://www.paypal.com/paypalme/abhinabaghosh"],"categories":[],"sub_categories":[],"readme":"# cypress-react-selector\n\n[![Build Status](https://circleci.com/gh/abhinaba-ghosh/cypress-react-selector.svg?style=shield\u0026branch-=master)](https://app.circleci.com/pipelines/github/abhinaba-ghosh/cypress-react-selector)\n[![NPM release](https://img.shields.io/npm/v/cypress-react-selector.svg 'NPM release')](https://www.npmjs.com/package/cypress-react-selector)\n[![code style: prettier](https://img.shields.io/badge/code_style-prettier-ff69b4.svg?style=flat-square)](https://github.com/prettier/prettier)\n[![NPM Downloads](https://img.shields.io/npm/dt/cypress-react-selector.svg?style=flat-square)](https://www.npmjs.com/package/cypress-react-selector)\n\n:warning: cypress-react-selector 3.x supports cypress 10+\n\n_cypress-react-selector_ is a lightweight plugin to help you to locate web elements in your REACT app using components, props and states. This extension allow you to select elements in a way that is native to React. Designed to help developers in component, integration and E2E testing.\n\nInternally, cypress-react-selector uses a library called [resq](https://github.com/baruchvlz/resq) to query React's VirtualDOM in order to retrieve the nodes.\n\n## Table of Contents\n\n- [Install and configure](#install-and-configure)\n  - [Add as a dependency:](#add-as-a-dependency-)\n  - [Include the commands](#include-the-commands)\n- [Highlights](#highlights)\n- [Type Definition](#type-definition)\n- [How to use React Selector?](#how-to-use-react-selector-)\n  - [Wait for application to be ready to run tests](#wait-for-application-to-be-ready-to-run-tests)\n  - [Find Element by React Component](#find-element-by-react-component)\n  - [Element filtration by Props and States](#element-filtration-by-props-and-states)\n  - [Wildcard selection](#wildcard-selection)\n  - [Find element by nested props](#find-element-by-nested-props)\n- [Get React Properties from element](#get-react-properties-from-element)\n  - [Get Props](#get-props)\n  - [Get current state](#get-current-state)\n- [Timeouts](#timeouts)\n- [Fetch indexed node](#fetch-indexed-node)\n- [Use fluent chained queries](#use-fluent-chained-queries)\n- [Sample Tests](#sample-tests)\n- [Community Projects](#community-projects)\n- [Tool You Need](#tool-you-need)\n- [Tell me your issues](#tell-me-your-issues)\n- [Contribution](#contribution)\n\n## Install and configure\n\n### Add as a dependency:\n\n```sh\nnpm i --save-dev cypress-react-selector\n```\n\n### Include the commands\n\nUpdate `cypress/support/e2e.js` and `cypress/support/component.js` file to include the cypress-react-selector commands by adding:\n\n```js\nimport 'cypress-react-selector';\n```\n\n### Update `component-index.html` (Component Testing only)\n\nIn order for `waitForReact()` to work appropriately in component testing, replace the `div` inside `component-index.html` with this:\n\n```js\n\u003cdiv id=\"__cy_root\" data-cy-root\u003e\u003c/div\u003e\n```\n\n### TSConfig Settings for types\n\nAdd the following to `tsconfig.json`:\n\n```js\n{\n  \"compilerOptions\": {\n    \"sourceType\": \"module\",\n    \"types\": [\"node\", \"cypress\", \"cypress-react-selector\"]\n  }\n}\n```\n\n### Configuring \u003e= Cypress 10\n\nThe following is a sample `cypress.config.js` file that sets up Cypress e2e and component testing to work with this plugin:\n\n```js\nconst { defineConfig } = require('cypress');\n\nmodule.exports = defineConfig({\n  video: false,\n  screenshotOnRunFailure: false,\n  env: {\n    'cypress-react-selector': {\n      root: '#__cy_root',\n    },\n  },\n  e2e: {\n    setupNodeEvents() {},\n    specPattern: 'cypress/e2e/**/*.cy.{js,ts,jsx,tsx}',\n    excludeSpecPattern: ['**/__snapshots__/*', '**/__image_snapshots__/*'],\n  },\n  component: {\n    setupNodeEvents() {},\n    specPattern: 'cypress/component/**/*.cy.{js,ts,jsx,tsx}',\n    excludeSpecPattern: ['**/__snapshots__/*', '**/__image_snapshots__/*'],\n    devServer: {\n      framework: 'create-react-app',\n      bundler: 'webpack',\n    },\n  },\n});\n```\n\n**Note:** if you're not using `component` testing, you can remove that from the config.\n\n## Highlights\n\n- cypress-react-selector supports NodeJS 8 or higher\n- It supports React 16 or higher\n- Retries each interaction until timeout to handle asynchronous calls\n- Supports shadow DOM\n- Supports wildcard selection for component names\n- Supports nested Props\n- Supports assertion on real-time react properties (props and states)\n\n## How to use React Selector?\n\nLets take this example REACT APP:\n\n```jsx\n// imports\n\nconst MyComponent = ({ someBooleanProp }) =\u003e (\n  \u003cdiv\u003eMy Component {someBooleanProp ? 'show this' : ''} \u003c/div\u003e\n);\n\nconst App = () =\u003e (\n  \u003cdiv id=\"root\"\u003e\n    \u003cMyComponent /\u003e\n    \u003cMyComponent someBooleanProp={true} /\u003e\n  \u003c/div\u003e\n);\n\nReactDOM.render(\u003cApp /\u003e, document.getElementById('root'));\n```\n\n### Wait for application to be ready to run tests\n\n`cypress-react-selector` needs the react root `css-selector` information to identify\n\n- Whether React has loaded\n- Retry React identification queries if state changes in run time/React loads asynchronously\n\nIn order to make sure that the React component tree has loaded, add the `waitForReact` call immediately after loading a page. Here is an example where it's done in the fixture's `before` hook.\n\n```js\nbefore(() =\u003e {\n  cy.visit('http://localhost:3000/myApp');\n  cy.waitForReact(1000, '#root'); // 1000 is the timeout in milliseconds, you can provide as per AUT\n});\n```\n\n_NOTE_ : The Best Configuration for React root is to declare it as an `env` variable\n\nWe always recommend to declare the `react root` as a `env` variable in the `cypress.config.js` file. It is a best approach rather than passing react root information to `waitForReact` method every time.\n\nAs an example:\n\n```json\n{\n  \"env\": {\n    \"cypress-react-selector\": {\n      \"root\": \"#root\"\n    }\n  }\n}\n```\n\nIf you choose to declare the `root selector` as a `configuration`, then you will have the freedom to call `waitForReact` method without passing the root parameter.\n\n```js\nbefore(() =\u003e {\n  cy.visit('http://localhost:3000/myApp');\n  cy.waitForReact();\n});\n```\n\n_NOTE_: If you are using Webpack with your project, you may need to manually pass in the [resq](https://www.npmjs.com/package/resq) module path.\n\nThere's an optional parameter in `waitForReact` that can be passed in at runtime.\n\nThis should be the path of the `resq` entrypoint\n\n```js\nbefore(() =\u003e {\n  cy.visit('http://localhost:3000/myApp');\n  cy.waitForReact(1000, '#root', 'node_modules/resq/dist/index.js'); // Manually passing in the resq module path\n});\n```\n\n### Find Element by React Component\n\nYou should have [React Develop Tool](https://chrome.google.com/webstore/detail/react-developer-tools/fmkadmapgofadopljbjfkapdkoienihi?hl=en) installed to spy and find out the component name as sometimes components can go though modifications. Once the React gets loaded, you can easily identify an web element by react component name:\n\n```js\ncy.react('MyComponent');\n\n// you can have your assertions chained like\nit('it should validate react selection with component name', () =\u003e {\n  cy.react('MyComponent').should('have.length', '1');\n});\n```\n\n### Element filtration by Props and States\n\nYou can filter the REACT components by its props and states like below:\n\n```ts\ncy.react(componentName, reactOpts);\n\n// ReactOpts:\n//{\n//  props: { someProp: someValue },\n//  state: { someState: someValue },\n//  exact: boolean\n//}\n\n// for the example APP\ncy.react('MyComponent', { props: { name: 'John' } });\n```\n\n### Deep Matching with `exact` flag\n\nIf you are in need of matching exactly every property and value in the object (or nested objects), you can pass the exact flag to the `cy.react` or `cy.getReact` function:\n\n```ts\ncy.react('MyComponent', { props: { name: 'John' }, exact: true });\n```\n\nMake sure all the `props` and/or `state` are listed while using this `flag`, if not matched it will return `undefined`\n\n### Wildcard selection\n\nYou can select your components by partial name use a wildcard selectors:\n\n```ts\n// Partial Match\ncy.react('My*', { props: { name: 'John' } });\n\n// Entire Match\ncy.react('*', { props: { name: 'John' } }); // return all components matched with the prop\n```\n\n### Find element by nested props\n\nLet's suppose you have an Form component\n\n```js\n\u003cForm\u003e\n  \u003cField name=\"email\" type=\"email\" component={MyTextInput} /\u003e\n  \u003cErrorMessage name=\"email\" component=\"div\" /\u003e\n  \u003cbr /\u003e\n  \u003cField type=\"password\" name=\"password\" component={MyTextInput} /\u003e\n  \u003cErrorMessage name=\"password\" component=\"div\" /\u003e\n  \u003cbr /\u003e\n  \u003cbutton type=\"submit\" disabled={isSubmitting}\u003e\n    Submit\n  \u003c/button\u003e\n\u003c/Form\u003e\n```\n\nAnd _**MyTextInput**_ component is developed as:\n\n```js\nconst MyTextInput = (props) =\u003e {\n  const { field, type } = props;\n\n  return (\n    \u003cinput {...field} type={type} placeholder={'ENTER YOUR ' + field.name} /\u003e\n  );\n};\n```\n\nthen you can use cypress-react-selector to identify the element with nested props\n\n```js\nit('enter data into the fields', () =\u003e {\n  cy.react('MyTextInput', { props: { field: { name: 'email' } } }).type(\n    'john.doe@cypress.com'\n  );\n  cy.react('MyTextInput', { props: { field: { name: 'password' } } }).type(\n    'whyMe?'\n  );\n});\n```\n\n## Get React Properties from element\n\nLet's take same [Form example](#find-element-by-nested-props)\n\n### Get Props\n\nYou can get the React properties from a React element and validate the properties run time.\n\n```js\n// set the email in the form\ncy.react('MyTextInput', { props: { field: { name: 'email' } } }).type(\n  'john.doe@cypress.com'\n);\n\n// validate the property runtime\ncy.getReact('MyTextInput', { props: { field: { name: 'email' } } })\n  .getProps('fields.value')\n  .should('eq', 'john.doe@cypress.com');\n\n// to get all the props, simply do not pass anything in getProps() method\ncy.getReact('MyTextInput', { props: { field: { name: 'email' } } }).getProps();\n```\n\n![get-props](./docs/get-props.png)\n\n### Get current state\n\n```js\ncy.getReact('MyTextInput', {\n  props: { field: { name: 'email' } },\n}).getCurrentState(); // can return string | boolean | any[] | {}\n```\n\n## Timeouts\n\nYou can configure the [timeouts](https://docs.cypress.io/guides/references/configuration.html#Timeouts) in the `cypress.config.js` configuration file. Alternatively, you can also pass the `timeout` as a object literal in the react commands like,\n\n```js\ncy.react('MyComponent', { options: { timeout: 50000 } });\n```\n\n## Fetch indexed node\n\n1. `cy.react` returns DOM element, so you can fetch the indexed node by [.eq(index)](https://docs.cypress.io/api/commands/eq.html), like:\n\n```js\ncy.react('MyComponent').eq(0).click();\n```\n\n2. `cy.getReact()` return RESQ node, so you can't fetch it through `.eq()`. You need to use `.nthNode(index)`, like:\n\n```js\ncy.getReact('MyComponent')\n  .nthNode(0)\n  .getProps('name')\n  .should('eq', 'First Item');\n```\n\n## Use fluent chained queries\n\nYou can chain `react-selector` queries like:\n\n- combine with cypress native element `.find()` -\n\n```js\ncy.react('FormComponent').find('input').type('buy milk');\ncy.react('FormComponent').find('button').click();\n```\n\n- fetch `HTMLElements` by chained `react` queries\n\n```js\ncy.react('MyComponent', { props: { name: 'Bob' } })\n  .react('MyAge')\n  .should('have.text', '50');\n```\n\n- fetch `react props and states` by chained `getReact` query\n\n```js\ncy.getReact('MyComponent', { props: { name: 'Bob' } })\n  .getReact('MyAge')\n  .getProps('age')\n  .should('eq', '50');\n```\n\n:warning: Fluent commands are not working in some special cases. It is being tracked [here](https://github.com/abhinaba-ghosh/cypress-react-selector/issues/41)\n\n## Sample Tests\n\n- Checkout component testing use cases [here](./component/)\n- Checkout e2e tests [here](./cypress/integration)\n\n## Community Projects\n\n- Credit goes to [Gleb Bahmutov](https://github.com/bahmutov) for drafting how `cypress-react-selector` can be used in `react component testing` [here](https://github.com/cypress-io/cypress/blob/develop/npm/react/cypress/component/advanced/react-book-example/src/components/ProductsList.spec.js)\n\n- Credit goes to [gregfenton](https://github.com/gregfenton) for presenting a `formik form` example that uses `Cypress-React-Selector`. Checkout the work [here](https://github.com/gregfenton/example-cypress-react-selector-formik)\n\n[If you have a cool project, feel free to portray here]\n\n## Tool You Need\n\n[React-Dev-Tool](https://chrome.google.com/webstore/detail/react-developer-tools/fmkadmapgofadopljbjfkapdkoienihi?hl=en) — You can inspect the DOM element by simply pressing the f12. But, to inspect REACT components and props, you need to install the chrome plugin.\n\n## Tell me your issues\n\nyou can raise any issue [here](https://github.com/abhinaba-ghosh/cypress-react-selector/issues)\n\n## Contribution\n\nAny pull request is welcome.\n\n## Before you go\n\nIf it works for you , give a [Star](https://github.com/abhinaba-ghosh/cypress-react-selector)! :star:\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fabhinaba-ghosh%2Fcypress-react-selector","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fabhinaba-ghosh%2Fcypress-react-selector","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fabhinaba-ghosh%2Fcypress-react-selector/lists"}