- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在尝试为使用 Formik 构建的 React Native 组件编写一些测试。这是一个要求用户名和密码的简单表单,我想使用使用 Yup 构建的验证模式。
当我使用模拟器并手动测试表单时,表单的行为符合预期,仅当输入值无效时才会显示错误消息。
但是,当我尝试使用 @testing-library/react-native
编写一些自动化测试时,行为并不是我所期望的。即使提供的值有效,错误消息也会显示在测试中。下面是代码:
// App.test.js
import React from 'react';
import { render, act, fireEvent } from '@testing-library/react-native';
import App from '../App';
it('does not show error messages when input values are valid', async () => {
const {
findByPlaceholderText,
getByPlaceholderText,
getByText,
queryAllByText,
} = render(<App />);
const usernameInput = await findByPlaceholderText('Username');
const passwordInput = getByPlaceholderText('Password');
const submitButton = getByText('Submit');
await act(async () => {
fireEvent.changeText(usernameInput, 'testUser');
fireEvent.changeText(passwordInput, 'password');
fireEvent.press(submitButton);
});
expect(queryAllByText('This field is required')).toHaveLength(0);
});
// App.js
import React from 'react';
import { TextInput, Button, Text, View } from 'react-native';
import { Formik } from 'formik';
import * as Yup from 'yup';
const Schema = Yup.object().shape({
username: Yup.string().required('This field is required'),
password: Yup.string().required('This field is required'),
});
export default function App() {
return (
<View>
<Formik
initialValues={{ username: '', password: '' }}
validationSchema={Schema}
onSubmit={(values) => console.log(values)}>
{({
handleChange,
handleBlur,
handleSubmit,
values,
errors,
touched,
validateForm,
}) => {
return (
<>
<View>
<TextInput
onChangeText={handleChange('username')}
onBlur={handleBlur('username')}
value={values.username}
placeholder="Username"
/>
{errors.username && touched.username && (
<Text>{errors.username}</Text>
)}
</View>
<View>
<TextInput
onChangeText={handleChange('password')}
onBlur={handleBlur('password')}
value={values.password}
placeholder="Password"
/>
{errors.password && touched.password && (
<Text>{errors.password}</Text>
)}
</View>
<View>
<Button
onPress={handleSubmit}
// If I explicitly call validateForm(), the test will pass
// onPress={async () => {
// await validateForm();
// handleSubmit();
// }}
title="Submit"
/>
</View>
</>
);
}}
</Formik>
</View>
);
}
我不确定我是否正确编写了测试。我认为 Formik 会在调用 handleSubmit
函数时自动验证表单。
在 App.js
中,如果我显式调用 validateForm
,测试将通过。但是,仅仅为了满足测试而更改 onPress
处理程序的实现感觉不对。也许我缺少有关此问题的一些基本概念。任何见解都会有所帮助,谢谢。
包版本:
"@testing-library/react-native": "^7.1.0",
"formik": "^2.2.6",
"react": "16.13.1",
"react-native": "0.63.4",
"yup": "^0.32.8"
最佳答案
终于有时间重新审视这个问题了。虽然我还不能 100% 确定幕后发生了什么,但我认为我发现的结果可能会使其他人受益,所以我会在这里分享。
这个问题与两个子问题交织在一起。第一个与 Promise
有关用于 React Native
的模块,第二个与 Formik
验证的异步性质有关
下面是App.test.js
中的代码修改后,同时保留App.js
不变,
// App.test.js
import React from 'react';
import { render, fireEvent, waitFor } from '@testing-library/react-native';
import App from '../App';
it('does not show error messages when input values are valid', async () => {
const { getByPlaceholderText, getByText, queryAllByText } = render(<App />);
const usernameInput = getByPlaceholderText('Username');
const passwordInput = getByPlaceholderText('Password');
const submitButton = getByText('Submit');
await waitFor(() => {
fireEvent.changeText(usernameInput, 'testUser');
});
await waitFor(() => {
fireEvent.changeText(passwordInput, 'password');
});
fireEvent.press(submitButton);
await waitFor(() => {
expect(queryAllByText('This field is required')).toHaveLength(0);
});
});
通常我们不需要使用act
包装 fireEvent
作为 fireEvent
已经用act
包裹了默认感谢 testing-library
.然而,由于 Formik
更改文本值后异步执行验证,并且验证功能不受 React
管理的调用栈,所以我们需要手动包装 fireEvent
用 act
打电话,或其他方便的方法:waitFor
.简而言之,我们需要包装 fireEvent.changeText
用waitFor
由于其异步性。
但是,将代码改成上面的格式并不能解决所有的问题。虽然测试通过了,但您会遇到与 act
相关的警告.这是与 Promise
相关的已知问题因为 React Native 的 Jest 预设会覆盖原生 Promise。 ( https://github.com/facebook/react-native/issues/29303 )
如果你注释掉这一行
global.Promise = jest.requireActual('promise');
在node_modules/react-native/jest/setup.js
在第 20 行左右,这个问题将得到解决。而是直接修改node_modules
中的文件不推荐。解决方法是设置一个笑话预设来恢复原生 Promise,就像这里 ( https://github.com/sbalay/without_await/commit/64a76486f31bdc41f5c240d28263285683755938 )
关于reactjs - 使用 Formik 和 Yup 作为验证模式时,React Native 测试失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65753374/
对此感到疯狂,真的缺少一些东西。 我有webpack 4.6.0,webpack-cli ^ 2.1.2,所以是最新的。 在文档(https://webpack.js.org/concepts/mod
object Host "os.google.com" { import "windows" address = "linux.google.com" groups = ["linux"] } obj
每当我安装我的应用程序时,我都可以将数据库从 Assets 文件夹复制到 /data/data/packagename/databases/ .到此为止,应用程序工作得很好。 但 10 或 15 秒后
我在 cc 模式缓冲区中使用 hideshow.el 来折叠我不查看的文件部分。 如果能够在 XML 文档中做到这一点就好了。我使用 emacs 22.2.1 和内置的 sgml-mode 进行 xm
已结束。此问题不符合 Stack Overflow guidelines .它目前不接受答案。 我们不允许提出有关书籍、工具、软件库等方面的建议的问题。您可以编辑问题,以便用事实和引用来回答它。 关闭
根据java: public Scanner useDelimiter(String pattern) Sets this scanner's delimiting pattern to a patt
我读过一些关于 PRG 模式以及它如何防止用户重新提交表单的文章。比如this post有一张不错的图: 我能理解为什么在收到 2xx 后用户刷新页面时不会发生表单提交。但我仍然想知道: (1) 如果
看看下面的图片,您可能会清楚地看到这一点。 那么如何在带有其他一些 View 的简单屏幕中实现没有任何弹出/对话框/模式的微调器日期选择器? 我在整个网络上进行了谷歌搜索,但没有找到与之相关的任何合适
我不知道该怎么做,我一直遇到问题。 以下是代码: rows = int(input()) for i in range(1,rows): for j in range(1,i+1):
我想为重写创建一个正则表达式。 将所有请求重写为 index.php(不需要匹配),它不是以/api 开头,或者不是以('.html',或'.js'或'.css'或'.png'结束) 我的例子还是这样
MVC模式代表 Model-View-Controller(模型-视图-控制器) 模式 MVC模式用于应用程序的分层开发 Model(模型) - 模型代表一个存取数据的对象或 JAVA PO
我想为组织模式创建一个 RDF 模式世界。您可能知道,组织模式文档基于层次结构大纲,其中标题是主要的分组实体。 * March auxiliary :PROPERTIES: :HLEVEL: 1 :E
我正在编写一个可以从文件中读取 JSON 数据的软件。该文件包含“person”——一个值为对象数组的对象。我打算使用 JSON 模式验证库来验证内容,而不是自己编写代码。符合代表以下数据的 JSON
假设我有 4 张 table 人 公司 团体 和 账单 现在bills/persons和bills/companys和bills/groups之间是多对多的关系。 我看到了 4 种可能的 sql 模式
假设您有这样的文档: doc1: id:1 text: ... references: Journal1, 2013, pag 123 references: Journal2, 2014,
我有这个架构。它检查评论,目前工作正常。 var schema = { id: '', type: 'object', additionalProperties: false, pro
这可能很简单,但有人可以解释为什么以下模式匹配不明智吗?它说其他规则,例如1, 0, _ 永远不会匹配。 let matchTest(n : int) = let ran = new Rand
我有以下选择序列作为 XML 模式的一部分。理想情况下,我想要一个序列: 来自 my:namespace 的元素必须严格解析。 来自任何其他命名空间的元素,不包括 ##targetNamespace和
我希望编写一个 json 模式来涵盖这个(简化的)示例 { "errorMessage": "", "nbRunningQueries": 0, "isError": Fals
首先,我是 f# 的新手,所以也许答案很明显,但我没有看到。所以我有一些带有 id 和值的元组。我知道我正在寻找的 id,我想从我传入的三个元组中选择正确的元组。我打算用两个 match 语句来做到这
我是一名优秀的程序员,十分优秀!