Mocking API call in JS - javascript

I need to mock API calls for a button click but the actual call is nested down in a utility file that is called by a middleware file. Some framework code was using Jest, axios-mock-adapter, and Enzyme. (I'm still wrapping my head around what each of these do).
So let me preface this. I'm an intern at a company where my task is to test some JS code for a piece of software built on a microservice architecture. So first let me apologize for any improper verbage. My background is in C/C++ and x86 assembly. No, I didn't fudge my resume when applying for this position. The company was fully aware that I had little to no experience with JS. I've attempted to create a mock = MockAdapter('axios') then calling that with mock.OnGet().reply() but when checking my coverage it seems to error every time.
Theres to much code to post so I'll try to give an example
class ComponentName extends component {
stuff
}
ComponentNameFunc {
this.middleware.funcName.then(
response ()=>{}
errorRespone ()={}
)
}
//funcName is a name of a middleware function that calls a function
//in the utility file. The utility file does the axios.get call
When I render the component then simulate a button click it calls this.middleware.funcName but then the coverage shows it going to the errorResponse portion. Heres a test example
describe('test',()=>{
test('button click', done => {
mock.onGet('aURL').reply(200,mockData);
Enzyme.configure({ adapter: new Adapter() });
const wrapper = shallow(
<ComponentName/>);
expect(wrapper.exists()).toBe(true);
wrapper
.find("Button")
.at(0)
.simulate("click");
done();
)};
)};
EDIT: So I found part of the issue. I had multiple mocks for different API calls and apparently only 1 was registering. However, some of these functions that I'm testing will make two API calls. How do I mock up two separate API calls for a single test? Originally I had some thing like this
import axios from "axios"
let mock = MockAdapter(axios);
let mock2 = MockAdapter(axios);
mock.OnGet("URL").reply(200,Data);
mock2.OnGet("URL2").reply(200,DifferentData);

So I figured it out. I was trying to make multiple mock variables (or are they objects?) like mock, mock2, mock3. It seems replicating mock.OnGet.reply with different information works just fine.

Related

Retrieve the status from multiple axios requests called from multiple components

I have a sort of Dashboard in my application. In this dashboard I let the user put many widgets (each widget is a class component). Each widget renders different stuff, such as, charts, images, and text. When I display it, each widget make an axios call to retrieve data from backend. I need a way to be able to tell when all the requests have finished so I can get the HTML completely rendered (I'm going to export it using HiqPdf later).
I need each widget to be independent so I can use in other components. That's why each widget make its own axios call. Otherwise I think I could make many axios calls in a single component that is above my widgets and then I would pass all the data as props to each widget. However, no... the axios calls must stay inside each widget.
I've found many places talking about promises, but every example talks show how to do it in a single component.
The reason I'm working on it is because I have the need to export it using a library call HiqPdf. This library receives a HTML as string and exports to PDF. Therefore, I need to know when the dashboard has been completely loaded to let the application export it.
Think about an event-driven framework that persists the global state of your single page app and notify subscribers whenever there is a change in the state.
One of the famous frameworks is redux.
Another simple framework is mufa. These are some similar questions that leverages mufa:
https://stackoverflow.com/a/42124013/747579
Stop the communication between react components using mufa after a condition
For your case, it might be something like this:
const all_calls = [];
const {on, one, fire, unsub} = mufa;
axios.get('call1').then((data) => {
fire('call1_received', data);
})
axios.get('call2').then((data) => {
fire('call2_received', data);
});
one('call1_received', () => {
all_calls.push('call1_received');
if (all_calls.length === 2) {
alert('!!!! All calls have been received')
}
})
one('call2_received', () => {
all_calls.push('call2_received');
if (all_calls.length === 2) {
alert('!!!! All calls have been received')
}
})
Note, one will subscribe once only.. while on subscribe forever.

Mocking functions in Jest

I am new to JavaScript testing and currently trying to write some test cases for a store (just an ES6 class) I created. I am using Jest as this is what we usually use for React projects, although here I am not testing a React Component but just a class wrapping a functionality.
The class I am testing extends another class, and has various methods defined in it. I want to test these methods (whether they are called or not), and also whether the properties declared in the class change as and when the corresponding class methods are called.
Now I have read about mocking functions, but from what I understand, they can only do checks like how many times a function is called, but can't replicate the functionality. But in my case, I need the functionality of the methods because I will be checking the class member values these methods change when called.
I am not sure if this is the right approach. Is it wrong to test functions in Jest without mocking? And inferentially, to test the internal workings of functions? When do we mock functions while testing?
The issue I am facing is that the project I am working on is a large one where there are multiple levels of dependencies of classes/functions, and it becomes difficult to test it through Jest as it will need to go through all of them. As I am using alias for file paths in the project, Jest throws errors if it doesn't find any module. I know its possible to use Webpack with Jest, but many of the dependent classes/functions in the code are not in React, and their alias file paths are not maintained by Webpack.
import { getData } from 'service/common/getData';
class Wrapper extends baseClass {
someVariable = false;
payload = null;
changeVariable() {
this.someVariable = true;
}
async getData() {
super.start();
response = await fetchData();
this.payload = response;
super.end();
}
}
This is a small representation of the actual code I have. Can't post the entire class here as I am working on a remote machine. Basically, I want to test whether changeVariable gets called when invoked, and whether it successfully changes someVariable to true when called; and similarly, check the value of payload after network request is complete. Note that fetchData is defined in some other file, but is critical to testing getData method. Also the path used here (service/common/getData) for importing getData is not the absolute path but an alias NOT defined in Webpack, but somewhere else. Jest can't resolve getData because of this. I will not have to worry about this if I mock getData, but then I will not be able to test its functionality I believe.
#maverick It's perfectly okay to test your class methods using jest. Check the code example in the link -
https://repl.it/repls/ClumsyCumbersomeAdware
index.js
class Wrapper {
constructor(){
this.someVariable = false;
}
changeVariable(){
this.someVariable = true;
}
getData(){
return new Promise(resolve => resolve('some data'));
}
}
module.exports = Wrapper;
index.test.js
const Wrapper = require('./index');
const wrapper = new Wrapper();
describe('Wrapper tests', () => {
it('should changeVariable', () => {
wrapper.changeVariable();
expect(wrapper.someVariable).toBe(true);
});
it('should get some data', () => {
wrapper.getData().then( res => expect(res).toBe('some data'));
});
});
This is a very simplistic example and in real life the async calls are much more complicated and dependent of 3rd party libraries or other project modules. In such cases it makes sense to have all the dependencies injected in out class and then mocked individually. For Example -
class GMapService {
constructor(placesApi, directionApi){
this.placesApi = placesApi;
this.directionApi = directionApi;
}
getPlaceDetails(){
this.placesApi.getDetails('NYC');
}
getDirections(){
this.directionApi.getDirections('A', 'B');
}
}
Now you can easily mock placesApi and directionApi, and test them individually without actually requiring Google Map dependencies.
Hope this helps ! 😇

Where to put context specific multi-step async logic in Redux

tl;dr I would like to know where to place context specific multi-step async callback logic in a redux architecture, and if I am on the right track with the example code I supply below. By "multi-step" and "context specific" I typically mean server calls initiated by some user action (onClicks, etc) where the logic might only be relevant for a given component (such as redirect to a given route when successful).
The redux docs has this to say on code with side effects:
In general, Redux suggests that code with side effects should be part of the action creation process. While that logic can be performed inside of a UI component, it generally makes sense to extract that logic into a reusable function so that the same logic can be called from multiple places—in other words, an action creator function.
While that seems fine, I am not totally sure whether it is "correct" to put calls to my routing component in there, as these action creators usually seem quite generic, and triggering routing to some other resource in the app is usually quite context dependant.
I also find it a bit weird to put these quite-different beasts, that trigger action creators asynchronously and dispatch the resulting actions, in the same files (foo-model/actions.js) as the "clean" sync action creators. Is this the right place? When reading tutorials on Redux it seems like they live side by side.
The example code is quite simple and basically describes these steps:
On a user click, call a function with some param
This function calls another async function (such as a network call)
When the async call completes, trigger a routing action to another page
Background: I want to gradually refactoring a Meteor project by moving all Meteor specific bits out of the React components, eventually substituting Meteor in the front and back for something else. As there are about 50KLOC I cannot do this in one go, so I am gradually working my way through one route at a time, hoping to end up with a standard React+Redux+ReduxRouter package. In the current code routing, data fetching, and rendering is somewhat intertwined in each component, and I am having some trouble finding out where to put multi-step async logic, such as the example below.
Details on the stack I am trying to wrangle my way out of:
FlowRouter for routing
Meteor/MiniMongo for data mutation and retrieval
React Komposer for Higher Order Components
old Meteor code in MyContainerComponent
// triggered as onClick={(e) => this.saveEncounter(e.target.value)}
// in render()
const saveEncounter = (encounter) => {
Meteor.call('createEncounter', encounter, handleSaveResult);
}
};
const handleSaveResult = (err, encounterId) => {
if (err) {
this.setState({errorMessages: err});
} else {
// route to another page
NavigationActions.goTo('encounter', {encounterId: this.props.encounter._id || encounterId});
}
}
new redux code - moved into actions.js
I am trying to keep the implementation straight forward (no additional deps) at this point to understand the foundations. "Simplification" using redux-thunk, redux-actions or redux-saga need to come later. Modeled after the example code in the Redux tutorial for Async Actions
export const saveEncounter = (encounter) => {
function handleSave(err, encounterId) {
if (err) {
dispatch(createEncounterFailure(err), encounter);
} else {
dispatch(createEncounterSuccess(encounterId));
}
}
dispatch(createEncounterRequest(encounter));
Meteor.call('createEncounter', encounter, handleSave);
}
// simple sync actions creators
export const CREATE_ENCOUNTER_REQUEST = 'CREATE_ENCOUNTER_REQUEST';
function createEncounterRequest(encounter) {
return {
type: CREATE_ENCOUNTER_REQUEST,
encounter
};
}
export const CREATE_ENCOUNTER_FAILURE = 'CREATE_ENCOUNTER_FAILURE';
function createEncounterFailure(error, encounter) {
return {
type: CREATE_ENCOUNTER_FAILURE,
error,
encounter
};
}
export const CREATE_ENCOUNTER_SUCCESS = 'CREATE_ENCOUNTER_SUCCESS';
function createEncounterSuccess(encounterId) {
return {
type: CREATE_ENCOUNTER_SUCCESS,
encounterId
};
}
As you noted in a comment, Dan Abramov discussed a lot of the ideas behind handling async work in Redux in his answer for how to dispatch an action with a timeout. He also wrote another excellent answer in why do we need middleware for async flow in Redux?.
You might want to read through some of the other articles in the Redux Side Effects category of my React/Redux links list to get a better idea of ways to handle async logic in Redux.
In general, it sounds like you may want to make use of either "sagas" or "observables" for managing some of your async logic and workflow. There's a huge variety of Redux middlewares for async behavior out there - I summarized the major categories and most popular libraries in my blog post The Tao of Redux, Part 2 - Practice and Philosophy. There's also some interesting thoughts on a very decoupled saga-based Redux architecture in a post called Redux Saga in Action.
I see your point, you would like to have a way to divide and categorize your actions, is that right? Actions that will execute sync code, async code, logger, etc.
Personally, I use some naming convention. If I have to dispatch an action that has to fetch some data, I call it REQUEST_DATA. If have to store some data arrived from the server to the ReduxStore, I call it STORE_DATA.
I don't have a specific pattern. I also have to point that I divide my codebase based on the feature, so the modules where I define my actions are pretty small and neat
In my experience with Redux, I haven't found any problems with putting async calls inside action creators. I think redux-thunk or some other middleware is very helpful, even for a simple setup.
The only thing I'd add is that I don't find your sample code very readable.
Personally I've come to like the ducks pattern, but also just keeping action types, action creators and reducers in separate files would work to improve clarity.
Hope this helps.

Creating an instance of API service in ES2015

I'm primarily a C# developer with limited experience in JavaScript/EcmaScript and trying to understand the right way to create an instance of an API service that I can reuse in my functions.
The app I'm working on is a React app and the API service I'm trying to consume is Google Places. I created an external file for all Google Places related functions so that they're reusable. Here's the function I have in that file that will make the API call to get some suggestions from Google.
export const googleCall = (keyword) => {
const googlePlacesAutocomplete = new google.maps.places.AutocompleteService();
googlePlacesAutocomplete.getQueryPredictions({input: keyword}, callback);
}
It makes no sense to keep "new"ing google.maps.places.AutocompleteService() every time a new keystroke comes into this function.
One option I can think of is that in my React app -- say in ComponentWillMount --- I can create an instance of this service and then pass it into this function along with the keyword but that seems a bit cumbersome. That would look something like this:
export const googleCall = (googleService, keyword) => {
googleService.getQueryPredictions({input: keyword}, callback);
}
I think a better way would be to make sure the googleCall() function can access what's in the state i.e. in my redux store. In other words, I could create an instance of the googleService in a ComponentWillMount function and place it in my redux store. Just not sure how I can have this function access what's in my state.
Or, more generally speaking, in ES -- in particular in ES2015 -- how do I create an instance of this service that my googleCall function can access every time I call it without having to create a new instance of the service? I'm just not sure how this is done in ES where we create an instance of something and keep it in memory for subsequent calls.
UPDATE:
In my React component, I simply get the googleCall function like this:
import {googleCall} from '../googlePlacesFunctions';
I'm somewhat confused by your question. Why not just?
// api.js
const googlePlacesAutocomplete = new google.maps.places.AutocompleteService();
export const googleCall = (keyword, callback) => {
googlePlacesAutocomplete.getQueryPredictions({input: keyword}, callback);
}
That way you're not passing things around anywhere and you're not creating more than one instance of AutocompleteService

React, Flux, React-Router Dispatch Error - Possible batchUpdates solution?

Alright so I'm stuck on an issue with reactjs, flux architecture, and react-router. I have the following routes (just a portion of the routes):
<Route name="prepare-seniors">
<Route name="senior" path=":candidateId" handler={SeniorCandidate}>
<DefaultRoute handler={SeniorProfile}/>
<Route name="senior-recommendations" path="recommends">
<DefaultRoute handler={SeniorRecommends}/>
<Route name="senior-rec-new" path="new"/>
</Route>
</Route>
</Route>
The Senior Profile view makes an API call to load the individual's data. When you navigate to the Recommends view, the individual's id is used to make another call to load the recommendations. It works great if I actually view the profile page first and navigate to the recommendations page. But if I do a hard reload I get:
Uncaught Error: Invariant Violation: Dispatch.dispatch(...): Cannot dispatch in the middle of a dispatch.
I realize this is because the dispatch is getting called after the first API returns, which goes out and starts updating components. Before it finishes the recommendations page calls its API and tries to dispatch its results. I read on a forum that React.addons.batchUpdates is a way to fix this, but I couldn't figure out how to get it to work. GitHub Batch Updates Issue and another link here that discusses something similar Trying to use waitFor. The first one recommends adjusting the dispatcher by adding the following:
// assuming a var `flux` containing your Flux instance...
var oldDispatch = flux.dispatcher.dispatch.bind(flux.dispatcher);
flux.dispatcher.dispatch = function(action) {
React.addons.batchedUpdates(function() {
oldDispatch(action);
});
};
But I could not make this work. Maybe I'm just implementing it incorrectly.
I've read the Chat and TodoMVC examples. I understand how the waitFor is used in the chat example...but those both use the same API so it's clear that the one is going to wait for the other. My issue involves a race condition between APIs and dispatch...and I don't think setTimeout is a good solution.
What I need is to see how to set up the dispatcher in such a way that it will queue the dispatch or API calls. Or a better way to tell each component to make an API call for it's data, so I don't even have a dispatch issue.
Oh so here's my Dispatcher.js file so you can see how it's set up:
'use strict';
var flux = require('flux'),
Dispatcher = require('flux').Dispatcher,
React = require('react'),
PayloadSources = require('../constants/PayloadSources'),
assign = require('object-assign');
//var oldDispatcher = flux.Dispatcher.dispatch.bind(AppDispatcher);
//
//flux.dispatcher.dispatch = function(action) {
// React.addons.batchedUpdates(function() {
// oldDispatcher(action);
// });
//};
var AppDispatcher = assign(new Dispatcher(), {
handleServerAction: function(action) {
var payload = {
source: PayloadSources.SERVER_ACTION,
action: action
};
this.dispatch(payload);
},
handleViewAction: function(action) {
if (!action.type) {
throw new Error('Empty action.type: you likely mistyped the action.');
}
var payload = {
source: PayloadSources.VIEW_ACTION,
action: action
};
this.dispatch(payload);
}
});
module.exports = AppDispatcher;
Ok first I'm just going to say I am learning React and Flux at the moment and am by no means an expert. However I'm going to give it a shot anyway:
From what you have said, it sounds like you have 2 asynchronous operations triggering off and then when they return trying to send dispatch messages The issue arising from the dispatch call being triggered twice from 2 independent aync webservice calls.
I don't think batching the updates would help in this case as it would depend heavily on timing(ie. if it has queued the re-render and is waiting for the opportunity to execute when the 2nd call comes in it could batch successfully, however if it comes in mid-update you are in the exactly the same situation place you are now).
I think the actual issue here is coming from how/when these Actions are being triggered(you mention this briefly at the end of your post). It sounds like you are triggering Actions from the React component Render calls(kind of like lazy loading). This is pretty much exactly the thing Flux is trying to avoid, as that is a pattern that could easily result in an infinite loop or weird states/patterns in the flow of the application.
As you mentioned in your description you probably need to trigger this loading up front instead of from the individual components, from the little I know I would suggest that needs to be done prior to calling React.render on your core component. If you look in the example chat app they do a similar thing in app.js:
ChatExampleData.init(); // load example data into localstorage
ChatWebAPIUtils.getAllMessages();
React.render(
<ChatApp />,
document.getElementById('react')
);
So I would suggest following the above pattern, loading any initial data up front while showing a loading spinner to the client.
Alternatively, depending on your tech stack you could render initially on the server (node example here .Net version at ReactJS.Net) so you don't have that delay while the client side boots up(also you avoid all the funny business with search engine indexing if that is a concern (BTW I haven't tried either of these, just read about them).

Categories