Cypressでinput1とinput2に入力した値を加算とし、その呼び出し元でonChangeをコールバック関数として値を取得するテストをCypressで組んでいるとonChangeが走る前にexpectが走ってしまうという現象があった。
AddNum.tsx
import React, { useState,useEffect } from 'react'
type AddNumParams = {
num1?: number
num2?: number
onChange?: (e: string) => void
}
// function AddNum(num1: Number, num2: Number) {
export default function AddNum(props: AddNumParams) {
//ステート保持
const [num1, setNum1] = useState(props.num1);
const [num2, setNum2] = useState(props.num2);
const [num3, setNum3] = useState(0);
const add = () => {
setNum3((!!num1 ? num1 : 0) + (!!num2 ? num2 : 0));
}
const onChangeNum1 = (e: React.ChangeEvent<HTMLInputElement>) => {
setNum1(Number(e.target.value));
console.log("num1:"+num1);
console.log("num2:"+num2);
}
const onChangeNum2 = (e: React.ChangeEvent<HTMLInputElement>) => {
setNum2(Number(e.target.value));
console.log("num1:"+num1);
console.log("num2:"+num2);
}
//初回時
useEffect(()=>{
add();
},[num1,num2])
useEffect(()=>{
if (!!props.onChange) {
props.onChange(String(num3));
}
},[num3])
return (
<>
<input data-cy="p1" value={num1} onChange={onChangeNum1}></input>
<input data-cy="p2" value={num2} onChange={onChangeNum2}></input>
<p data-cy="p3">{'計算結果:' + num1 + '+' + num2 + '=' + String(num3)}</p>
</>
);
}
AddNum.cy.tsx
describe('計算結果の値を戻す', () => {
it('callback関数を指定し、計算結果が取れる', () => {
let calcResult = "-1";
const onChange = (value: string) => {
calcResult = value;
}
cy.mount(<AddNum onChange={onChange} num1={0} num2={0} />);
cy.get('[data-cy=p1]').type('100');
cy.get('[data-cy=p2]').type('200');
expect(calcResult).to.eq(300); //ここでcalcResultが-1のまま
})
})
当たり前っちゃ当たり前なのだが、
expectは通常の関数であり(非同期でない)、
cy.get('[data-cy=p2]').type('200');
を待たずして処理が流れてきてしまうのでtypeが完了する前に
expectが先に処理されてしまう。
そのためcalcResultが更新されず、期待値が取得できなかったのである。
正しくは以下のように、typeの後でthenをかまし、
その中でexpectを行えばよい。
AddNum.cy.tsx
describe('計算結果の値を戻す', () => {
it('callback関数を指定し、計算結果が取れる', () => {
let calcResult = "-1";
const onChange = (value: string) => {
calcResult = value;
}
cy.mount(<AddNum onChange={onChange} num1={0} num2={0} />);
cy.get('[data-cy=p1]').type('100');
cy.get('[data-cy=p2]').type('200').then(() => {
expect(calcResult).to.eq("300");
});
})
})