在React Enzyme测试中设置参考电流的clientHeight和scrollHeight



我的函数组件对一个元素进行了回调,我想测试这个回调是否在单击时触发。然而,只有当ref的clientHeight和scrollHeight不同时,才会呈现此元素,但在这些测试期间,这两个值都返回为0(当我从useLayoutEffect中登录到控制台时可以看到(。为了进行此测试,我如何将ref.current.clientHeight和ref.current.sollHeight的值设置为不同的非零值?

这是我的组件:

import React, { useState } from "react";

const MyComponent = (props: React.PropsWithChildren<MyComponentProps>) => {
const ref: React.RefObject<HTMLInputElement> = React.CreateRef();
const { myCallBack } = props;
const [showItem, setShowItem] = React.useState(false);
React.useLayoutEffect(() => {
if (ref.current && ref.current.clientHeight < ref.current.ScrollHeight) {
setShowItem(true);
}
}, [ref]);
const someAction = (e: React.ChangeEvent<any>) => {
myCallBack();
}
return(
<div>
<div ref={ref}>
<p>Some text...</p>
</div>
{showItem && <div><p class="some-class" onClick={someAction}>Some more text...</p></div>}
</div>
);
}
export default MyComponent;

这是我的测试:

describe("my tests", (() => { 
it("my test", async () => {
let myCallBackMock = jest.fn();
let wrapper = mount(
<MyComponent myCallBack={myCallBackMock} />
);
wrapper.find(".some-class").simulate("click", { type: "click" });
expect(myCallBackMock).toHaveBeenCalled();
});
});

这是我收到的错误消息:

Method "stimulate" is meant to be run on 1 node. 0 found instead.

Jestjs使用jsdom作为其测试环境。JSDOM没有布局引擎。请参阅web平台的未实现部分

Layout:计算CSS将在何处可视化布局元素的能力,这会影响getBoundingClientRects()等方法或offsetTop等属性。

因此,它将为许多与布局相关的属性(如element.clientHeight(返回零。

在这种情况下,我们必须模拟ref及其属性。您案例中的clientHeightscrollHeight属性。因此,showItem状态将在组件装载时设置为true。

尽管我们必须模拟React.createRef,但我们只是在ref.currentsetter函数中为其添加属性和值,并返回它,而不是完全伪造的ref。这意味着ref.current仍然引用HTMLdiv元素,而不是伪JS对象。

例如

MyComponent.tsx:

import React from 'react';
export interface MyComponentProps {
myCallBack(): void;
}
export const MyComponent = ({ myCallBack }: React.PropsWithChildren<MyComponentProps>) => {
const ref: React.RefObject<HTMLInputElement> = React.createRef();
const [showItem, setShowItem] = React.useState(false);
React.useLayoutEffect(() => {
console.log('clientHeight: %s, scrollHeight: %s', ref.current?.clientHeight, ref.current?.scrollHeight);
if (ref.current && ref.current.clientHeight < ref.current.scrollHeight) {
setShowItem(true);
}
}, []);
const someAction = (e: React.ChangeEvent<any>) => {
myCallBack();
};
return (
<div>
<div ref={ref}>
<p>Some text...</p>
</div>
{showItem && (
<div>
<p className="some-class" onClick={someAction}>
Some more text...
</p>
</div>
)}
</div>
);
};

MyComponent.test.tsx:

import { mount } from 'enzyme';
import React from 'react';
import { MyComponent } from './MyComponent';
export function createFCRefMock(props: { [propName: string]: any }) {
const ref = { current: {} };
const refKey = Symbol('ref');
Object.defineProperty(ref, 'current', {
set(current) {
// intercept the process of setting ref.current
if (current) {
Object.entries(props).forEach(([prop, value]) => {
Object.defineProperty(current, prop, { value });
});
}
this[refKey] = current;
},
get() {
return this[refKey];
},
});
return ref;
}
describe('my tests', () => {
it('my test', async () => {
const myCallBackMock = jest.fn();
const ref = createFCRefMock({ clientHeight: 10, scrollHeight: 20 });
jest.spyOn(React, 'createRef').mockReturnValueOnce(ref);
const wrapper = mount(<MyComponent myCallBack={myCallBackMock} />);
wrapper.find('.some-class').simulate('click');
expect(myCallBackMock).toHaveBeenCalled();
});
});

测试结果:

PASS  stackoverflow/73060890/MyComponent.test.tsx (11.738 s)
my tests
✓ my test (73 ms)
console.log
clientHeight: 10, scrollHeight: 20
at stackoverflow/73060890/MyComponent.tsx:11:13
-----------------|---------|----------|---------|---------|-------------------
File             | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
-----------------|---------|----------|---------|---------|-------------------
All files        |     100 |    78.57 |     100 |     100 |                   
MyComponent.tsx |     100 |    78.57 |     100 |     100 | 11-12             
-----------------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        12.354 s

最新更新