[React] - Testando um elemento DOM via Ref. #1212
Replies: 6 comments
-
Não sou um expert em testes em React, mas já chegou a ver sobre a lib react-testing-library? O criador (Kent C. Dodds) chegou a fazer um artigo falando sobre evitar shallow rendering (em inglês) pois na verdade acaba não testando realmente o que o componente faz. |
Beta Was this translation helpful? Give feedback.
-
Opa @ninetails valeu por tirar um tempo para responder aqui. A gente usa react testing mas mais para testes de integração. Esse teste ai no final testa exatamente o que o componente precisa fazer. Nesse caso não é um shallowing com snapshot, que eu concordo ser o caso que o Kent advoca contra. Minha curiosidade maior é saber se existe uma forma mais simples de testar esse comportamento dada a limitação de stack. |
Beta Was this translation helpful? Give feedback.
-
@wmsbill (meu xará de nome e sobrenome), isso aqui funciona? it('scrolls correctly', () => {
const wrapper = shallow(
<ScrollableComponent />,
);
const instance = wrapper.instance();
const stubScrollHolder = {
current: {
scrollHeight: 200,
clientHeight: 100,
scrollTop: 0,
},
};
instance.scrollHolder = stubScrollHolder; // stubs the `scrollHolder`
instance.componentDidUpdate(); // forces calling update
expect(instance.scrollHolder.current.scrollTop).toEqual(100);
}); E aqui o source que usei pra testar no browser (deixei collapsed pois ficou meio grande): import React, { Component } from 'react';
export default class ScrollableComponent extends Component {
constructor() {
super();
this.scrollHolder = React.createRef();
setTimeout(() => {
this.setState({}); // Forcing update after 1s
}, 1000);
}
componentDidUpdate() {
this.scrollToBottom();
}
scrollToBottom() {
this.scrollHolder.current.scrollTop =
this.scrollHolder.current.scrollHeight -
this.scrollHolder.current.clientHeight
;
}
render() {
return (
<div ref={this.scrollHolder} style={{
width: '300px',
margin: '0 auto',
height: '200px',
overflow: 'scroll',
}}>
<div>
Adipisicing ea id totam eum delectus Molestiae dolorem
molestias sint soluta assumenda consequuntur ducimus.
Expedita voluptates officia aut illum nobis Rem corrupti
harum cupiditate ipsa beatae. Reprehenderit ipsam error odit.
</div>
<div>
Adipisicing beatae odit eos distinctio corporis?
Doloribus corrupti libero veniam mollitia obcaecati.
Accusantium sunt quis consequatur at iusto. Impedit rem
obcaecati culpa suscipit aut Voluptas ut vero aperiam vel
laboriosam.
</div>
<div>
Adipisicing ea id totam eum delectus Molestiae dolorem
molestias sint soluta assumenda consequuntur ducimus.
Expedita voluptates officia aut illum nobis Rem corrupti
harum cupiditate ipsa beatae. Reprehenderit ipsam error odit.
</div>
<div>
Adipisicing beatae odit eos distinctio corporis?
Doloribus corrupti libero veniam mollitia obcaecati.
Accusantium sunt quis consequatur at iusto. Impedit rem
obcaecati culpa suscipit aut Voluptas ut vero aperiam vel
laboriosam.
</div>
<div>
Adipisicing ea id totam eum delectus Molestiae dolorem
molestias sint soluta assumenda consequuntur ducimus.
Expedita voluptates officia aut illum nobis Rem corrupti
harum cupiditate ipsa beatae. Reprehenderit ipsam error odit.
</div>
<div>
Adipisicing beatae odit eos distinctio corporis?
Doloribus corrupti libero veniam mollitia obcaecati.
Accusantium sunt quis consequatur at iusto. Impedit rem
obcaecati culpa suscipit aut Voluptas ut vero aperiam vel
laboriosam.
</div>
</div>
);
}
} Testei aqui e rolou no meu caso, com o seguinte setup:
|
Beta Was this translation helpful? Give feedback.
-
Legal @wmartins (a resposta e o homonimo ;) ) A sua solução não cobre o que eu quero pois shallow chama componentDidUpdate mas eu vi aqui que dá para dar skip no life cycle methods quando se faz shallow e isso junto com a sua solução deve fazer o teste ser mais fácil de ser entendido pelos outros devs. Valeu! |
Beta Was this translation helpful? Give feedback.
-
Aqui funcionou da seguinte maneira: it('should scroll to bottom on componentDidMount', () => {
const scrollHolder = {
current: {
scrollHeight: 200,
scrollTop: 0,
clientHeight: 100,
},
};
const instance = shallow(
<Component />,
{ disableLifecycleMethods: true }
).instance();
instance.scrollHolder = scrollHolder;
instance.componentDidMount();
expect(scrollHolder.current.scrollTop).toBe(100);
}); Apesar da minha primeira solução parecer semanticamente mais correta, essa é mais legível para os demais programadores que não vão precisar saber o que é um Proxy para dar manutenção nesse código e ambos testam a mesma coisa ;). Valeu cara! |
Beta Was this translation helpful? Give feedback.
-
Massa @wmsbill, tinha esquecido que o De qualquer forma, particularmente falando, eu gostei bastante da tua solução com A maior vantagem de fazer com |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
Olá povo! Tive um desafio interessante esses dias e queria compartilhar a minha solução com vocês para receber feedback. Vocês vão entender o porquê.
Contexto
Estava eu desenvolvendo um componente que deveria dar scroll para o final do conteúdo sempre que o componente fosse montado. O snippet de código poderia ser abstraido para algo assim:
A meta do teste é checar se o scrollTop no final foi attribuido o valor esperado quando o componente foi montado.
A stack de teste unitário aqui é bem comum, jest + enzyme. Aqui começa o meu perrengue.
scrollHolder
é uma propriedade de instância, eu não consiguia atribuir nenhum mock a ela antes de eu instanciar o componente.shallow(<Component />).instance()
, mas fazendo isso o métodocomponentDidMount
já vai ter sido chamado e eu não consigo atribuir o mock ao atributoscrollHolder
mais.Object.defineProperty()
parece não funcionar (salvo eu tenha feito alguma burrada homérica) por, de novo, ser um atributo de instância.Minha solução
Depois quebrar a cabeça um pouco, eu me lembrei que poderia usar proxy para criar um hook e modificar a instancia. Então a minha solução ficou mais ou menos assim:
Isso resolveu o meu problema, mas por eu não ter achado nenhuma literatura sobre esse tema, estou achando que eu estou fazendo alguma coisa muito errada. Algum React/Jest/Enzyme expert pode dar um help para ver se existe alguma solução mais simples para isso?
Beta Was this translation helpful? Give feedback.
All reactions