Repository: ViacomInc/data-point
Pull request #385 (2019-08-21 22:02:14)

feat(data-point): add ReducerConstnat support
<!--
Thanks for your interest in the project. We appreciate bugs filed and PRs submitted!

Please make sure that you are familiar with and follow the Code of Conduct for
this project (found in the CODE_OF_CONDUCT.md file).

Also, please make sure you're familiar with and follow the instructions in the
contributing guidelines (found in the CONTRIBUTING.md file).

Please fill out the information below to expedite the review and (hopefully)
merge of your pull request!

BREAKING CHANGES:

If your PR includes a breaking change, please submit it with a codemod under
data-point-codemods that will help users upgrade their codebase.

Breaking changes without a codemod will not be accepted unless a codemod is not
viable or does not apply to the specific situation.
-->

<!-- What changes are being made? (What feature/bug is being fixed here?) -->
**What**:

Adds ReducerConstant, its a dependency for porting the ReducerObject

<!-- 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
- [ ] Documentation
- [x] Tests
- [x] Ready to be merged <!-- In your opinion, is this ready to be merged as soon as it's reviewed? -->
- [ ] Added username to **all-contributors** list

<!-- feel free to add additional comments -->


codecov[bot]: # [Codecov](https://codecov.io/gh/ViacomInc/data-point/pull/385?src=pr&el=h1) Report
> Merging [#385](https://codecov.io/gh/ViacomInc/data-point/pull/385?src=pr&el=desc) into [canary](https://codecov.io/gh/ViacomInc/data-point/commit/952c62fc8b066cf95daa184c6b159f8c787c2778?src=pr&el=desc) will **not change** coverage.
> The diff coverage is `100%`.

[![Impacted file tree graph](https://codecov.io/gh/ViacomInc/data-point/pull/385/graphs/tree.svg?width=650&token=LYxItnrx4i&height=150&src=pr)](https://codecov.io/gh/ViacomInc/data-point/pull/385?src=pr&el=tree)

```diff
@@          Coverage Diff          @@
##           canary   #385   +/-   ##
=====================================
  Coverage     100%   100%           
=====================================
  Files          12     15    +3     
  Lines         243    256   +13     
  Branches       37     39    +2     
=====================================
+ Hits          243    256   +13
```


| [Impacted Files](https://codecov.io/gh/ViacomInc/data-point/pull/385?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [packages/data-point/src/Reducer.js](https://codecov.io/gh/ViacomInc/data-point/pull/385/diff?src=pr&el=tree#diff-cGFja2FnZXMvZGF0YS1wb2ludC9zcmMvUmVkdWNlci5qcw==) | `100% <100%> (ø)` | :arrow_up: |
| [...s/data-point/src/reducer-helpers/constant/index.js](https://codecov.io/gh/ViacomInc/data-point/pull/385/diff?src=pr&el=tree#diff-cGFja2FnZXMvZGF0YS1wb2ludC9zcmMvcmVkdWNlci1oZWxwZXJzL2NvbnN0YW50L2luZGV4Lmpz) | `100% <100%> (ø)` | |
| [packages/data-point/src/is-reducer-constant.js](https://codecov.io/gh/ViacomInc/data-point/pull/385/diff?src=pr&el=tree#diff-cGFja2FnZXMvZGF0YS1wb2ludC9zcmMvaXMtcmVkdWNlci1jb25zdGFudC5qcw==) | `100% <100%> (ø)` | |
| [...ata-point/src/reducer-helpers/constant/constant.js](https://codecov.io/gh/ViacomInc/data-point/pull/385/diff?src=pr&el=tree#diff-cGFja2FnZXMvZGF0YS1wb2ludC9zcmMvcmVkdWNlci1oZWxwZXJzL2NvbnN0YW50L2NvbnN0YW50Lmpz) | `100% <100%> (ø)` | |

------

[Continue to review full report at Codecov](https://codecov.io/gh/ViacomInc/data-point/pull/385?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/ViacomInc/data-point/pull/385?src=pr&el=footer). Last update [952c62f...eaed196](https://codecov.io/gh/ViacomInc/data-point/pull/385?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).


Patch:
diff --git a/packages/data-point/src/Reducer.js b/packages/data-point/src/Reducer.js
index a7315a6..4fc7b05 100644
--- a/packages/data-point/src/Reducer.js
+++ b/packages/data-point/src/Reducer.js
@@ -25,6 +25,10 @@ class Reducer {
     });
   }
 
+  static isReducer(value) {
+    return !!value && value[IS_REDUCER] === true;
+  }
+
   async resolveReducer(accumulator, resolveReducer) {
     return this.resolve(accumulator, resolveReducer);
   }
diff --git a/packages/data-point/src/is-reducer-constant.js b/packages/data-point/src/is-reducer-constant.js
new file mode 100644
index 0000000..b131a23
--- /dev/null
+++ b/packages/data-point/src/is-reducer-constant.js
@@ -0,0 +1,7 @@
+const { Reducer } = require("./Reducer");
+
+function isReducerConstant(value) {
+  return Reducer.isReducer(value) && value.type === "constant";
+}
+
+module.exports = isReducerConstant;
diff --git a/packages/data-point/src/reducer-helpers/constant/constant.js b/packages/data-point/src/reducer-helpers/constant/constant.js
new file mode 100644
index 0000000..9651262
--- /dev/null
+++ b/packages/data-point/src/reducer-helpers/constant/constant.js
@@ -0,0 +1,30 @@
+const cloneDeep = require("lodash/cloneDeep");
+
+const { Reducer } = require("../../Reducer");
+
+class ReducerConstant extends Reducer {
+  constructor(spec) {
+    super("constant", undefined, spec);
+    // We clone the source to truly respect the nature of a constant, if the
+    // original source is ever changed the data integrity of the constant
+    // should be kept
+    this.constantValue = cloneDeep(spec);
+  }
+
+  static create(spec) {
+    return new ReducerConstant(spec);
+  }
+
+  /**
+   * @returns {any} deep cloned version of the original source
+   */
+  resolve() {
+    // this clone happens so any future changes to the output do not
+    // affect the original value of this.constantValue
+    return cloneDeep(this.constantValue);
+  }
+}
+
+module.exports = {
+  ReducerConstant
+};
diff --git a/packages/data-point/src/reducer-helpers/constant/index.js b/packages/data-point/src/reducer-helpers/constant/index.js
new file mode 100644
index 0000000..532163e
--- /dev/null
+++ b/packages/data-point/src/reducer-helpers/constant/index.js
@@ -0,0 +1,3 @@
+const { ReducerConstant } = require("./constant");
+
+module.exports = ReducerConstant.create;


Test patch:
diff --git a/packages/data-point/src/Reducer.test.js b/packages/data-point/src/Reducer.test.js
index c369c44..b6d27ae 100644
--- a/packages/data-point/src/Reducer.test.js
+++ b/packages/data-point/src/Reducer.test.js
@@ -46,6 +46,16 @@ describe("Reducer", () => {
     });
   });
 
+  describe("isReducer", () => {
+    it("should check if an object is a reducer or not", async () => {
+      const reducer = createReducer();
+
+      expect(Reducer.isReducer(reducer)).toEqual(true);
+      expect(Reducer.isReducer({})).toEqual(false);
+      expect(Reducer.isReducer(undefined)).toEqual(false);
+    });
+  });
+
   describe("resolveReducer", () => {
     it("should call resolve method", async () => {
       const reducer = createReducer();
diff --git a/packages/data-point/src/is-reducer-constant.test.js b/packages/data-point/src/is-reducer-constant.test.js
new file mode 100644
index 0000000..fc51a0d
--- /dev/null
+++ b/packages/data-point/src/is-reducer-constant.test.js
@@ -0,0 +1,10 @@
+const isReducerConstant = require("./is-reducer-constant");
+const { Reducer } = require("./Reducer");
+const constant = require("./reducer-helpers/constant");
+
+describe("isReducerConstant", () => {
+  it("should testName", () => {
+    expect(isReducerConstant(constant(true))).toEqual(true);
+    expect(isReducerConstant(new Reducer())).toEqual(false);
+  });
+});
diff --git a/packages/data-point/src/reducer-helpers/constant/constant.test.js b/packages/data-point/src/reducer-helpers/constant/constant.test.js
new file mode 100644
index 0000000..311d020
--- /dev/null
+++ b/packages/data-point/src/reducer-helpers/constant/constant.test.js
@@ -0,0 +1,61 @@
+const { ReducerConstant } = require("./constant");
+
+describe("ReducerConstant", () => {
+  describe("constructor", () => {
+    it("should set type to 'constant'", () => {
+      const reducer = new ReducerConstant("value");
+      expect(reducer.type).toEqual("constant");
+    });
+
+    it("should set constantValue to source received", () => {
+      const reducer = new ReducerConstant("value");
+      expect(reducer.constantValue).toEqual("value");
+    });
+
+    it("should set constantValue to be deep cloned from source received", () => {
+      const sourceObject = {
+        test: "test"
+      };
+      const reducer = new ReducerConstant(sourceObject);
+
+      sourceObject.mutateSource = true;
+
+      expect(reducer.constantValue).not.toHaveProperty("mutateSource", true);
+      expect(reducer.constantValue).toEqual({
+        test: "test"
+      });
+    });
+  });
+
+  describe("create", () => {
+    it("should create new instance", () => {
+      const reducer = ReducerConstant.create("value");
+      expect(reducer.type).toEqual("constant");
+      expect(reducer.constantValue).toEqual("value");
+    });
+  });
+
+  describe("resolve", () => {
+    it("should return provided source", () => {
+      const sourceObject = {
+        test: "test"
+      };
+      const reducer = ReducerConstant.create(sourceObject);
+      expect(reducer.resolve()).toEqual(sourceObject);
+    });
+
+    it("should return deep cloned value", () => {
+      const sourceObject = {
+        test: "test"
+      };
+      const reducer = ReducerConstant.create(sourceObject);
+      const result = reducer.resolve();
+      result.mutateResult = true;
+
+      expect(sourceObject).not.toHaveProperty("mutateResult", true);
+      expect(sourceObject).toEqual({
+        test: "test"
+      });
+    });
+  });
+});