test shallow react node.js testing reactjs jsdom reactjs-testutils

node.js - shallow - Llamar a setState en pruebas basadas en jsdom que causan el error "No se puede representar el marcado en un subproceso de trabajo"



react-test-renderer (4)

En el momento de la carga, React determina si puede usar DOM y lo almacena como un valor booleano.

var canUseDOM = !!( typeof window !== ''undefined'' && window.document && window.document.createElement ); ExecutionEnvironment.canUseDOM = canUseDOM;

Esto significa que si se carga antes de que se cumplan esas condiciones, se supone que no puede usar DOM.

Podrías parchearlo en tu antes de cada uno.

require(''fbjs/lib/ExecutionEnvironment'').canUseDOM = true

O podrías fingirlo al principio:

global.window = {}; global.window.document = {createElement: function(){}};

O asegúrese de no cargar React antes de configurar JSDOM, que es la única manera en que estoy seguro, pero también es la más difícil y propensa a errores.

O puede informar de esto como un problema, o inspeccionar la fuente de jest y ver cómo se resuelve.

Estoy probando mis componentes React bajo jsdom usando mi propia pequeña utilidad de "navegador virtual". Funciona bien, hasta que estoy tratando de establecer setState . Por ejemplo, al probar un control de entrada de edades de niños:

describe(''rendering according to the draft value'', function () { var component; beforeEach(function () { component = TestUtils.renderIntoDocument( React.createElement(ChildrenInput, {value: []}) ); component.setState({draft: [{age: null}, {age: null}]}, done); }); it(''overrides the value property for the count'', function () { assert.strictEqual(component.refs.count.props.value, 2); }); it(''overrides the value property for the ages'', function () { assert.strictEqual(component.refs.age1.props.value, null); }); });

... en la línea setState estoy recibiendo:

Error no detectado: Infracción invariante: dangerouslyRenderMarkup (...): no se puede representar el marcado en un subproceso de trabajo. Asegúrese de que la window y el document estén disponibles en todo el mundo antes de solicitar React al realizar la prueba de unidad o use React.renderToString para la representación del servidor.

Sé que las window y document globales están de hecho establecidos por el TestBrowser basado en TestBrowser , así:

global.document = jsdom.jsdom(''<html><body></body></html>'', jsdom.level(1, ''core'')); global.window = global.document.parentWindow;

Incluso intenté envolver setState en un setTimeout(..., 0) . No ayuda ¿Cómo puedo hacer que los cambios de estado de prueba funcionen?



Si usa Mocha y Babel, necesitará configurar jsdom antes de que los compiladores evalúen el código React.

// setup-jsdom.js var jsdom = require("jsdom"); // Setup the jsdom environment // @see https://github.com/facebook/react/issues/5046 global.document = jsdom.jsdom(''<!doctype html><html><body></body></html>''); global.window = document.defaultView; global.navigator = global.window.navigator;

Con el --require arg:

$ mocha --compilers js:babel/register --require ./test/setup-jsdom.js test/*.js

Consulte https://github.com/facebook/react/issues/5046#issuecomment-146222515

Source


También tengo este error usando Babel para probar el código ES6. El punto es que hay una diferencia entre import React from ''react'' y const React = require(''react'') . Si está usando la sintaxis de import , entonces todas sus importaciones se harían antes que cualquier otra cosa, por lo que no puede simular una window o document antes.

Así que el primer bit es reemplazar la import por la require en las pruebas (donde sea importante)

El segundo bit es global.navigator utilizando global.navigator = global.window.navigator .

Espero que ayude a alguien.