Incompatibility with jest-mock-extended
Bug description
Trying to mergeDeep with mocks from jest-mock-extended leads to strange behavior:
import { mergeDeep } from 'immutable';
import { mock } from 'jest-mock-extended';
describe('immutable + jest-mock-extended', () => {
test('mergeDeep', () => {
const myMock = mock();
const merged = mergeDeep({ myMock }, { myMock });
console.log(merged.myMock); // undefined!
expect(merged.myMock).toBe(myMock); // fails because merged.myMock is undefined
});
});Cause
It seems that the various isImmutable functions (e.g isCollection) make their assertion on "symbols" like so:
function isImmutable(obj) {
return new Boolean(obj && obj[SYMBOL]);
}The problem is with the obj[SYMBOL] assertion, which will return true for any truthy value, and not necessarily what the package set as value (a literal true).
Now, the mocks from jest-mock-extended seem to return a Proxy that, if a key on the object is accessed, the proxy populates that key with a function (which is truthy):
test('isImmutable', () => {
const myMock = mock();
isImmutable(myMock);
console.log(myMock); // it now has `'@@__IMMUTABLE_ITERABLE__@@': [Function: mockConstructor] { ... }` property
});This makes the package think that the original values (the mocks) given to mergeDeep originated from the package, which likely messes up with its logic. I'm assuming this will affect other methods as well.
Potential solutions
- Perform a more strict check on the value of the "symbol" (
=== trueor even=== SOME_UNIQUE_SYMBOL). - Change the symbol check to
obj.hasOwnProperty(SYMBOL), which will not "trigger" the auto population of the mock proxy.
Source: immutable-js/immutable-js