测试时如何设置React组件的宽度?

2024-03-07

I'm trying to test a slider component.

该滑块组件的宽度可以是可变的。当您单击滑块的“轨道”时,它应该更改值并触发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 时分母最终为零,这导致它为无穷大。这导致它只使用max值为 200。

TLDR

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


今天我自己也一直在解决同样的问题 - 我正在构建一个组件,该组件将根据元素的大小缩放其文本大小。由于 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 来查询它)。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

测试时如何设置React组件的宽度? 的相关文章

  • 如何让 webpack 转换 React 生产文件?

    当我使用 webpack 与 React 16 捆绑我的应用程序时 我在浏览器中收到 Uncaught ReferenceError require is not Defined 对于react和react dom 导致错误的资源是reac
  • redux - 如何存储和更新键/值对

    我正在使用 redux 和 React js 我想存储简单的键 值对 但无法获得正确的减速器语法 在这种情况下 每个键 值对将保持与外部系统的连接 这是正确的做法吗 我刚开始使用 redux 所以这有点神秘 export default s
  • 在AWS S3中部署react-redux应用程序

    我在堆栈溢出中遇到了很多类似的问题one https stackoverflow com questions 16267339 s3 static website hosting route all paths to index html
  • ref scrollIntoView 不适用于反应上的平滑行为

    我正在创建一个组件 该组件将保存动态元素列表 出于样式原因 我需要将每个部分的标题保留在粘性导航菜单中 当用户上下滚动部分列表时 我需要应用样式规则 并将菜单导航中的同一部分带入视图 因此我尝试将scrollIntoView与菜单部分引用一
  • React router dom 6 中的受保护路由

    我在反应中创建了简单的用户上下文 用户提供者 export const AuthContext createContext export const AuthProvider children gt const user setUser u
  • Guice 字段注入不起作用(返回 null)

    我在使用 Guice 时遇到空值问题 接下来我将向您展示一个类似场景的示例 我知道字段注入是一种不好的做法 但我希望它在演示中像这样工作 我有一个名为B 这是我要注入的 class B Inject public B public void
  • 单击react.js 切换列表的背景颜色

    我正在尝试创建一个具有以下功能的列表 悬停时更改列表项的背景颜色 单击时更改列表项的背景颜色 在单击的元素之间切换背景颜色 即列表中只有一个元素可以具有 clicked 属性 我已经执行了 onhover 1 和 2 功能 但无法实现第三个
  • 运行 tsc(TypeScript 编译器)时如何复制 dist 或 build 文件夹中的 package.json

    我有一个 TypeScript React 组件 它使用package json文件 参见屏幕截图 然后我运行tsc为了在我的中将其转译为 es5dist文件夹但package json文件没有被复制 请注意 在屏幕截图中 我手动将其复制到
  • Rspec 控制器测试,传递 JSON 参数

    我试图实现以下目标 在 RSpec 控制器测试中创建 POST json 请求 并向其传递参数 这是我的代码 it returns access token do post login email bla password bla1 for
  • VSCode 不会从 Next.js 项目中的“react”自动导入

    This is not的副本这个问题 https stackoverflow com questions 71476308 how to stop vs code importing react methods from minified
  • 无法在scrollView中滚动

    我有一个屏幕 我可以在输入字段中输入内容并获得相应的搜索结果 该列表在 ScrollView 中呈现 但当键盘打开时 在 Android 中 它仍然不允许我滚动 我怎样才能解决这个问题 return lt gt addressesFound
  • React.JS:类型错误:无法读取 findLoader 处未定义的属性“过滤器”

    我正在按照教程进行工作 https www fullstackreact com articles react tutorial cloning yelp routing https www fullstackreact com artic
  • 所有junit测试后的清理

    在我的项目中 我必须在所有测试之前进行一些存储库设置 这是使用一些棘手的静态规则来完成的 然而 在所有测试之后我不知道如何进行清理 我不想保留一些神奇的静态数字来引用所有测试方法的数量 我应该一直维护它 最受赞赏的方法是添加一些侦听器 该侦
  • 使用 RSpec 进行 Rails 片段缓存测试

    我觉得这是一个没有太多记录的主题 至少我在这里找到最佳实践时遇到了很多麻烦 我使用 cache key 在视图中进行片段缓存 tbody employees each do employee cache employee do tr emp
  • Redux如何处理reducer中的错误

    我不确定如何处理 redux 减速器中的错误 当我的 API 获取返回数据时 我需要转换其结构并检查结果数据上设置的各种属性 但是 我不能在减速器中抛出错误 因为 redux 至少需要返回之前的状态 我该如何处理这个问题 注意 我正在使用反
  • 我可以关闭 create-react-app 分块机制吗?

    我正在使用以下命令设置我的 React 应用程序项目create react app 我想知道是否有一种方法可以关闭内置于反应脚本中的分块机制 问题是我需要修复在构建中创建的包的名称 可以通过扩展您的 CRA 来完成react app re
  • 在 React 组件中等待异步函数并显示 Spinner

    初学者在这里 尝试从服务器获取一些数据并在获取后将其显示在我的反应组件中 但是 我在将异步函数集成到我的反应组件中时遇到了麻烦 import React useState from react import request from gra
  • 如何在单击按钮时清除反应挂钩中的间隔

    我正在用反应钩子构建一个简单的计时器 我有两个按钮启动和重置 当我单击开始按钮时 handleStart 函数工作正常 计时器启动 但我不知道如何在单击重置按钮时重置计时器 这是我的代码 const App gt const timer s
  • Permissions-Policy 标头错误:无法识别的功能:“interest-cohort”

    我才刚刚开始反应 我的页面在本地主机上运行良好 现在我正尝试在 github 上托管我的页面 我使用了 npm run deploy 并托管 这是我的 package json 现在 当我尝试访问我的页面时 我遇到了错误 第一个警告最让我担
  • 有什么办法可以避免使用 React 的 SSR 中的“文本内容不匹配”警告?

    我已经用 webpack 和 HMR 设置了 SSR 环境 有一个静态呈现的标记 服务器传递给客户端和client js捆绑与ReactDOM hydrate 方法 如果我更改源代码 HMR 可以正常工作 但会在控制台中发出警告 指出客户端

随机推荐