〒番号から住所取得できるAPIを呼び出し、Cypressでテストを行ってみた。
〒API:
https://zipcloud.ibsnet.co.jp/api/search?zipcode=XXXXXXX
XXXXXXXはqueryparam
方針:
当初は〒APIをフロントエンドから直接呼出しをしようとしていたが、
フロント側からだとCORSエラーになるため、
今後の拡張考えバックエンドから〒APIを呼ぶようにした。
テストについてはフロントエンドからのコンポーネントテストという形で実施。
※今回モックなし。
ソースは以下においてます。
https://github.com/thithi7110/sample-react-cypress
フロント側
npm create-react-app sample-react-cypress --template typescript
cypressのインストール
npm i cypress -D
package.jsonにcypress open追加
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject",
"cyopen": "cypress open"
},
npm run cyopen
を実行し、components設定を追加する。
import React, { useState, useEffect, EventHandler, ChangeEventHandler } from 'react'
import axios from "axios"
type Props = {
zipcode?: string
onChange?: (e: string) => void
}
// function AddNum(num1: Number, num2: Number) {
export default function Address(props: Props) {
const initialState = {
"zipcode": "",
"address1": "",
"address2": "",
"address3": "",
"kana1": "",
"kana2": "",
"kana3": "",
"prefcode": "",
}
const [zipInfo, setZipInfo] = useState(initialState);
const getPostInfo = (zipcode: string) => {
axios.create({
baseURL: "http://localhost:8085/api",
headers: {
"Content-type": "application/json",
}
}).get(
`/zip?zipcode=${zipcode}`
).then((res: any) => {
let inputdata = { ...zipInfo };
inputdata.address1 = res.data.results[0].address1;
inputdata.address2 = res.data.results[0].address2;
inputdata.address3 = res.data.results[0].address3;
inputdata.kana1 = res.data.results[0].kana1;
inputdata.kana2 = res.data.results[0].kana2;
inputdata.kana3 = res.data.results[0].kana3;
inputdata.prefcode = res.data.results[0].prefcode;
setZipInfo(inputdata);
}).catch(e => {
let error = { ...initialState };
error.address1 = e;
setZipInfo(error);
});
}
const onChange = (e: React.ChangeEvent<HTMLInputElement>): void => {
let inputdata = { ...initialState };
inputdata.zipcode = e.target.value;
setZipInfo(inputdata);
if (e.target.value.length == 7) {
//API呼び出し
getPostInfo(e.target.value);
}
}
return (
<>
<div>
<input data-cy='zipcode' value={props.zipcode} onChange={onChange} />
</div>
<input data-cy='address1' value={zipInfo.address1} />
<input data-cy='address2' value={zipInfo.address2} />
<input data-cy='address3' value={zipInfo.address3} />
<input data-cy='kana1' value={zipInfo.kana1} />
<input data-cy='kana2' value={zipInfo.kana2} />
<input data-cy='kana3' value={zipInfo.kana3} />
<input data-cy='prefcode' value={zipInfo.prefcode} />
</>
);
}
テストコード
//Adressコンポーネントのテスト
import React, { EventHandler } from 'react'
import Address from '../../src/Address'
describe('住所表示', () => {
it('Adreesに郵便番号を入力すると郵便番号APIから住所を検索し、郵便番号の下に住所を文字として表示する', () => {
cy.mount(<Address />)
cy.get('[data-cy=zipcode]').type('9000025').then(() => {
cy.get('[data-cy=address1]').should('have.value', "沖縄県");
})
})
})
バック側
{
"name": "nodejs-express-sequelize-postgresql",
"version": "1.0.0",
"description": "Node.js Rest Apis with Express",
"main": "server.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [
"nodejs",
"express",
"rest",
"api"
],
"author": "kenji",
"license": "ISC",
"dependencies": {
"cors": "^2.8.5",
"express": "^4.17.1",
"request": "^2.88.2"
},
"devDependencies": {
}
}
パッケージの取得
npm i
〒APIを呼ぶ箇所
requestで呼び出し
// Find a single Tutorial with an id
exports.findzip = (req, res) => {
var request = require('request');
const pZipCode = req.query.zipcode;
// クエリーを準備
const formData = {
zipcode: pZipCode
};
console.log('pZipCode:'+pZipCode);
try{
request({url:'http://zipcloud.ibsnet.co.jp/api/search', qs:formData}, (error, response, body) => {
// 実際の処理
res.send(response.body);
});
}catch(e){
res.send({error:"error"});
}
};
module.exports = app => {
const controller = require("../controllers/controller.js");
var router = require("express").Router();
router.get("/zip", controller.findzip);
app.use("/api", router);
};
const express = require("express");
// const bodyParser = require("body-parser"); /* deprecated */
const cors = require("cors");
const app = express();
//CORS対策
const whitelist = ['http://localhost:8080', 'http://localhost:51401']
var corsOptions = {
origin: (origin, callback) => {
console.log(origin);
callback(null, true)
}
};
app.use(cors(corsOptions));
// parse requests of content-type - application/json
app.use(express.json()); /* bodyParser.json() is deprecated */
// parse requests of content-type - application/x-www-form-urlencoded
app.use(express.urlencoded({ extended: true })); /* bodyParser.urlencoded() is deprecated */
// simple route
app.get("/", (req, res) => {
res.json({ message: "Welcome to bezkoder application." });
});
require("./app/routes/routes")(app);
// set port, listen for requests
const PORT = process.env.PORT || 8085;
app.listen(PORT, () => {
console.log(`Server is running on port ${PORT}.`);
});
テスト実行
フロント側で以下を実行
npm run cyopen
コンポーネントテストのAddress.cy.tsxを選択
実行OK
フロント側でAPI呼び出しをinterceptする方法を次回試してみる。