Repository: ViacomInc/data-point (js)

Issue:
Find reducers can't return falsy values
**Problem description**:

```js
const reducer = find(x => x === 0)
const input = [0, 1, 2]
// this should return 0, but it returns undefined instead
dataPoint.resolve(reducer, input)
```

**Suggested solution**:

Refactor the `ReducerFilter#resolve` function.

Pull request:
fix(data-point): Allow find reducers to return falsy values
**What**:

`find` reducers can now return falsy values.

**Why**:

closes #256

**How**:

Refactors `FindReducer#resolve`

<!-- Have you done all of these things?  -->
**Checklist**:
<!-- add "N/A" to the end of each line that's irrelevant to your changes -->
<!-- to check an item, place an "x" in the box like so: "- [x] Documentation" -->
- [ ] Has Breaking changes n/a
- [ ] Documentation n/a
- [x] Tests
- [x] Ready to be merged <!-- In your opinion, is this ready to be merged as soon as it's reviewed? -->

Patch:
diff --git a/packages/data-point/lib/reducer-types/reducer-helpers/reducer-find/resolve.js b/packages/data-point/lib/reducer-types/reducer-helpers/reducer-find/resolve.js
index 3898485..12d8d07 100644
--- a/packages/data-point/lib/reducer-types/reducer-helpers/reducer-find/resolve.js
+++ b/packages/data-point/lib/reducer-types/reducer-helpers/reducer-find/resolve.js
@@ -15,19 +15,21 @@ function resolve (manager, resolveReducer, accumulator, reducerFind) {
     return Promise.resolve(utils.set(accumulator, 'value', undefined))
   }
 
+  let hasResult = false
   const reducer = reducerFind.reducer
   return Promise.reduce(
     accumulator.value,
     (result, itemValue) => {
+      if (hasResult) {
+        return result
+      }
       const itemContext = utils.set(accumulator, 'value', itemValue)
-      return (
-        result ||
-        resolveReducer(manager, itemContext, reducer).then(res => {
-          return reducerPredicateIsTruthy(reducer, res.value)
-            ? itemValue
-            : undefined
-        })
-      )
+      return resolveReducer(manager, itemContext, reducer).then(res => {
+        if (reducerPredicateIsTruthy(reducer, res.value)) {
+          hasResult = true
+          return itemValue
+        }
+      })
     },
     null
   ).then(result => utils.set(accumulator, 'value', result))


Test patch:
diff --git a/packages/data-point/lib/reducer-types/reducer-helpers/reducer-find/resolve.test.js b/packages/data-point/lib/reducer-types/reducer-helpers/reducer-find/resolve.test.js
index f4cf3c1..a1b5417 100644
--- a/packages/data-point/lib/reducer-types/reducer-helpers/reducer-find/resolve.test.js
+++ b/packages/data-point/lib/reducer-types/reducer-helpers/reducer-find/resolve.test.js
@@ -47,6 +47,17 @@ describe('ReducerFind#resolve', () => {
     )
   })
 
+  test("it should find a matching item that's falsy", () => {
+    const value = [0, 1, 2]
+    const accumulator = AccumulatorFactory.create({ value })
+    const reducer = Factory.create(Reducer.create, input => input === 0)
+    return Resolve.resolve(manager, Reducer.resolve, accumulator, reducer).then(
+      result => {
+        expect(result.value).toBe(0)
+      }
+    )
+  })
+
   test('It should return undefined when no match is found', () => {
     const value = [
       {
@@ -89,6 +100,7 @@ describe('ReducerFind#resolve with reducer objects', () => {
       }
     )
   })
+
   test('it should match the item with truthy keys', () => {
     const value = [
       {