Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Fix] reduce/reduceRight: follow Array#reduce when omitting initialValue #673

Merged
merged 1 commit into from
Sep 1, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions docs/api/ReactWrapper/reduce.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,7 @@ following arguments:
- `node` (`ReactWrapper`): A wrapper around the current node being processed
- `index` (`Number`): The index of the current node being processed

2. `initialValue` (`T` [optional]): If provided, this will be passed in as the first argument to the
first invocation of the reducing function.
2. `initialValue` (`T` [optional]): If provided, this will be passed in as the first argument to the first invocation of the reducing function. If omitted, the first `node` will be provided and the iteration will begin on the second node in the collection.



Expand Down
3 changes: 1 addition & 2 deletions docs/api/ReactWrapper/reduceRight.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,7 @@ following arguments:
- `node` (`ReactWrapper`): A wrapper around the current node being processed
- `index` (`Number`): The index of the current node being processed

2. `initialValue` (`T` [optional]): If provided, this will be passed in as the first argument to the
first invocation of the reducing function.
2. `initialValue` (`T` [optional]): If provided, this will be passed in as the first argument to the first invocation of the reducing function. If omitted, the first `node` will be provided and the iteration will begin on the second node in the collection.



Expand Down
3 changes: 1 addition & 2 deletions docs/api/ShallowWrapper/reduce.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,7 @@ following arguments:
- `node` (`ShallowWrapper`): A wrapper around the current node being processed
- `index` (`Number`): The index of the current node being processed

2. `initialValue` (`T` [optional]): If provided, this will be passed in as the first argument to the
first invocation of the reducing function.
2. `initialValue` (`T` [optional]): If provided, this will be passed in as the first argument to the first invocation of the reducing function. If omitted, the first `node` will be provided and the iteration will begin on the second node in the collection.



Expand Down
3 changes: 1 addition & 2 deletions docs/api/ShallowWrapper/reduceRight.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,7 @@ following arguments:
- `node` (`ShallowWrapper`): A wrapper around the current node being processed
- `index` (`Number`): The index of the current node being processed

2. `initialValue` (`T` [optional]): If provided, this will be passed in as the first argument to the
first invocation of the reducing function.
2. `initialValue` (`T` [optional]): If provided, this will be passed in as the first argument to the first invocation of the reducing function. If omitted, the first `node` will be provided and the iteration will begin on the second node in the collection.



Expand Down
52 changes: 52 additions & 0 deletions packages/enzyme-test-suite/test/ReactWrapper-spec.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ import {
import { ITERATOR_SYMBOL, sym } from 'enzyme/build/Utils';
import { REACT013, REACT014, REACT16, is } from './_helpers/version';

const getElementPropSelector = prop => x => x.props[prop];
const getWrapperPropSelector = prop => x => x.prop(prop);

describeWithDOM('mount', () => {
describe('top level wrapper', () => {
it('does what i expect', () => {
Expand Down Expand Up @@ -2348,6 +2351,10 @@ describeWithDOM('mount', () => {
});

describe('.reduce(fn[, initialValue])', () => {
it('has the right length', () => {
expect(ReactWrapper.prototype.reduce).to.have.lengthOf(1);
});

it('should call a function with a wrapper for each node in the wrapper', () => {
const wrapper = mount(
<div>
Expand Down Expand Up @@ -2388,9 +2395,33 @@ describeWithDOM('mount', () => {
baz: 'foo hoo',
});
});

it('allows the initialValue to be omitted', () => {
const one = (<div id="bax" className="foo qoo" />);
const two = (<div id="bar" className="foo boo" />);
const three = (<div id="baz" className="foo hoo" />);
const wrapper = mount(
<div>
{one}
{two}
{three}
</div>,
);
const counter = (<noscript id="counter" />);
const result = wrapper
.find('.foo')
.reduce((acc, n) => [].concat(acc, n, new ReactWrapper(counter)))
.map(getWrapperPropSelector('id'));

expect(result).to.eql([one, two, counter, three, counter].map(getElementPropSelector('id')));
});
});

describe('.reduceRight(fn[, initialValue])', () => {
it('has the right length', () => {
expect(ReactWrapper.prototype.reduceRight).to.have.lengthOf(1);
});

it('should call a function with a wrapper for each node in the wrapper in reverse', () => {
const wrapper = mount(
<div>
Expand Down Expand Up @@ -2431,6 +2462,27 @@ describeWithDOM('mount', () => {
baz: 'foo hoo',
});
});

it('allows the initialValue to be omitted', () => {
const one = (<div id="bax" className="foo qoo" />);
const two = (<div id="bar" className="foo boo" />);
const three = (<div id="baz" className="foo hoo" />);
const wrapper = mount(
<div>
{one}
{two}
{three}
</div>,
);

const counter = (<noscript id="counter" />);
const result = wrapper
.find('.foo')
.reduceRight((acc, n) => [].concat(acc, n, new ReactWrapper(counter)))
.map(getWrapperPropSelector('id'));

expect(result).to.eql([three, two, counter, one, counter].map(getElementPropSelector('id')));
});
});

describe('.slice([begin[, end]])', () => {
Expand Down
51 changes: 51 additions & 0 deletions packages/enzyme-test-suite/test/ShallowWrapper-spec.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ import { REACT013, REACT014, REACT16, is } from './_helpers/version';
// we should be able to go un-skip all of the tests that are skipped with this flag.
const BATCHING = !REACT16;

const getElementPropSelector = prop => x => x.props[prop];
const getWrapperPropSelector = prop => x => x.prop(prop);

describe('shallow', () => {
describe('top level wrapper', () => {
it('does what i expect', () => {
Expand Down Expand Up @@ -2131,6 +2134,10 @@ describe('shallow', () => {
});

describe('.reduce(fn[, initialValue])', () => {
it('has the right length', () => {
expect(ShallowWrapper.prototype.reduce).to.have.lengthOf(1);
});

it('should call a function with a wrapper for each node in the wrapper', () => {
const wrapper = shallow(
<div>
Expand Down Expand Up @@ -2174,9 +2181,33 @@ describe('shallow', () => {
baz: 'foo hoo',
});
});

it('allows the initialValue to be omitted', () => {
const one = (<div id="bax" className="foo qoo" />);
const two = (<div id="bar" className="foo boo" />);
const three = (<div id="baz" className="foo hoo" />);
const wrapper = shallow(
<div>
{one}
{two}
{three}
</div>,
);
const counter = (<noscript id="counter" />);
const result = wrapper
.find('.foo')
.reduce((acc, n) => [].concat(acc, n, new ShallowWrapper(counter)))
.map(getWrapperPropSelector('id'));

expect(result).to.eql([one, two, counter, three, counter].map(getElementPropSelector('id')));
});
});

describe('.reduceRight(fn[, initialValue])', () => {
it('has the right length', () => {
expect(ShallowWrapper.prototype.reduceRight).to.have.lengthOf(1);
});

it('should call a function with a wrapper for each node in the wrapper in reverse', () => {
const wrapper = shallow(
<div>
Expand Down Expand Up @@ -2220,6 +2251,26 @@ describe('shallow', () => {
baz: 'foo hoo',
});
});

it('allows the initialValue to be omitted', () => {
const one = (<div id="bax" className="foo qoo" />);
const two = (<div id="bar" className="foo boo" />);
const three = (<div id="baz" className="foo hoo" />);
const wrapper = shallow(
<div>
{one}
{two}
{three}
</div>,
);
const counter = (<noscript id="counter" />);
const result = wrapper
.find('.foo')
.reduceRight((acc, n) => [].concat(acc, n, new ShallowWrapper(counter)))
.map(getWrapperPropSelector('id'));

expect(result).to.eql([three, two, counter, one, counter].map(getElementPropSelector('id')));
});
});

describe('.slice([begin[, end]])', () => {
Expand Down
36 changes: 26 additions & 10 deletions packages/enzyme/src/ReactWrapper.js
Original file line number Diff line number Diff line change
Expand Up @@ -783,11 +783,19 @@ class ReactWrapper {
* @param {*} initialValue - the initial value
* @returns {*}
*/
reduce(fn, initialValue) {
return this.getNodesInternal().reduce(
(accum, n, i) => fn.call(this, accum, this.wrap(n), i),
initialValue,
);
reduce(fn, initialValue = undefined) {
if (arguments.length > 1) {
return this.getNodesInternal().reduce(
(accum, n, i) => fn.call(this, accum, this.wrap(n), i),
initialValue,
);
}
return this.getNodesInternal().reduce((accum, n, i) => fn.call(
this,
i === 1 ? this.wrap(accum) : accum,
this.wrap(n),
i,
));
}

/**
Expand All @@ -798,11 +806,19 @@ class ReactWrapper {
* @param {*} initialValue - the initial value
* @returns {*}
*/
reduceRight(fn, initialValue) {
return this.getNodesInternal().reduceRight(
(accum, n, i) => fn.call(this, accum, this.wrap(n), i),
initialValue,
);
reduceRight(fn, initialValue = undefined) {
if (arguments.length > 1) {
return this.getNodesInternal().reduceRight(
(accum, n, i) => fn.call(this, accum, this.wrap(n), i),
initialValue,
);
}
return this.getNodesInternal().reduceRight((accum, n, i) => fn.call(
this,
i === 1 ? this.wrap(accum) : accum,
this.wrap(n),
i,
));
}

/**
Expand Down
36 changes: 26 additions & 10 deletions packages/enzyme/src/ShallowWrapper.js
Original file line number Diff line number Diff line change
Expand Up @@ -892,11 +892,19 @@ class ShallowWrapper {
* @param {*} initialValue - the initial value
* @returns {*}
*/
reduce(fn, initialValue) {
return this.getNodesInternal().reduce(
(accum, n, i) => fn.call(this, accum, this.wrap(n), i),
initialValue,
);
reduce(fn, initialValue = undefined) {
if (arguments.length > 1) {
return this.getNodesInternal().reduce(
(accum, n, i) => fn.call(this, accum, this.wrap(n), i),
initialValue,
);
}
return this.getNodesInternal().reduce((accum, n, i) => fn.call(
this,
i === 1 ? this.wrap(accum) : accum,
this.wrap(n),
i,
));
}

/**
Expand All @@ -907,11 +915,19 @@ class ShallowWrapper {
* @param {*} initialValue - the initial value
* @returns {*}
*/
reduceRight(fn, initialValue) {
return this.getNodesInternal().reduceRight(
(accum, n, i) => fn.call(this, accum, this.wrap(n), i),
initialValue,
);
reduceRight(fn, initialValue = undefined) {
if (arguments.length > 1) {
return this.getNodesInternal().reduceRight(
(accum, n, i) => fn.call(this, accum, this.wrap(n), i),
initialValue,
);
}
return this.getNodesInternal().reduceRight((accum, n, i) => fn.call(
this,
i === 1 ? this.wrap(accum) : accum,
this.wrap(n),
i,
));
}

/**
Expand Down