gpt4 book ai didi

testing - 如何在测试期间设置 React 组件的宽度?

转载 作者:行者123 更新时间:2023-11-28 19:41:09 24 4
gpt4 key购买 nike

我正在尝试测试 slider 组件。

此 slider 组件的宽度可以变化。当您单击 slider 的“轨道”时,它应该更改值并触发 onChange 回调。该值基于您在轨道上单击的位置。如果您在最小值为 100 且最大值为 200 时单击中间点,则它应报告值为 150

我遇到的问题是,当我使用 ReactTest.renderIntoDocument 渲染组件时,组件没有任何宽度,因此当您单击它。

这里是组件Slider.js

import React, {PropTypes} from 'react';
import ReactDOM from 'react-dom';
import { noop } from 'lodash';
import style from './style.scss';

export default class Slider extends React.Component {
render() {
return (
<div
className='Slider'
onClick={this.handleClick.bind(this)}
{...this.props}
>
<div
className='handle'
style={{left: `${this.calculateLeft()}%`}}>
</div>
<div className='track'></div>
</div>
);
}

handleClick(e) {
let node = ReactDOM.findDOMNode(this);
let {clientX, clientY} = e;
let {offsetLeft, offsetWidth, clientWidth} = node;
let xPercent = (clientX - offsetLeft) / offsetWidth;
console.log(offsetLeft, offsetWidth, clientWidth, xPercent);
this.props.onChange(normalize(xPercent, this.props.min, this.props.max));
}

calculateLeft() {
let numerator = this.props.value - this.props.min;
let denominator = this.props.max - this.props.min;
return numerator / denominator * 100;
}
}

// Proptypes
// ----------------------------------------------------------------------------
Slider.propTypes = {
// Callback for when the value changes.
onChange: PropTypes.func,
// The value for when the slider is at 0%
min: PropTypes.number,
// The value for when the slider is at 100%
max: PropTypes.number,
// The starting value
value: validateValue,
}

Slider.defaultProps = {
onChange: noop,
min: 0,
max: 100,
}

// Custom Validation
// ----------------------------------------------------------------------------
function validateValue(props, propName, componentName) {
let value = props[propName];

if (typeof(value) !== 'number') {
return new Error(`value must be a number, got ${typeof(value)}`);
}

if (value > props.max || value < props.min) {
return new Error(
`value: ${value} must be between max: ${props.max}
and min: ${props.min}`
);
}
}

// Helpers
// ---------------------------------------------------------------------------

function normalize(floatValue, min, max) {
let range = max - min;
let normalizedValue = floatValue * range + min;
// cleverly restrict the value be between the min and max
return [min, normalizedValue, max].sort()[1];
}

样式表(style.scss):

.Slider {
position: relative;
display: block;
width: 100px;

.track {
height: 4px;
background: #666;
border-radius: 2px;
}

.handle {
width: 12px;
height: 12px;
background: #fff;
border-radius: 10px;
position: absolute;
top: 50%;
transform: translate(-50%, -50%);
transition: left 100ms linear;
}
}

这是我的测试:

import Slider from './Slider';
import React from 'react';
import {
renderIntoDocument,
findRenderedDOMComponentWithClass,
findRenderedDOMComponentWithTag,
Simulate
} from 'react-addons-test-utils';

describe('Slider', function() {

describe('click', function() {
it('triggers the onChange callback', function() {
const onChange = sinon.spy();
const component = renderIntoDocument(
<Slider
style={{width: 100, height: 40}}
min={100}
max={200}
value={150}
onChange={onChange}
/>
);

const track = findRenderedDOMComponentWithClass(component, 'track');

Simulate.click(track, {clientY: 0, clientX: 10})
expect(onChange).to.have.been.calledWith(110);
});
});
});

测试输出

LOG LOG: 0, 0, 0, Infinity
click
✗ triggers the onChange callback
AssertionError: expected onChange to have been called with arguments 10
onChange(200)

at /components/Slider/test.js:99 < webpack:///src/components/Slider/test.js:55:6

这些日志语句来自组件中的 handleClick() 函数。

宽度为零,因此在计算 xPercent 时分母最终为零,这导致它为无穷大。这导致它只使用 200 的 max 值。

长见识

如何在测试期间渲染时让组件具有宽度?

最佳答案

今天我自己也遇到了同样的问题 - 我正在构建一个组件,该组件将根据元素的大小缩放其文本大小。因为 renderIntoDocument 将组件放置在分离的 DOM 节点中,所以无法计算 offsetWidth、clientWidth 等。

您是在浏览器还是在 node.js 中进行测试? (编辑:我看到你标记了 PhantomJS 问题,所以我猜是浏览器!)如果你在浏览器中,你可以将组件真正渲染到 DOM 中:

React.render(<Slider />, document.body);

如果你担心测试隔离,你可以创建一个 IFrame 来渲染组件,然后清理它:

beforeEach(function() {
this.iframe = document.createElement('iframe');
document.body.appendChild(this.iframe);
});

React.render(<Slider />, this.iframe.contentDocument.body);

afterEach(function() {
document.body.removeChild(this.iframe);
});

然后调用 this.iframe.contentDocument.body.querySelectorAll('.track') 获取 HTML 元素并对它运行断言(这是一个纯 HTML 元素,而不是 React 组件,因此请使用标准 API 对其进行查询)。

关于testing - 如何在测试期间设置 React 组件的宽度?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33325893/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com