I'm trying to spy on a function that's called by another function, both of which reside in an external file and imported.
Funcs.spec.js:
import * as Funcs from './Funcs'
describe('funcA', () => {
it('calls funcB', () => {
jest.spyOn(Funcs, 'funcB')
Funcs.funcA()
expect(Funcs.funcB).toHaveBeenCalled()
}
}
Funcs.js:
export const funcA = () => {
funcB()
}
export const funcB = () => {}
For some reason the spy is not respected in scope of Funcs.js. What can I do to spy on funcB so I know funcA has called it?
Only methods can be spied. There is no way to spy on funcB if it's called directly like funcB() within same module.
In order for exported function to be spied or mocked, funcA and funcB should reside in different modules.
This allows to spy on funcB in transpiled ES module (module object is read-only in native ESM):
import { funcB } from './b';
export const funcA = () => {
funcB()
}
Due to that module imports are representations of modules, this is transpiled to:
var _b = require('./b');
var funcA = exports.funcA = function funcA() {
(0, _b.funcB)();
};
Where funcB method is tied to _b module object, so it's possible to spy on it.
The problem you describe is referenced on a jest issue.
A possible solution to your problem (if you want to keep the functions inside the same file) is to use CommonJS, consider the following example:
fns.js
exports.funcA = () => {
exports.funcB();
};
exports.funcB = () => {};
fns.spec.js
const fns = require("./fns");
describe("funcA", () => {
it("calls funcB", () => {
fns.funcB = jest.fn();
fns.funcA();
expect(fns.funcB).toBeCalled();
});
});
Related
gulp-intercept allows synchronous manipulations with file:
import gulpIntercept from "gulp-intercept";
import VinylFile from "vinyl";
// ...
.pipe(gulpIntercept((compiledHtmlFile: VinylFile): VinylFile => {
doSomethingSyncWith(compiledHtmlFile)
return compiledHtmlFile;
}))
// ...
But I am not sure it will not work for asynchronous manipulations because it has not been documented. Well, when this package was development, maybe even Promises did not exist in ECMAScript.
import gulpIntercept from "gulp-intercept";
import VinylFile from "vinyl";
// ...
// I suppose it will not work.
.pipe(gulpIntercept(async (compiledHtmlFile: VinylFile): VinylFile => {
// does "gulp.pipe" really will wait until it ends?
await doSomethingAsyncWith(compiledHtmlFile)
return compiledHtmlFile;
}))
// ...
There is should be another gulp plugin for for asynchronous manipulations instead. Would you please to teach me it?
Looks like the library you are using doesn't support async functions as an input (as you already said!) but you don't need to use the library at all you can use event-stream and map your function and call callback at the end in following manner:
import VinylFile from "vinyl";
const es = require('event-stream');
const gulp = require('gulp');
// ..
.pipe(
es.map(
async (compiledHtmlFile: VinylFile, callback: any): VinylFile => {
// "gulp.pipe" will really wait until it ends!!!
await doSomethingAsyncWith(compiledHtmlFile);
callback(null, compiledHtmlFile);
}
)
)
// ...
or use with then:
// ..
.pipe(
es.map(
async (compiledHtmlFile: VinylFile, callback: any): VinylFile => {
doSomethingAsyncWith(compiledHtmlFile)
.then(() => {
callback(null, compiledHtmlFile);
});
}
)
)
// ...
I have a simple question.
I want to run the function I created in App.js in a different screen.
Each screen is connected to an AppContainer in context.
I'm going to use state on another screen, but I do not know how to do it.
Can you give me a simple example?
_setDefaultLocation = locationKey => {
console.log("call _setDefaultLocation function");
this.setState({ defaultLocation: locationKey });
console.log(this.state.defaultLocation);
this._getCurrent(locationKey);
};
The above function is called this.props._setDefaultLocation (); I tried to do this and it did not work.
import React from "react";
const WeatherContext = React.createContext();
function withWeather(WrappedComponent) {
return function withContext(props) {
return (
<WeatherContext.Consumer>
{value => <WrappedComponent value={value} {...props} />}
</WeatherContext.Consumer>
);
};
}
export { WeatherContext, withWeather };
Context is used to make it like that.
You can use global keyword to make your function global. Then you can use it in any screen.
For example, assume that you have a function is called 'myFunction'. You can implement your function in App.js as following.
global.myFunction = () => {
console.warn('I am a global function...')
// your function body
};
Then you can call this function in any screen just like other function calling..
In your case your function can implement in this format.
global._myFunction = locationKey => {
console.warn('I am a global function...')
// your function body
};
And when you are calling the function call it as _myFunction(locationKey).
NOTE: 'locationKey' is the parameter that you should pass for your function.
Think this solution will help you.
I have tried researching this but was rather swamped, was wondering if someone has a solid answer regarding use of named functions in redux action creators vs named functions - is there any performance difference? Or any other factors that affect this?
eg:
function getUserIdentity() {
return (dispatch) => {
dispatch({
type: types.GET_USER_IDENTITY,
});
}
}
vs
const getUserIdentity = () => (dispatch) => { dispatch({type: types.GET_USER_IDENTITY}) };
Thanks!
Any performance difference doesn't matter, the two functions aren't even doing the same. The arrow function "equivalent" of your function declaration would be
const getUserIdentity = () => (dispatch) => { dispatch({type: types.GET_USER_IDENTITY}) };
not
const getUserIdentity = (dispatch) => dispatch({ type: types.GET_USER_IDENTITY });
as in your question.
Regarding the updated question, no there is no performance difference between calling the different function types. However, there is still a behavioural difference, see Arrow function vs function declaration / expressions: Are they equivalent / exchangeable? and also var functionName = function() {} vs function functionName() {} - a variable initialisation happens at a different time than that of a "hoisted" function declaration, which might make a difference depending on how/where the function is used.
I have created a Rust library of type cdylib using
cargo web build --target=wasm32-unknown-unknown
I use a modified version of the "rust-wasm-loader" NPM package to build and load the WASM file. rust-wasm-loader uses this as a way to use the Rust code:
const wasm = require('./main.rs')
wasm.initialize().then(module => {
// Use your module here
const doub = module.cwrap('doub', 'number', ['number'])
console.log(doub(21))
})
I do not want to initialize the module every time I want to use the code. How do I load the module and use it like a library?
Since the loading of WebAssembly is asynchronous and may actually take some time for large modules, you need to handle the state when the module is not loaded, and then let the rest of the application know when the WebAssembly module is loaded.
You do not say how you are handling state in your Vue application, but if you are e.g. using Vuex you can do something like this:
const doubPlugin = store => {
wasm.initialize().then(module => {
const doub = module.cwrap('doub', 'number', ['number'])
store.subscribe((mutation, state) => {
if (mutation.type === 'DOUB_REQUEST') {
store.commit('DOUB_RESULT', doub(mutation.payload))
}
})
store.commit('DOUB_READY')
})
}
const store = new Vuex.Store({
state,
mutations,
plugins: [doubPlugin]
})
I've done a similar thing in an Elm/WebAssembly application (relevant JavaScript), so if you want to see how this can be applied in practice you can check that out.
Making a wrapper JS module that performs initialization and re-exports the promise seems like the most straightforward approach.
// main.js
module.exports = require("./main.rs").initialize().then(module => {
return {
doub: module.cwrap('doub', 'number', ['number'])
};
});
Then anything can do
require("./main.js").then(api => {
console.log(api.doub(21));
});
and will always get the same module. Or alternatively you could invert the async part and do
// main.js
const api = require("./main.rs").initialize().then(module => {
return {
doub: module.cwrap('doub', 'number', ['number'])
};
});
exports.doub = async function (val) {
return (await api).doub(val);
};
Then users of your module could do
const api = require("./main.js");
api.doub(21).then(result => {
console.log(result);
});
I created a class to wrap the WebAssembly loading and created a cwrap for every function:
class mkLib {
ready = false
_mod = require("./main.rs").initialize().then(module => {
this._mod = module
this.doub = module.cwrap('doub', 'number', ['number'])
this.ready = true
})
}
export default mkLib
In the Vue component's data there is a variable for the new class and in watch I wait for a change in the ready property:
data () {
return {
mod: new mkLib,
ready: false
}
},
watch: {
'mod.ready': function () {
this.ready = true
// now this.mod.FUNC(PARAMS) can be used
console.log(this.mod.doub(20))
}
}
Sometimes my Redux selectors are quite complicated. I need some means for debugging each step in the chain.
Here is a simplified selector as an example:
export const selectCompletedFilesForSaveToServer = state => {
return state
.getIn(['file', 'saveToServerQueue'])
.filterNot(item => item.get('isPosting'))
.valueSeq();
};
And this is what I want to do:
export const selectCompletedFilesForSaveToServer = state => {
return state
.getIn(['file', 'saveToServerQueue'])
.intercept(item => console.log(item.toJS())
.filterNot(item => item.get('isPosting'))
.intercept(item => console.log(item.toJS())
.valueSeq();
};
I.e. the intercept function should take whatever collection is thrown at it (Map, List, etc), iterate over the collection and then return the original collection for further chaining.
I tried to use .forEach(), but I didn't understand how it works.
My current solution is to manually break up the chain into separate intermediate variables for inspection, but this is not a nice solution.
Well.. while writing my question I kind of got some perspective and solved it.
The .filter() function essentially is a peek function. Just remember to return true..
export const selectCompletedFilesForSaveToServer = state => {
return state
.getIn(['file', 'saveToServerQueue'])
.filter(item => {
console.log(item.toJS());
return true;
});
.filterNot(item => item.get('isPosting'))
.filter(item => {
console.log(item.toJS());
return true;
});
.valueSeq();
};
edit:
I found an even better function: .update(). It's chainable and takes a custom function as an argument. The custom function gets the collection as argument and should return the collection as well (in my use case).
https://facebook.github.io/immutable-js/docs/#/Collection/update
New example:
export const selectCompletedFilesForSaveToServer = state => {
const peek = function(collection) {
console.log(collection.toJS());
return collection;
};
return state
.getIn(['file', 'saveToServerQueue'])
.update(peek);
.filterNot(item => item.get('isPosting'))
.update(peek);
.valueSeq();
};