天道酬勤,学无止境

使用 jQuery 反应组件而不需要 - 开玩笑的单元测试(React component using jQuery without require - jest unit tests)

问题

我有一个非常简单的 React mixin,它使用 jQuery 来触发一个事件

MyMixin = {
  trackStructEvent: function () {
    args = Array.prototype.slice.call(arguments);
    $('body').trigger('myEvent', args);
  }
module.exports = MyMixin

这是使用 browserify 作为一组新组件的一部分导入到主站点的。 由于包含这些组件的主站点将始终包含 jQuery,我不想在 browserify 中使用 jQuery,因为它会被复制。

这在行为方面不是问题 - 但是在运行 jest 以使用此 mixin 对组件进行单元测试时会导致问题,从而引发错误。

ReferenceError: $ is not defined

我知道我可以通过在 browserify 中包含 jQuery 来解决这个问题,但这会将 2 个副本加载到我的网站中。

有什么办法可以开玩笑地告诉我的反应组件 jQuery 已经存在于窗口中而不用担心它?

回答1

我有一个类似的问题,但我认为到目前为止我已经解决了您的问题。 你需要在你的反应文件中使用 require 在 $ 下定义 jQuery

var $ = require('jquery');

MyMixin = {
   trackStructEvent: function () {
      args = Array.prototype.slice.call(arguments);
      $('body').trigger('myEvent', args);
   }
module.exports = MyMixin

然后你需要告诉 jest 不要模拟 jquery

jest.dontMock('jquery')

然后你的笑话单元测试应该通过(假设他们没有验证 jQuery 正在做的事情 - 这是我的测试失败的地方)。

您还需要告诉 browserify jQuery 是外部的,那么结果将是您对 $ 的所有引用都已定义,jquery 库已加载用于测试,但未包含在您的 browserify 包中。 (使用 browserify-shim)

回答2

我要的是:

if (process.env.NODE_ENV === 'test') window.$ = require('jquery');

我希望这可以帮助别人!

更新:

我已经开始在所有使用 jQuery 的 React 文件中import $ from 'jquery' 。 这消除了对 window.$ 的依赖,这是我期望的 jQuery 类型(我遇到了其他库与 window.$ 混淆的问题。起初,我担心在任何地方导入 jQuery,因为我担心这会增加我的捆绑包大小。但是捆绑的工作方式,所有这些导入都指向一个单例,因此捆绑包的大小不会增加。

回答3

就我而言,我对测试组件中的 jQuery 功能不感兴趣。 此外,我没有在我的包中包含 jQuery,因为它在我的应用程序所在的整个网站上都被使用和包含。 例如,我做了以下工作:

// SubmitRender.js

// ...import statements...

var SubmitRender = React.createClass({
  componentWillMount: function () {
    $('form').on('submit', (e)=>{
      this.handleSubmit(e);
    });
  },

  // ...more code...
});
export default SubmitRender;

.

// SubmitRender.spec.js

// ...import statements...

describe('SubmitRender', () => {
  beforeAll(() => {
    // mocking jQuery $()
    global.window.$ = jest.fn(() => {return {on: jest.fn()}});
  });

  it('renders without error', () => {
    expect( () => render(<SubmitRender />) ).not.toThrow();
  });
});

我知道如果不调用$函数,我的组件将无法安装。 所以我只是在beforeAll()使用jest.fn模拟该函数。 现在,我也知道我的实际组件中的 jQuery 函数是链接的。 所以我知道我还需要考虑 jQuery 的.on() ,所以我确保返回一个带有on函数的对象。 没有进一步的链接,所以这就是我可以停止的地方。

如果我有一组更复杂的链式函数,我可以这样做:

beforeAll(() => {
  // mocking jQuery $()
  var fakeQuery = jest.fn(() => {
    return {
      on: fakeQuery,
      off: fakeQuery,
      click: fakeQuery
    }
  })
  global.window.$ = fakeQuery;
});

受限制的 HTML

  • 允许的HTML标签:<a href hreflang> <em> <strong> <cite> <blockquote cite> <code> <ul type> <ol start type> <li> <dl> <dt> <dd> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>
  • 自动断行和分段。
  • 网页和电子邮件地址自动转换为链接。

相关推荐
  • 用coffeescript jsx开玩笑?(Jest with coffeescript jsx?)
    问题 如何使用 Jest 测试用 CoffeeScript + React jsx 编写的 React 组件? Jest 提供的唯一 CoffeeScript 示例使用普通的 CoffeeScript,并且不适用于 CoffeeScript + React JSX(到达<时出现语法错误)。 我试过的 第一次尝试:execSync // preprocessor.js var execSync = require('exec-sync'); module.exports = { process: function (src, path) { return execSync('browserify -t coffee-reactify ' + path); } }; 这有效,但需要太多时间(虚拟测试需要 12 秒)。 然后我尝试: 第二次尝试:coffee-react-transform // preprocessor.js var coffee = require('coffee-script'); var transform = require('coffee-react-transform'); module.exports = { process: function(src, path) { if (path.match(/\.coffee$/)) { return
  • 不能用玩笑模拟模块,并测试函数调用(Cannot mock a module with jest, and test function calls)
    问题 我使用 create-app-component 创建了一个项目,它使用构建脚本(babel、webpack、jest)配置一个新的应用程序。 我写了一个我正在尝试测试的 React 组件。 该组件需要另一个 javascript 文件,公开一个函数。 我的 search.js 文件 export { search, } function search(){ // does things return Promise.resolve('foo') } 我的反应组件: import React from 'react' import { search } from './search.js' import SearchResults from './SearchResults' export default SearchContainer { constructor(){ this.state = { query: "hello world" } } componentDidMount(){ search(this.state.query) .then(result => { this.setState({ result, })}) } render() { return <SearchResults result={this.state.result} /> } }
  • 由于需要 DOM,使用 reactjs renderIntoDocument 进行测试失败(Test with reactjs renderIntoDocument keep failed due to required DOM)
    问题 我是 reactJS 的新手,并尝试学习如何使用它进行测试。 我遇到了以下测试 util 方法。 但是我不断收到相同的错误message:ReferenceError: document is not defined 。 渲染到文档 ReactComponent renderIntoDocument( ReactElement instance ) 将组件渲染到文档中分离的 DOM 节点中。 这个函数需要一个 DOM。 注意:在导入 React 之前,您需要全局可用的 window、window.document 和 window.document.createElement。 否则 React 会认为它无法访问 DOM 并且像 setState 这样的方法将无法工作。 我知道它缺少 DOM 失败的原因,但是我如何插入 DOM 或需要它? 我的测试如下: import expect from 'expect.js'; import React from 'react'; import Header from '../../components/header'; import {renderShallow} from './help'; import ReactAddOn from 'react/addons'; var TestUtils = ReactAddOn
  • 浅谈Vue和React的区别
    作为一个一直使用vue的初级前端,对react也有着学习的憧憬,当时选择vue只是因为左手石头剪刀布输给了右手(开玩笑) 在工作之余,也准备花点时间去了解一下react,毕竟在移动端开发react也是必会的一个技能。 先看看Vue和React的介绍: React: 除非你最近一直不关注前端的发展,不然你肯定听说过由Facebook创建的JavaScript UI框架——React。它支撑着包括 Instagram在内的大多数Facebook网站。React与当时流行的jQuery,Backbone.js和Angular 1等框架不同,它的诞生改变了 JavaScript的世界。其中最大的变化是React推广了Virtual DOM(我们稍后探究)并创造了新的语法——JSX,JSX允许开发者 在JavaScript中书写HTML。 Vue: Vue致力解决的问题与React一致,但却提供了另外一套解决方案。Vue使用模板系统而不是JSX,使其对现有应用的升级更加容 易。这是因为模板用的就是普通的HTML,通过Vue来整合现有的系统是比较容易的,不需要整体重构。同时Vue声称它更容易 学习,我最近才接触Vue,能证明所言非虚。关于Vue还需要说的是,Vue主要是由一位开发者进行维护的,而不像React一样由 如Facebook这类大公司维护。 作为两款现在比较火热的前端框架
  • 「前端架构」Grab的前端学习指南
    原帖可以在Github上找到。未来的学习指南将在那里更新。如果你喜欢你正在阅读的东西,给它打一颗星吧!公司是东南亚(SEA)领先的运输平台,我们的使命是利用公司最新的技术和人才,推动SEA前进。截至2017年5月,我们每天处理230万次乘车,我们正在快速增长和招聘。为了跟上Grab惊人的增长,我们的网络团队和网络平台也必须增长。幸运的是,或者不幸的是,在Grab上,web团队已经跟上了最新的最佳实践,并在我们的web应用程序中集成了现代JavaScript生态系统。的结果是,我们的新员工或后端工程师,他们并不一定了解现代JavaScript的生态系统,可能会感到被接二连三的新事物,他们必须学习只是为了完成他们的特性或web应用程序的bug修复。前端开发从未像今天如此复杂和令人兴奋的。每隔一天就会出现新的工具、库、框架和插件,还有很多东西需要学习。必须引导web团队的新成员接受前端的这种演化,学会轻松地在生态系统中导航,并尽可能快地向用户交付代码。我们提出了一个学习指南,介绍我们为什么要做我们所做的,以及我们如何处理前端的规模。本学习指南的灵感来自于“治愈JavaScript疲劳的学习计划”,在某种意义上,我们建议针对前端开发的每个方面学习特定的库/框架,这些库/框架基于当前认为最适合于Grab的内容。我们解释了为什么选择某个库/框架/工具,并提供了学习资源的链接,让读者能够自己学习
  • 如何对React-Redux连接的组件进行单元测试?(How to Unit Test React-Redux Connected Components?)
    问题 我正在使用Mocha,Chai,Karma,Sinn,Webpack进行单元测试。 我按照此链接为React-Redux Code配置了我的测试环境。 如何使用Karma,Babel和Webpack在React上实现测试+代码覆盖率 我可以成功地测试我的动作和reducers javascript代码,但是当涉及到测试我的组件时,它总是会抛出一些错误。 import React from 'react'; import TestUtils from 'react/lib/ReactTestUtils'; //I like using the Test Utils, but you can just use the DOM API instead. import chai from 'chai'; // import sinon from 'sinon'; import spies from 'chai-spies'; chai.use(spies); let should = chai.should() , expect = chai.expect; import { PhoneVerification } from '../PhoneVerification'; let fakeStore = { 'isFetching': false, 'usernameSettings
  • jquery 不适用于 jsdom/enzyme(jquery doesn't work with jsdom/enzyme)
    问题 我有一个带有以下组件的最小测试反应应用程序: import React from 'react'; import $ from 'jquery'; export default class App extends React.Component { componentDidMount() { console.log('componentDidMount', $('#helloDiv').length); } render() { return <div id='helloDiv'> Hello React! </div>; } } 在浏览器(Chrome)中加载它时效果很好。 componentDidMount() 中的 console.log() 打印出找到的 1 helloDiv 元素 但是,如果我使用 mocha + 酶 + jsdom 运行测试,App 组件中相同的 console.log() 会打印出 0: import React from 'react'; import { mount } from 'enzyme'; import { expect } from 'chai'; import App from '../src/client/app/first' describe('first test', () => { it('should pass', (
  • 什么时候应该在酶/反应测试中使用渲染和浅化?(When should you use render and shallow in Enzyme / React tests?)
    问题 在发布此问题之前,我尝试在sqa stackexchange中进行搜索,但是我没有找到有关浅层和渲染的文章,因此希望有人可以在这里为我提供帮助。 什么时候应该在测试反应组件时使用浅化和渲染? 根据airbnb文档,我对两者的区别提出了一些意见: 由于浅层将组件作为一个整体进行测试,因此应将其用于“父级”组件。 (例如桌子,包装纸等) 渲染用于子组件。 我问这个问题的原因是,我很难确定应该使用哪一个(尽管文档说它们非常相似) 那么,我怎么知道在特定情况下要使用哪一个呢? 回答1 根据酶文档: 用于完整DOM呈现的mount(<Component />)非常适合用于您具有可能与DOM API交互或可能需要完整生命周期才能完全测试组件的组件(例如componentDidMount等)的用例。 与 用于浅层渲染的shallow(<Component />)有助于约束您将组件作为一个单元进行测试,并确保您的测试不会间接断言子组件的行为。 与 render用于渲染组件到静态HTML并分析生成的HTML结构。 您仍然可以在浅层渲染中看到底层的“节点”,因此,例如,您可以使用AVA作为规范运行器来执行类似(略做作)的示例: let wrapper = shallow(<TagBox />); const props = { toggleValue: sinon.spy() }; test(
  • 反应功能性无状态组件,PureComponent,Component; 有什么区别,什么时候应该使用什么?(React functional stateless component, PureComponent, Component; what are the differences and when should we use what?)
    问题 从React v15.3.0知道,我们有了一个名为PureComponent的新基类,以扩展内置的PureRenderMixin 。 我了解的是,在shouldComponentUpdate此方法对shouldComponentUpdate内部的道具进行了较浅的比较。 现在,我们有3种方法来定义React组件: 不扩展任何类的功能性无状态组件扩展PureComponent类的组件扩展Component类的常规组件 一段时间以前,我们曾经将无状态组件称为“纯组件”,甚至称为“哑组件”。 似乎“纯”一词的整个定义现在已经在React中改变了。 尽管我了解这三者之间的基本区别,但是我仍然不确定何时选择什么。 另外,每种性能对性能的影响和权衡是什么? 更新: 这些是我希望得到澄清的问题: 我应该选择将我的简单组件定义为功能性的(出于简单性考虑)还是扩展PureComponent类(出于性能的考虑)? 我为失去的简单性而付出了真正的权衡取舍,从而提高了性能吗? 当我始终可以使用PureComponent以获得更好的性能时,是否需要扩展普通的Component类? 回答1 您如何决定,如何根据我们组件的目的/尺寸/道具/行为在这三者之间进行选择? 使用自定义shouldComponentUpdate方法从React.PureComponent或从React
  • 如何将Jest与React Native一起使用(How to use Jest with React Native)
    问题 React Native文档的测试部分建议Jest是进行单元测试的官方方法。 但是,他们没有解释如何进行设置。 无需任何设置运行玩笑给出语法错误(不带行号:(),因为它不适用的变换(例如ES6功能,JSX和流量),其阵营本地代码往往使用。有一个jestSupport文件夹中的阵营本地源尝试包含一个env.js和scriptPrerocess.js ,后者具有用于应用转换的代码,因此我已将其复制到我的项目中,并将以下部分添加到我的package.json中: "jest": { "scriptPreprocessor": "jestSupport/scriptPreprocess.js", "setupEnvScriptFile": "jestSupport/env.js" }, 这样可以解决第一个错误,但仍然出现以下错误: Using Jest CLI v0.4.0 FAIL js/sync/__tests__/SynchronisedStorage-tests.js SyntaxError: /Users/tom/my-project/js/sync/__tests__/SynchronisedStorage-tests.js: /Users/tom/my-project/js/sync/SynchronisedStorage.js: /Users/tom/my
  • 开玩笑嘲笑`document`(Mocking `document` in jest)
    问题 我正在开玩笑地为我的Web组件项目编写测试。 我已经在es2015预设中使用babel。 加载js文件时遇到问题。 我遵循了一段代码,其中document对象具有currentScript对象。 但是在测试环境中,它为null 。 所以我想嘲笑一样。 但是jest.fn()并没有真正帮助。 我该如何处理这个问题? 开玩笑失败的一段代码。 var currentScriptElement = document._currentScript || document.currentScript; var importDoc = currentScriptElement.ownerDocument; 我写的测试用例。 component.test.js import * as Component from './sample-component.js'; describe('component test', function() { it('check instance', function() { console.log(Component); expect(Component).toBeDefined(); }); }); 以下是开玩笑引发的错误 Test suite failed to run TypeError: Cannot read property
  • 反应路由器“无法读取未定义的属性'推送'”(react-router “ Cannot read property 'push' of undefined”)
    问题 我对反应和反应路由器很陌生。 react 的问题就在这里,在我的应用程序的某些页面上,react-router 正在工作,有些页面给出了这样的错误:“无法读取未定义的属性‘推送’”。 我正在使用反应 0.14.1 我的路由代码如下所示: render( <Router history={hashHistory}> <Route path="/" component={Loginpanel}/> <Route path="Index" component={Index}/> <Route path="Form" component={Form} /> <Route path="Checkindex" component={Index}/> <Route path="Signup" component={Signup}/> <Route path="Admin" component={Admin}/> <Route path="AdminEditDetails" component={AdminEditDetails}/> <Route path="AdminDetails" component={AdminDetails}/> </Router>, document.getElementById('js-main')); 我的组件现在是这样的: class App
  • 在React JS中触发onchange事件的最佳方法是什么(What is the best way to trigger onchange event in react js)
    问题 我们使用Backbone + ReactJS捆绑包来构建客户端应用程序。 我们非常依赖臭名昭著的valueLink我们通过自己的支持ReactJS接口进行双向绑定的包装器将值直接传播到模型。 现在我们面对这个问题: 我们有jquery.mask.js插件,可以以编程方式设置输入值的格式,因此不会触发React事件。 当模型从用户输入中接收未格式化的值而从插件中丢失格式化的值时,所有这些都会导致情况。 似乎React依赖于浏览器有很多事件处理策略。 有什么通用的方法来触发特定DOM元素的更改事件,以便React可以听到吗? 回答1 对于React 16和React> = 15.6 Setter .value=不能按我们期望的那样工作,因为React库会覆盖输入值setter,但我们可以直接在input作为上下文调用该函数。 var nativeInputValueSetter = Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype, "value").set; nativeInputValueSetter.call(input, 'react 16 value'); var ev2 = new Event('input', { bubbles: true}); input.dispatchEvent
  • 是否可以在 React 中使用 Polymer?(Is it possible to use Polymer inside of React?)
    问题 我一直在使用 React 并希望在 React 中使用 Polymer 标签。 React 不识别 Polymer 标签,因为 React 只处理基本的 DOM 标签。 有没有办法将 Polymer 标签添加到 React DOM 库? 回答1 是的,有可能。 创建聚合物元素。 <link rel="import" href="../../bower_components/polymer/polymer.html"> Polymer({ is: 'calender-element', ready: function(){ this.textContent = "I am a calender"; } }); 通过在 html 页面中导入聚合物组件,使其成为 html 标签。 例如,将它导入到您的 React 应用程序的 index.html 中。 <link rel="import" href="./src/polymer-components/calender-element.html"> 在 jsx 文件中使用该元素。 'use strict'; import React from 'react'; class MyComponent extends React.Component{ render(){ return ( <calender-element><
  • 如何用玩笑和酶模拟React组件方法(How to mock React component methods with jest and enzyme)
    问题 我有一个react组件(为了演示该问题而对其进行了简化): class MyComponent extends Component { handleNameInput = (value) => { this.searchDish(value); }; searchDish = (value) => { //Do something } render() { return(<div></div>) } } 现在,我想测试handleNameInput()使用提供的值调用searchDish 。 为了做到这一点,我想创建一个代替组件方法的笑话模拟函数。 到目前为止,这是我的测试用例: it('handleNameInput', () => { let wrapper = shallow(<MyComponent/>); wrapper.searchDish = jest.fn(); wrapper.instance().handleNameInput('BoB'); expect(wrapper.searchDish).toBeCalledWith('BoB'); }) 但是我在控制台中得到的只是SyntaxError : 语法错误 at XMLHttpRequest.open (node_modules/jsdom/lib/jsdom/living/xmlhttprequest
  • 如何访问 React 中的方法进行单元测试(How do I access methods in React for unit testing)
    问题 我在用 React 进行单元测试时遇到了难以置信的困难。 TestUtils 上的文档很少,并且没有示例。 谷歌似乎只给了我几个结果。 我正在使用 Jasmine,但这并不是真正让我感到悲伤的部分。 这是我尝试过的最简单的测试: var BigButton = React.createClass({ render: function () { return ( <button className="big-submit" data-color={this.props.color} onClick={this.props.action}>{this.props.text}</button> ); }, foo: function () {}, bar: function () { this.foo(); } }); 我有一个测试 describe('BigButton', function () { describe('render', function () { it('creates a button', function () { var button = <BigButton />; TestUtils.renderIntoDocument(button); debugger; }); }); }); 我的问题是如何从外部访问 React 类中任何有意义的内容?
  • 如何模拟反应路由器上下文(How to mock react-router context)
    问题 我有相当简单的反应组件(如果路由处于活动状态,则链接包装器会添加“活动”类): import React, { PropTypes } from 'react'; import { Link } from 'react-router'; const NavLink = (props, context) => { const isActive = context.router.isActive(props.to, true); const activeClass = isActive ? 'active' : ''; return ( <li className={activeClass}> <Link {...props}>{props.children}</Link> </li> ); } NavLink.contextTypes = { router: PropTypes.object, }; NavLink.propTypes = { children: PropTypes.node, to: PropTypes.string, }; export default NavLink; 我应该如何测试它? 我唯一的尝试是: import NavLink from '../index'; import expect from 'expect'; import { mount
  • 使用在React Components中转换DOM的JQuery插件?(Using JQuery plugins that transform the DOM in React Components?)
    问题 一些JQuery插件不仅会向DOM节点添加行为,还会对其进行更改。 例如,Bootstrap Switch转 <input type="checkbox" name="my-checkbox" checked> 变成像 <div class="bootstrap-switch bootstrap-switch-wrapper bootstrap-switch-on bootstrap-switch-large bootstrap-switch-animate"> <div class="bootstrap-switch-container"> <span class="bootstrap-switch-handle-on bootstrap-switch-primary">ON</span> <label class="bootstrap-switch-label"> </label> <span class="bootstrap-switch-handle-off bootstrap-switch-default">OFF</span> <input type="checkbox" name="download-version" checked="" data-size="large" data-on-text="3" data-off-text="2.0.1"> <
  • React js - 如何在测试组件时模拟上下文(React js - How to mock Context when testing component)
    问题 我正在尝试测试一个从根组件继承上下文的组件,而不是从根向下加载/渲染所有内容。 我已经尝试并搜索了有关如何模拟上下文的示例,但找不到任何内容(至少不使用玩笑)。 这是我要实现的目标的简化示例。 有没有一种简单的方法可以模拟 reactEl.context 进行测试? /** * Root Element that sets up & shares context */ class Root extends Component { getChildContext() { return { language: { text: 'A String'} }; } render() { return ( <div> <ElWithContext /> </div> ); } } Root.childContextTypes = { language: React.PropTypes.object }; /** * Child Element which uses context */ class ElWithContext extends React.Component{ render() { const {language} = this.context; return <p>{language.text}</p> } } ElWithContext.contextTypes = {
  • 它不是预处理我的JSX(Jest not preprocessing my JSX)
    问题 我正在按照Jest教程来测试React组件,并且遇到了我的jsx的预处理问题。 我认为错误是由于预处理造成的,错误消息不是很有帮助。 谷歌搜索显示了较早版本的react / jest的类似错误,已通过包含/** @jsx React.DOM */ docblock进行了修复,据我所知,此错误已得到修复。 当我运行测试时: Using Jest CLI v0.8.0, jasmine1 FAIL spec/MyComponent_spec.js Runtime Error SyntaxError: /Users/asdf/react/stuff-react/spec/MyComponent_spec.js: Unexpected token (13:6) npm ERR! Test failed. See above for more details. 有问题的那一行是应该呈现我的组件的那一行: jest.dontMock('../src/MyComponent'); let React = require('react'); let ReactDOM = require('react-dom'); let TestUtils = require('react-addons-test-utils'); const MyComponent = require('../src