Mock api calls from Storybook - reactjs

Does axios-mock-adapter only work on requests made with axios?
I have written a component that POSTs to an API (using vanilla XHR, not axios). I'm testing it in Storybook and want to intercept those POST requests since the endpoint doesn't exist yet:
import React from "react"
import { storiesOf } from "#kadira/storybook"
import MyComponent from "./MyComponent"
import axios from "axios"
import MockAdapter from "axios-mock-adapter"
var mock = new MockAdapter(axios)
storiesOf("My Component", module).addWithInfo(
"Simulator",
() => {
mock.onPost().reply(500)
return <MyComponent />
},
{}
)
My component still is trying to hit the API endpoint and I am getting a 404 response - not the expected 500 response.
Does axios-mock-adapter only work on requests made with axios?
Does the mock call have to be inside MyComponent?
Thanks.

xhr-mock should work for local testing where you probably don't want to make requests across the internet.
Outside of testing, if you are waiting on the real endpoints to be built you could use Mock/it (https://mockit.io) in development. You can claim your own dedicated subdomain and swap it out later for the real one. Disclaimer: this is a side project I recently released and would love any feedback on it!

You can use xhr-mock instead of axios-mock-adapter.
Utility for mocking XMLHttpRequest.
Great for testing. Great for prototyping while your backend is still being built.
Works in NodeJS and in the browser. Is compatible with Axios, jQuery, Superagent >and probably every other library built on XMLHttpRequest
import mock from 'xhr-mock';
storiesOf("My Component", module).addWithInfo("Simulator",
() => {
mock.post('', {
status: 500,
body: '{}'
});
return <MyComponent />
},
{}
)
Additionaly you need to add jquery script in preview-head.html file in storybook
1) https://www.npmjs.com/package/xhr-mock

I've started using json-server to intercept API calls. You have to start it in one tab, and start storybook in another, but it is pretty cool.

You can use fetchMock npm module. All XHR call will be mocked with data you provide.
Storybook configuration:
import React from 'react';
import Messages from '../components/messagesList';
import fetchMock from "fetch-mock";
import MESSAGES from './data/messages';
fetchMock.get('/messages', MESSAGES);
export default {
title: 'Messages',
component: Messages
};
export const ToStorybook = () => <Messages />;
ToStorybook.story = {
name: 'Messages list',
};
The complete tutorial how to do it is on YouTube

You can use storybook-addon-mock to mock any fetch or XHR request using the addon panel.
This package supports
Modify response from the panel and test on the fly.
Modify the status code to verify the error response.
Add a delay time to experience the loading state.

Related

Importing firebase cloud functions in a React project

I am building a react app (this part might be inconsequential) and have a server cloud function built:
exports.myFunction = functions.https.onCall(async (data, context) => {
...
}
I know that calling this in my client would normally consist of calling
firebase.functions().httpsCallable('myFunction');
And I have tried this in a separate project, and it works. However, that was using a script tag to import the functions module in my index.html:
<script src="/__/firebase/7.7.9/firebase-functions.js"></script>
but in my current project, my modules are imported in my firebase.js source:
import { initializeApp } from "firebase/app";
import { getAuth } from "firebase/auth";
const firebaseConfig = {
apiKey: ...
...
};
const app = initializeApp(firebaseConfig);
export const auth = getAuth(app);
I wasn't able to find any example code for importing functions this way, and everything I have tried has failed.
How can I import functions so that I can invoke the above method? Even better, how could I figure this out on my own? (I have been relying on example code so far). I assume that these are referencing the NPM packages I have npm install'ed (or in my case, yarn add'ed), but I don't immediately see where the code is actually being referenced so I can work this out on my own.
As far what I have understood from you question it is regarding how can firebase cloud function module be imported while using a react app which is calling a HTTPS callable function at the client side.You can use any library or built-in command of your environment to call a HTTPS function.
I would recommend you to try the following to your imports and see if that works.
import { getFunctions, httpsCallable } from "firebase/functions";
OR
import * as functions from 'firebase-functions'; import React from 'react'; import { renderToString } from 'react-dom/server'; import App from './src/App';
Check the below for similar implementation examples to better understand this and implement according to your requirements.
How to call Firebase function from within react component
Call Firebase HTTPS callable function in react
Implement callable function in react app
Firebase callable function CORS

Jest + React Testing Library: waitFor is not working

I am writing unit tests for my React JS application using Jest and React testing library. I am trying to test the async functions. But it is not working.
This is my test
import React from 'react';
import "regenerator-runtime/runtime"
import {render, waitFor, fireEvent, screen} from '#testing-library/react';
import {DonorSelect} from "../../src/components";
import MockAdapter from "axios-mock-adapter";
import Axios from 'axios';
import vars from "../configVars";
import {searchUsersResponse} from "../mock/apiResponse";
import { act } from "react-dom/test-utils"
test ("DonorSelect Component", async () => {
let selectedUser = null;
let users = [ ];
let inputValue=""
//mock the users api endpoint
let mock = new MockAdapter(Axios);
mock.onGet(`${vars.baseApEndpoint}/users?keyword=client`)
.reply(200, searchUsersResponse)
await act(async() => await render(
<DonorSelect
id={"user_select"}
onSelect={(user, displayText) => {
selectedUser = { ...user }
}}
onInputChange={(textFieldValue) => {
inputValue = textFieldValue;
}}
onUsersFetched={(userItems) => {
users = [ ...userItems ]
}}
onChange={(name, value) => {
}}
label={"Search User"}
placeholder={"Please, select a user."}
name={"user"}
value={selectedUser!=null? selectedUser.id:""}
inputValue={inputValue}
/>
))
//assert that input is rendered
expect(screen.getByTestId("user_select_input")).toBeTruthy()
fireEvent.change(screen.getByTestId("user_select_input"), {
target: { value: "client" }
})
fireEvent.focus(screen.getByTestId("user_select_input"))
await waitFor(() => {
//assert that if the label is rendered
expect(screen.getByTestId("user_select_label")).toBeTruthy()
// assert that input is rendered
expect(screen.getByTestId("user_select_user_item_0")).toBeTruthy()
})
})
As you can see in the test what is not working is the last expect()
expect(screen.getByTestId("user_select_user_item_0")).toBeTruthy()
It is always failing. What that component is doing is that, when the input value changes and focus on the input, it will make the api request and render the items. The component is working as expected. I have fully tested it. But it is just not working in the test. What is wrong with my code and how can I fix it?
The default waitFor timeout time is 1000ms.
If you are calling a real endpoint without mocking (mocking is recommended, for example using msw), this might take more than 1 second to execute.
This will result in the timeout being exceeded and the waitFor throws an error.
IF you do not want to mock the endpoint, intercept it and return a test value, which should be under 1 sec, you could also extend the timeout time ti wait for the real api call to be executed and resolved:
await waitFor(() => {
//assert that if the label is rendered
expect(screen.getByTestId("user_select_label")).toBeTruthy()
// assert that input is rendered
expect(screen.getByTestId("user_select_user_item_0")).toBeTruthy()
}
,{timeout: 4000}) // this will now wait 4 secs for the execution, but you should see what works for you.
Based on the information here:
Testing: waitFor is not a function #8855 link
The Solution that works for me is update the library to new version:
This module is distributed via npm which is bundled with node and should be installed as one of your project's devDependencies:
npm install --save-dev #testing-library/react
or
for installation via yarn
yarn add --dev #testing-library/react
This library has peerDependencies listings for react and react-dom.
React Testing Library versions 13+ require React v18. If your project uses an older version of React, be sure to install version 12:
npm install --save-dev #testing-library/react#12
yarn add --dev #testing-library/react#12
For more information

Use ApolloClient in Gatsby with localhost / local IP uri

I am trying to use ApolloClient with a local IP as uri, but when I set it, it automatically changes it from http to https and, of course, it doesn't work locally.
I've tried 2 way of configuring Gatsby to use ApolloClient.
The first way is in gatsby-browser like so:
import React from 'react';
import 'core-js/modules/es6.set';
import 'core-js/modules/es6.map';
import 'raf/polyfill';
import Apollo from 'providers/Apollo';
export const wrapRootElement = ({ element }) => <Apollo>{element}</Apollo>;
And, the ApolloClient config:
import React from 'react';
import { ApolloProvider, ApolloClient, InMemoryCache } from '#apollo/client';
export default ({ children }) => {
const client = new ApolloClient({
uri: 'http://192.162.1.112:4000/graphql',
cache: new InMemoryCache(),
request: async operation => {
...
},
fetchOptions: {
mode: 'no-cors',
},
});
return <ApolloProvider client={client}>{children}</ApolloProvider>;
};
The second way is using the plugin gatsby-plugin-apollo in gatsby-config like so
{
resolve: 'gatsby-plugin-apollo',
options: {
uri: 'http://192.168.1.112:4000/graphql'
}
}
Notice both uri have http.
Also, it is either one or the other, not both. (Although I've tried with both and it the same result).
This is what I get trying to do a gql query in the network tab:
It is enforcing https and I can't test locally. How do can I make request to http using Gatsby and ApolloClient?
By the way, I set ApolloClient just like this in another project that doesn't use Gatsby (obviously not using the gatsby plugin either) and it works as expected.
There are a few confusing things in the way you are using apollo client.
There is no point in explaining something that has already been done.
You might want to check out this talk and demo by Jason Lengstorf. Here he explained how one can get started with gatsby + apollo client.
Youtube
gatsby-with-apollo

Mock import/module with Jest in React application

I am working on a React application and I want to test one module, let's call it B, that depends on another module, let's call it A.
The scenario could be something like this:
moduleA.js
export function helperFn() {
return { prop1: 10, prop2: 20 };
}
moduleB.js
import React from 'react';
import { helperFn } from '../moduleA';
export class CustomComp extends React.Component {
render() {
const helperObj = helperFn();
return (
<div>{helperObj.prop1}</div>
);
}
}
The core libraries to test my components are Jest and Enzyme. My goal here is to test module B, but I want to test it in isolation and so I want to mock the dependency on moduleA.js.
I know one way would be to inject the helperFn as a prop instead of importing it so during the test I can inject a mock function, but there are modules quite big on this app that have a few dependencies each of them.
Researching a bit I found it is posible to mock a dependecy using Jest, but I tried many things with no success. I tried approaches from this question, also from this post and I have no luck. I also read the Manual Mocks and Mock Functions guides from Jest docs, but I think they are pretty confusing.
I could make it work (i.e. I could mock moduleA.js dependency) using the approach on this post, but I had another problem then. It worked just fine to test moduleB.js, but when I went ahead and test moduleA.js, I had to import moduleA.js in moduleA.test.js and I got the mock while I wanted the real module.
So, I need help to understand how I can mock dependency A in moduleB test file.
I hope I was clear if not let me know and I will add the clarifications you might need.
Thanks in advance !
Indeed you can use jest to mock your dependency. There is some configuration you need to set in order to make it work with import. E.g. configuring babel-jest.
If you already have that configuration then you can mock it like so.
import React from 'react';
import { shallow } from 'enzyme';
import { helperFn } from '../moduleA';
jest.mock('../moduleA');
describe("CustomComp", () => {
it("should render component", () => {
helperFn.mockReturnValueOnce({
prop1: "dummy"
});
const component = shallow(<CustomComp />);
});
You can see a working example here.
I'm using Vue2 and trying to write tests for a Vue component. The Vue component uses a lot of other components that aren't really needed to test.
So for that reason, I created a mock for importing other components like below
jest.mock('#/core/components/UserInput.vue', () => ({
exec: jest.fn(),
}));

React starter kit communication with RESTful backend API service

https://github.com/kriasoft/react-starter-kit
I have a backend API server running and I am looking for a frontend framework. Then I came across this react-starter-kit that seems to be a good candidate.
My understanding is that I am dealing with react components one at a time. and I can put the all code logic such as API calls, DOM element changes....etc in componentDidMount() so there will be interaction between DOM and the logic. (am I right?)
import React, { PropTypes } from 'react'; // eslint-disable-line no-unused-vars
import styles from './ContactPage.less'; // eslint-disable-line no-unused-vars
import withStyles from '../../decorators/withStyles'; // eslint-disable-line no-unused-vars
#withStyles(styles)
class ContactPage {
static contextTypes = {
onSetTitle: PropTypes.func.isRequired
};
render() {
let title = 'Contact Us';
this.context.onSetTitle(title);
return (
<div className="ContactPage">
<div className="ContactPage-container">
<h1>{title}</h1>
<p>...</p>
</div>
</div>
);
}
}
export default ContactPage;
This is the original code of the react component I am trying to hack. I tried to include "request" module so that I can make http requests.
var request = require('request'); // for backend API calls
componentDidMount() {
request('https://www.google.com')
}
It didn't work. So what I am doing wrong here? Thanks.
The error message is very long, started with the following message.
ERROR in ./~/request/lib/har.js
Module not found: Error: Cannot resolve module 'fs' in /Users/ssmlee04/Desktop/react-starter-kit/node_modules/request/lib
# ./~/request/lib/har.js 3:9-22
Request.js is a lib for Node. It is not meant to be used in the browser. That is why you are seeing the error module fs not found. fs is the file system module of node js.
Since you are already using ES6 I suggest to use fetch (https://fetch.spec.whatwg.org/) to make request to the remote server. It is already supported by chrome and firefox. To have compatibility with older browser you can use fetch polyfill from github. Here it is the link to the repo https://github.com/github/fetch.

Resources