Am new to javascript and i have been trying to write tests for his code but i have not been able to,we are supposed to use jest. I have researched for long without getting a solution.
document.getElementById("signup").addEventListener("submit", function(e) {
e.preventDefault();
data = {
username: document.getElementById("username").value,
email: document.getElementById("email").value,
password: document.getElementById("password").value,
confirm_password: document.getElementById("confirmPassword").value,
};
});
signUp = (data) => {
fetch("https://diaryapi-v2.herokuapp.com/mydiary/v1/auth/register", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(data)
})
.then(res => res.json())
.then(data => {
if (data.message === "Your account was created") {
let msg = data.message;
document.getElementById("white").innerHTML = msg;
window.location.href = "/signin";
} else {
let msg = Object.values(data);
console.log(msg)
document.getElementById("white").innerHTML = msg;
}
})
.catch(error => console.error("Error:", error));
}
Your code does not have any exports so you will need to use require()
at the point in your test you want it to run.
It makes network requests and sets the window location so you will want to use Mocks Functions to verify it is working as expected without actually making network requests and setting the window location.
It performs some work asynchronously through the use of callbacks given to then()
so you will need to account for that in your test.
Jest
uses jsdom
to provide a browser-like environment within the unit tests and you can use that to set everything up before running your code with require()
.
I made a few small modifications to your code noted in the comments below:
code.js
document.getElementById("signup").addEventListener("submit", function (e) {
e.preventDefault();
// add 'const'
const data = {
username: document.getElementById("username").value,
email: document.getElementById("email").value,
password: document.getElementById("password").value,
confirm_password: document.getElementById("confirmPassword").value,
};
signUp(data); // call signUp with the data
});
// add 'const'
const signUp = (data) => {
fetch("https://diaryapi-v2.herokuapp.com/mydiary/v1/auth/register", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(data)
})
.then(res => res.json())
.then(data => {
if (data.message === "Your account was created") {
let msg = data.message;
document.getElementById("white").innerHTML = msg;
window.location.assign("/signin"); // change this to assign() so it can be mocked
} else {
let msg = Object.values(data);
console.log(msg)
document.getElementById("white").innerHTML = msg;
}
})
.catch(error => console.error("Error:", error));
}
Here is a working test for the above code that you can use as a reference:
code.test.js
describe('code', () => {
let fetchMock;
let assignMock;
beforeEach(() => {
// Jest uses jsdom as the default test environment which emulates
// a browser and provides a document object for the unit tests.
// Initialize the document body with the HTML needed for the tests
document.body.innerHTML += `
<form id="signup">
<input type="text" id="username" value="the username">
<input type="text" id="email" value="the email">
<input type="text" id="password" value="the password">
<input type="text" id="confirmPassword" value="the confirmPassword">
<input type="submit" id="submitbutton">
</form>
<div id="white"></div>
`;
// Create a mock for fetch and provide a mock implementation
// so the unit tests aren't actually making network requests
fetchMock = jest.spyOn(global, 'fetch');
fetchMock.mockImplementation(() => Promise.resolve({
json: () => Promise.resolve({ message: 'Your account was created' })
}));
// Create a mock for window.location.assign()
// so the unit tests aren't actually changing the window location
assignMock = jest.spyOn(window.location, 'assign');
assignMock.mockImplementation(() => {});
// With everything set up, require the code
require('./code');
});
afterEach(() => {
// After each test call mockRestore() to restore the original functions
fetchMock.mockRestore();
assignMock.mockRestore();
// resetModules() resets the module registry in Jest and ensures
// a fresh copy of './code' executes on require()
jest.resetModules();
});
it('should fetch data, change contents of #white, and change the page location on submit', async () => {
// Submit the form
document.getElementById('submitbutton').click();
// Check that fetch was called with the expected arguments
expect(fetchMock).toHaveBeenCalledTimes(1);
const fetchArgs = fetchMock.mock.calls[0];
expect(fetchArgs[0]).toBe('https://diaryapi-v2.herokuapp.com/mydiary/v1/auth/register');
expect(fetchArgs[1]).toEqual({
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({
username: 'the username',
email: 'the email',
password: 'the password',
confirm_password: 'the confirmPassword',
})
});
// pause synchronous execution of the test for two event loop cycles
// so the callbacks queued by the then()'s within signUp have a chance to run
await Promise.resolve().then();
// Check that window.location.assign() was called with the expected arguments
expect(assignMock).toHaveBeenCalledTimes(1);
expect(assignMock.mock.calls[0][0]).toBe('/signin');
// Check that #white was updated
expect(document.getElementById('white').innerHTML).toBe('Your account was created');
});
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With