
[英]TypeError: Cannot read property '__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED' of undefined React-test-renderer
[英]react-test-renderer test failing TypeError: Cannot read properties of undefined (reading 'current')
我正在尝试使用 react-test-renderer 进行单元测试,但我似乎无法通过测试,即使我正在测试的底层组件有效。 有人可以告诉我我做错了什么
这是组件的代码
import React, { useState } from "react";
import styles from "./styles";
import { View, Pressable, Animated } from "react-native";
import Text from "components/Text/";
import { t } from "services/i18n";
import Form, { Checkbox } from "components/Form";
import WarrantyDetails from "components/WarrantyDetails";
import Icons from "icons";
import { Color } from "theme";
import animation from "./animation";
const WarrantyToggle = ({ checked = false, price = 0, onUpdate = () => { }, disabled = false }) => {
const [detailsVisible, setDetailsVisible] = useState(false);
const [isChecked, setIsChecked] = useState(checked);
const [opacity, scale] = animation(isChecked);
const onChange = (value) => {
onUpdate(value);
setIsChecked(value);
};
return (
<View style={styles.container}>
<Form
style={styles.form}
initialValues={{ warranty: checked }}>
<Checkbox
id="warranty"
name="warranty"
onChange={onChange}
disabled={disabled}
testID="boxcheck"
style={styles.checkbox}
contentStyle={styles.priceRow}
checkbox={() => (
<View style={styles.heartCheckbox}>
<Icons.Warranty size={28} color={Color.dark} strokeWidth={3} />
<Animated.View style={[styles.heart, { opacity: opacity, transform: [{ scale: scale }] }]} >
<Icons.WarrantySelected size={28} color={Color.red} strokeWidth={3} />
</Animated.View>
</View>
)}
label={() => (<Text size="3" font="bold">{t("common:add-protection-plan")}</Text>)}>
<Text style={[styles.price, { opacity: isChecked ? 1 : 0.6 }]}>{`$${price?.toFixed(2)}`}</Text>
<Pressable testID="pressdetails" size={2.5} underline onPress={() => setDetailsVisible(true)}><Text underline style={styles.details}>{t("common:details")}</Text></Pressable>
</Checkbox>
</Form>
<WarrantyDetails
testID = "warrantydetailshigher"
selected={isChecked}
setSelected={setIsChecked}
visible={detailsVisible}
onClose={() => setDetailsVisible(false)}
onChange={onChange}
price={price}
/>
</View>
);
};
export default WarrantyToggle;
这是测试代码
import React from "react";
import renderer from "react-test-renderer";
import WarrantyToggle from "../../../src/components/WarrantyToggle";
const tree = renderer.create(<WarrantyToggle/>)
test(" Perfect lib error screen renders correctly", () => {
const tree1 = renderer
.create(
<WarrantyToggle name="hello test" />
)
.toJSON();
expect(tree1).toMatchSnapshot();
});
test('box checked' ,() =>{
const warrantycheck = tree.root.findByProps({testID:'boxcheck'})
const detailstate = tree.root.findByProps({testID:'warrantydetailshigher'})
if(detailstate.selected == true){
renderer.act(() => warrantycheck.onChange());
expect(detailstate.selected).toEqual(true)
}
else{
renderer.act(() => warrantycheck.onChange());
expect(detailstate.selected).toEqual(false)
}
});
test('press details' ,() =>{
const warrantypress = tree.root.findByProps({testID:'pressdetails'})
const detailstate = tree.root.findByProps({testID:'warrantydetailshigher'})
renderer.act(() => warrantypress.onPress());
expect(detailstate.visible).toEqual(true)
});
这些是我得到的错误
FAIL __tests__/components/WarrantyToggle/WarrantyToggle.test.js
● Console
console.error
The above error occurred in the <WarrantyToggle> component:
at WarrantyToggle (/Users/robertbeit/Documents/sally2/app-mobile-sally-reactnative/src/components/WarrantyToggle/index.js:3777:35)
Consider adding an error boundary to your tree to customize error handling behavior.
Visit https://reactjs.org/link/error-boundaries to learn more about error boundaries.
at logCapturedError (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:10989:23)
at update.callback (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:11022:5)
at callCallback (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:3662:12)
at commitUpdateQueue (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:3683:9)
at commitLifeCycles (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:11855:11)
at commitLayoutEffects (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:14443:7)
at HTMLUnknownElement.callCallback (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:11391:14)
at HTMLUnknownElement.callTheUserObjectsOperation (node_modules/jsdom/lib/jsdom/living/generated/EventListener.js:26:30)
● Perfect lib error screen renders correctly
TypeError: Cannot read properties of undefined (reading 'current')
at iconAnimation (src/components/WarrantyToggle/animation.js:411:83)
at WarrantyToggle (src/components/WarrantyToggle/index.js:3847:54)
at renderWithHooks (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:6016:18)
at mountIndeterminateComponent (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:8744:13)
at beginWork (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:9966:16)
at performUnitOfWork (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:13800:12)
at workLoopSync (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:13728:5)
at renderRootSync (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:13691:7)
at performSyncWorkOnRoot (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:13404:18)
at node_modules/react-test-renderer/cjs/react-test-renderer.development.js:2537:26
at unstable_runWithPriority (node_modules/scheduler/cjs/scheduler.development.js:468:12)
at runWithPriority (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:2486:10)
at flushSyncCallbackQueueImpl (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:2532:9)
at flushSyncCallbackQueue (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:2519:3)
at scheduleUpdateOnFiber (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:13004:9)
at updateContainer (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:16454:3)
at Object.create (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:17149:3)
at Object.<anonymous> (__tests__/components/WarrantyToggle/WarrantyToggle.test.js:8:3)
我尝试运行 yarn test 但它失败了。
这里编辑的是animation文件的代码
import { useRef, useEffect, useCallback } from "react";
import { Animated, Easing } from "react-native";
const iconAnimation = (selected) => {
const opacityValue = useRef(new Animated.Value(0)).current;
const scaleValue = useRef(new Animated.Value(0)).current;
const animateOpacityValue = useCallback(
() => {
Animated.timing(opacityValue, {
toValue: selected ? 1 : 0,
easing: Easing.inOut(Easing.quad),
duration: 300,
useNativeDriver: true,
isInteraction: false
}).start();
Animated.timing(scaleValue, {
toValue: selected ? 1.1 : 1,
easing: selected ? Easing.out(Easing.back(25)) : Easing.inOut(Easing.quad),
duration: 500,
useNativeDriver: true,
isInteraction: false
}).start();
},
[selected],
);
useEffect(() => {
animateOpacityValue();
}, [animateOpacityValue]);
return [opacityValue, scaleValue];
};
export default iconAnimation;```
this is from the index.js form file
import React, { useRef, Fragment, useEffect } from "react";
import { View } from "react-native";
import styles from "./style";
import { Formik } from "formik";
function Row({ children, getRef = () => { }, nextElement = () => { }, values, onUpdate, onPressHandler, style }) {
children = children.filter(function (element) {
return element !== undefined;
});
return (
<View style={[styles.row, style]}>
{
React.Children.map(children, (child, index) => {
if (!child || child.props === undefined) {
return <View />;
}
const id = child.props.id;
return (
<Fragment key={`row-${index}`}>
{
React.cloneElement(child, {
containerStyle: styles.rowItem,
getRef: getRef,
value: (values && values[id]) ? values[id] : "",
values: values,
flex: child.props.flex ? child.props.flex : 1,
onUpdate: onUpdate,
onPressHandler: onPressHandler ?? child.props.onPress,
nextElement: nextElement,
})
}
{
index < children.length - 1 &&
<View style={styles.gutter} />
}
</Fragment>
);
})
}
</View>
);
}
function Form({
formRef,
children,
values,
onUpdate,
initialValues,
initialTouched,
validationSchema,
onSubmitHandler,
fieldValueRef,
resetForm = false,
style = {},
gutterStyle = {}
}) {
const internalFormRef = React.createRef(undefined);
useEffect(() => {
if ((formRef && formRef.current) && resetForm) {
formRef.current.resetForm();
} else if ((internalFormRef && internalFormRef.current) && resetForm) {
internalFormRef.current.resetForm();
}
}, [resetForm, formRef, internalFormRef]);
const inputRefs = useRef([]);
const focusNextElement = (event) => {
const index = inputRefs.current.indexOf(event.target);
if (index !== -1) {
const nextElement = inputRefs.current[index + 1];
if (nextElement) {
nextElement.focus();
}
}
};
const getRef = (element, name) => {
if (element && !inputRefs?.current?.includes(element)) {
inputRefs.current.push(element);
}
};
return (
<View style={[styles.formContainer, style]}>
<Formik
innerRef={formRef ?? internalFormRef}
initialValues={initialValues}
initialTouched={initialTouched}
enableReinitialize={true}
validateOnBlur={true}
validateOnChange
validationSchema={validationSchema}
onSubmit={onSubmitHandler}
>
{({ handleSubmit, setFieldValue }) => {
if (fieldValueRef) {
fieldValueRef.current = setFieldValue;
}
return (
<>
{
React.Children.map(children, (child, index) => {
if (!child || child.props === undefined) {
return <View />;
}
return (
<Fragment>
{
React.cloneElement(child, {
nextElement: focusNextElement,
getRef: getRef,
value: (values && values[child.props.id]) ? values[child.props.id] : "",
values: values,
onUpdate: onUpdate,
onPress: child.props.willHandleSubmit ? handleSubmit : child.props.onPress
})
}
{
index < children.length - 1 &&
<View style={[styles.gutter, gutterStyle]} />
}
</Fragment>
);
})
}
</>
);
}}
</Formik>
</View>
);
}
export default Form;
export { Row };
export { default as FormValidationSchema } from "./formValidationSchemas";
export { default as Button } from "./Button";
export { default as Link } from "./Link";
export { default as NumberInput } from "./NumberInput";
export { default as LoadingIndicator } from "./LoadingIndicator";
export { default as Checkbox } from "./Checkbox";
export { default as PLPCheckbox } from "./PLPCheckbox";
export { default as Modal } from "./Modal";
export { default as RadioGroup, RadioButton } from "./RadioGroup";
export { default as SelectInput } from "./SelectInput";
export { default as TextInput } from "./TextInput";
export { default as GooglePlacesInput } from "./GooglePlacesInput";
export { default as DatePicker } from "./DatePicker";
export { default as TextInputButton } from "./TextInputButton";
我认为问题出在 animation.js 文件中。 最后一个错误行指向 animation.js 文件。 你能分享 animation.js 文件吗
iconAnimation (src/components/WarrantyToggle/animation.js:411:83)
问题未解决?试试以下方法:
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.