Jest is a JavaScript testing framework that runs in a Node.js environment, so, if you use versions below 18, probably you need to set additional configures in the file jest.config.js because not recognized me the sentence fetch in versions below 18 to the execute the tests, otherwise is not neccesary to configure nothing.
-
Here we have all the methods of the sentence expect that i've gotten
NOTE: the .not modifier is used to negate an assertion. It allows you to test that something does not meet a specific condition. You can chain .not before any Jest matcher to invert its behavior.
expect('team').not.toMatch(/I/)
NOTE2: done is a function that jest provides to tell when the test is finished. jest not wait for the callback, so we need to use done() to tell jest that the test is finished
const asyncCallback = (cb) => { setTimeout(() => { cb(true); }, 1000); }; test('example of async with callback', (done) => { asyncCallback((result) => { expect(result).toBe(true); done(); }); });
NOTE3: the following sentence
import "@testing-library/jest-dom"imports the jest-dom library, which extends Jest's matchers with custom DOM-specific matchers. It provides additional matchers for Jest, such as:* toBeInTheDocument: Checks if an element exists in the DOM. * toHaveTextContent: Checks if an element contains specific text. * toHaveClass: Checks if an element has a specific CSS class. * toHaveAttribute: Checks if an element has a specific attribute with a given value. * toBeVisible: Checks if an element is visible in the DOM.
| Feature | Description | Example |
|---|---|---|
| .objectContaining | is used to match an object with a subset of properties | expect(response.body).toEqual(expect.objectContaining({email: successfulUser.email})); |
| .stringMatching | is used to match a string with a regular expression | expect(response.body).toEqual({ message: expect.stringMatching(/resource not found/i), stack: expect.anything(), }); expect(getImgRepositoryCell(repositoryCell)).toHaveAttribute("alt", expect.stringMatching(new RegExp(search, "i"))); |
| .anything | is used to match any value | expect(response.body).toEqual({ message: expect.stringMatching(/resource not found/i), stack: expect.anything(), }); |
| .toBe | is used to check the referential identity of object instances | expect(typeof letter).toBe('string'); expect(typeof number).toBe('number'); |
| .toEqual | compare objects or arrays and check that they have the same value. | expect(user).toEqual({...testUser, surname: undefined}); expect(letter).toEqual(expect.any( String )); |
| .toStrictEqual | to compare primitive values or to check referential identity of object instances | expect(user).not.toStrictEqual({uid: 'ABC567', username: name, surname: undefined}); expect(number).toStrictEqual(expect.any( Number )); |
| .toBeTruthy() | is a matcher used to assert if the value exists and is not null, undefined, false, 0, NaN, or an empty string. | expect(screen.getByRole("link", {name: /marvel/i}).classList.contains("active")).toBeTruthy(); |
| .toBeFalsy() | is a matcher used to assert if the value doesn't exists and is null, undefined, false, 0, NaN, or an empty string. | expect(screen.getByRole("link", {name: /marvel/i}).classList.contains("active")).toBeFalsy(); |
| .toMatch() | is a matcher used to check if a string matches a given regular expression or contains a specific substring. | expect(screen.getByRole("link", {name: /marvel/i}).getAttribute("href")).toMatch(/marvel/i); |
| .toContain | is used to check if an array or string contains a specific value. It is a simple and effective way to verify that a value exists within a collection or a substring exists within a string | expect(screen.getByRole("heading", {level: 2}).innerHTML).toContain(String(initialValue)); expect(arrayOrString).toContain(value); |
| .toMatchSnapshot | is a function that takes a snapshot of the component and compares it with the previous snapshot, if they are different, it will show an error. If we don't have a previous snapshot, it will create one | const {container} = render(<CounterApp value={initialValue} />); expect(container).toMatchSnapshot(); |
| .toHaveBeenCalled | is used to check if the function was called | let handleAddCategory = jest.fn(); expect(handleAddCategory).toHaveBeenCalled(); |
| .toHaveBeenCalledTimes | is used to check how many times the function was called | expect(handleAddCategory).toHaveBeenCalledTimes(1); |
| .toHaveBeenCalledWith | is used to check if the function was called with the value that we passed | expect(handleAddTodo).toHaveBeenCalledWith({id: expect.any(String), description: valueToChange, done: false}); |
| .not.toHaveBeenCalled | is used to check if the function was not called | expect(handleAddCategory).not.toHaveBeenCalled(); |
| .toBeGreaterThan | is used to assert that a numeric value is greater than a specified number. | const { result } = renderHook(() => useFetch(https://api.breakingbadquotes.xyz/v1/quotes/${quotes})); await waitFor(() => { expect(result.current.data.length).toBeGreaterThan(0); }) |
| .any | is a matcher that allows you to assert that a value is of a specific type or matches a specific constructor, without needing to check the exact value. | expect.any(Function) // Matches any function expect.any(String) // Matches any string expect.any(Number) // Matches any number expect.any(Object) // Matches any object expect.any(Array) // Matches any array |
| .toBeInTheDocument | check whether a specific element exists in this rendered DOM tree after the render method from @testing-library/react renders your React components into a virtual DOM. | expect(screen.getByRole("button", {name: /login/i})).toBeInTheDocument(); |
| .toHaveValue | it is used to check the value of form elements, such as , <textarea>, or other elements that have a value attribute. | expect(screen.getByRole("textbox", {name: /searchText/i})).toHaveValue("batman"); |
| .toThrow | it is used to test if a function throws an error when it is called | function compileAndroidCode(){throw new Error('you are using the wrong JDK');} expect(compileAndroidCode).toThrow(/JDK/); |
| .toHaveAttribute | is used to check if a DOM element has a specific attribute, and optionally, if that attribute has a specific value. | expect(linkProduct).toHaveAttribute("href"); expect(linkProduct.getAttribute("href")).toMatch(new RegExp(firstProductDB.slug, "i")); expect(getLinkRepositoryCell(repositoryCell)).toHaveAttribute("href", expect.stringMatching(/https://github.com//i)); |
| .toHaveTextContent | is used to match the text content of the element and all its descendants (children). | expect(starsCell).toHaveTextContent(/\d+/i) |
| .toHaveValue | is used to check if the element has the specified value through the property "value". | expect(select).toHaveValue("2"); |
| .toHaveLength | is used to check the length of the array. | expect(getTableHeaders()).toHaveLength(5); |
-
Here we have some mocks in jest
NOTE: It's generally better to define mocks outside of the describe function.
-
beforeEach: is a lifecycle method that runs a specific block of code before each test in a test suite
beforeEach(() => { //jest.clearAllMocks: clears the call history of all mocked functions. This ensures that each test starts with a clean slate and that mock calls from previous tests do not interfere with the current test. jest.clearAllMocks(); });
-
jest.fn: creates a mock function. You use it to replace a function with a mock implementation, track calls, and set return values.
const dispatch = jest.fn(); const mockStartGoogleSignIn = jest.fn(); jest.mock("../../../store/hooks", () => { const originalModule = jest.requireActual("../../../store/hooks") return { ...originalModule, // Keep other hooks intact useAppDispatch: () => dispatch, // Mock only useAppDispatch }; }); jest.mock("../../../store/auth/thunks", () => { const originalModule = jest.requireActual("../../../store/auth/thunks"); return { ...originalModule, // Keep other hooks intact startGoogleSignIn: () => mockStartGoogleSignIn, // Mock only useAppDispatch }; }); describe("Tests on LoginPage", () => { . . .
-
jest.mock (affects all the tests on your file, not recomendable to test every test in isolation): mocks an entire module. It replaces all exports from a module with mocks, allowing you to control how imported modules behave in your tests.
All the objects returned of the url mocked, automatically they are mocked with undefined values, if you want to change the value of this object, you have to use mockReturnValue or mockReturnValueOnce mockResolvedValue or even mockRejectedValue
NOTES: Always put jest.mock at the top level of your test file, before imports that use the mocked module.
- mockReturnValue
import { useFetchGifs } from "../../../src/hooks/useFetchGifs"; jest.mock('../../../src/hooks/useFetchGifs'); describe('tests on component GifGridCategory', () => { test('should show the component correctly', () => { // Use mockReturnValue for mocking sync functions or when you don't need to simulate a promise. useFetchGifs.mockReturnValue({ gifs: [], isLoading: true }); ...
- mockReturnValueOnce
test('basic mock examples of jest', () => { const firstValueFunction = true; const secondValueFunction = 'hello world'; const thirdValueFunction = 5; //this jest object is native of jest and it is used for mock a function const myMock = jest.fn() //mockReturnValueOnce is used for return a value when the function is called .mockReturnValueOnce(firstValueFunction) //the next time that the function is called, it will return the next value .mockReturnValueOnce(secondValueFunction) .mockReturnValueOnce(thirdValueFunction); //if not configure the mockReturnValueOnce, the function will return undefined const result1 = myMock(); const result2 = myMock(); const result3 = myMock(); ...
- mockResolvedValue
import { signInWithGoogle } from "../../../firebase/providers"; import { UserLogged, } from "../../fixtures/authFixtures"; jest.mock("../../../firebase/providers"); describe("tests on thunks of auth", () => { const dispatch = jest.fn(); beforeEach(() => { jest.clearAllMocks(); }) test("should call checkingCredentials and login on startGoogleSignIn thunk", async () => { // Use mockResolvedValue for mocking async functions that return promises. (signInWithGoogle as jest.Mock).mockResolvedValue(UserLogged); await startGoogleSignIn()(dispatch); expect(dispatch).toHaveBeenCalledWith(checkingCredentials()); expect(dispatch).toHaveBeenCalledWith(login(UserLogged)); }); ... ``` - **mockRejectedValue** ```javascript import { signInWithGoogle } from "../../../firebase/providers"; jest.mock("../../../firebase/providers"); describe("tests on thunks of auth", () => { const dispatch = jest.fn(); beforeEach(() => { jest.clearAllMocks(); }) test("should call checkingCredentials and logout error on startGoogleSignIn thunk", async () => { const messageError = notAuthenticatedState.message; (signInWithGoogle as jest.Mock).mockRejectedValue(new Error(messageError)); await startGoogleSignIn()(dispatch); expect(dispatch).toHaveBeenCalledWith(checkingCredentials()); expect(dispatch).toHaveBeenCalledWith(logout(messageError)); }); ... ```
- mockReturnValue
-
jest.spyOn (better when you want to test every test in isolation): creates a spy on an existing method of an object. Lets you track calls, arguments, and optionally replace the implementation.
The original method is still available and can be restored. Example: const setItemSpy = jest.spyOn(Storage.prototype, "setItem");
NOTE: Always try to put jest.spyOn after test cases that includes changing of services, because if you put this test cases that contain changing services after those test cases that includes jest.spyOn, sometimes these tests will not work.
- mockImplementation
This method allows you to replace the implementation of a function with a mock function, which can be useful for testing purposes.
const dispatch = jest.fn(); describe("......", () => { test("should add the product to the cart when clicking the 'add to cart' button", async () => { jest.spyOn(hooks, "useAppDispatch").mockImplementation(() => dispatch); const addToCartButton = within(getProductItem()).getByRole("button", { name: /add to cart/i, }); expect(addToCartButton).toBeInTheDocument(); await userEvent.click(addToCartButton); expect(dispatch).toHaveBeenCalled(); expect(dispatch).toHaveBeenCalledWith(addToCart({product, qty: 1})); }); })
- mockImplementation
This method allows you to replace the implementation of a function with a mock function, which can be useful for testing purposes.
-
Storage: is a built-in web API in JavaScript that provides access to the browser's storage mechanisms, such as localStorage and sessionStorage.
//Both localStorage and sessionStorage inherit from the Storage prototype. The Storage prototype defines methods like setItem, getItem, removeItem, and clear. Storage.prototype.setItem = jest.fn(); describe("Tests on PrivateRoute", () => { beforeEach(() => { jest.clearAllMocks(); localStorage.clear(); });