React セレクター
ReactJS は、Web で最も広く使用されているフロントエンドライブラリの 1 つです。React と並んで、多くの開発者は JSX の className
props を介して HTML 要素に添付された class 属性値を縮小または書き換えるスタイリングツールを使用しています。これらの縮小と上書きにより、クラス名が同じままであることが保証されないため、findElement
や findElements
などの WebDriver のクエリコマンドを使用して生成された HTML を選択することが困難になります。
本日、WebdriverIO のブラウザオブジェクトに、使いやすい API を使用してページ内の単一または複数の React コンポーネントインスタンスをクエリできる 2 つの新しいコマンド、browser.react$
と browser.react$$
を導入します。これらの新しいコマンドは、クエリに対応する WebdriverIO 要素を返します。そこでは、完全な要素コマンド API にアクセスできます。
使用方法
内部的には、WebdriverIO は resq と呼ばれるライブラリを使用して React の VirtualDOM をクエリし、ノードを取得します。このライブラリを使用すると、WebdriverIO はコンポーネントの名前で VirtualDOM 内の任意のコンポーネントを見つけることができ、状態や props でこの選択をフィルタリングすることもできます。
WebdriverIO が提供する API、browser.react$
および browser.react$$
メソッドには、3 つのパラメーターがあります。最初のパラメーターはクエリするセレクターで、このパラメーターは必須です。2 番目と 3 番目のパラメーターは、それぞれオプションのフィルター props
と state
です。
const selector = 'MyComponent'
const propFilter = { someProp: true }
const stateFilter = 'this is my state'
browser.react$(selector, {
props: propFilter,
state: stateFilter
})
例では、3 つすべてのパラメーターの基本的な使用方法について説明します。
例
以下の例では、このサンプルの React アプリケーションに対してクエリを実行します。
// mycomponent.jsx
import React from 'react'
import ReactDOM from 'react-dom'
const MyComponent = (props) => {
const { name } = props;
const [state] = React.useState(name === 'there' ? ', how are you?' : '')
return (
<div>
Hello {name || 'World'}{state}
</div>
)
}
ReactDOM.render(
<div>
<MyComponent />
<MyComponent name="Barry"/>
<MyComponent name="WebdriverIO"/>
<MyComponent name="there"/>
</div>,
document.getElementById('#root'),
)
このアプリでは、渡されたプロパティ name
に応じてテキストをレンダリングするコンポーネントが 1 つあります。
選択とフィルタリング
さて、MyComponent
の最初のインスタンスがブラウザに正しく表示されていることをテストしたいとしましょう。browser.react$
コマンドを使用すると、この最初のインスタンスを選択してクエリを実行できます。
// spec/mycomponent.test.js
test('it should be displayed', () => {
const myComponent = browser.react$('MyComponent')
expect(myComponent.isDisplayed()).toBe(true) // pass
})
簡単ですよね?しかし、Hello WebdriverIO
と表示されているコンポーネントを選択して、テキストが正しいことを確認したい場合はどうでしょうか?クエリをフィルタリングできます!
// spec/mycomponent.test.js
test('it should correctly display "Hello WebdriverIO"', () => {
const myComponent = browser.react$('MyComponent', {
props: { name: 'WebdriverIO' }
})
expect(myComponent.getText()).toBe('Hello WebdriverIO') // pass
})
React では、props は常にオブジェクトであるため、このフィルターパラメーターには、結果をフィルタリングするために使用されるオブジェクトのみを渡すことができます。
コンポーネントには、名前が there
と一致する場合にテキストを追加する状態があることに気付いたかもしれません。現在の状態によってコンポーネントをフィルタリングすることで、このコンポーネントを選択できます。
// spec/mycomponent.test.js
test('it should correctly display "Hello WebdriverIO"', () => {
const myComponent = browser.react$('MyComponent', {
state: ', how are you?'
})
expect(myComponent.getText()).toBe('Hello there, how are you?') // pass
})
ご覧のとおり、状態フィルターには、コンポーネントの現在の状態と等しい文字列を渡します。関数のこの最後のパラメーターは、文字列、数値、ブール値、配列、またはオブジェクトのいずれかになります。これは、これらすべてのタイプが React の有効な状態タイプであるためです。
browser.react$$
については?
ここまで、すべての例で browser.react$
を使用している理由が気になるかもしれません。まあ、どちらのコマンドも同じパラメーターを持ち、ほとんど同じように動作します。**唯一の違い**は、browser.react$$
はセレクターやフィルターのいずれかに一致するすべての WebdriverIO 要素の配列を返すことです。
最後に
この追加に非常に満足しており、皆様に最大限に活用していただければ幸いです。React Dev Tools を使用することをお勧めします。このツールを使用すると、アプリケーション内のコンポーネントの呼び出し方法、それらが持つ props、およびそれらが現在どの状態にあるかを確認できます。この情報がわかれば、WebdriverIO の React API を使用するのがはるかに簡単になります。
**注:** このブログ投稿は、v6 リリース後にコマンドインターフェースの変更を反映するために更新されました。