I am trying to migrate from expect to chai and Sinon.
I expect we do something like this
this.check = expect.spyOn(module, "method").andCall(function(dep) {
return dep;
});
But I want this behavior with Chai and Sinon.
this.check = sinon.spy(module, "method")
But how do I get the andCall as I refer the docs and I guess callsFake cant be call with spy and I don't really think this will have similar behavior with stud.
Any help is appreciated.
You could do something like this:
it('makes blue cheese', () => {
const mySpy = sinon.spy()
sinon.stub(module, 'method')
.callsFake((...args) => {
mySpy(...args)
// Do other stuff here like return a value
return 'blue cheese'
})
const testValue = module.method('hello', 'world')
expect(testValue).to.eq('blue cheese')
expect(mySpy).to.have.been.calledWith('hello', 'world')
})
This way of stubbing and calling a spy works in tests I've written using Sinon 8.1.1.
I haven't tried the following, but here's an example of using async/await syntax:
it('makes blue cheese async', async () => {
const mySpy = sinon.spy()
sinon.stub(module, 'method')
.callsFake(async (...args) => {
mySpy(...args)
return 'blue cheese'
})
const testValue = await module.method('hello', 'world')
expect(testValue).to.eq('blue cheese')
})
Related
I use react-native-reanimated version: '1.7.1' and I tried to process delay between 4 different timing functions.
I tried to find instructions on the web and didn't find one that was clear:
https://docs.swmansion.com/react-native-reanimated/docs/1.x.x/about#reanimated-overview
https://docs.swmansion.com/react-native-reanimated/docs/1.x.x/declarative
I know that in the original reactNative API there is a delay so I tried to find something comparable with this good library
export const createTimingAnimation = (value: Animated.Node<number>, duration = 500, easing = Easing.inOut(Easing.ease), toValue = 1) => {
return Animated.timing(value, {
toValue,
duration,
easing,
});
};
I didn't find any formal way, so I created one:
export const timingAnimationWithDelay = (delay: number, timingAnimation: Animated.BackwardCompatibleWrapper, finishCallback?: any): void => {
setTimeout(() => {
timingAnimation.start(() => {
finishCallback && finishCallback();
});
}, delay);
};
And then you call it like this:
const greetingNfnTiming = createTimingAnimation(animatedValue, 480, Easing.out(Easing.cubic));
timingAnimationWithDelay(1000, greetingNfnTiming, onGreetingFinish);
Suppose I have the following component:
const MyComponent = () => null;
In React Testing Library (RTL), the following, AFAIK, should work:
const { container } = render(<MyComponent />);
expect(container.firstChild).toBeEmpty();
where .toBeEmpty is a custom matcher from jest-dom. However, in NTL, container.firstChild is not defined so I can't use .toBeEmpty matcher from jest-native. After some experimentation, I got it to work as follows:
expect(container.children[0]).toBeUndefined();
Is there any other, possibly better, way to do this?
In my case I had a situation like so:
function PhotoComponent({policy}) {
if (policy === 'unavailable')
return null;
return (<View />);
}
Tested like this:
it("should not render if policy is 'unavailable'", () => {
const {toJSON} = render(<PhotoComponent policy={'unavailable'} />);
const children = toJSON().children;
expect(children.length).toBe(0);
});
Some times you will want to filter the children like, for instance:
const children = toJSON().children.filter(
(child) => child.type === 'View' || child.type === 'Modal'
);
Keep calm and Happy coding!
My previous javascript underscore function:
export const getQuantity = (obj, name: string) => {
const quantityInIfcObject = _.findWhere(obj.quantities, { name: quantity });
return quantityInIfcObject ? quantityInIfcObject.value : null;
};
const quantity = getQuantity(obj, 'area');
What would a Ramda-version of this look like?
Tried this:
export const getQuantity = (name) => R.pipe(
R.map((o: IIfcObject) => o.quantities),
R.find(R.propEq('name', name)),
R.map((q: IIfcQuantity) => q.value)
)(quantity);
const quantity = getQuantity(obj, 'area');
Not working. In the examples I've read of pipe there's no arguments. Maybe wrong to use pipe here?
You should get the quantities (R.prop), find the name, and get the value if exists, or null if it doesn't:
export const getQuantity = (name) => R.pipe(
R.prop('quantities'),
R.find(R.propEq('name', name)),
R.propOr(null, 'value'),
)(quantity);
Calling the function is a two steps process, since R.pipe returns a function when invoked. When you call getQuantity('area'), R.pipe will return a function. That function expects an object to operate on:
const getQuantityForArea = getQuantity('area');
const quantity = getQuantityForArea(obj);
You can call it in one step by combining both calls:
const quantity = getQuantity('area')(obj);
My production code looks like:
exports.convertWord = number => { /* some logic here */ }
exports.methodUnderTest = () => {
return exports.convertWord(1);
}
Test code:
const mockConvertToWord = sinon.stub();
mockConvertToWord.withArgs(1).returns('one');
fileUnderTest.convertWord = mockConvertToWord;
const result = fileUnderTest.methodUnderTest();
expect(result).toBeEqual('one');
Test above is green. I expect my test will break if I change prod code to this:
exports.convertWord = number => { /* some logic here */ }
exports.methodUnderTest = () => {
return exports.convertWord(1, 'another arg');
}
but it's not. Sinon works fine even when I pass extra params which I didn't point in withArgs method. How can I tell sinon to return value only when method has been called with exact number of params?
stub
One way to do this is to use stub.callsFake(fakeFunction):
mockConvertToWord.callsFake((...args) => args.length === 1 && args[0] === 1 ? 'one' : undefined);
An alternative approach with a stub is to use a sinon.assert to make sure the stub was called with the epected arguments as noted by #deerawan.
mock
Another approach is to use a mock:
const mock = sinon.mock(fileUnderTest);
mock.expects('convertWord').withExactArgs(1).returns("one");
const result = fileUnderTest.methodUnderTest();
expect(result).toBeEqual('one');
mock.verify();
Another alternative, perhaps you can try to check the call of convertToWord like
...
expect(result).toBeEqual('one');
// check the function
sinon.assert.alwaysCalledWithExactly(mockConvertToWord, '1');
Ref:
https://sinonjs.org/releases/v6.3.4/assertions/#sinonassertalwayscalledwithexactlyspy-arg1-arg2-
Hope it helps
Forgive me, I'm new to normalizr+redux. I've managed to normalize my data and create a reducer and end up with :
state = {
installations:{
"1":{...},
"2":{...}
}
}
I would then like to filter this data for use in a UI component into two separate categories (in this case where the installation.operator is equal to the current user). I've managed an implementation that works however it seems exhaustive:
const mapStateToProps = (state, ownProps) => {
console.log("mapStateToProps", state.installations);
let assignedInstallations = Object.keys(state.installations)
.filter(i => {
return state.installations[i].operator == state.login;
})
.map(i => {
return state.installations[i];
});
let unassignedInstallations = Object.keys(state.installations)
.filter(i => {
return state.installations[i].operator != state.login;
})
.map(i => {
return state.installations[i];
});
return {
assignedInstallations,
unassignedInstallations,
loginUserId: state.login
};
};
I'm also new to ES6 and am not across all the new syntax shortcuts etc so I suspect there are much better ways to do this.
Is there a more succinct approach with a similar outcome?
you can do this with only one reduce():
const mapStateToProps = (state, ownProps) => {
console.log("mapStateToProps", state.installations);
let {assignedInstallations,
unassignedInstallations } = Object.keys(state.installations)
.reduce(function(acc, cur, i){
if(state.installations[i].operator == state.login){
acc.assignedInstallations.push(state.installations[i]);
}else{
acc.unassignedInstallations .push(state.installations[i]);
}
return acc
}, {assignedInstallations: [], unassignedInstallations: [] })
return {
assignedInstallations,
unassignedInstallations,
loginUserId: state.login
};
};
lodash (An utility library) have a notion of collection (Here is an example https://lodash.com/docs/4.17.4#filter for filter function). It takes as input Object or Array and returns an Array. It seems to fit to your needs. Here is the refactored code:
import {
filter,
} from 'lodash'
const mapStateToProps = (state, ownProps) => {
let assignedInstallations = filter(state.installations, installation => installation.operator == state.login);
let unassignedInstallations = filter(state.installations, installation => installation.operator != state.login);
return {
assignedInstallations,
unassignedInstallations,
loginUserId: state.login
};
};