I do have two Jest Test Cases which seem to fail but I dont know what is wrong. It is about Post functions and somehow it doesnt recognize it and gets the error on fetch.
Any ideas appreciated.
This is what the test outcome says:
● Testing if UI updates correctly › Testing 'updateUI' function...
TypeError: Cannot read property 'weather' of undefined
3 | console.log('all data returned is:')
4 | console.log(data)
> 5 | const precip = Math.round(data.weather.precip * 10) / 10
| ^
6 | const postHolder = document.getElementById('all-posts')
7 | const newDiv = document.createElement('div');
8 | newDiv.classList.add('entry-holder');
at updateUI (src/client/js/updateUI.js:5:36)
at Object.<anonymous> (__test__/testUpdateUI.test.js:10:12)
FAIL __test__/testPostData.test.js
● Testing the posting of the data › Test 'postInput' function to make a successful post
ReferenceError: fetch is not defined
1 | // POST input data to server
> 2 | const postInput = async (url = '', data = {}) => {
| ^
3 | const response = await fetch(url, {
4 | method: 'POST',
5 | credentials: 'same-origin',
at _callee$ (src/client/js/postData.js:2:19)
at tryCatch (src/client/js/postData.js:10:2404)
at Generator._invoke (src/client/js/postData.js:10:1964)
at Generator.next (src/client/js/postData.js:10:3255)
at asyncGeneratorStep (src/client/js/postData.js:12:103)
at _next (src/client/js/postData.js:14:194)
at src/client/js/postData.js:14:364
at src/client/js/postData.js:14:97
at postInput (src/client/js/postData.js:2:16)
at _callee$ (__test__/testPostData.test.js:13:11)
at tryCatch (__test__/testPostData.test.js:15:2404)
at Generator._invoke (__test__/testPostData.test.js:15:1964)
at Generator.next (__test__/testPostData.test.js:15:3255)
at asyncGeneratorStep (__test__/testPostData.test.js:17:103)
at _next (__test__/testPostData.test.js:19:194)
at __test__/testPostData.test.js:19:364
at Object.<anonymous> (__test__/testPostData.test.js:19:97)
And these are the functions:
// POST input data to server
const postInput = async (url = '', data = {}) => {
const response = await fetch(url, {
method: 'POST',
credentials: 'same-origin',
headers: { 'Content-Type': 'application/json', },
body: JSON.stringify(data),
})
try {
const newData = await response.json();
console.log('newData in postInput function is:')
console.log(newData)
Client.updateUI(newData)
} catch (error) {
console.log('ERROR in POST:', error);
}
}
export { postInput }
And the second one
// Fetches gathered data from server & updates UI with it
function updateUI(data) {
console.log('all data returned is:')
console.log(data)
const precip = Math.round(data.weather.precip * 10) / 10
const postHolder = document.getElementById('all-posts')
const newDiv = document.createElement('div');
newDiv.classList.add('entry-holder');
newDiv.innerHTML =`
<img src="${data.pix.webformatURL}" alt="destination">
<div class="stat-holder">
<div class="wait-time"><i>${data.geo.name}, ${Client.checkCountry(data.geo)} is ${Client.dateDiff()} days away.</i></div>
<h3>Typical weather for then is:</h3>
<div class="temp">High: ${data.weather.max_temp}°C, Low: ${data.weather.min_temp}°C</div>
<div class="precip">With a chance for ${precip}mm of precipitation</div>
</div>
`;
postHolder.appendChild(newDiv);
}
export { updateUI }
Late answer, but perhaps helps someone passing by this question.
By default, jest runs tests in Node environment. Therefore, depending on your packages and configuration, fetch may not be available in your tests.
Therefore, the solution is to add fetch in the test environment.
Write a mock function in a module, say mock-fetch.ts, as follows.
export function mockFetch(data: any) {
return jest.fn().mockImplementation(() =>
Promise.resolve({
ok: true,
json: () => data,
}),
);
}
Then in your test file, you could use it to mock fetch as follows.
import { mockFetch } from './mock-fetch';
test('postInput()', async () => {
window.fetch = mockFetch(someJson);
// ... your postInput or component render here
const result = await postInput();
// Assert your expectations
expect(result).toEqual(someJson);
});
In this approch, you could mock fetch only where necessary. On the other hand, the mock implementation might grow complex if you want to test scenarios like network error or response not ok.
Use a library like cross-fetch while running tests.
This approach is as follows:
cross-fetch as a dev dependency.npm i --save-dev cross-fetch
jest.setup.js|ts.import 'cross-fetch/polyfill';
jest.config.js.module.exports = {
testEnvironment: 'jsdom',
injectGlobals: true,
setupFilesAfterEnv: ['<rootDir>/jest.setup.ts'],
moduleNameMapper: {
'\\.(css|less|scss)$': 'identity-obj-proxy',
'^@/(.*)$': '<rootDir>/src/$1',
},
};
In this approach, you could use msw to mock API communication as recommended by testing-library.
axios for the entire appUse axios instead of fetch in the app.
Then mock the axios module using Jest in the test cases.
import axios from 'axios';
jest.mock('axios');
test('postInput()', async () => {
const resp = {data: someJson};
axios.get.mockImplementation(() => Promise.resolve(resp));
// ... your postInput or component render here
const result = await postInput();
// Assert your expectations
expect(result).toEqual(someJson);
});
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