Habréには、 PuppeteerとJestを使用したライティングテストについて説明した出版物があります。 まだPuppeteerが何であるかわからない場合は、これに慣れることをお勧めします。 この記事では、Reactコンポーネントの例を使用して、コールバック関数の呼び出しをテストする方法について説明します。 たとえば、props
onChange
持つコンポーネントがあり、一部のユーザーアクションで、予想されるパラメーターを渡してコールバック関数が呼び出されることをテストする必要があります。 これには、 Puppeteer-ioライブラリが使用されます。 しかし、最初に、ライブラリやフレームワークを参照せずに、htmlおよび純粋なjavascriptの小さな例を見てみましょう...
セレクターによって要素のイベントハンドラーをハングアップする
addEvent
関数があるとします。 イベントでハンドラーが呼び出されることを確認するテストを作成する必要があります。 index.htmlファイルを作成します。
<button> </button> <script> function addEvent(selector, eventType, handler) { let elements = document.querySelectorAll(selector); Array.prototype.forEach.call(elements, element => { element.addEventListener(eventType, handler, false); }); } addEvent("button", "click", event => console.log("Button.click")); </script>
これは、テストが行われるページです。 クリックイベントハンドラーがハングするボタンがあります。 このイベントで、ハンドラーは
console.log
を呼び出し、アクションの識別子文字列を渡します
console.log
これを受け取ると、テストが成功したことを意味します。 次に、Jestのテストコードを含むindex.html.test.jsファイルを作成します。
const puppeteer = require("puppeteer"); const io = require("puppeteer-io"); test(`addEvent() `, async () => { let browser = await puppeteer.launch(); let page = await browser.newPage(); await page.goto(`file://${__dirname}/test.html`); await io({ page, async input() { await page.click("button"); }, async output({ message }) { await message("Button.click"); } }); await page.close(); await browser.close(); });
Puppeteer-ioについて詳しく説明します。 このライブラリは、並行して実行される2つの非同期関数を受け入れます。
input()
関数はブラウザを制御します。たとえば、要素をクリックするかキーボード入力をシミュレートしますが、
output(api)
はブラウザからデータを受信して処理します。 この場合、
message
関数が使用され、そこに予期されるメッセージの識別子文字列が渡されます。 この識別子を持つ
console.log
がブラウザで呼び出されない場合、テストはフリーズし、Jestは失敗したと見なします。
Reactコンポーネントのテスト
例として、次のコンポーネントが使用されます。
import React from "react"; import PropTypes from "prop-types"; const iItem = PropTypes.shape({ id: PropTypes.string.isRequired, text: PropTypes.string.isRequired }); export default class Select extends React.Component { static propTypes = { items: PropTypes.arrayOf(iItem).isRequired, onChange: PropTypes.func }; getChangeHandler() { return ({ target }) => { if (this.props.onChange) { this.props.onChange(this.props.items[target.selectedIndex].id); } }; } toOption(item, index) { return <option key={`id_${index}_${item.id}`}> {item.text} </option> } render() { return <select onChange={this.getChangeHandler()}> {this.props.items.map(this.toOption)} </select> } }
これは、標準選択の単なるラッパーです。 アイテムが選択されると、選択されたアイテムのIDが渡されるコールバック関数が呼び出されます。 実際に、この機能をテストします。 これを行うには、Puppeteerがブラウザーで開くテスト用の特別なページを作成します。
import React from "react"; import ReactDOM from "react-dom"; import Select from "path-to/select-component.js"; const testItems = [ { id: "0e210d4a-ccfd-4733-a179-8b51bda1a7a5", text: "text 1"}, { id: "ea2cecbd-206c-4118-a1c9-8d88474e5a87", text: "text 2"}, { id: "c812a9dc-6a54-409e-adb5-8eb09337e576", text: "text 3"} ]; // console.log("test-items", testItems); function TestPage() { const onChange = id => console.log("Select: change", id); return <div> <Select items={testItems} onChange={onChange} /> </div> } ReactDOM.render(<TestPage />, document.getElementById("application"));
そして、たとえばhttp:// localhost:8080というURLでこのページを展開します。 現在、2つの引数が
console.log
渡されることに注意してください
console.log
最初の引数はidで、2番目の引数はdataです。 次に、テストコードを記述します。
const puppeteer = require("puppeteer"); const io = require("puppeteer-io"); test(` onChange id`, async () => { let browser = await puppeteer.launch(); let page = await browser.newPage(); await io({ page, async input() { await page.goto("http://localhost:8080"); let select = await page.$("select"); await select.focus(); await select.press("Enter"); await select.press("ArrowDown"); await select.press("Enter"); }, async output({ dataFromMessage }) { let [,secondItem] = await dataFromMessage("test-items"); let selectedId = await dataFromMessage("Select: change"); expect(selectedId).toBe(secondItem.id); } }); await page.close(); await browser.close(); });
出力関数のコードを検討してください。 最初のステップは、テストデータを取得することです。 これを行うには、
page.goto
がページの
page.goto
イベントを予期しているため、入力ストリームでURLジャンプをトリガーすることが重要です
console.log("test-items", testItems)
その時点までに
console.log("test-items", testItems)
既に機能し、メッセージは受信されません。 データを取得するには、
dataFromMessage
関数を使用します。この関数は、
console.log
渡される2番目の引数を返します。 テストデータを受信したら、選択したIDを待機し、結果を期待されるIDと比較できます。 機能テスト済み。
キャッチエラー
結論として、エラーの処理方法の例。 ページを作成します。
<script> throw new Error("test-error"); </script>
エラーをキャッチするには、
error
関数を使用し
error
関数は、パラメーターとして文字列または正規表現を使用して、
message
プロパティの対応するテキストでエラーを検索し、エラーの全文を返します。 ページでエラーが発生したことを確認するテスト:
const puppeteer = require("puppeteer"); const io = require("puppeteer-io"); test(`, `, async () => { let browser = await puppeteer.launch(); let page = await browser.newPage(); await io({ page, async input() { await page.goto(`file://${__dirname}/index.html`); }, async output({ error }) { await error("test-error"); } }); await page.close(); await browser.close(); });
以上です。 html要素またはそれらのテキストコンテンツの存在をチェックするのではなく、結果を取得し、それを予想と比較することに基づいてテストする方法を検討しました。