¿Cuándo debería usar render y shallow en las pruebas Enzyme / React?

95

Antes de publicar esta pregunta, intenté buscar en sqa stackexchange pero no encontré ninguna publicación sobre superficial y renderizado allí, así que espero que alguien pueda ayudarme aquí.

¿Cuándo debo usar shallow y render al probar los componentes de React? Según los documentos de Airbnb, he hecho algunas opiniones sobre la diferencia de los dos:

  1. Dado que superficial está probando componentes como una unidad , debe usarse para componentes 'principales'. (ej. Mesas, envoltorios, etc.)

  2. Render es para componentes secundarios.

La razón por la que hice esta pregunta es que estoy teniendo dificultades para averiguar cuál debería usar (aunque los documentos dicen que son muy similares)

Entonces, ¿cómo sé cuál usar en un escenario específico?

Cyval
fuente
2
La diferencia entre shallow () y mount () es que shallow () prueba los componentes de forma aislada de los componentes secundarios que representan, mientras que mount () profundiza y prueba los elementos secundarios de un componente. En el caso de shallow (), esto significa que si el componente principal representa otro componente que no se puede representar, se seguirá procesando una representación superficial () en el elemento principal.
Shyam Kumar

Respuestas:

160

Según los documentos de Enzyme :

mount(<Component />) para la representación de DOM completo es ideal para casos de uso en los que tiene componentes que pueden interactuar con las API de DOM, o pueden requerir el ciclo de vida completo para probar completamente el componente (es decir, componentDidMount, etc.)

vs.

shallow(<Component />) para el renderizado superficial es útil para limitarse a probar un componente como una unidad y para asegurarse de que sus pruebas no afirmen indirectamente el comportamiento de los componentes secundarios.

vs.

renderque se utiliza para representar componentes de reacción a HTML estático y analizar la estructura HTML resultante.

Todavía puede ver los "nodos" subyacentes en un renderizado poco profundo, por lo que, por ejemplo, puede hacer algo como este ejemplo (ligeramente artificial) usando AVA como el corredor de especificaciones:

let wrapper = shallow(<TagBox />);

const props = {
    toggleValue: sinon.spy()
};

test('it should render two top level nodes', t => {
    t.is(wrapper.children().length, 2);
});

test('it should safely set all props and still render two nodes', t => {
    wrapper.setProps({...props});
    t.is(wrapper.children().length, 2);
});

test('it should call toggleValue when an x class is clicked', t => {
    wrapper.setProps({...props});
    wrapper.find('.x').last().simulate('click');
    t.true(props.toggleValue.calledWith(3));
});

Tenga en cuenta que el renderizado , la configuración de accesorios y la búsqueda de selectores e incluso los eventos sintéticos son compatibles con el renderizado superficial, por lo que la mayoría de las veces puede usar eso.

Pero, no podrá obtener el ciclo de vida completo del componente, por lo que si espera que sucedan cosas en componentDidMount, debe usar mount(<Component />);

Esta prueba usa Sinon para espiar el componentecomponentDidMount

test.only('mount calls componentDidMount', t => {

    class Test extends Component {
        constructor (props) {
            super(props);
        }
        componentDidMount() {
            console.log('componentDidMount!');
        }
        render () {
            return (
                <div />
            );
        }
    };

    const componentDidMount = sinon.spy(Test.prototype, 'componentDidMount');
    const wrapper = mount(<Test />);

    t.true(componentDidMount.calledOnce);

    componentDidMount.restore();
});

Lo anterior no pasará con renderizado superficial o renderizado

render le proporcionará solo el html, por lo que aún puede hacer cosas como esta:

test.only('render works', t => {

    // insert Test component here...

    const rendered = render(<Test />);
    const len = rendered.find('div').length;
    t.is(len, 1);
});

¡espero que esto ayude!

4m1r
fuente
1
Todavía no obtengo el 100%, por qué los tres verbos traen diferentes métodos con ellos. Por ejemplo, se puede usar wrapper.getNode () en superficial pero no en render. ¿Alguna explicación / enlace / docs / blogs, que me ayude a juntar esto?
Paulquappe
@HenryZhu debe quedar claro en los documentos que el renderizado es más complicado que superficial, ya que en realidad intenta imitar el árbol DOM para ese nodo de componente en particular
AGE
11
La migración de enzimas de v2 a v3 ha activado los métodos del ciclo de vida de forma predeterminada en github.com/airbnb/enzyme/blob/master/docs/guides/…
Abhinav Singi
Una buena explicación adicional de las diferencias está aquí github.com/airbnb/enzyme/issues/465#issuecomment-227697726 y aquí github.com/airbnb/enzyme/issues/465#issuecomment-229116418
Dmitry Gonchar
9

La diferencia entre shallow () y mount () es que shallow () prueba los componentes de forma aislada de los componentes secundarios que representan, mientras que mount () profundiza y prueba los elementos secundarios de un componente.

En el caso de shallow (), esto significa que si el componente principal representa otro componente que no se puede representar, se seguirá procesando una representación superficial () en el elemento principal.

Shyam Kumar
fuente