Enzyme: Iterable children not working on environments where Symbol API is not available

Created on 6 Nov 2017  路  6Comments  路  Source: enzymejs/enzyme

Support for iterable children was recently released https://github.com/airbnb/enzyme/pull/1187. It enables to write Enzyme tests for components that return array-like children, for example ES6 Map and Set, and Immutable List.

We run our unit tests on PhantomJS, and iterable children support was not working for us. But works just fine on latest version of Chrome.

After some discussion with @ljharb in the comments of https://github.com/airbnb/enzyme/pull/1187, I found that the problem is that the iterable support that was implemented for Enzyme relies on the ES6 Symbol API. A polyfill for Symbol makes sense to make it work on our environment, but there are a few reasons why I think a fallback should be added as part of Enzyme instead.

  1. It used to work on v2. Enzyme was able to deal with iterable children even though Symbol API was not available.
  2. React implements a fallback to @@iterator when Symbol API is not available since v 13. Here is a fiddle that shows iterable children support on React 13 https://jsfiddle.net/inucoder/n11gvjgz/ and the source code using @@iterator can be found here https://github.com/facebook/react/blob/v0.13.0/src/utils/getIteratorFn.js
  3. It's not a hard to fix issue that can help make users of Enzyme life easier.

The purposed fix is as follows. In https://github.com/airbnb/enzyme/blob/master/packages/enzyme-adapter-utils/src/Utils.js from enzyme-adapter-utils, we could change the code for isIterable function from

function isIterable(obj) {
  return (
    obj != null &&
    typeof Symbol === 'function' &&
    typeof Symbol.iterator === 'symbol' &&
    typeof obj[Symbol.iterator] === 'function'
  );
}

to

function isIterable(obj) {
  return (
    obj != null && (
      (
        typeof Symbol === 'function' &&
        typeof Symbol.iterator === 'symbol' &&
        typeof obj[Symbol.iterator] === 'function'
      ) ||
      obj['@@iterator']
    )
  );
}

If you guys think it makes sense to include such change, I'm open to submit a PR during this week (our team is looking forward to bump to v3). Thanks so much and keep the great work!

mount shallow help wanted package 0.13 package 0.14 package 15 package 15.4 package 16 v3 bugs

Most helpful comment

@ljharb You could assign it to me if possible, and will submit a PR for it during these days.

All 6 comments

After testing above change, I can make below unit test pass when Symbol API is unavailable.

'use strict';

import Enzyme        from 'enzyme';
import Immutable     from 'immutable';
import Adapter       from 'enzyme-adapter-react-15';
import {isArrayLike} from 'enzyme-adapter-utils';

Enzyme.configure({adapter: new Adapter()});

describe('Enzyme 3', () => {
  it('should play nice with Immutable.List children', () => {
    const children = Immutable.fromJS([1, 2, 3]);

    expect(isArrayLike(children))
      .toBe(true);
  });
});

The real bug is that Immutable should never have installed a @@iterator property in the first place; it was non-standard, and Firefox shouldn't have shipped it either.

However, since React 13+ supports it, we unfortunately have to as well.

@ljharb You could assign it to me if possible, and will submit a PR for it during these days.

I am also experiencing this exact problem; it's good to see there's already a fix ready to be shipped. Any idea when this is going to land in master?

Hi @ljharb, any chance this one can get a couple more reviews and be released soon? Would really appreciate it. And glad that will help others like @anthonyhastings as well!

Fixed in #1334.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

heikkimu picture heikkimu  路  3Comments

modemuser picture modemuser  路  3Comments

blainekasten picture blainekasten  路  3Comments

benadamstyles picture benadamstyles  路  3Comments

mattkauffman23 picture mattkauffman23  路  3Comments