PageSourceSearch

https://webdriver.io/assets/js/e177f45c.682da338.js

js webdriver.io collected 2026-09-24 08:33:28 UTC 9,785 bytes, 1 lines download raw bytes

1"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[11913],{22002:(e,t,n)=>{n.d(t,{R:()=>a,x:()=>i});var s=n(7378);const r={},o=s.createContext(r);function a(e){const t=s.useContext(o);return s.useMemo(function(){return"function"==typeof e?e(t):{...t,...e}},[t,e])}function i(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:a(e.components),s.createElement(o.Provider,{value:t},e.children)}},47718:e=>{e.exports=JSON.parse('{"permalink":"/blog/2019/04/03/react-selectors","editUrl":"https://github.com/webdriverio/webdriverio/edit/main/website/blog/blog/2019-04-03-react-selectors.md","source":"@site/blog/2019-04-03-react-selectors.md","title":"React Selectors","description":"ReactJS is one of the most widely use Front-End libraries in the web. Along side React, many developers use styling tools that will minify or re-write the class attribute values attached to the HTML elements via className props in JSX. These minifications and overwrites make it difficult to select the generated HTML using the WebDriver\'s query commands like findElement or findElements since it\'s not guaranteed that the class name will remain the same.","date":"2019-04-03T00:00:00.000Z","tags":[],"readingTime":3.6,"hasTruncateMarker":true,"authors":[{"name":"Baruch Velez","url":"http://github.com/baruchvlz","socials":{"github":"https://github.com/baruchvlz"},"imageURL":"https://avatars1.githubusercontent.com/u/14321495?s=460&v=4","key":"barry","page":null}],"frontMatter":{"title":"React Selectors","authors":"barry"},"unlisted":false,"prevItem":{"title":"Visual Regression for V5","permalink":"/blog/2019/05/18/visual-regression-for-v5"},"nextItem":{"title":"Shadow DOM Support & reusable component objects","permalink":"/blog/2019/02/22/shadow-dom-support"}}')},57441:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>l,contentTitle:()=>i,default:()=>d,frontMatter:()=>a,metadata:()=>s,toc:()=>c});var s=n(47718),r=n(86106),o=n(22002);const a={title:"React Selectors",authors:"barry"},i=void 0,l={authorsImageUrls:[void 0]},c=[{value:"Usage",id:"usage",level:2},{value:"Examples",id:"examples",level:2},{value:"Selecting and filtering",id:"selecting-and-filtering",level:4},{value:"What about <code>browser.react$$</code>?",id:"what-about-browserreact",level:4},{value:"Final Words",id:"final-words",level:2}];function h(e){const t={a:"a",blockquote:"blockquote",code:"code",h2:"h2",h4:"h4",p:"p",pre:"pre",strong:"strong",...(0,o.R)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsxs)(t.p,{children:[(0,r.jsx)(t.a,{href:"https://github.com/facebook/react",children:"ReactJS"})," is one of the most widely use Front-End libraries in the web. Along side React, many developers use styling tools that will minify or re-write the class attribute values attached to the HTML elements via ",(0,r.jsx)(t.code,{children:"className"})," props in JSX. These minifications and overwrites make it difficult to select the generated HTML using the WebDriver's query commands like ",(0,r.jsx)(t.code,{children:"findElement"})," or ",(0,r.jsx)(t.code,{children:"findElements"})," since it's not guaranteed that the class name will remain the same."]}),"\n",(0,r.jsxs)(t.p,{children:["Today we introduce two new commands, ",(0,r.jsx)(t.code,{children:"browser.react$"})," and ",(0,r.jsx)(t.code,{children:"browser.react$$"}),", to WebdriverIO's browser object that allows you to query for a single or multiple React component instances in the page with an easy to use API. These new commands will return the WebdriverIO element(s) for the query in where you will have access to the complete element commands API."]}),"\n",(0,r.jsx)(t.h2,{id:"usage",children:"Usage"}),"\n",(0,r.jsxs)(t.p,{children:["Internally, WebdriverIO uses a library called ",(0,r.jsx)(t.a,{href:"https://github.com/baruchvlz/resq",children:"resq"})," to query React's VirtualDOM in order to retrieve the nodes. This library allows WebdriverIO to find any component in the VirtualDOM by the component's name and also filter this selection by state and/or props."]}),"\n",(0,r.jsxs)(t.p,{children:["WebdriverIO's provided API, ",(0,r.jsx)(t.code,{children:"browser.react$"})," and ",(0,r.jsx)(t.code,{children:"browser.react$$"}),", methods have three parameters. The first parameter is the selector to query, this parameter is required. The second and third parameters are optional filters, ",(0,r.jsx)(t.code,{children:"props"})," and ",(0,r.jsx)(t.code,{children:"state"})," respectively."]}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-js",children:"const selector = 'MyComponent'\nconst propFilter = { someProp: true }\nconst stateFilter = 'this is my state'\n\nbrowser.react$(selector, {\n    props: propFilter,\n    state: stateFilter\n})\n"})}
1),"\n",(0,r.jsx)(t.p,{children:"In the examples we will cover basic usages for all three parameters."}),"\n",(0,r.jsx)(t.h2,{id:"examples",children:"Examples"}),"\n",(0,r.jsx)(t.p,{children:"In the following examples, we will base our queries against this example React application."}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-jsx",children:"// mycomponent.jsx\nimport React from 'react'\nimport ReactDOM from 'react-dom'\n\nconst MyComponent = (props) => {\n    const { name } = props;\n    const [state] = React.useState(name === 'there' ? ', how are you?' : '')\n\n    return (\n        <div>\n            Hello {name || 'World'}{state}\n        </div>\n    )\n}\n\nReactDOM.render(\n    <div>\n        <MyComponent />\n        <MyComponent name=\"Barry\"/>\n        <MyComponent name=\"WebdriverIO\"/>\n        <MyComponent name=\"there\"/>\n    </div>,\n    document.getElementById('#root'),\n)\n"})}),"\n",(0,r.jsxs)(t.p,{children:["In this app, we have one component that renders some text depending on the property ",(0,r.jsx)(t.code,{children:"name"})," passed to it."]}),"\n",(0,r.jsx)(t.h4,{id:"selecting-and-filtering",children:"Selecting and filtering"}),"\n",(0,r.jsxs)(t.p,{children:["Now, let's say we want to test that the first instance of ",(0,r.jsx)(t.code,{children:"MyComponent"})," is correctly displayed in the browser. Well, with the ",(0,r.jsx)(t.code,{children:"browser.react$"})," command, we can select this first instance and then query against it."]}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-javascript",children:"// spec/mycomponent.test.js\n\ntest('it should be displayed', () => {\n    const myComponent = browser.react$('MyComponent')\n\n    expect(myComponent.isDisplayed()).toBe(true) // pass\n})\n"})}),"\n",(0,r.jsxs)(t.p,{children:["Simple, no? But what if we want to select the component that says ",(0,r.jsx)(t.code,{children:"Hello WebdriverIO"})," and verify that the text is correct? Well, we can filter our queries!"]}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-javascript",children:"// spec/mycomponent.test.js\n\ntest('it should correctly display \"Hello WebdriverIO\"', () => {\n    const myComponent = browser.react$('MyComponent', {\n        props: { name: 'WebdriverIO' }\n    })\n\n    expect(myComponent.getText()).toBe('Hello WebdriverIO') // pass\n})\n"})}),"\n",(0,r.jsx)(t.p,{children:"In React, the props will always be an object so for this filter parameter we can only pass an object to be used to filter our results."}),"\n",(0,r.jsxs)(t.p,{children:["You might've noticed that in our component we have a state that adds extra text if the name matches ",(0,r.jsx)(t.code,{children:"there"}),". We can select this component by filtering the components by their current state."]}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-javascript",children:"// spec/mycomponent.test.js\n\ntest('it should correctly display \"Hello WebdriverIO\"', () => {\n    const myComponent = browser.react$('MyComponent', {\n        state: ', how are you?'\n    })\n\n    expect(myComponent.getText()).toBe('Hello there, how are you?') // pass\n})\n"})}),"\n",(0,r.jsx)(t.p,{children:"As you can see, for the state filter we pass the string that equals to the current state of the component, this last parameter in the function can be any of the following: string, number, boolean, array, or object. This is because all these types are valid state types for React."}),"\n",(0,r.jsxs)(t.h4,{id:"what-about-browserreact",children:["What about ",(0,r.jsx)(t.code,{children:"browser.react$$"}),"?"]}),"\n",(0,r.jsxs)(t.p,{children:["By now you might be wondering why we are using ",(0,r.jsx)(t.code,{children:"browser.react$"})," in all the examples. Well, both commands have the same parameters and work almost the same with the ",(0,r.jsx)(t.strong,{children:"only difference"})," being that ",(0,r.jsx)(t.code,{children:"browser.react$$"})," will return an array of all the WebdriverIO elements corresponding to the selector and/or filter match."]}),"\n",(0,r.jsx)(t.h2,{id:"final-words",children:"Final Words"}),"\n",(0,r.jsxs)(t.p,{children:["We are very pleased with this addition and we hope you can take full advantage of it. We suggest you use ",(0,r.jsx)(t.a,{href:"https://github.com/facebook/react-devtools",children:"React Dev Tools"}),", using this tool will help you see how the components in the application are called, which props they have, and which state they are currently in. Once you know this information, using WebdriverIO's React API will be a lot easier."]}
1),"\n",(0,r.jsxs)(t.blockquote,{children:["\n",(0,r.jsxs)(t.p,{children:[(0,r.jsx)(t.strong,{children:"Note:"})," This blog post was updated after the v6 release to reflect changes to the command interface."]}),"\n"]})]})}function d(e={}){const{wrapper:t}={...(0,o.R)(),...e.components};return t?(0,r.jsx)(t,{...e,children:(0,r.jsx)(h,{...e})}):h(e)}}}]);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.