React组件状态联动UI测试问题:输入有效地址后按钮未启用
问题:输入有效钱包地址后,测试无法验证按钮启用状态
我已经给expect(input.value)添加了waitFor(),消除了act错误,但测试仍失败。需要验证的场景是:当WalletAddressInput组件输入有效钱包地址后,ReqTokensButton组件变为可用状态。
组件代码
FaucetCard.js
export default function FaucetCard({ setSuccess, setError }) { const [walletAddress, setWalletAddress] = useState(""); const [showTransactionCard, setShowTransactionCard] = useState(false); const [walletBalance, setWalletBalance] = useState(null); const [txHash, setTxHash] = useState(null); async function callContract() { if (!walletAddress) { setError("Please enter a valid wallet address!"); return; } try { setSuccess( "Requesting tokens... It may take a few seconds to mine on the testnet." ); const api = new Axios(); const res = await api.requestTokens(walletAddress); setSuccess(res.message); setWalletBalance(res.balance); setTxHash(res.txHash); setShowTransactionCard(true); } catch (error) { setSuccess(""); const message = error?.response?.data?.error ? JSON.stringify(error.response.data.error) : error.message; const msg = message ? message : "Check console for error"; setError(`Something went wrong! Error: ${msg}`); console.log(error); setShowTransactionCard(false); } } return ( <div className="card" data-testid="faucet-card"> <div className="card-header"> <h1>Faucet</h1> <img src={drip} alt="drippy" /> </div> <div className="button"> <WalletAddressInput type="text" variant="outlined" placeholder="Address..." label="Wallet Address" value={walletAddress} onChange={(e) => setWalletAddress(e.target.value)} /> <ReqTokensButton onClick={callContract} isDisabled={!isAddress(walletAddress)} /> </div> {showTransactionCard && ( <div className="transaction-card"> <TransactionCard title="Transaction success! " txHash={txHash} balance={walletBalance} /> </div> )} </div> ); }
isAddress 是从ethers.js库导入的函数,根据输入地址是否有效返回布尔值。
WalletAddressInput.js
const WalletAddressInput = styled(TextField)({ width: "100%", marginBottom: "1em", "& .MuiOutlinedInput-root": { "& fieldset": { borderColor: "#148FA0", borderRadius: ".25em", }, "&:hover fieldset": { borderColor: "#117684", }, "&.Mui-focused fieldset": { borderColor: "#148FA0", }, }, "& .MuiInputBase-input": { fontFamily: "Rubik", fontWeight: "400", fontSize: "16px", color: "#333", }, "& .MuiFormLabel-root": { fontFamily: "Rubik", fontWeight: "400", fontSize: "16px", color: "#148FA0", "&.Mui-focused": { color: "#117684", }, }, }); export default WalletAddressInput;
ReqTokensButton.js
const CustomButton = styled(Button)({ borderRadius: ".25em", width: "252px", height: "56px", margin: "0 0 0 20px", padding: "0", "& .MuiTouchRipple-root": { color: "#fff", }, boxShadow: "0px 4px 4px rgba(0, 0, 0, 0.25)", background: "#148FA0", "&:hover": { background: "#117684", cursor: "pointer", }, border: "none", fontFamily: "Rubik", fontWeight: "400", fontSize: "16px", lineHeight: "19px", textAlign: "center", color: "#FFFFFF", // Add styles for the disabled state "&:disabled": { background: "#B0B0B0", // Grey background when disabled color: "#FFFFFF", // Keep text white or adjust as needed boxShadow: "none", // Remove shadow to make it look flat cursor: "not-allowed", // Change cursor to not-allowed to indicate it's disabled }, }); export default function ReqTokensButton({ onClick, isDisabled }) { return ( <CustomButton data-testid="request-tokens-button" onClick={onClick} disabled={isDisabled}> Request Tokens </CustomButton> ); }
测试代码
jest.mock("ethers/lib/utils.js", () => ({ isAddress: jest.fn(), })); const validWalletAddress = "0x117875b555f......."; describe("Request Tokens", () => { beforeEach(() => { // Reset mocks before each test isAddress.mockReset(); }); it.only("enables the request tokens button if the wallet address input has a valid address", async () => { render(<FaucetCard setSuccess={jest.fn()} setError={jest.fn()} />) const input = screen.getByRole("textbox"); expect(input).toBeInTheDocument(); const button = screen.getByTestId("request-tokens-button"); expect(button).toBeInTheDocument(); // Simulate user entering a valid wallet address userEvent.type(input, validWalletAddress); expect(input.value).toBe("0x117875b555f........."); await waitFor(() => { expect(input.value).toBe("0x117875b555f........"); }); expect(button).not.toBeDisabled(); }); });
此前遇到的错误(已解决)
When testing, code that causes React state updates should be wrapped into act(...):
act(() => { /* fire events that update state */ }); /* assert on the output */This ensures that you're testing the behavior the user would see in the browser.
目前UI实际运行正常,但测试始终失败,找不到问题根源。
内容的提问来源于stack exchange,提问作者melly18
相关产品推荐
相关产品推荐

