IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

React Discussion :

Mocker un refresh de page pour tester une fonctionnalité d'un composant


Sujet :

React

  1. #1
    Membre averti
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2022
    Messages
    21
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 24
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2022
    Messages : 21
    Par défaut Mocker un refresh de page pour tester une fonctionnalité d'un composant
    Salut tout le monde,

    Je n'arrive pas à forcer le rafraîchissement de ma page lorsque je teste mon composant.

    J'ai un composant fonctionnel en React qui lorsqu'on appuie sur un bouton rafraîchit la page.
    Voici le composant que j'ai essayé de simplifier au maximum :

    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
    import { useLocation } from "react-router-dom" ;
     
    const Component : React.FC<{ initialData? : string | undefined }> = ({ initialData = undefined }) => {
        const [someInternalData, setSomeInternalData] = useState(initialData) ;
        const [someBoolean, setSomeBoolean] = useState(false) ;
     
        const location:any = useLocation() ;
     
        useEffect(() => 
            {
                if(location.state == null){
                    console.log("première implémentation") ;
                } else {
                    const someDataFromLocation:string|undefined = location.state.someData ;
                    if(someDataFromLocation) {
                        setInternalData(someDataFromLocation) ;
                        setSomeBoolean(true) ;
                    }
                }
            }
            ,
            [setSomeInternalData]
        ) ;
     
        function refreshPage() {
            window.history.replaceState({}, document.title);
            window.location.reload();
        }
     
        return(
            <div>
               <div>
                  <button type="button" data-testid="refresh-button" onClick={refreshPage}>Refresh</button>
               </div>
               ...//J'ai besoin ici de la variable someBoolean pour décider de ce qu'il faut afficher après
            </div>
        );
    }
     
    export default Component;
    Pour tester ce composant, j'ai réalisé le test suivant dans lequel je veux appeler la méthode window.location.reload() à un moment donné :

    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
    import React from 'react';
    import { BrowserRouter as Router } from 'react-router-dom';
    import { render, screen, fireEvent, waitFor, cleanup } from '@testing-library/react';
     
    import Component from './Component';
     
    //Autre fonction de mocks pour axios et un composant enfant mais je n'en ai pas besoin pour la partie problématique de mon test, je ne pense pas que le problème vienne de là.
    jest.mock('axios');
    const mockChildComponent = jest.fn();
     
    describe('Component', () => {
      afterEach(cleanup);
     
      beforeEach(()=>{
        jest.clearAllMocks()
      })
     
      const reload = window.location.reload ;
     
      beforeAll(() => {
        Object.defineProperty(window, 'location', {
          valeur : { reload : jest.fn() }
        }) ;
      }) ;
     
      afterAll(() => {
        window.location.reload = reload ;
      }) ;
     
      test('il peut être cliqué', async () => {
        jest.spyOn(window.location, 'reload') ;
     
        render(<Router>
                <Component />
              </Router>,) ;
     
        //Je teste ensuite les différentes fonctionnalités de mon composant qui fonctionne très bien jusqu'à ce que je doive appeler window.location.reload dans mon composant.
     
        fireEvent.click(screen.getByTestId(/refresh-button/i)) ;
     
        await waitFor(() => {
          expect(window.location.reload).toHaveBeenCalledTimes(1) ; //OK mais c'est normal que cela fonctionne car je l'ai mocké
     
          //Attends qu'un élément soit visible sur la page après le rafraîchissement mais échoue parce que window.location.state n'a pas fonctionné et j'ai toujours mon ancienne page.
          expext(screen.queryByTestId(/some-test-id/i)).toBeInTheDocument() ;
     
          //Attends qu'un autre élément ne soit pas visible sur la page après le rafraîchissement mais échoue parce que window.location.state n'a pas fonctionné et 'ai toujours mon ancienne page.
          expect(screen.queryByTestId(/some-other-test-id/i)).toBeNull() ;
        }) ;
      }) ;
    }) ;
    Comme j'ai essayé de l'expliquer dans les commentaires, après avoir testé les différentes fonctionnalités de mon composant qui fonctionne bien, je teste ensuite le bouton de rafraîchissement.

    Lorsque j'arrive à la partie du test qui va utiliser window.location.reload(), le test peut continuer mais la page ne se recharge pas, les données restent les mêmes qu'au début du test et ne sont pas remises à 0.

    Savez-vous comment forcer un rafraîchissement de la page dans la méthode simulée de window.location.reload() ? Dans tous les cas si c'est faisable je suis preneur d'une solution mais est-ce que selon vous il s'agit d'une fonctionnalité inutile à tester car trop générique? Je ne vais pas rester longtemps sur ce projet et le code n'étant pas trop complexe il n'est pas commenté, on considère les noms de variables et les tests comme étant suffisants pour comprendre le code. Du coup je pensais mettre ce test dans le cas où ce bouton serait "cassé" par la suite, pour garder une trace et informé les futurs personnes qui serait amené à travailler sur le code.

    Merci d'avance si vous prenez le temps de m'aider.

  2. #2
    Membre Expert
    Avatar de gwyohm
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Octobre 2007
    Messages
    925
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Octobre 2007
    Messages : 925
    Par défaut
    Hello,

    J'ai lu en diagonale, mais déjà,
    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
    useEffect(() =>         {
                if(location.state == null){
                    console.log("première implémentation") ;
                } else {
                    const someDataFromLocation:string|undefined = location.state.someData ;
                    if(someDataFromLocation) {
                        setInternalData(someDataFromLocation) ;
                        setSomeBoolean(true) ;
                    }
                }
            }
            ,
            [setSomeInternalData] ) ;
    
    c'est bizarre ce [setSomeInternalData] non ? Ce ne serait pas plutôt [someInternalData] ? Ensuite, tu ne t'en sers pas... donc est-ce parce que s'il change, ceux que tu utilises ont forcément changé ?

  3. #3
    Membre averti
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2022
    Messages
    21
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 24
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2022
    Messages : 21
    Par défaut
    Salut,

    Merci pour ton retour,

    En effet en me relisant c'est bien someInternalData et non pas setSomeInternalData, j'avais modifié mon code pour essayer de simplifier l'explication de mon problème et c'est un petit raté .
    La variable est bien utilisée et modifiée, il y a notamment d'autres useEffect qui font des appels API et des boutons qui vont modifier d'autres variables mais je n'ai pas inclus ces parties dans le code pour plus de clarté.

    Le code et sa logique sont bons, mais je n'avais jamais mis en place de test du coup j'ai eu un peu de mal à les écrire. Il ne me reste qu'à réaliser ce test sur le refresh d'une page via window.location.reload qui, comme je l'ai dit à la fin du premier message, est peut-être inutile, mais j'aimerai tout de même essayer de le mettre en place.

    Je ne sais pas si ça peut aider mais j'utilise jestjs avec react-testing-library pour écrire mes tests.

Discussions similaires

  1. Fonction pour tester une forme
    Par ibtissamr dans le forum PL/SQL
    Réponses: 1
    Dernier message: 26/08/2008, 15h58
  2. Réponses: 6
    Dernier message: 26/05/2008, 18h13
  3. trigger pour tester une clé primaire
    Par keumlebarbare dans le forum PL/SQL
    Réponses: 3
    Dernier message: 15/04/2007, 10h29
  4. Réponses: 7
    Dernier message: 09/11/2006, 18h57
  5. [Wifi]Logiciel pour tester une connection wifi ?
    Par genoud dans le forum Autres Logiciels
    Réponses: 2
    Dernier message: 15/08/2005, 13h29

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo