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