Repository: Yoctol/bottender (ts)

Issue:
context.state should not reference to the initialState when create state 
Should deeply clone the `initialState` and assign it to `context.state`.

Pull request description:
Fix initialState reference
should fix #163 

Patch:
diff --git a/src/context/Context.js b/src/context/Context.js
index 27ac5a34..ca1f1e94 100644
--- a/src/context/Context.js
+++ b/src/context/Context.js
@@ -1,6 +1,7 @@
 /* @flow */
 
 import warning from 'warning';
+import cloneDeep from 'lodash/cloneDeep';
 
 type Options = {|
   client: any,
@@ -32,7 +33,8 @@ export default class Context {
     this._initialState = initialState || {};
 
     if (this._session && !this._session._state) {
-      this._session._state = this._initialState;
+      const sess = this._session;
+      sess._state = cloneDeep(this._initialState);
     }
 
     this.response = {
@@ -109,7 +111,8 @@ export default class Context {
    */
   resetState(): void {
     if (this._session) {
-      this._session._state = this._initialState;
+      const sess = this._session;
+      sess._state = cloneDeep(this._initialState);
     } else {
       warning(
         false,


Test patch:
diff --git a/src/context/__tests__/Context.spec.js b/src/context/__tests__/Context.spec.js
index 070090c9..58105c23 100644
--- a/src/context/__tests__/Context.spec.js
+++ b/src/context/__tests__/Context.spec.js
@@ -43,6 +43,15 @@ describe('state', () => {
       expect(context.state).toEqual(initialState);
     });
 
+    it('should not reference to the initialState', () => {
+      const initialState = { a: 1 };
+
+      const { context } = setup({ initialState });
+
+      expect(context.state).toEqual(initialState);
+      expect(context.state).not.toBe(initialState);
+    });
+
     it('should not do initialize when state exists', () => {
       const state = { a: 1 };
 
@@ -101,6 +110,18 @@ describe('state', () => {
       expect(context.state).toEqual(initialState);
     });
 
+    it('should not reference to initialState', () => {
+      const state = { a: 2 };
+      const initialState = { a: 1 };
+
+      const { context } = setup({ session: { _state: state }, initialState });
+
+      context.resetState();
+
+      expect(context.state).toEqual(initialState);
+      expect(context.state).not.toBe(initialState);
+    });
+
     it('should call warning if dont have session', async () => {
       const { context } = setup({ session: false });