React测试库表单提交事件与真实浏览器不同
React testing library form submit event is different from the real browser
所以我正在尝试测试一个在 React 中实现的表单。当我通过 jest 提交表单时,我得到的事件与通过浏览器提交事件时不同。
我用的测试是这个:
it("shows success message if registering was successful", async () => {
fetchMock.mockReturnValueOnce(Promise.resolve(new Response("", { status: 200 })));
const wrapper = render(<Provider store={getStore()}>
<RegisterComponent/>
</Provider>);
const emailTextfield = wrapper.getByPlaceholderText(/email@domain.de/i);
const password = wrapper.getByPlaceholderText(/eingeben/i);
const firstName = wrapper.getByPlaceholderText(/max/i);
const lastName = wrapper.getByPlaceholderText(/mustermann/i);
const retryPassword = wrapper.getByPlaceholderText(/wiederholen/i);
const privacyPolicy = wrapper.getByRole("checkbox");
const registerButton = wrapper.getByRole("button");
fireEvent.change(emailTextfield, { target: { value: "test@test.de" } });
fireEvent.change(password, { target: { value: "Test1234!" } });
fireEvent.change(retryPassword, { target: { value: "Test1234!" } });
fireEvent.change(firstName, { target: { value: "Lukas" } });
fireEvent.change(lastName, { target: { value: "Germerott" } });
fireEvent.change(privacyPolicy, { target: { checked: true } });
fireEvent.click(registerButton);
const successMessage = await wrapper.findByText(/erfolgreich/i);
expect(successMessage).toBeTruthy();
});
所以我正在为所有输入安装组件和触发事件。记录的事件是这个:
<ref *1> HTMLFormElement {
'__reactFiber$sikt1ggzmx': <ref *2> FiberNode {
tag: 5,
key: null,
elementType: 'form',
type: 'form',
stateNode: [Circular *1],
return: FiberNode {
tag: 0,
key: null,
elementType: [Function: RegisterComponent],
type: [Function: RegisterComponent],
stateNode: null,
return: [FiberNode],
child: [Circular *2],
sibling: null,
index: 0,
ref: null,
pendingProps: {},
memoizedProps: {},
updateQueue: [Object],
memoizedState: [Object],
dependencies: [Object],
mode: 0,
flags: 0,
nextEffect: null,
firstEffect: null,
lastEffect: null,
lanes: 0,
childLanes: 0,
alternate: [FiberNode],
actualDuration: 0,
actualStartTime: -1,
selfBaseDuration: 0,
treeBaseDuration: 0,
_debugID: 10780,
_debugSource: [Object],
_debugOwner: null,
_debugNeedsRemount: false,
_debugHookTypes: [Array]
},
child: FiberNode {
tag: 11,
key: null,
elementType: [Object],
type: [Object],
stateNode: null,
return: [Circular *2],
child: [FiberNode],
sibling: null,
index: 0,
ref: null,
pendingProps: [Object],
memoizedProps: [Object],
updateQueue: [Object],
memoizedState: [Object],
dependencies: [Object],
mode: 0,
flags: 0,
nextEffect: null,
firstEffect: null,
lastEffect: null,
lanes: 0,
childLanes: 0,
alternate: [FiberNode],
actualDuration: 0,
actualStartTime: -1,
selfBaseDuration: 0,
treeBaseDuration: 0,
_debugID: 10784,
_debugSource: [Object],
_debugOwner: [FiberNode],
_debugNeedsRemount: false,
_debugHookTypes: [Array]
},
sibling: null,
index: 0,
ref: null,
pendingProps: {
onSubmit: [Function: submit],
'data-testid': 'formular',
children: [Object]
},
memoizedProps: {
onSubmit: [Function: submit],
'data-testid': 'formular',
children: [Object]
},
updateQueue: null,
memoizedState: null,
dependencies: null,
mode: 0,
flags: 0,
nextEffect: null,
firstEffect: null,
lastEffect: null,
lanes: 0,
childLanes: 0,
alternate: FiberNode {
tag: 5,
key: null,
elementType: 'form',
type: 'form',
stateNode: [Circular *1],
return: [FiberNode],
child: [FiberNode],
sibling: null,
index: 0,
ref: null,
pendingProps: [Object],
memoizedProps: [Object],
updateQueue: null,
memoizedState: null,
dependencies: null,
mode: 0,
flags: 0,
nextEffect: null,
firstEffect: [FiberNode],
lastEffect: [FiberNode],
lanes: 0,
childLanes: 1,
alternate: [Circular *2],
actualDuration: 0,
actualStartTime: -1,
selfBaseDuration: 0,
treeBaseDuration: 0,
_debugID: 10782,
_debugSource: [Object],
_debugOwner: [FiberNode],
_debugNeedsRemount: false,
_debugHookTypes: null
},
actualDuration: 0,
actualStartTime: -1,
selfBaseDuration: 0,
treeBaseDuration: 0,
_debugID: 10782,
_debugSource: {
fileName: '/Users/lukasgermerott/Dev/flundr/clientnew/src/components/Register.tsx',
lineNumber: 61,
columnNumber: 12
},
_debugOwner: FiberNode {
tag: 0,
key: null,
elementType: [Function: RegisterComponent],
type: [Function: RegisterComponent],
stateNode: null,
return: [FiberNode],
child: [Circular *2],
sibling: null,
index: 0,
ref: null,
pendingProps: {},
memoizedProps: {},
updateQueue: [Object],
memoizedState: [Object],
dependencies: [Object],
mode: 0,
flags: 0,
nextEffect: null,
firstEffect: null,
lastEffect: null,
lanes: 0,
childLanes: 0,
alternate: [FiberNode],
actualDuration: 0,
actualStartTime: -1,
selfBaseDuration: 0,
treeBaseDuration: 0,
_debugID: 10780,
_debugSource: [Object],
_debugOwner: null,
_debugNeedsRemount: false,
_debugHookTypes: [Array]
},
_debugNeedsRemount: false,
_debugHookTypes: null
},
'__reactProps$sikt1ggzmx': {
onSubmit: [Function: submit],
'data-testid': 'formular',
children: {
'$$typeof': Symbol(react.element),
type: [Object],
key: null,
ref: null,
props: [Object],
_owner: [FiberNode],
_store: {}
}
}
}
但是当我在浏览器中记录相同的事件时,我得到了这个
<form>
<div class="MuiGrid-root MuiGrid-container MuiGrid-spacing-xs-2 MuiGrid-direction-xs-column">
<div class="MuiGrid-root MuiGrid-item MuiGrid-grid-xs-12">…</div>
<h5 class="MuiTypography-root MuiTypography-h5">Registration</h5>
</div>
<div class="MuiGrid-root MuiGrid-item MuiGrid-grid-xs-12">…</div>
<p class="MuiTypography-root MuiTypography-body1">Persönliche Daten</p>
</div>
<div class="MuiGrid-root MuiGrid-item MuiGrid-grid-xs-12">…</div>
<div class="MuiGrid-root MuiGrid-item MuiGrid-grid-xs-12">…</div>
<div class="MuiGrid-root MuiGrid-item MuiGrid-grid-xs-12">…</div>
<div class="MuiGrid-root MuiGrid-item MuiGrid-grid-xs-12">…</div>
<div class="MuiGrid-root MuiGrid-item MuiGrid-grid-xs-12">…</div>
<div class="MuiGrid-root MuiGrid-item MuiGrid-grid-xs-12">…</div>
<div class="MuiGrid-root MuiGrid-item MuiGrid-grid-xs-12">…</div>
</div>
</form>
这是对的,因为现在我可以通过事件访问这些值。我的 onsubmit 函数如下:
function submit(event: React.SyntheticEvent) {
event.preventDefault();
// Create target object to extract information from
const target = event.target as typeof event.target & {
email: { value: string };
firstName: { value: string };
lastName: { value: string };
privacyPolicy: { checked: boolean };
};
console.log(target, "TARGET");
const user : IUserRegistrationModel = {
email: target.email.value,
firstName: target.firstName.value,
lastName: target.lastName.value,
password: password,
privacyPolicy: target.privacyPolicy.checked,
};
dispatch(authActions.register(user));
}
测试中的问题是:当它提交事件时,它无法从事件中提取值而只是崩溃。对于浏览器事件,它工作正常。
你们有什么想法吗?
编辑:复制示例 https://codesandbox.io/s/brave-goldberg-8hfri?file=/src/App.tsx
这是这个的副本:
The problem you have it with trying to access the input directly from event.target. You should access it from event.target.elements instead: https://developer.mozilla.org/en-US/docs/Web/API/HTMLFormElement/elements.
基于给定的沙箱,我能够通过更新以下代码使测试通过:
function onSubmit(event: React.SyntheticEvent<HTMLFormElement>) {
event.preventDefault();
// Create target object to extract information from
const payload = event.currentTarget.elements as typeof event.currentTarget.elements & {
email: { value: string };
};
console.log(payload.email.value);
setShow(true);
}
所以我正在尝试测试一个在 React 中实现的表单。当我通过 jest 提交表单时,我得到的事件与通过浏览器提交事件时不同。
我用的测试是这个:
it("shows success message if registering was successful", async () => {
fetchMock.mockReturnValueOnce(Promise.resolve(new Response("", { status: 200 })));
const wrapper = render(<Provider store={getStore()}>
<RegisterComponent/>
</Provider>);
const emailTextfield = wrapper.getByPlaceholderText(/email@domain.de/i);
const password = wrapper.getByPlaceholderText(/eingeben/i);
const firstName = wrapper.getByPlaceholderText(/max/i);
const lastName = wrapper.getByPlaceholderText(/mustermann/i);
const retryPassword = wrapper.getByPlaceholderText(/wiederholen/i);
const privacyPolicy = wrapper.getByRole("checkbox");
const registerButton = wrapper.getByRole("button");
fireEvent.change(emailTextfield, { target: { value: "test@test.de" } });
fireEvent.change(password, { target: { value: "Test1234!" } });
fireEvent.change(retryPassword, { target: { value: "Test1234!" } });
fireEvent.change(firstName, { target: { value: "Lukas" } });
fireEvent.change(lastName, { target: { value: "Germerott" } });
fireEvent.change(privacyPolicy, { target: { checked: true } });
fireEvent.click(registerButton);
const successMessage = await wrapper.findByText(/erfolgreich/i);
expect(successMessage).toBeTruthy();
});
所以我正在为所有输入安装组件和触发事件。记录的事件是这个:
<ref *1> HTMLFormElement {
'__reactFiber$sikt1ggzmx': <ref *2> FiberNode {
tag: 5,
key: null,
elementType: 'form',
type: 'form',
stateNode: [Circular *1],
return: FiberNode {
tag: 0,
key: null,
elementType: [Function: RegisterComponent],
type: [Function: RegisterComponent],
stateNode: null,
return: [FiberNode],
child: [Circular *2],
sibling: null,
index: 0,
ref: null,
pendingProps: {},
memoizedProps: {},
updateQueue: [Object],
memoizedState: [Object],
dependencies: [Object],
mode: 0,
flags: 0,
nextEffect: null,
firstEffect: null,
lastEffect: null,
lanes: 0,
childLanes: 0,
alternate: [FiberNode],
actualDuration: 0,
actualStartTime: -1,
selfBaseDuration: 0,
treeBaseDuration: 0,
_debugID: 10780,
_debugSource: [Object],
_debugOwner: null,
_debugNeedsRemount: false,
_debugHookTypes: [Array]
},
child: FiberNode {
tag: 11,
key: null,
elementType: [Object],
type: [Object],
stateNode: null,
return: [Circular *2],
child: [FiberNode],
sibling: null,
index: 0,
ref: null,
pendingProps: [Object],
memoizedProps: [Object],
updateQueue: [Object],
memoizedState: [Object],
dependencies: [Object],
mode: 0,
flags: 0,
nextEffect: null,
firstEffect: null,
lastEffect: null,
lanes: 0,
childLanes: 0,
alternate: [FiberNode],
actualDuration: 0,
actualStartTime: -1,
selfBaseDuration: 0,
treeBaseDuration: 0,
_debugID: 10784,
_debugSource: [Object],
_debugOwner: [FiberNode],
_debugNeedsRemount: false,
_debugHookTypes: [Array]
},
sibling: null,
index: 0,
ref: null,
pendingProps: {
onSubmit: [Function: submit],
'data-testid': 'formular',
children: [Object]
},
memoizedProps: {
onSubmit: [Function: submit],
'data-testid': 'formular',
children: [Object]
},
updateQueue: null,
memoizedState: null,
dependencies: null,
mode: 0,
flags: 0,
nextEffect: null,
firstEffect: null,
lastEffect: null,
lanes: 0,
childLanes: 0,
alternate: FiberNode {
tag: 5,
key: null,
elementType: 'form',
type: 'form',
stateNode: [Circular *1],
return: [FiberNode],
child: [FiberNode],
sibling: null,
index: 0,
ref: null,
pendingProps: [Object],
memoizedProps: [Object],
updateQueue: null,
memoizedState: null,
dependencies: null,
mode: 0,
flags: 0,
nextEffect: null,
firstEffect: [FiberNode],
lastEffect: [FiberNode],
lanes: 0,
childLanes: 1,
alternate: [Circular *2],
actualDuration: 0,
actualStartTime: -1,
selfBaseDuration: 0,
treeBaseDuration: 0,
_debugID: 10782,
_debugSource: [Object],
_debugOwner: [FiberNode],
_debugNeedsRemount: false,
_debugHookTypes: null
},
actualDuration: 0,
actualStartTime: -1,
selfBaseDuration: 0,
treeBaseDuration: 0,
_debugID: 10782,
_debugSource: {
fileName: '/Users/lukasgermerott/Dev/flundr/clientnew/src/components/Register.tsx',
lineNumber: 61,
columnNumber: 12
},
_debugOwner: FiberNode {
tag: 0,
key: null,
elementType: [Function: RegisterComponent],
type: [Function: RegisterComponent],
stateNode: null,
return: [FiberNode],
child: [Circular *2],
sibling: null,
index: 0,
ref: null,
pendingProps: {},
memoizedProps: {},
updateQueue: [Object],
memoizedState: [Object],
dependencies: [Object],
mode: 0,
flags: 0,
nextEffect: null,
firstEffect: null,
lastEffect: null,
lanes: 0,
childLanes: 0,
alternate: [FiberNode],
actualDuration: 0,
actualStartTime: -1,
selfBaseDuration: 0,
treeBaseDuration: 0,
_debugID: 10780,
_debugSource: [Object],
_debugOwner: null,
_debugNeedsRemount: false,
_debugHookTypes: [Array]
},
_debugNeedsRemount: false,
_debugHookTypes: null
},
'__reactProps$sikt1ggzmx': {
onSubmit: [Function: submit],
'data-testid': 'formular',
children: {
'$$typeof': Symbol(react.element),
type: [Object],
key: null,
ref: null,
props: [Object],
_owner: [FiberNode],
_store: {}
}
}
}
但是当我在浏览器中记录相同的事件时,我得到了这个
<form>
<div class="MuiGrid-root MuiGrid-container MuiGrid-spacing-xs-2 MuiGrid-direction-xs-column">
<div class="MuiGrid-root MuiGrid-item MuiGrid-grid-xs-12">…</div>
<h5 class="MuiTypography-root MuiTypography-h5">Registration</h5>
</div>
<div class="MuiGrid-root MuiGrid-item MuiGrid-grid-xs-12">…</div>
<p class="MuiTypography-root MuiTypography-body1">Persönliche Daten</p>
</div>
<div class="MuiGrid-root MuiGrid-item MuiGrid-grid-xs-12">…</div>
<div class="MuiGrid-root MuiGrid-item MuiGrid-grid-xs-12">…</div>
<div class="MuiGrid-root MuiGrid-item MuiGrid-grid-xs-12">…</div>
<div class="MuiGrid-root MuiGrid-item MuiGrid-grid-xs-12">…</div>
<div class="MuiGrid-root MuiGrid-item MuiGrid-grid-xs-12">…</div>
<div class="MuiGrid-root MuiGrid-item MuiGrid-grid-xs-12">…</div>
<div class="MuiGrid-root MuiGrid-item MuiGrid-grid-xs-12">…</div>
</div>
</form>
这是对的,因为现在我可以通过事件访问这些值。我的 onsubmit 函数如下:
function submit(event: React.SyntheticEvent) {
event.preventDefault();
// Create target object to extract information from
const target = event.target as typeof event.target & {
email: { value: string };
firstName: { value: string };
lastName: { value: string };
privacyPolicy: { checked: boolean };
};
console.log(target, "TARGET");
const user : IUserRegistrationModel = {
email: target.email.value,
firstName: target.firstName.value,
lastName: target.lastName.value,
password: password,
privacyPolicy: target.privacyPolicy.checked,
};
dispatch(authActions.register(user));
}
测试中的问题是:当它提交事件时,它无法从事件中提取值而只是崩溃。对于浏览器事件,它工作正常。
你们有什么想法吗?
编辑:复制示例 https://codesandbox.io/s/brave-goldberg-8hfri?file=/src/App.tsx
这是这个的副本:
The problem you have it with trying to access the input directly from event.target. You should access it from event.target.elements instead: https://developer.mozilla.org/en-US/docs/Web/API/HTMLFormElement/elements.
基于给定的沙箱,我能够通过更新以下代码使测试通过:
function onSubmit(event: React.SyntheticEvent<HTMLFormElement>) {
event.preventDefault();
// Create target object to extract information from
const payload = event.currentTarget.elements as typeof event.currentTarget.elements & {
email: { value: string };
};
console.log(payload.email.value);
setShow(true);
}