0

i have created login page,which works fine, when i created unit test for that module with jest, i am getting issue, it doesn't return promiss when login api calls, here is my code for react and jest respectively, i am not getting console for console.log("after login"); can anyone please check my code and help to resolve this issue ?

validateAll(formData, rules, message).then(async () => {


            dispatch(setLoading(true))

            console.log("before login");    
            const login = await authApi.login(app, email, password)
            console.log("after login");    

            if (login && login.error && login.error !== null) {

                dispatch(setLoading(false))
                ToastAlert({ msg: login.error.error || login.error.message, msgType: 'error' });
                dispatch(setToken(''))

            } else {
                console.log("done");
                dispatch(setToken(login.data._accessToken))
                setSuccess(true)
                dispatch(setLoading(false))
                //router.replace("/");
                ToastAlert({ msg: 'You have successfully logged in', msgType: 'success' });
            }
        }

auth

import { resolve } from "./resolve";
import * as Realm from "realm-web";
function auth() {
    const register = async (app: any, data: object) => {
        return await resolve(
            app.emailPasswordAuth.registerUser(data)
                .then((response: any) => response)
        )
    }
    const login = async (app: any, email: string, password: string) => {
        const credentials = await Realm.Credentials.emailPassword(email, password);
        return await resolve(
            app.logIn(credentials)
                .then((response: any) => response)
        )
    }
    const confirmUser = async (app: any, data: object) => {
        return await resolve(
            app.emailPasswordAuth.confirmUser(data)
                .then((response: any) => response)
        )
    }
    const logout = async (app: any) => {
        return await resolve(

            app.currentUser.logOut()
                .then((response: any) => response)
        )
    }
    return {
        register,
        login,
        confirmUser,
        logout
    }
}
const authApi = auth();
export default authApi;

unit test

test('login with correct username and password', async () => {
        const initialState = {
            email: '',
            password: '',
            error: {
                email: "",
                password: ""
            },
        };
        const mockStore = configureStore();
        let store;
        store = mockStore(initialState);
        const { getByText,getByLabelText } = render(
            <Provider store={store}>
                <Authenticate  />
            </Provider>
        );
        // fill out the form
        fireEvent.change(screen.getByLabelText('Email'), {
            target: {value: '***@gmail.com'},
        })
        fireEvent.change(screen.getByLabelText(/Parola/i), {
            target: {value: '****@123'},
        })
        const loginAwait = screen.getByText(/Authentificare/i);      
        await fireEvent.click(loginAwait)

        // wait for the error message
        const alert = await screen.findByRole('alert')
        expect(alert).toHaveTextContent(/You have successfully logged in/i)
    })
Nikul Panchal
  • 1,542
  • 3
  • 35
  • 58

1 Answers1

2

As mentioned in the comments you can't make real requests in jest. You have 2 big options to solve your issue:


  1. Option 1.1: As was mentioned in the comment (and shown in the link) you can mock your request library (in your case is not axios, is Realm.Credentials.emailPassword, but you probably also have to mock the app.logIn part) :

Just replace Realm, for example, you should add something like this to your unit test:

...
const Realm = require("realm-web");
jest.mock("realm-web")
...
test('login with correct username and password', async () => {
  Realm.Credentials.emailPassword.mockResolvedValue({token: "test-token"})
})

WARNING: As mentioned above this by itself most likely won't fix your problem since you have to also mock app.logIn (however assuming app.logIn is just calling under the hood Realm.App.logIn you might be able to mock that too by adding:

Realm.App.logIn.mockResolvedValue({user: {...})

(Realm.App might need to be Realm.App())

If Realm.Credentials.emailPassword throws an error you might need to define them first when defining jest.mock("realm-web"). So something like :

jest.mock("realm-web", () => ({
  App: (config) => {
    return {
      logIn: jest.fn()
    }
  },
  Credentials: {
    emailPassword: jest.fn()
  }
}))

or you can just mock the library at the beginning using something like:

jest.mock("realm-web", () => ({
  App: (config) => {
    return {
      logIn: (token:string) => ({user: {...}})
    }
  },
  Credentials: {
    emailPassword: (email: string, password:string) => ({token: "test-token"})
  }
}))

)

If this is not the case you need to figure how to mock that as well (is kind of hard to properly fix your issue without a working example). But assuming you are doing something like app = new Realm.App(...) you might want to check how to mock new Function() with Jest here. If you get to this, you will most likely need a hybrid solution (to mock both new Realm.App and Realm.Credentials.emailPassword)

You could also try to mock the entire module at once, at the beginning of the test file using something like:

jest.mock("realm-web", () => ({
  App: (config) => {
    return {
      logIn: (token:string) => ({user: {...}})
    }
  },
  Credentials: {
    emailPassword: (email: string, password:string) => ({token: "test-token"})
  }
}))

OBS: adjusments might be required. This is just an example. Also please be aware that this will create a mock for all the tests following the execution of this code.

Option 1.2: You could also use a similar strategy to mock your authApi (you have some examples on how to mock a default export here). Just make sure you mock the the login function from it (and if there is any other function from the api -> like confirmUser used on the same test mock that as well). This option would be easier to implement but it's really up to what you want your test to cover. Also a hybrid might be mocking the app part together with Realm.Credentials.emailPassword.


  1. Option 2: You might find an existing solution. Here are some interesting links:

github Realm mock

react native example from mogoDB page -> this won't work copy-pasted, but might serve as inspiration.


Another maybe somehow related question would be How to fake Realm Results for tests. It is not answering your question but might also help a little.

Berci
  • 2,876
  • 1
  • 18
  • 28