Mocking hook firestore data in cypress - reactjs

I have hook which downloads data from firestore and I am trying to mock this data in cypress tests. I am trying to do it with cy.intercept() but is not working as cypress still takes data from firestore instead of taking in it from todos.json(). Can it be fixed or maybe I should take different approach to actually try mock hook. If so - how can it be done?
describe("Todo actions", () => {
beforeEach(() => {
cy.visit("localhost:3000");
});
it("filtering by name", () => {
cy.intercept(
"GET",
"https://firestore.googleapis.com/google.firestore.v1.Firestore/Listen/channel?gsessionid=Jxzmhr-WFyT0LyY1M3YlRf__I7Mjuh0z3h-hTaCRr0E&VER=8&database=projects%2Ftodos-d2fcf%2Fdatabases%2F(default)&RID=rpc&SID=ZNjOxc2aZe3ayyf87HY8IA&CI=0&AID=0&TYPE=xmlhttp&zx=iq073faeg7z7&t=1",
{ fixture: "todos.json" }
);
});
});

Related

Testing a component in Next.js with testing-library that relies on tRCP

I was experimenting with tRCP and diligently followed the setup for my Next.js project described in the official docs over here: https://trpc.io/docs/nextjs
However I noticed that a simple component that relies on tRPC such as this
export const Sample = () => {
const { data } = trpc.useQuery(['hello', { text: 'User' }]);
if (data === undefined) {
return <div>Loading...</div>;
}
return <div>{data.greeting}</div>;
};
cannot be properly tested since the following trivial test
describe('Sample', () => {
it('should render successfully', () => {
const { baseElement } = render(<Sample />);
expect(baseElement).toBeTruthy();
});
});
since there is no setup of provider such as the setup with the withTRCP HOC used for the application itself. As such the test fails claiming client (presumably the trcpClient, unlike the queryClient) is undefined.
I'd like to know how to setup the test correctly, in this case providing a correct client, as well as mocking the queries, since I don't have the respective server-side code running while invoking the tests.
Since you are getting undefined for the trpc client implementation, you can try spying on the query call.
import trpc from 'utils/trpc'; // This is the client implementation
describe('Sample', () => {
it('should render successfully', () => {
jest.spyOn(trpc, 'useQuery')
.mockReturnValue({ greeting: "Greeting" });
const { baseElement } = render(<Sample />);
expect(baseElement).toBeTruthy();
});
});
This is also possible with the mutations but you need to provide a mock implementation for the useMutation response for mutate property.

Mock fetched data with react-testing-library - still in loading state

Using react hooks I am fetching some data on component mount. I set loading in state.
const fetchData = () => {
setIsLoading(true);
fetch(url)
.then(response => response.json())
.then(data => {
setData([data?.data]);
setIsLoading(false);
})
.catch(error => {
setIsLoading(false);
console.error(error);
});
};
useEffect(() => {
fetchData();
}, []);
I want to test a component with a data fetched. Here's what I tried:
const expectedResponse = {
data: [{ id: 'id', name: 'name' }],
};
(fetch as jest.MockedFunction<typeof fetch>).mockResolvedValueOnce(
new Response(JSON.stringify(expectedResponse)),
);
Also with fetch-mock:
import fetchMock from 'fetch-mock';
fetchMock.restore().get(ENDPOINT, {
data: [
{ id: 'id', name: 'name' },
],
});
in both cases data is not fetched. When I check the component's snapshot I see the Loader indicator. Looks like it is never loaded?
Any advices?
You should provide as much code as possible, and ideally a working example for future questions as this helps us understand better what you are trying to solve.
I don´t have any context of the test, but I assume you can be checking the snapshot synchronously, and the Promise is not being resolved before the check. You can use any of the async methods that Testing Library provides.
The async methods do polling and try to execute the queries several times until it reaches a timeout (that you can set in the Testing Library config), and if you want to know what happens after every execution, you can wrap some function inside a waitFor call:
test('an async example', async () => {
renderXXX();
await waitFor(() => {
screen.logTestingPlaygroundURL();
expect(screen.queryByTest('just an example').toBeInTheDocument();
});
});
If it also helps, here is another tip that might help as well, regarding how to mock API requests:
Mocking react custom hook

Using Jest Mock API Calls to SetState

I have an API call which runs whenever a certain component mounts. If this API call is successful the response data is used to update the state of one of my React Hooks.
The issue I am having is either related to asynchronicity or a poorly formatted mock API call, but no matter what I try I cannot get this test to work.
Here is a simplified version of the API:
const getOrg =() => {
axios.get(URL, config)
.then(response => response.data)
.then(data => {
setOrgTitle(data.name)
}
}
Basically the API is triggered and my setOrgTitle hook is updated from the response.
const [orgTitle, setOrgTitle] = useState("");
Now in my return statement I am displaying the value of orgTitle:
<h1 className={styles.titleText} id="document-folders-h1">
{orgTitle} Folders
</h1>
Alright, so the component is pretty simple. When I am trying to test things my two ideas were to either set the initial orgTitle hook state in my test or to mock the API. After some research I decided mocking the API was the way to go.
So I have a mockAxios component:
const mockAxios = {
get: jest.fn(() => Promise.resolve({ data: {} }))
};
module.exports = mockAxios;
And my test file:
import mockAxios from "../../mockTests/DocumentFoldersMock";
it("fetches results for getAdminOrg", () => {
axios.get.mockImplementation(() =>
Promise.resolve({ data: { name: "GETtest" } })
);
const wrapper = mount(
<AppProviders>
<DocumentFolders />
</AppProviders>
);
const orgTitle = wrapper.find("#document-folders-h1");
expect(orgTitle.text()).toContain("GETtest Folders");
});
I am mocking the response data, however I am not sure how to run the setOrgTitle function which is called in the .then of my actual axios call. How can I do this from my mock axios call using my mock response?
The result of the Jest test says expected("GETtest Folders") received(" Folders") so I am pretty sure that I am either having an issue with asynchronicity or an issue calling the hook update.

integration tests - redux/react + nock.js

I have no clue how to find a way to write this integration test.
I am using enzyme for mocking react components, jest for testing and nock for mocking axios api calls.
So far I created test which simulate clicking on button and I would like to mock the api call.
In the internet there is no much help.
My test:
it('Should invoke clear action and clear the group', (done) => {
// GIVEN
const clearButtonComponent = wrapper.find('[id="123"]');
nock('http://localhost:8080')
.intercept('/path/api/brum/123/group', 'DELETE')
.reply(200, {
status: 200,
message: 'cleared',
});
const service = new myService();
// WHEN
clearButtonComponent.first().simulate('click');
const result = Promise.resolve(service.clearGroup(123));
// THEN
expect(result).toEqual({ x: 'x' }); // I know it's not what I expect
wrapper.update();
done();
});
async action redux:
export const clearGroup = id=> (dispatch, getState) => {
myService.clearGroup(id)
.then(() => {
return dispatch(getGroup(id))
});
};
method in myService:
clearGroup(id) {
return this._delete(`/${id}/group`);
}
of course path is more complex but my service extends base service which has this base url.
Can anybody tell me how to mock it to let code goes further?
It still complain that id is undefined - look like nock does not mock it.
I would drop nock (I try to only use it for testing clients these days) and mock myService with jest.
I don't use axios, so haven't used this, but it might do the trick.. https://github.com/knee-cola/jest-mock-axios.
Otherwise you could look at writing your own mock.. https://jestjs.io/docs/en/es6-class-mocks

Manual mocks with Jest -- I'm not understanding something

I'm learning jest, and trying to do a manual mock for an api, I'm missing something.
I'm mocking an api call to giphy. I'm seeing a lot of different syntaxes for the manual mocks, and unfortunately, they're not making much sense to me right now. I've been trying to code along with https://hackernoon.com/api-testing-with-jest-d1ab74005c0a and https://facebook.github.io/jest/docs/en/tutorial-async.html, but I'm stuck.
I have a component called GifListContainer that displays 3 gifs, there's search functionality, I just want a manual mock with fake data to learn.
I'm using create-react-app, I see a lot of people using isomorphic-fetch and other packages, but since jest is built in can't I do it without adding anything else?
I can't figure out how to manually write the mock, I feel I'm missing something simple. It's testing fine if I don't use the mock (using different testing syntax because I'm not testing the _ mock _ file). Thank you for your time.
The error I'm getting:
● should load gifs
TypeError: GifContainer.api is not a function
at Object.<anonymous>.it (src/Part_2/GifContainer.test.js:10:23)
✕ should load gifs (6ms)
GifListContainer.js
import {gifApi} from './api'
class GifListContainer extends Component {
state = {
gifs: []
};
componentDidMount() {
this.displayGifs('coding');
}
displayGifs = (query) => {
gifApi(query)
.then(res => res.json())
.then(json => {
let firstThreeGifs = json.data.slice(0, 3);
let urls = firstThreeGifs.map(
gif => gif.images.original.url.split("?")[0]
);
this.setState({
gifs: [...urls]
});
});
};
//after this there's a search function and the render and such.
api.js
const urlPartOne = "http://api.giphy.com/v1/gifs/search?q="
const urlPartTwo = "&api_key=UE0dCN2WofIwVF0RPbpHo0Lz0k9VhqdG"
const gifApi = (query) => {
return fetch(urlPartOne + query + urlPartTwo)
}
export {gifApi}
GifContainer.test.js
import React from 'react'
let mockFunction = jest.mock('./api.js');
import * as GifContainer from './GifContainer';
it('should load gifs', () => {
return GifContainer.displayGifs('sunshine')
.then(data => {
expect(data).toBeDefined()
expect(data.entity.data.type).toEqual('gif')
})
})
_ mocks _/api.js
I'm really just not getting how to write this.
const fs = require('fs')
const api = (query) => new Promise((resolve, reject) => {
fs.readFile(`./src/Part_2/__mockData__/query.json`, 'utf8', (err, data) => {
if (err) reject(err)
resolve({ entity: JSON.parse(data) })
})
})
export default api
and then mock data in a folder _ mockData _/sushine.json
/* http://api.giphy.com/v1/gifs/search?q=sunshine&api_key=UE0dCN2WofIwVF0RPbpHo0Lz0k9VhqdG */
{
"data": [
{
"type": "gif",
}
],
"meta": {
"status": 200,
"msg": "OK",
"response_id": "5b11716a33554c732e0ddf42"
}
}
Thank you!
I don't think so the problem is on the mock itself.
Actually, first of all you need to improve the way you are doing react unit testing.
Nowadays, there are tools like Enzyme(http://airbnb.io/enzyme/) which helps you a lot to test React components.
Have you check the Testing React Apps section for Jest? Specially the DOM Testing part? Take a look here: https://facebook.github.io/jest/docs/en/tutorial-react.html#dom-testing
Back to your problem, I think it's because you are exporting the fn as default in the mock file but haven't done that on the api file. Try to put both equals and let me know!

Resources