Bonjour tout le monde,
Je développe une application en React et pour la première fois j'ai décidé de mettre en place des tests. J'ai commencé par les composants les plus simples, avec lesquels j'ai tout de même eu des problèmes, mais maintenant je voudrais tester des composants plus complexes, notamment avec des appels d'API via Axios.
Mon application ressemble à ceci:
Mon test ressemble à ceci:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55 import * as React from "react"; import Axios from "axios"; import { AnyData } from "../../interface/AnyDataInterface"; interface IProps { } interface IState { loading: boolean | undefined, myData: AnyData | undefined } export default class Home extends React.Component <IProps, IState> { constructor (props: IProps){ super(props); this.state = { loading: true, myData: { field: undefined, ... } }; } fetchData = ():void => { this.setState({ loading: true }); Axios.get<AnyData>('my-url') .then(res => { if (res.status === 200 && res != null) { this.setState({ myData:{... res.data} }); this.setState({ loading: false }); } else { console.log('problem when fetching the logs from backend'); } }) .catch(error => { console.log(error); }); } render():JSX.Element { return( <div className="container"> <div> <button role="button" onClick={this.fetchData}>Search</button> </div> {this.state.loading == true ? <p>Wait</p>: <div role="composite"> { Some child component that will render data } </div> } </div> ); } }
Lorsque j'ai écrit ce test, il a échoué à chaque fois, mais le problème ne venait pas de mon test, mais de ma fonction de récupération des données. Dans le .then, j'avais une condition qui était la suivante : if (res.status === 200 && res != null) { et le res.status === 200 était une condition jamais satisfaite.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32 import axios from 'axios'; import React from 'react'; import { render, screen, fireEvent, waitFor } from '@testing-library/react'; import Home from './Home'; jest.mock('axios'); describe('Home component', () => { test('it can be clicked', async () => { const fakeData = [{ some_field: some_data, ... }]; axios.get = jest.fn().mockResolvedValue(() => Promise.resolve({data: fakeData})); render(<Home />); fireEvent.click(screen.getByRole('button')); await waitFor(() => { expect(axios.get).toBeCalledWith("my-url"); }); await waitFor(() => { //Les deux expect devraient passer, si le titre est là, les données devraient également apparaître. expect(screen.getByText('some title text')).toBeInTheDocument(); //Passe sans erreur expect(screen.getByText('the data from fakeData that should be there')).toBeInTheDocument(); //M'envoie une erreur parce que jest est incapable de trouver some_data }); }); });
J'ai donc supprimé cette condition et l'appel se déroule normalement. Mais j'ai dû changer une partie de mon code qui n'est normalement pas problématique, y a-t-il un moyen de simuler le statut de la réponse aussi ? Pour que je puisse remettre cette condition dans ma fonction.
J'ai un autre problème qui apparaît maintenant, dans mon test mon composant affiche bien les informations "après le clique" mais chaque champ qui apparaît a ses données correspondantes vides, les données semblent ne pas passer bien alors que le .then passe et ne m'envoie pas dans le .catch.
Ce qui me semble étrange, c'est qu'en supprimant la condition res.status === 200 dans ma fonction de récupération des données et en laissant la condition res != null, le test passe toujours (avec le même problème de données vides). Enfin, en ajoutant un console.log("data : ", res); dans mon .then dans ma fonction de récupération de données de mon composant j'obtiens, lorsque le test est exécuté, le log suivant : data : [Fonction (anonyme)].
Je ne sais pas si cela peut expliquer ce comportement mais mon test est en javascript alors que mes classes et fonctions sont en Typescript. Mais les données que je remplis dans mon test ont la bonne forme (la même que le type demandé dans ma classe) donc Typescript devrait voir que le type correspond et n'avoir aucun problème particulier
Si quelqu'un sait comment répondre à l'une ou l'autre de ces questions, cela m'aiderait vraiment, je galère sur ce test depuis un moment et cela commence à me rendre fou.
Je viens de réaliser que dans fetchData() de mon composant, j'essaie d'accéder à res.data mais la fakeData que j'envoie dans mon test est sous la forme fakeData = [{...}]. Cela pourrait-il être la raison pour laquelle mon objet est vide ?
J'ai essayé de changer ces fausses données dans mon test en : fakeData = [{ data : { ...}}] mais j'ai toujours le même problème de réponse vide lorsque j'appelle la méthode get de Axios.
J'ai essayé de changer le fichier de test en un fichier .tsx et j'ai changé ma "fakeData" dans mon test en :
Mais même avec cette méthode, ça ne fonctionne toujours pas, pourtant j'ai vraiment l'impression que le problème vient du formatage des données que j'envoie et je ne vois pas en quoi mes données diffèrent de celles demandées dans fetchData(). Quant aux champs de mes données, je suis sûr qu'ils sont bons, donc je suppose que le problème vient de la lecture de res.data dans mon composant.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45 jest.mock('axios'); describe('Home component', () => { test('it can be clicked', async () => { const fakeData: AnyData = { "some_field": some_data, ... }; const fakeConfig: AxiosRequestConfig<any> = { "maxBodyLength": -1 }; const fakeHeaders: AxiosResponseHeaders= { "access-control-allow-credentials": "true", "access-control-allow-headers": "*", "access-control-allow-methods": "*", "access-control-allow-origin": "some-url", "access-control-expose-headers": "scrollId",= "content-type": "application/json; charset=utf-8", .... "x-powered-by": "Express" } const res: AxiosResponse<AnyData, any> = { config: fakeConfig, data: fakeData, headers: fakeHeaders, status: 200, statusText: "OK", }; axios.get = jest.fn().mockResolvedValue(() => Promise.resolve({res: res})); render(<Home />); fireEvent.click(screen.getByRole('button')); await waitFor(() => { expect(axios.get).toBeCalledWith("my-url"); }); ... }); });
Lorsque je fais le nouveau test en mettant un console.log de myData dans fetchData() j'obtiens les données suivantes : { some_field : undefined, ... }
Merci d'avance si vous prenez le temps de m'aider.
Partager