React Testing

https://youtube.com/playlist?list=PL0Zuz27SZ-6NTWVG8eM7Dt43vvzulnIbK&si=O2C2WCCd4LKX5ht1

https://github.com/mukeshphulwani66/react-testing-library-course

https://youtu.be/pV9Dl4XUWug?si=HzxuLXj0F1DFYgT_

3type of Testing

  • unit -> test case for single component --> react testing library(jest)

  • integrated -> interlinked test case for more than single component -->

  • end to end ->full application testing --> cypress, selenium(browser)

test(<description>,()=>{})
it(<description>,()=>{})
import React from 'react';
import { render, screen } from '@testing-library/react';
import App from './App'; // Replace with the path to your component

//render --> test case for which component
//screen --> fetch element from the specified component in render
//expect --> check whether the element is present in toBeInTheDocument()
//getByText --> 'learn react' bring element with this text 

test('check link', () => {
  render(<App />); 
  const linkElement = screen.getByText(/learn react/i); // Matches text case-insensitively
  expect(linkElement).toBeInTheDocument();
});
// getByRole('button',{name:'test button',exact:false}) 
// 'button' -->element
//  name --> text inside the button element
// exact:false --> case Insensitive of the text inside the button specified

test('check button', () => {
  render(<App />); 
  const ButtonElement = screen.getByRole('button',{name:'test button',exact:false}); // Matches text case-insensitively
  expect(ButtonElement).toBeInTheDocument();
});
npm test
// if you dont know the role of each element,then you acn find it by -->logRoles
<div data-testid="myrootdiv">


</div>

import { render, screen, logRoles } from '@testing-library/react';
test('check button', () => {
  render(<App />); 
  logRoles(screen.getByTestId(myrootdiv))
});

find element in 3 ways

  • getBy --> if element is not present then --> throw error and test case will fail

  • querryBy -->if element is not present then --> throw null and test case will pass

  • findBy --> if element is not present then --> throw error and test case will fail , but it is used for async

// querryByRole('button',{name:'test button',exact:false}) 
// 'button' -->element
//  name --> text inside the button element
//  exact:false --> case Insensitive of the text inside the button specified
//  not --> check element is not present in document

<div data-testid="myrootdiv">
 // <button>test button</button>
</div>

test('check button', () => {
  render(<App />); 
  const ButtonElement = screen.querryByRole('button',{name:'test button',exact:false}); // Matches text case-insensitively
  expect(ButtonElement).not.toBeInTheDocument();
  // expect(ButtonElement).toBeNull()
});

TDD --> test driven development --> 1st test is written then the code

import {render,screen, fireEvent} from '@testing-library/react'
import CommentForm from '../components/CommentForm';
import userEvent  from '@testing-library/user-event'

test('Initial Conditions',()=>{
    // to check whether input and checkbox is present in document, button is also disabled in CommentForm component 
    render(<CommentForm />)
    const commentInput = screen.getByRole("textbox")
    expect(commentInput).toBeInTheDocument()
    const checkbox = screen.getByLabelText('i agree to terms and conditions',{exact:false})
    expect(checkbox).toBeInTheDocument()
    const submitButton = screen.getByRole("button",{name:'comment',exact:false})
    expect(submitButton).toBeDisabled()
})

test('Enable submit button on type and checkbox click',async ()=>{
    // to minic user interaction in CommentForm component-->
    // if commentInput has value written by user and checkbox is checked --> then only enable the button

    render(<CommentForm />)
    const checkbox = screen.getByLabelText('i agree to terms and conditions',{exact:false})
    const submitButton = screen.getByRole("button",{name:'comment',exact:false})
    const commentInput = screen.getByPlaceholderText('write your comment here',{exact:false})

    //fireEvent.change(commentInput,{target:{value:"something"}})
    //fireEvent.click(checkbox)
    //expect(submitButton).toBeEnabled()

    await userEvent.type(commentInput,"something")
    await userEvent.click(checkbox)
    expect(submitButton).toBeEnabled()

    //fireEvent.click(click)
    //expect(submitButton).toBeDisabled()

    await userEvent.click(checkbox)
    expect(submitButton).toBeDisabled()
})
import React,{useState} from 'react'

const CommentForm = ({setComments}) => {
  const [text,setText] = useState("")
  const [checked,setChecked] = useState(false)

  // const addComments = ()=>{
  //   setComments((prev)=>[...prev,{id:Date.now(),text:text}])
  //   setText("")
  // }

  const postComment = async ()=>{
    const res =  await fetch('http://localhost:5000/addcomment',{
       method:"post",
       headers:{
         'Content-Type':"application/json"
       },
       body:JSON.stringify({
         text:text
       })
     })
       const result =  await res.json()
      setComments((prev)=>[...prev,result])
      setText("")
  }

  return (
    <div>
          <h2>comment form</h2>
          <input 
            placeholder="write your comment here"
            value={text} 
            onChange={e => setText(e.target.value)}
          />
          <input 
            type="checkbox"
            id="checkbox"
            defaultChecked={checked}
            onChange={()=> setChecked(!checked)}
          />  
          <label htmlFor="checkbox">    
            I agree to terms and conditions
          </label>
         <button 
          disabled={!checked || !text} 
          onClick={postComment}
         >
           comment
         </button>
    </div>
  )
}

export default CommentForm
import {render,screen, fireEvent} from '@testing-library/react'
import CommetList from '../components/CommetList';


test('commnets are not available',()=>{
    // if comments are not available then ---> show h2 tag ->no comments
    render(<CommetList allcomments={[]} />)
    const h2Element = screen.getByText('no comments',{exact:false})
    expect(h2Element).toBeInTheDocument()
})

test('List all comments',()=>{
     // if comments are available then ---> show comment in list and h2 tag should not be present
    const comments =  [
            {id:1,text:"Comment 1"},
            {id:2,text:"Comment 2"},
        ]
    render(<CommetList allcomments={comments} />)
    const h2Element = screen.queryByText('no comments',{exact:false})
    expect(h2Element).not.toBeInTheDocument()

    const commentLi = screen.getAllByRole('listitem')
    expect(commentLi.length).toBe(comments.length)

})
import React from 'react'

const CommetList = ({allcomments}) => {
    if(allcomments.length == 0){
        return <h6>No Comments</h6>
    }  

    return (
      <div>
        <ul>
            {
             allcomments.map(item=>{
                 return <li key={item.id}>{item.text}</li>
             })
            }
        </ul>

      </div>
    )
}

export default CommetList

integration testing

import {render,screen, waitFor} from '@testing-library/react'
import userEvent  from '@testing-library/user-event'
import App from '../App'

test('Comment gets displayed after submitting',async ()=>{
    render(<App />)
    const checkbox = screen.getByLabelText('i agree to terms and conditions',{exact:false})
    const submitButton = screen.getByRole("button",{name:'comment',exact:false})
    const commentInput = screen.getByPlaceholderText('write your comment here',{exact:false})

    await userEvent.type(commentInput,'nice pic dear')
    await userEvent.click(checkbox)
    await userEvent.click(submitButton)

  //  const commentLi = screen.getByText('nice pic dear',{exact:false})
   const commentLi = await screen.findByText('nice pic dear',{exact:false})
    expect(commentLi).toBeInTheDocument()
})

test('2 Comment gets displayed after submitting',async ()=>{
    render(<App />)

    const checkbox = screen.getByLabelText('i agree to terms and conditions',{exact:false})
    const submitButton = screen.getByRole("button",{name:'comment',exact:false})
    const commentInput = screen.getByPlaceholderText('write your comment here',{exact:false})

    await userEvent.type(commentInput,'nice pic dear')
    await userEvent.click(checkbox)
    await userEvent.click(submitButton)

    await userEvent.clear(commentInput)

    await userEvent.type(commentInput,'awesome')
    await userEvent.click(submitButton)


    // check async code comming from api
    await waitFor(()=>{
        const commentLi = screen.getAllByRole('listitem')
        expect(commentLi.length).toBe(2)
    })

    // to debug to test case
    screen.debug()


})
npm i msw # for moking api server