作者:手机用户2602924091 | 来源:互联网 | 2023-09-10 22:03
我正在使用React表单,并具有onSubmit函数。我只在onSubmit
函数中添加了以下几行。
const id = this.getErrorPositionById();
const errorPosition = document.getElementById(id).offsetTop; //CANNOT READ PROPERTY 'offsetTop' of null
window.scrollTo({
top: errorPosition,behavior: "smooth"
});
这是onSubmit
函数。
public getErrorPositiOnById= () => {
const error = this.state.errors;
return Object.keys(error).find(id => error[id] != null);
};
public OnSubmit= (e: React.FormEvent) => {
e.preventDefault();
const id = this.getErrorPositionById();
const errorPosition = document.getElementById(id).offsetTop;
window.scrollTo({
top: errorPosition,behavior: "smooth"
});
if (
!this.state.isValid ||
(!this.props.allowMultipleSubmits && this.state.isSubmitted)
) {
return;
}
Promise.all(this.validateFields())
.then((validationErrors: IValidationErrors[]) => {
this.setError(Object.assign({},...validationErrors),() => {
this.isFormValid() ? this.setSubmitted(e) : this.scrollFormToView();
});
})
.then(() => {
const newErrors = this.state.errors;
this.setState({ errors: { ...newErrors,...this.props.apiErrors } });
});
};
这是测试用例
beforeEach(() => {
jest.clearAllMocks();
formFields = jest.fn();
OnSubmit= jest.fn();
OnValidate= jest.fn();
validate = jest.fn();
mockPreventDefault = jest.fn();
mockEvent = jest.fn(() => ({ preventDefault: mockPreventDefault }));
mockValidateAllFields = jest.fn(() => Promise);
mockChildFieldCompOnent= { validate };
instance = formWrapper.instance();
});
it("should not reValidate if form has been submitted already",() => {
instance.validateFields = mockValidateAllFields;
instance.setSubmitted();
expect(instance.state.isSubmitted).toBe(true);
instance.onSubmit(mockEvent());
expect(mockValidateAllFields).toHaveBeenCalledTimes(0);
});
测试用例因错误而失败
TypeError:无法读取null的属性“ offsetTop”
在行
下方
const errorPosition = document.getElementById(id).offsetTop;
有人可以帮助我了解如何消除此错误。
您应该为document.getElementById(id)
制作存根。为简单起见,我从组件中删除了您的业务逻辑。
例如
index.tsx
:
import React,{ Component } from 'react';
class SomeComponent extends Component {
state = {
errors: {
'#selector': {},},};
public getErrorPositiOnById= () => {
const error = this.state.errors;
return Object.keys(error).find((id) => error[id] != null);
};
public OnSubmit= (e: React.FormEvent) => {
e.preventDefault();
const id = this.getErrorPositionById() as string;
const errorPosition = document.getElementById(id)!.offsetTop;
window.scrollTo({
top: errorPosition,behavior: 'smooth',});
};
public render() {
return (
);
}
}
export default SomeComponent;
index.spec.tsx
:
import React from 'react';
import { shallow } from 'enzyme';
import SomeComponent from './';
describe('SomeComponent',() => {
afterEach(() => {
jest.resetAllMocks();
});
it('should handle submit correctly',async () => {
const mElement = { offsetTop: 123 };
document.getElementById = jest.fn().mockReturnValueOnce(mElement);
window.scrollTo = jest.fn();
const wrapper = shallow();
const mEvent = { preventDefault: jest.fn() };
wrapper.find('form').simulate('submit',mEvent);
expect(mEvent.preventDefault).toHaveBeenCalledTimes(1);
expect(document.getElementById).toBeCalledWith('#selector');
expect(window.scrollTo).toBeCalledWith({ top: 123,behavior: 'smooth' });
});
});
带有覆盖率报告的单元测试结果:
PASS src/stackoverflow/53352420/index.spec.tsx (12.859s)
SomeComponent
✓ should handle submit correctly (20ms)
-----------|----------|----------|----------|----------|-------------------|
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s |
-----------|----------|----------|----------|----------|-------------------|
All files | 100 | 100 | 100 | 100 | |
index.tsx | 100 | 100 | 100 | 100 | |
-----------|----------|----------|----------|----------|-------------------|
Test Suites: 1 passed,1 total
Tests: 1 passed,1 total
Snapshots: 0 total
Time: 14.751s
源代码:https://github.com/mrdulin/jest-codelab/tree/master/src/stackoverflow/53352420