Skip to content

Commit 5686e34

Browse files
authored
Uses new deep clone library (#69)
1 parent 0474203 commit 5686e34

File tree

4 files changed

+229
-117
lines changed

4 files changed

+229
-117
lines changed

package-lock.json

Lines changed: 63 additions & 17 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "substate",
3-
"version": "9.0.0-alpha.1",
3+
"version": "9.0.0-alpha.2",
44
"description": "Simple State Management with Optional Deep Cloning",
55
"main": "dist/index.js",
66
"types": "dist/index.d.ts",
@@ -12,7 +12,7 @@
1212
"scripts": {
1313
"test": "jest",
1414
"build": "rollup -c",
15-
"test.dev": "jest --watch",
15+
"test.watch": "jest --watch",
1616
"pre": "npm test && npm run build && npm publish --tag next",
1717
"safe-publish": "npm test && npm run build && npm publish"
1818
},
@@ -32,8 +32,8 @@
3232
"license": "MIT",
3333
"devDependencies": {
3434
"@babel/preset-env": "^7.10.2",
35+
"@types/clone-deep": "^4.0.4",
3536
"@types/jest": "^29.5.12",
36-
"@types/rfdc": "^1.1.0",
3737
"husky": "^4.2.5",
3838
"jest": "^29.7.0",
3939
"prettier": "^2.0.5",
@@ -47,8 +47,8 @@
4747
"typescript": "^5.3.3"
4848
},
4949
"dependencies": {
50-
"object-bystring": "^5.0.1",
51-
"rfdc": "^1.3.1"
50+
"clone-deep": "^4.0.1",
51+
"object-bystring": "^6.0.1"
5252
},
5353
"husky": {
5454
"hooks": {

src/index.test.ts

Lines changed: 120 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,6 @@
11
//FizzBuzz.test.ts
22
/// <reference types="jest" />
3-
import substate from "./index";
4-
5-
const func1 = jest.fn((x) => {
6-
x.count ? (x.count = ++x.count) : (x.count = 1);
7-
});
8-
const func2 = jest.fn((x) => {
9-
x.count2 ? ++x.count2 : (x.count2 = 1);
10-
});
3+
import Substate, { ISubstate } from "./index";
114

125
const STATE = {
136
name: "Thomas",
@@ -19,70 +12,135 @@ const STATE = {
1912
},
2013
};
2114

22-
const A = new substate({
23-
name: "HamburgerStore",
24-
defaultDeep: true,
25-
state: STATE,
26-
beforeUpdate: [func1],
27-
afterUpdate: [func2],
28-
});
15+
let A: ISubstate;
16+
let func1: jest.Mock;
17+
let func2: jest.Mock;
18+
let func3: jest.Mock;
19+
let func4: jest.Mock;
2920

30-
/** initialization tests */
31-
test("creates new instance of substate", () => {
32-
expect(A instanceof substate).toBe(true);
33-
});
21+
describe("Substate instantiation", () => {
22+
beforeEach(() => {
23+
func1 = jest.fn();
24+
func2 = jest.fn();
25+
func3 = jest.fn();
26+
func4 = jest.fn();
3427

35-
test("expects store to have name", () => {
36-
expect(A.name).toBe("HamburgerStore");
37-
});
28+
A = new Substate({
29+
name: "HamburgerStore",
30+
defaultDeep: true,
31+
state: STATE,
32+
beforeUpdate: [func1, func3],
33+
afterUpdate: [func2, func4],
34+
});
35+
});
36+
test("creates new instance of substate", () => {
37+
expect(A instanceof Substate).toBe(true);
38+
});
3839

39-
test("events to contain UPDATE_STATE on initialization", () => {
40-
expect(A.events.UPDATE_STATE).toHaveLength(1);
41-
});
40+
test("expects store to have name", () => {
41+
expect(A.name).toBe("HamburgerStore");
42+
});
4243

43-
test("get props to return correct value", () => {
44-
expect(A.getProp("nested.double.reason")).toBe("Just the start");
44+
test("events to contain UPDATE_STATE on initialization", () => {
45+
expect(A.events.UPDATE_STATE).toHaveLength(1);
46+
});
4547
});
4648

47-
test("getCurrentState returns current state and fires middleware", () => {
48-
expect(A.getCurrentState()).toMatchObject(STATE);
49-
A.emit("UPDATE_STATE", { timeOfFun: new Date().toISOString() });
50-
expect(func1).toHaveBeenCalledTimes(1);
51-
expect(func2).toHaveBeenCalledTimes(1);
52-
});
49+
describe("Substate getters", () => {
50+
beforeEach(() => {
51+
func1 = jest.fn();
52+
func2 = jest.fn();
53+
func3 = jest.fn();
54+
func4 = jest.fn();
5355

54-
test("getState returns correct state from array", () => {
55-
expect(A.getState(0)).toMatchObject(STATE);
56-
});
56+
A = new Substate({
57+
name: "HamburgerStore",
58+
defaultDeep: true,
59+
state: STATE,
60+
beforeUpdate: [func1, func3],
61+
afterUpdate: [func2, func4],
62+
});
63+
});
5764

58-
test("deep clone works and does not alter older nested state", () => {
59-
const NEWTEXT = "This has changed";
60-
A.emit("UPDATE_STATE", { "nested.double.reason": NEWTEXT });
61-
expect(func1).toHaveBeenCalledTimes(2);
62-
expect(func2).toHaveBeenCalledTimes(2);
63-
expect(A.getState(0)).not.toBe(NEWTEXT);
64-
});
65+
test("get props to return correct value", () => {
66+
expect(A.getProp("nested.double.reason")).toBe("Just the start");
67+
});
6568

66-
// FIXME: This test is not working as expected
67-
test("updateState updates state and fires middleware", () => {
68-
const NEWTEXT = "This has changed";
69-
A.updateState({ "nested.double.reason": NEWTEXT });
70-
expect(func1).toHaveBeenCalledTimes(3);
71-
expect(func2).toHaveBeenCalledTimes(3);
72-
});
69+
test("getCurrentState returns current state and fires middleware", () => {
70+
expect(A.getCurrentState()).toMatchObject(STATE);
71+
A.emit("UPDATE_STATE", { timeOfFun: new Date().toISOString() });
72+
expect(func1).toHaveBeenCalledTimes(1);
73+
expect(func2).toHaveBeenCalledTimes(1);
74+
expect(func3).toHaveBeenCalledTimes(1);
75+
expect(func4).toHaveBeenCalledTimes(1);
76+
});
7377

74-
test("callback fires for custom $type", () => {
75-
const myMock = jest.fn();
76-
const DATEUPDATED = "DATE_UPDATED";
77-
A.on(DATEUPDATED, myMock);
78-
A.emit("UPDATE_STATE", { timeOfFun: new Date(), $type: DATEUPDATED });
79-
expect(myMock).toHaveBeenCalled();
78+
test("getState returns correct state from array", () => {
79+
expect(A.getState(0)).toMatchObject(STATE);
80+
});
8081
});
8182

82-
test("callback for custom $type contains correct $type value", () => {
83-
const myMock = jest.fn();
84-
const DATEUPDATED = "DATE_UPDATED";
85-
A.on(DATEUPDATED, myMock);
86-
A.emit("UPDATE_STATE", { timeOfFun: new Date(), $type: DATEUPDATED });
87-
expect(A.getProp("$type")).toBe(DATEUPDATED);
83+
describe("Substate state management", () => {
84+
beforeEach(() => {
85+
func1 = jest.fn();
86+
func2 = jest.fn();
87+
func3 = jest.fn();
88+
func4 = jest.fn();
89+
90+
A = new Substate({
91+
name: "HamburgerStore",
92+
defaultDeep: true,
93+
state: STATE,
94+
beforeUpdate: [func1, func3],
95+
afterUpdate: [func2, func4],
96+
});
97+
});
98+
99+
test("deep clone does not alter older nested state", () => {
100+
const NEWTEXT = "This has changed";
101+
A.emit("UPDATE_STATE", { "nested.double.reason": NEWTEXT });
102+
expect(A.getState(0)).not.toMatchObject(A.getCurrentState());
103+
expect(A.getState(0)).not.toMatchObject(A.getCurrentState());
104+
});
105+
106+
test("update via string notation works", () => {
107+
const NEWTEXT = "This has changed";
108+
A.emit("UPDATE_STATE", { "nested.double": NEWTEXT });
109+
expect(A.getProp("nested.double")).toMatch(NEWTEXT);
110+
});
111+
112+
test("updateState updates state updates nested string", () => {
113+
const NEWTEXT = "foobar";
114+
A.updateState({ "nested.double": NEWTEXT });
115+
expect(A.getCurrentState().nested.double).toBe(NEWTEXT);
116+
});
117+
118+
test("updateState fires middleware", () => {
119+
const NEWTEXT = "foobar";
120+
A.updateState({ "nested.double": NEWTEXT });
121+
expect(func1).toHaveBeenCalledTimes(1);
122+
expect(func2).toHaveBeenCalledTimes(1);
123+
expect(func3).toHaveBeenCalledTimes(1);
124+
expect(func4).toHaveBeenCalledTimes(1);
125+
});
126+
127+
test("callback fires for custom $type", () => {
128+
const myMock = jest.fn();
129+
const DATEUPDATED = "DATE_UPDATED";
130+
A.on(DATEUPDATED, myMock);
131+
A.emit("UPDATE_STATE", { timeOfFun: new Date(), $type: DATEUPDATED });
132+
expect(myMock).toHaveBeenCalled();
133+
});
134+
135+
test("UPDATE_STATE emit sets $type", () => {
136+
const DATEUPDATED = "DATE_UPDATED";
137+
A.emit("UPDATE_STATE", { timeOfFun: new Date(), $type: DATEUPDATED });
138+
expect(A.getProp("$type")).toMatch(DATEUPDATED);
139+
});
140+
141+
test("Update state sets $type value", () => {
142+
const DATEUPDATED = "DATE_UPDATED";
143+
A.updateState({ timeOfFun: new Date(), $type: DATEUPDATED });
144+
expect(A.getProp("$type")).toMatch(DATEUPDATED);
145+
});
88146
});

0 commit comments

Comments
 (0)