React 尝试在 JSDom 下附加事件

React trying to attachEvents under JSDom

我正在尝试以我认为完全传统的方式测试我的 React(用于浏览器)代码:Mocha 作为测试运行器,JSDom 模拟浏览器,Enzyme 来检查结果。

我的问题是:每当我手动将焦点设置在组件上时,React 就会抛出异常。问题是 deep inside React:

 activeElement.attachEvent('onpropertychange', handlePropertyChange);

活动元素已设置,但作为 JSDom HTMLInputElement,它没有 attachEvent。我发现如果我破解文件 node_modules/jsdom/lib/jsdom/living/generated/HTMLInputElement.js 以提供名为 attachEventdetachEvent 的 class 空方法,异常就会消失。

但显然,这不是正确的解决方案。

对该函数的评论以及我在其他地方找到的一些零碎信息表明这是一个用于旧版 IE 的填充程序,根本不是 JSDom。所涉及的函数 startWatchingForValueChange 仅在未设置标志 isInputEventSupported 时调用,并且设置它需要设置另一个 canUseDOM 。强行设置这些标志中的任何一个都会导致其他问题。

输入这个问题,我想通了。

由于搭建了测试系统,我在初始化JSDom的时候,也设置了一个全局的afterEach(),每次测试后都会重置DOM的内容。这并没有直接造成问题,但确实意味着初始化的顺序必然是这样的:

  1. 反应
  2. 摩卡
  3. JSDom

所以当 React 初始化时,它环顾四周,发现没有任何工作 DOM,然后想,"Damn, I must be running on IE or something." 在那之后,一切都走下坡路了。

所以我自信地重组了它:

  1. JSDom
  2. 反应
  3. 摩卡

那...什么也没做。

然后我意识到问题是,我是这样做的:

import { JSDOM } from "jsdom";
import Enzyme from "enzyme";
import Adapter from "enzyme-adapter-react-16";

global.jsdom = initDom();
...

React 在导入时实际上是在初始化自己 — 通过导入 Enzyme!

于是我自信满满地改写成这样:

import { JSDOM } from "jsdom";
global.jsdom = initDom();

import Enzyme from "enzyme";
import Adapter from "enzyme-adapter-react-16";

那个...什么也没做。

因为 import 语句有效地提升到文件的顶部。

于是我自信满满地改写成这样:

import { JSDOM } from "jsdom";
let jsdom = new JSDOM("");
...
const Enzyme = require("enzyme");
const Adapter = require("enzyme-adapter-react-16");

然后...修复了它。