How to mock AWS Auth.sign up/in API inside reactJs project - reactjs

I'm starting with AWS-Cognito and the reactJs app, the service is working very well.
I want to test this function using react-testing-library and Jest.
I don't know how to mock the response Promise received from Auth.signUp(email, password) API
const Handelsregister = async (event) => {
event.preventDefault();
try {
const user = await Auth.signUp(email, password);
console.log("Registred user info", user);
} catch (e) {
console.log(e)
}
}
My test file looks like this :
it('should render sign up component', async function () {
const handleRegisterSpy = jest.fn();
const user = {
email: 'test#PWDil.com',
pwd: 'SignUp#2022'
};
const {getByTestId} = render(<Authentication screen={1} setScreen={setScreenSpy()} handleRegister={handleRegisterSpy()}/>);
const email = getByTestId("email");
const passwd = getByTestId("pwd");
const signUp = getByTestId("btnSignUpField");
expect(email).toBeInTheDocument();
expect(passwd).toBeInTheDocument();
expect(signUp).toBeInTheDocument();
fireEvent.change(email, {target: {value: user.emailValue}});
fireEvent.change(passwd, {target: {value: user.pwdValue}});
expect(email).toHaveAttribute("type", "email");
expect(email.value).toEqual("test#gmail.com");
expect(passwd).toHaveAttribute("type", "password");
expect(passwd.value).toEqual("SignUp#2022");
fireEvent.click(signUp);
expect(handleRegisterSpy).toHaveBeenCalled();
});
My question is, how can I mock the Auth.SignUp behavior to test both responses
mockResolvedValue and mockRejectedValue

Related

TypeError: assert.equal is not a function

I created solidity contracts and compiled it with truffle successfully but when I run truffle test for test files of my contracts it gives the error
TypeError: assert.equal is not a function
my code
const { assert } = require('console');
const Tether = artifacts.require('Tether.sol');
const RWD = artifacts.require('RWD');
const DecentralBank = artifacts.require('DecentralBank');
require('chai')
.use(require('chai-as-promised'))
.should()
contract('DecentralBank', ([owner, customer]) => {
let tether, rwd, decentralBank;
function tokens(number) {
return web3.utils.toWei(number, 'ether')
}
before(async () => {
tether = await Tether.new()
rwd = await RWD.new()
decentralBank = await DecentralBank.new(rwd.address, tether.address)
await rwd.transfer(decentralBank.address, tokens('1000000'));
await tether.transfer(customer, tokens('100'),{from: owner});
})
describe('Tether', async () =>{
it('matches name successfully', async () => {
const name = await tether.name()
console.log(name)
assert.equal(name, 'Tether')
})
})
})
you are using the wrong assert. you do not need this
const { assert } = require('console');
You probably automatically imported by mistake when typed assert. Truffle uses mocha and assert is globally available.

Cannot add a promise implementation on jest mock function outside test block

const mockedLogin = jest.fn(() => Promise.resolve()); //does not work if implementation is done here: "cannot read then of undefined"
jest.mock("../../hooks/useAuth", () => {
return () => ({
login: mockedLogin,
});
});
test("submitting the form calls onSubmit with username and password", async () => {
mockedLogin.mockImplementation(() => Promise.resolve()); //works fine here
render(<Login />);
const username = "name";
const password = "i need no password";
await userEvent.type(screen.getByLabelText(/username/i), username);
await userEvent.type(screen.getByLabelText(/password/i), password);
await userEvent.click(screen.getByRole("button", { name: /submit/i }));
expect(mockedLogin).toHaveBeenCalledWith({
username,
password,
});
expect(mockedLogin).toHaveBeenCalledTimes(1);
});
I am trying to mock login function returned by a custom hook.
The login function returns a promise.
If I use mockImplementation inside the test block it works fine but if I use it outside of the test block mockedLogin returns undefined.
Have you tried:
const mockedLogin = jest.fn().mockResolvedValue();

React creating a mock login service with async await

I am creating a mock login button which will return a user object after 5 seconds of clicking the login button.
I have the following event handler for the login button:
import UserService from "../services/user";
export default class Login extends Component {
constructor(props) {
super(props);
this.state = {
field: {
username: "",
password: "",
},
};
}
login = async (event) => {
event.preventDefault();
const res = await UserService.login({
username: this.state.field.username,
password: this.state.field.password,
});
console.log("RESPONSE DATA", res);
// Set user variable to the response
};
And this is the user service:
let user = null;
const login = async (credentials) => {
await setTimeout(() => {
user = {
name: "test user",
username: credentials.username,
password: credentials.password,
token: "test token",
};
console.log("login service finished");
}, 5000);
return user;
};
Basically, I want the user object to appear on the console.log("RESPONSE DATA", res) part. However, what I'm getting instead is null. How do I go around on doing this properly?
==================================
EDIT:
Decided to rewrite into function components. I'm still getting the same results
const Login = () => {
const [username, setUsername] = useState("");
const [password, setPassword] = useState("");
const userContext = useContext(UserContext);
const login = async (event) => {
event.preventDefault();
console.log("logging in:", username, password);
try {
const user = await UserService.login({
username: username,
password: password,
});
console.log(user);
// userContext[1](user);
// console.log(userContext);
} catch (exception) {
console.log(exception);
}
};
The main issue here is that setTimeout return value is basically
a positive integer value which identifies the timer created by the call to setTimeout(). (which can be passed to clearTimeout() to cancel the timeout)
So in order to achive this you need to transform your function so it returns a promise. You can find some options here. In your case you could edit it slightly the answers so do something like:
let user = null;
const login = async (credentials) => {
return new Promise(resolve => setTimeout(() => {
user = {
name: "test user",
username: credentials?.username,
password: credentials?.password,
token: "test token",
};
console.log("login service finished");
return resolve(user);
}, 5000))
};

How to Perform E2E login process and test more pages

I'm using testcafe in an Electron-React app trying to integrate some basic e2e tests.
The test works, however it's not relevant.
I would like to know i can pass the login page and have extra clicks on the other pages.
App.e2e.js
import { Selector } from 'testcafe';
import { getPageTitle, getPageUrl, fixture, test, login } from './helpers';
const assertNoConsoleErrors = async browser => {
const { error } = await browser.getBrowserConsoleMessages();
await browser.expect(error).eql([]);
};
fixture`Electron Client`.page('../../app/app.html').afterEach(assertNoConsoleErrors);
test('should atempt login without credentials', async browser => {
await login({
email: 'name#name.com',
password: '123456',
browser,
});
await browser
.click('button[type=submit]')
.expect(getPageUrl())
.contains('/login');
const email = Selector('[name="email"]');
const password = Selector('[name="password"]');
await browser.expect(email.value).eql('name#name.com');
await browser.expect(password.value).eql('123456');
});
helpers.js
import { ClientFunction } from 'testcafe';
export const getPageTitle = ClientFunction(() => document.title);
export const fixture = (...args) => global.fixture(...args);
export const test = (...args) => global.test(...args);
export const getPageUrl = ClientFunction(() => window.location.href);
export const login = async ({ email, password, browser }) => {
await browser.typeText('[data-test="email"]', email);
await browser.typeText('[data-test="password"]', password);
await browser.click('button[type=submit]');
};
You can use the User Roles API to meet your requirements.
See an example below.
const loginAsTestUser = Role('../../app/app.html', async t => {
await t
.typeText('[data-test="email"]', email)
.typeText('[data-test="password"]', password)
.click('button[type=submit]');
});
fixture`Electron Client`
.page('../../app/app.html')
.beforeEach(async t => {
await t.useRole(loginAsTestUser);
});
.afterEach(assertNoConsoleErrors);
test('should atempt login without credentials', async browser => {
await browser
.click('button[type=submit]')
.expect(getPageUrl())
.contains('/login');
const email = Selector('[name="email"]');
const password = Selector('[name="password"]');
await browser.expect(email.value).eql('name#name.com');
await browser.expect(password.value).eql('123456');
});

FormData is not defined in React Jest

I am writing a unit testing code for the React project. I am trying to test one function
//function aa
export const login = (values) => async => (dispatch) => {
let bodyFormData = new FormData();
bodyFormData.append('username', values.login);
bodyFormData.append('password', values.password);
return await axios({
method: 'post',
url: url,
data: bodyFormData
}
}
//aa test
it("Login Action", async () => {
afterEach(() => {
store.clearActions();
});
const values = {
login: "aaaaa",
password: "bbbbb"
};
const expectedResult = { type: "LOGIN_PASS" };
const result = await store.dispatch(login(values));
expect(result).toEqual(expectedResult);
});
In the browser, this works ok. but when testing I get below error
ReferenceError: FormData is not defined
I tried to use this module but no luck...
https://www.npmjs.com/package/form-data
I do not want to just test axios, I need to test full function.
You will need to mock FormData within your unit test, as the FormData web API is not available in the node.js/jsdom environment.
function FormDataMock() {
this.append = jest.fn();
}
global.FormData = FormDataMock
If you wish to mock other methods within the FormData global:
const entries = jest.fn()
global.FormData = () => ({ entries })
I was also facing this issue and it turned out that testEnvironment (inside jest.config.js) was set to 'node'. Changing it to 'jsdom' resolved it.
You need to mock the FormData for same, simply add below lines in top of test file.
// #ts-ignore
global.FormData = require('react-native/Libraries/Network/FormData');

Resources