[Chapter 8]オーダーページとMock Service Workerの使用
作成するショッピングモールアプリケーションの紹介
オーダーページ
OK、完了ページ
このように3ページ作りましょう.
ショッピングモールアプリケーションの全体構造の作成
サーバは以下のようになります.
受注要約ページのフォームの作成
確認後、以下のように考えることができます.
やるべきこと
受注確認ボタンをクリックできるのは、「受注確認」チェック・ボックスをクリックすることのみです.
テストの作成→テストの実行→失敗
SummaryPage.test.js
import SummaryPage from "../SummaryPage";
import {screen,render} from "@testing-library/react";
test('checkbox and button',()=>{
render(<SummaryPage/>)
const checkbox = screen.getByRole('checkbox',{
name: "주문하려는 것을 확인하셨나요?"
});
expect(checkbox.checked).toEqual(false);
const confirmButton = screen.getByRole('button',{
name:"주문 확인"
});
expect(confirmButton.disabled).toBeTruthy();
})
予想通り失敗する.実際のコードの作成を開始します.テストに対応する実際のコードの作成->テストの実行->合格
SummaryPage.jsx
import React from 'react'
function SummaryPage() {
return (
<div>
<form>
<input
type="checkbox"
checked={false}
id="confirm-checkbox"
/>
{/* htmlFor과 id가 같아야함 */}
{/* label과 test에 적은게 동일해야함 */}
<label htmlFor="confirm-checkbox">
주문하려는 것을 확인하셨나요?
</label>
<button disabled={true} type="submit">
주문 확인
</button>
</form>
</div>
)
}
export default SummaryPage
UIの作成後、テストに成功しました.
まだinputにonchangeをしていないので赤い字が表示されます…!この部分を解決しましょう.
Inputラベルのエラーの解決
import React, { useState } from 'react'
function SummaryPage() {
const [checked, setChecked] = useState(false);
return (
<div>
<form>
<input
type="checkbox"
checked={checked}
onChange={(e)=>setChecked(e.target.checked)} //이벤트를 가져온다
id="confirm-checkbox"
/>
{/* htmlFor과 id가 같아야함 */}
{/* label과 test에 적은게 동일해야함 */}
<label htmlFor="confirm-checkbox">
주문하려는 것을 확인하셨나요?
</label>
<button disabled={!checked} type="submit">
주문 확인
</button>
</form>
</div>
)
}
export default SummaryPage
useStateを使用してハードコーディング部分を削除します.追加onChange,エラー消失!
モバイル・サービス・ワークベンチ(MSW)について
最初のページでは、製品オプションがバックエンド・サーバからインポートされます.これらのセクションをテストするにはどうすればいいですか?
サーバに要求を送信すると、要求をMock Service Workerにブロックし、シミュレーション応答を送信します.
MSW起動方式
ブラウザにサービスキットを登録して外部ネットワークリクエストを検出
要求が実際のサーバに到達すると、中間的にブロックされ、MSWクライアント側ライブラリに送信される.
登録されたプロセッサでリクエストを処理し、シミュレーション応答をブラウザに送信します.
使用方法
https://mswjs.io/docs/getting-started/mocks/rest-api
設定
npm install msw --save
ハンドラの作成
Handlerタイプ
http,method,get,post,..
import {rest} from "msw";
export const handlers = [
rest.get(`http://localhost:4000/products`,(req,res,ctx)=>{
return res(
ctx.json([
{
name : "America",
imagePath:"/images/america.jpeg"
},
{
name : "England",
imagePath:"/images/england.jpeg"
}
])
)
}),
rest.get(`http://localhost:4000/options`,(req,res,ctx)=>{
return res(
ctx.json([
{
name : "Insurance",
},
{
name : "Dinner",
}
])
)
})
]
ノードとの統合
サーバの作成
server.jsの作成
import { setUpServer } from 'msw/node';
import { handlers } from './handlers';
// create mocking server
export const server = setUpServer(...handlers);
API Mocking設定
setUpTest.jsの作成
import '@testing-library/jest-dom';
import {server} from './mocks/server';
beforeAll(()=> server.listen());
afterEach(()=> server.resetHandler());
afterAll(()=> server.close());
MSWを使用して商品画像のインポートをテストする
製品セクションをテストします.
今からテストを書きましょう.
import { render, screen } from "@testing-library/react";
import Type from '../Type';
test("display product images from server",async()=>{
render(<Type orderType="products" />);
// 이미지 찾기
const productImages = await screen.findAllByRole("img",{
name: /product$/i // i를 통해 대소문자 구문없이 잡아줌
})
expect(productImages).toHaveLength(2);
const altText = productImages.map((element)=>element.alt);
expect(altText).toEqual(["America product","England product"]);
})
もちろん今までは間違いがありました.実際のコードの作成を開始します.
商品情報をインポートする実際のコードの作成
typeから書こう
type.jsx
import React, { useState,useEffect } from 'react'
import axios from 'axios';
import Products from './Products';
export default function Type({orderType}) {
const [items, setItems] = useState([]);
useEffect(()=>{
loadItems(orderType)
},[orderType]);
const loadItems = async(orderType)=>{
try{
let respons = await axios.get(`http://localhost:4000/${orderType}`)
setItems(respons.data);
}catch(error){
}
}
const ItemComponent = orderType === "products" ? Products : null ;
const optionItems = items.map((item)=>(
//map에는 Key필수
<ItemComponent
key={item.name}
name={item.name}
imagePath={item.imagePath}
/>
))
return <div>{optionItems}</div>
}
Products.jsx
import React from 'react'
export default function Products({
name,imagePath
}) {
return (
<div>
<img
style={{width:"75%"}}
src={`http://localhost:4000/${imagePath}`}
alt={`${name} product`}
/>
<form style={{marginTop : "10px"}}>
<label style={{textAlign:"right"}}>
{name}
</label>
<input
style={{marginLeft:7}}
type="number"
name="quantity"
min="0"
defaultValue={0}
/>
</form>
</div>
)
}
axiosが完了し、正しくロードされた場合はテストに合格した.
サーバからデータをインポート中に発生したエラーの処理
エラーが発生したときのエラー文の表現をします.
2番目のテストケースを行います.
Type.test.jsx
// 테스트 케이스 2
test("when fetching product data, face an error", async()=>{
server.resetHandlers(
rest.get(`http://localhost:4000/products`,(req,res,ctx)=>{
return res(ctx.status(500))
})
)
render(<Type orderType="products"/>)
const errorBanner = await screen.findByTestId("error-banner")
expect(errorBanner).toHaveTextContent("에러가 발생했습니다.");
})
エラー発生時に作成されたテストコードの実際のコードの作成
ErrorBanner.jsx
import React from 'react'
export default function ErrorBanner({message}) {
return <div
data-testid="error-banner"
style={{backgroundColor : "red", color:"white"}}
>
{message}
</div>
}
エラーバナーの作成Type.jsx
if(error){
return <ErrorBanner message="에러가 발생했습니다." />
}
でエラー処理を行えばよい.オプション商品情報の取得
オプション情報を持ってきて、チェックボックスで表示されている部分をテストします!
もちろんテストして失敗~!
Type.test.jsx
// 테스트 케이스3
test("fetch option imformation from server", async()=>{
render(<Type orderType="options" />)
// bring checkbox
const optionCheckboxes = await screen.findAllByRole("checkbox");
expect(optionCheckboxes).toHaveLength(2);
})
テストをしてくれました.対応する実際のコードの作成を開始します.
type.jsxからnullではなくOptions構成部品をインポートします.
次のようにOptionsコンポーネントを作成します.
Options.jsx
import React from 'react'
export default function Options({name}) {
return (
<form>
<input type="checkbox" id={`${name} option`}/>
<label htmlFor={`${name} option`}>{name}</label>
</form>
)
}
商品注文ページUI完了
今からUIを作りましょう~!
今このような姿が現れた.
まず、私たちはまず全体的な枠組みを制定します.
じゃ、このまま出てきます!
Reference
この問題について([Chapter 8]オーダーページとMock Service Workerの使用), 我々は、より多くの情報をここで見つけました https://velog.io/@seochan99/Chapter-8-주문-페이지-및-Mock-Service-Worker-사용テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol