最近、UIを作るにあたってテストの重要性を感じるようになってきていて、E2Eテストのplaywrightを試しで使っています
その中で今回はAxiosの通信の中身を確認するテストをplaywrightで作成します
例えば、UIのボタンを押すと、同じPCのlocalhostのAPIサーバにアクセスしたり、外部のAPIサーバにアクセスしたのをテストで確認する想定です
「画面内のボタンが押されたらAxiosを使ってAPIサーバへ通信して、その通信が正しいか」
ということをテストで確認したいと思っています
create-react-appでベースとなるプロジェクトを作成
今回はcreate-react-appでプロジェクトを作ります
Next.jsでも何でも大丈夫です
npx create-react-app playwright-test --template typescript
playwrightのインストール
cd playwright-test
npm init playwright@latest
App.tsxの編集
import { useState } from 'react';
import axios from 'axios';
function App() {
const [postResult, setPostResult] = useState("not post");
const [getReslt, setGetResult] = useState("not get")
function onClickPostAxios(){
axios.post('https://httpbin.org/post', {
firstName: 'Fred',
lastName: 'Flintstone'
})
.then(function (response) {
setPostResult("POST")
})
.catch(function (error) {
console.log(error);
});
}
function onClickGetAxios(){
axios.get('https://httpbin.org/get', {
params:{
ID: 12345
}
}).then(function (response){
setGetResult("GET")
})
}
return (
<div className="App">
<button onClick={onClickPostAxios}>Axios POST Data</button>
<text>Post Result:</text>
<text data-testid= "post_result">{postResult}</text>
<br></br>
<button onClick={onClickGetAxios}>Axios GET Data</button>
<text>Get Result:</text>
<text data-testid = "get_result">{getReslt}</text>
</div>
);
}
export default App;
編集したら以下のコマンドで起動します
npm run start
localhost:3000にアクセスような画面が表示されます
「Axios POST Data」ボタンを押すと、https://httpbin.org/postへPOSTリクエスト送り、成功すれば「not post」→「POST」へ変化します
「Axios GET Data」ボタンを押すと、https://httpbin.org/getへGETリクエストを送り、成功すれば「not get」→「GET」へ変化します
テストコードの作成
今回は最初に書いたように、画面内のボタンが押されたらAxiosを使ってAPIサーバへ通信して、その通信が正しいかを確認します
また、通信に成功した場合、表示も変わるのでこれもチェックします
ファイル名は「axiosTest.spec.ts」にして、このファイルをplaywrightインストール時に自動で作られたtestsファイルに入れます
import { test, expect } from '@playwright/test';
test("POSTボタンが押されたときの通信を確認するテスト", async ({ page }) => {
// httpbinにリクエストが送られたときにここで受け取る
await page.route('https://httpbin.org/post', route => {
const request = route.request();
// 送られたリクエストがPOSTリクエストかどうかを判定
if (request.method() === 'POST') {
console.log("POST DATA!!!")
// postData()にPOSTされたJSONデータが入っているのでパースして判定する
expect(JSON.parse(request.postData() ?? "nodata")).toEqual({
firstName: "Fred",
lastName: "Flintstone"
});
// ここでレスポンスを返す
route.fulfill({
status: 200, // HTTPステータスコード
contentType: 'application/json', // コンテンツタイプ
body: JSON.stringify({ // レスポンスボディ
data: "Response from mock"
})
});
}
// console.log(request)
// リクエストを続行
// route.continue();
})
// ローカルホストに立てているページにアクセスする
await page.goto('http://localhost:3000/');
// Axios POST Dataボタンを押す
await page.getByTestId('postButton').click()
// 表示がPOSTになったかを確認
const POSTtext = await page.textContent('[data-testid="postResult"]');
expect(POSTtext).toBe("POST")
});
test("GETボタンが押されたときの通信を確認するテスト", async ({ page }) => {
// httpbinにリクエストが送られたときにここで受け取る
await page.route('https://httpbin.org/get', route => {
const request = route.request();
// 送られたリクエストがGETリクエストかどうかを判定
if (request.method() === 'GET') {
console.log("GET DATA!!!")
// ここでレスポンスを返す
route.fulfill({
status: 200, // HTTPステータスコード
contentType: 'application/json', // コンテンツタイプ
body: JSON.stringify({ // レスポンスボディ
data: "Response from mock"
})
});
}
// console.log(request)
// リクエストを続行
// route.continue();
})
// ローカルホストに立てているページにアクセスする
await page.goto('http://localhost:3000/');
// Axios POST Dataボタンを押す
await page.getByTestId('getButton').click()
// 表示がPOSTになったかを確認
const GETtext = await page.textContent('[data-testid="getResult"]');
expect(GETtext).toBe("GET")
});
今回のテストコードの重要点
今回の一番重要な部分は「どのようにAxiosの通信先を元のコード変えないままテストコードへ誘導するか?」
これにはRoute機能を使います
テストコードの中のこの部分です
await page.route('https://httpbin.org/post', route => {
Route機能で通信先のAPIサーバのモックを作り、ここで送信した通信内容のテストを行います
今回はメソッドの判定と中のbodyデータの判定を行っています
また、GET関数はURLがクエリで動的に変わってしまうのですが、これはワイルドカードで対応すれば良さそうです
テストの実行
UIの立ち上げ
npm run start
テストの立ち上げ
npx playwright test axiosTest.spec.ts --ui
テストの実行
画面左の緑三角ボタンを押すとテストが実行されます
まとめ
AxisoのPOST関数の通信時のデータの中身をテストする方法について書きました
Jestの単体テストでは「ボタンが実際に押されててAxiosがデータを送信する」流れのテストが書きにくかったのでE2Eのplaywrightを使って書いてみました
この方法が正しいのかわかりませんがとりあえず想定通りの挙動を示したので良しとします
今回作成したプログラムは参考文献の一番下に置いておきます
コメント