1

I have a react component that uses Ionic React framework. The component has IonInput to insert the text and a form submission. I am trying to write a test that covers the state update inside the function that handles the inputtext, but could not succeed with running the test and have a code coverage of the test passing. Below is my component.

import { IonContent,
    IonHeader, 
    IonPage,
    IonTitle,
    IonToolbar,
    IonImg,
    IonItem,
    IonLabel,
    IonInput,
    IonCheckbox,
    IonButton,
    IonList,
    IonRow,
    IonCol,
    IonRouterLink,
    IonGrid,
    IonModal
} from '@ionic/react'

import ExploreContainer from '../components/ExploreContainer'
import './PasswordReset.css'
import { Storage } from '@ionic/storage'
import React, { useState } from 'react'
import Debug from '../lib/helper'
// import core service for firebase
import firebase from 'firebase/app'
// import individual services into the firebase namespace.
import 'firebase/auth'
import '../styles/global.css'
// import firebase configuration module
import PasswordResetModal from '../modals/PasswordResetModal'
import { useHistory } from 'react-router-dom'
import { Service } from 'src/libs/sdk'

const PasswordReset: React.FC = () => {
    
    /*Start Hooks*/
    const [username, setUsername] = useState('')
    const [error, setError] = useState('')
    const [showModal, setShowModal] = useState(false)
    const history = useHistory()
    /*End Hooks*/   
    Debug.getInstance()
    Debug.logDebug(true)

    const handleUsernameInput= (e: any) =>{
        setUsername(e.target.value)
    }

    const submit = async () => {
        return Service.loginControllerResetPassword({ username: username })
            .then((response) => {
                console.log(response)
                setShowModal(true)
                // Debug.logDebug('EMAIL RESET PASSWORD SENT!')
            })
            .catch((e) => {
                setError(e.message)
            })
    }

    const dismissModal = () => {
        console.log('dismiss')
        setShowModal(false)
        history.push('/login')
    }

    return (
      <IonPage>
        <IonHeader>
          <IonToolbar data-testid="password-reset">
            <IonTitle>Password Reset</IonTitle>
          </IonToolbar>
        </IonHeader>
        <IonContent data-testid="reset-button" fullscreen>
          <IonModal isOpen={showModal}>
            <PasswordResetModal />
            <IonItem>
              <IonButton slot="end" onClick={() => dismissModal()}>
                Ok
              </IonButton>
            </IonItem>
          </IonModal>
          <IonHeader collapse="condense">
            <IonToolbar>
              <IonTitle size="large" data-testid="title">
                Password Reset
              </IonTitle>
            </IonToolbar>
          </IonHeader>
          <div className="ion-text-center">
            <p className="redColor" data-testid="reset-error">
              {error}
            </p>
          </div>
          <form
            onSubmit={(e) => {
              e.preventDefault();
              submit();
            }}
          >
            <IonList>
              <IonItem>
                <IonLabel position="floating" data-testid="reset-email">
                  Email
                </IonLabel>
                <IonInput
                  data-testid="input-field"
                  name="username"
                  value="sss"

                  onIonInput={(e: any) => handleUsernameInput(e)}
                />
              </IonItem>
              <IonButton
                className="ion-margin"
                type="submit"
                expand="block"
                data-testid="password-reset-button"
              >
                Reset Password
              </IonButton>
            </IonList>
          </form>
        </IonContent>
      </IonPage>
    );
}
export default PasswordReset

to be precise, I am trying to write a test that covers the following function:

  const handleUsernameInput= (e: any) =>{
        setUsername(e.target.value)
    }

UPDATE: I tried this test:

 it("testing on-change event", async() => {
    const { getByTestId } = render(<PasswordReset />);
    const input = getByTestId("input-field");
    const button = getByTestId("password-reset-button");
    fireEvent.ionChange(input, "username@email.com");
    fireEvent.click(button);

Update2: I managed to have the test pass using this code:

test("check email inserted and reset button clicked", async () => {
    const {  findByTitle, findByText } = render(<PasswordReset />);
    const input = await findByTitle("Email");
    const button = await findByText("Reset Password");
    fireEvent.ionChange(input, EMAIL_ADDRESS);
    fireEvent.click(button);
  });

Now form submission is not passing. Anyone can suggest a similar approach that would work for submit?

any help or suggestions on how I can write a code coverage test to cover the state update inside my function?

Thank you

Ahmed J.
  • 484
  • 6
  • 11

1 Answers1

1

Unlike class components, actually changing the value is the only way to add that line to the coverage.

There is a tech blog post on testing ionic components.

https://ionicframework.com/blog/testing-ionic-react-apps-with-jest-and-react-testing-library/

Basically, you do

import { ionFireEvent as fireEvent } from '@ionic/react-test-utils';

const input = /*that exact target you wish to test input */
fireEvent.ionChange(input, 'test todo');

--EDIT--

It seems like you set value of IonInput as "aaa".

Should it not be username ?

promet99
  • 494
  • 2
  • 10