@webkrafters/react-observable-context 5.0.0-rc.2 → 5.0.0-rc.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +17 -4
- package/dist/main/hooks/use-prehooks-ref/index.test.d.ts +0 -1
- package/dist/main/hooks/use-prehooks-ref/index.test.js +0 -21
- package/dist/main/hooks/use-render-key-provider/index.test.d.ts +0 -1
- package/dist/main/hooks/use-render-key-provider/index.test.js +0 -72
- package/dist/main/hooks/use-store/index.test.d.ts +0 -1
- package/dist/main/hooks/use-store/index.test.js +0 -456
- package/dist/main/index.test.d.ts +0 -11
- package/dist/main/index.test.js +0 -1298
- package/dist/main/test-apps/normal.d.ts +0 -36
- package/dist/main/test-apps/normal.js +0 -243
- package/dist/main/test-apps/with-connected-children.d.ts +0 -25
- package/dist/main/test-apps/with-connected-children.js +0 -229
- package/dist/main/test-apps/with-pure-children.d.ts +0 -15
- package/dist/main/test-apps/with-pure-children.js +0 -127
- package/dist/model/storage/index.test.d.ts +0 -1
- package/dist/model/storage/index.test.js +0 -139
- package/dist/test-artifacts/data/create-state-obj.d.ts +0 -58
- package/dist/test-artifacts/data/create-state-obj.js +0 -95
- package/dist/test-artifacts/suppress-render-compat.d.ts +0 -1
- package/dist/test-artifacts/suppress-render-compat.js +0 -7
package/package.json
CHANGED
|
@@ -54,8 +54,21 @@
|
|
|
54
54
|
"typescript": "^5.4.5"
|
|
55
55
|
},
|
|
56
56
|
"files": [
|
|
57
|
-
"
|
|
58
|
-
"
|
|
57
|
+
"logo.png",
|
|
58
|
+
"dist/main/hooks/use-store/index.js",
|
|
59
|
+
"dist/main/hooks/use-store/index.d.ts",
|
|
60
|
+
"dist/main/hooks/use-render-key-provider/index.js",
|
|
61
|
+
"dist/main/hooks/use-render-key-provider/index.d.ts",
|
|
62
|
+
"dist/main/hooks/use-prehooks-ref/index.js",
|
|
63
|
+
"dist/main/hooks/use-prehooks-ref/index.d.ts",
|
|
64
|
+
"dist/model/storage/index.js",
|
|
65
|
+
"dist/model/storage/index.d.ts",
|
|
66
|
+
"dist/main/index.js",
|
|
67
|
+
"dist/main/index.d.ts",
|
|
68
|
+
"dist/index.js",
|
|
69
|
+
"dist/index.d.ts",
|
|
70
|
+
"dist/constants.js",
|
|
71
|
+
"dist/constants.d.ts"
|
|
59
72
|
],
|
|
60
73
|
"homepage": "https://eagleeye.js.org",
|
|
61
74
|
"keywords": [
|
|
@@ -98,5 +111,5 @@
|
|
|
98
111
|
"test:watch": "eslint --fix && jest --updateSnapshot --watchAll"
|
|
99
112
|
},
|
|
100
113
|
"types": "dist/index.d.ts",
|
|
101
|
-
"version": "5.0.0-rc.
|
|
102
|
-
}
|
|
114
|
+
"version": "5.0.0-rc.3"
|
|
115
|
+
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import '../../../test-artifacts/suppress-render-compat';
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
const react_1 = require("@testing-library/react");
|
|
7
|
-
require("../../../test-artifacts/suppress-render-compat");
|
|
8
|
-
const _1 = __importDefault(require("."));
|
|
9
|
-
describe('usePrehooksRef', () => {
|
|
10
|
-
test('retains prehooks prop in a `react-ref` object', () => {
|
|
11
|
-
const PREHOOK = 'PREHOOK_STUB';
|
|
12
|
-
const { result, rerender } = (0, react_1.renderHook)(_1.default, {
|
|
13
|
-
initialProps: PREHOOK
|
|
14
|
-
});
|
|
15
|
-
expect(result.current).toEqual({ current: PREHOOK });
|
|
16
|
-
const PREHOOK2 = 'PREHOOK2_STUB';
|
|
17
|
-
rerender(PREHOOK2);
|
|
18
|
-
expect(result.current).not.toEqual({ current: PREHOOK });
|
|
19
|
-
expect(result.current).toEqual({ current: PREHOOK2 });
|
|
20
|
-
});
|
|
21
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import '../../../test-artifacts/suppress-render-compat';
|
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
const clone_total_1 = __importDefault(require("@webkrafters/clone-total"));
|
|
7
|
-
const _1 = __importDefault(require("."));
|
|
8
|
-
const react_1 = require("@testing-library/react");
|
|
9
|
-
require("../../../test-artifacts/suppress-render-compat");
|
|
10
|
-
describe('useRenderKeyProvider', () => {
|
|
11
|
-
let selectorMap;
|
|
12
|
-
beforeAll(() => { selectorMap = { _a: 'a', _b: 'b', _c: 'c' }; });
|
|
13
|
-
test('calculates new selectors for new selectorMap', () => {
|
|
14
|
-
const initialProps = (0, clone_total_1.default)(selectorMap);
|
|
15
|
-
const { result, rerender } = (0, react_1.renderHook)(_1.default, { initialProps });
|
|
16
|
-
const selectors = result.current;
|
|
17
|
-
const updateProps = { ...selectorMap, _y: 'y', _z: 'z' };
|
|
18
|
-
rerender(updateProps);
|
|
19
|
-
expect(result.current).toEqual(Object.values(updateProps));
|
|
20
|
-
expect(result.current).not.toEqual(selectors);
|
|
21
|
-
expect(result.current).not.toBe(selectors);
|
|
22
|
-
});
|
|
23
|
-
test('ensures no abrupt updates to selectors for new list with same selectorMap', () => {
|
|
24
|
-
const { result, rerender } = (0, react_1.renderHook)(_1.default, { initialProps: selectorMap });
|
|
25
|
-
const selectors = result.current;
|
|
26
|
-
rerender((0, clone_total_1.default)(selectorMap));
|
|
27
|
-
expect(result.current).toBe(selectors);
|
|
28
|
-
});
|
|
29
|
-
describe('productive call', () => {
|
|
30
|
-
let expected;
|
|
31
|
-
beforeAll(() => { expected = ['a', 'b', 'c']; });
|
|
32
|
-
test.each([
|
|
33
|
-
['object', { _a: 'a', _b: 'b', _c: 'c' }],
|
|
34
|
-
['array', ['a', 'b', 'c']]
|
|
35
|
-
])('allows an %s type selectoMap', (label, value) => {
|
|
36
|
-
const { result } = (0, react_1.renderHook)(_1.default, { initialProps: value });
|
|
37
|
-
expect(result.current).toEqual(expected);
|
|
38
|
-
});
|
|
39
|
-
});
|
|
40
|
-
describe.each([
|
|
41
|
-
['undefined', undefined],
|
|
42
|
-
['null', null],
|
|
43
|
-
['[]', []],
|
|
44
|
-
['{}', {}]
|
|
45
|
-
])('empty selectoMap = %s', (label, value) => {
|
|
46
|
-
test('returns empty renderKeys list', () => {
|
|
47
|
-
const { result } = (0, react_1.renderHook)(_1.default, { initialProps: value });
|
|
48
|
-
expect(result.current).toEqual([]);
|
|
49
|
-
});
|
|
50
|
-
});
|
|
51
|
-
describe.each([
|
|
52
|
-
['string', 'abc'],
|
|
53
|
-
['number', 22],
|
|
54
|
-
['function', () => { }],
|
|
55
|
-
['boolean', true],
|
|
56
|
-
['Map', new Map()],
|
|
57
|
-
['Set', new Set()],
|
|
58
|
-
['Uint8Array', new Uint8Array()]
|
|
59
|
-
])('incompatible selectorMap type = %s', (label, value) => {
|
|
60
|
-
test('throws Type error', () => {
|
|
61
|
-
try {
|
|
62
|
-
(0, react_1.renderHook)(_1.default, {
|
|
63
|
-
initialProps: value
|
|
64
|
-
});
|
|
65
|
-
}
|
|
66
|
-
catch (e) {
|
|
67
|
-
expect(e.constructor.name).toEqual('TypeError');
|
|
68
|
-
expect(e.message).toEqual('Incompatible Selector Map type provided.');
|
|
69
|
-
}
|
|
70
|
-
});
|
|
71
|
-
});
|
|
72
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import '../../../test-artifacts/suppress-render-compat';
|
|
@@ -1,456 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
-
if (mod && mod.__esModule) return mod;
|
|
20
|
-
var result = {};
|
|
21
|
-
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
-
__setModuleDefault(result, mod);
|
|
23
|
-
return result;
|
|
24
|
-
};
|
|
25
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
26
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
27
|
-
};
|
|
28
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
|
-
const auto_immutable_1 = __importDefault(require("@webkrafters/auto-immutable"));
|
|
30
|
-
const react_1 = require("@testing-library/react");
|
|
31
|
-
require("../../../test-artifacts/suppress-render-compat");
|
|
32
|
-
const constants_1 = require("../../../constants");
|
|
33
|
-
const _1 = __importStar(require("."));
|
|
34
|
-
const noop = () => { };
|
|
35
|
-
beforeAll(() => { jest.spyOn(_1.deps, 'createStorageKey').mockReturnValue(expect.any(String)); });
|
|
36
|
-
afterAll(jest.restoreAllMocks);
|
|
37
|
-
describe('useStore', () => {
|
|
38
|
-
let initialState;
|
|
39
|
-
beforeAll(() => { initialState = { a: 1 }; });
|
|
40
|
-
describe('fundamentals', () => {
|
|
41
|
-
test('creates a store', () => {
|
|
42
|
-
const { result } = (0, react_1.renderHook)(({ prehooks: p, value: v }) => (0, _1.default)(p, v), {
|
|
43
|
-
initialProps: {
|
|
44
|
-
prehooks: {},
|
|
45
|
-
value: initialState
|
|
46
|
-
}
|
|
47
|
-
});
|
|
48
|
-
expect(result.current).toEqual(expect.objectContaining({
|
|
49
|
-
cache: expect.any(auto_immutable_1.default),
|
|
50
|
-
resetState: expect.any(Function),
|
|
51
|
-
setState: expect.any(Function),
|
|
52
|
-
subscribe: expect.any(Function)
|
|
53
|
-
}));
|
|
54
|
-
});
|
|
55
|
-
test('retains a clone of the initial state in storage', () => {
|
|
56
|
-
const clone = jest.fn().mockReturnValue(initialState);
|
|
57
|
-
const removeItem = noop;
|
|
58
|
-
const setItem = jest.fn();
|
|
59
|
-
(0, react_1.renderHook)(({ prehooks: p, value: v, storage: s }) => (0, _1.default)(p, v, s), {
|
|
60
|
-
initialProps: {
|
|
61
|
-
prehooks: {},
|
|
62
|
-
value: initialState,
|
|
63
|
-
storage: { clone, getItem: () => { }, removeItem, setItem }
|
|
64
|
-
}
|
|
65
|
-
});
|
|
66
|
-
expect(clone).toHaveBeenCalledTimes(1);
|
|
67
|
-
expect(clone).toHaveBeenCalledWith(initialState);
|
|
68
|
-
expect(setItem).toHaveBeenCalledTimes(1);
|
|
69
|
-
expect(setItem.mock.calls[0][1]).toStrictEqual(initialState);
|
|
70
|
-
});
|
|
71
|
-
test('cleans up retained state from storage on store unmount if storage supported', () => {
|
|
72
|
-
const clone = v => v;
|
|
73
|
-
const setItem = noop;
|
|
74
|
-
const removeItem = jest.fn();
|
|
75
|
-
const { unmount } = (0, react_1.renderHook)(({ prehooks: p, value: v, storage: s }) => (0, _1.default)(p, v, s), {
|
|
76
|
-
initialProps: {
|
|
77
|
-
prehooks: {},
|
|
78
|
-
value: initialState,
|
|
79
|
-
storage: { clone, getItem: () => { }, removeItem, setItem }
|
|
80
|
-
}
|
|
81
|
-
});
|
|
82
|
-
expect(removeItem).not.toHaveBeenCalled();
|
|
83
|
-
unmount();
|
|
84
|
-
expect(removeItem).toHaveBeenCalledTimes(1);
|
|
85
|
-
});
|
|
86
|
-
test('merges copies of subsequent value prop updates to state', async () => {
|
|
87
|
-
const setStateSpy = jest.fn();
|
|
88
|
-
const ConnectionMock = {
|
|
89
|
-
disconnect: noop,
|
|
90
|
-
set: setStateSpy
|
|
91
|
-
};
|
|
92
|
-
const ImmutableConnectSpy = jest
|
|
93
|
-
.spyOn(auto_immutable_1.default.prototype, 'connect')
|
|
94
|
-
.mockReturnValue(ConnectionMock);
|
|
95
|
-
const { rerender } = (0, react_1.renderHook)(({ prehooks: p, value: v }) => (0, _1.default)(p, v), {
|
|
96
|
-
initialProps: {
|
|
97
|
-
prehooks: {},
|
|
98
|
-
value: initialState
|
|
99
|
-
}
|
|
100
|
-
});
|
|
101
|
-
expect(setStateSpy).not.toHaveBeenCalled();
|
|
102
|
-
const updateState = { v: 3 };
|
|
103
|
-
rerender({ prehooks: {}, value: updateState });
|
|
104
|
-
expect(setStateSpy).toHaveBeenCalledTimes(1);
|
|
105
|
-
expect(setStateSpy.mock.calls[0][0]).toBe(updateState);
|
|
106
|
-
ImmutableConnectSpy.mockRestore();
|
|
107
|
-
});
|
|
108
|
-
});
|
|
109
|
-
describe('store', () => {
|
|
110
|
-
let storage;
|
|
111
|
-
beforeAll(() => {
|
|
112
|
-
storage = {
|
|
113
|
-
clone: jest.fn().mockReturnValue(initialState),
|
|
114
|
-
getItem: jest.fn().mockReturnValue(initialState),
|
|
115
|
-
removeItem: jest.fn(),
|
|
116
|
-
setItem: jest.fn()
|
|
117
|
-
};
|
|
118
|
-
});
|
|
119
|
-
describe('normal flow', () => {
|
|
120
|
-
let ConnectionMock, ImmutableConnectSpy, initialProps, prehooks, setAddSpy, setDeleteSpy, setStateSpy, store;
|
|
121
|
-
beforeAll(() => {
|
|
122
|
-
jest.clearAllMocks();
|
|
123
|
-
setStateSpy = jest.fn();
|
|
124
|
-
ConnectionMock = {
|
|
125
|
-
disconnect: noop,
|
|
126
|
-
get: expect.anything,
|
|
127
|
-
set: setStateSpy
|
|
128
|
-
};
|
|
129
|
-
ImmutableConnectSpy = jest
|
|
130
|
-
.spyOn(auto_immutable_1.default.prototype, 'connect')
|
|
131
|
-
.mockReturnValue(ConnectionMock);
|
|
132
|
-
setAddSpy = jest.spyOn(Set.prototype, 'add');
|
|
133
|
-
setDeleteSpy = jest.spyOn(Set.prototype, 'delete');
|
|
134
|
-
prehooks = {
|
|
135
|
-
resetState: jest.fn().mockReturnValue(true),
|
|
136
|
-
setState: jest.fn().mockReturnValue(true)
|
|
137
|
-
};
|
|
138
|
-
initialProps = { prehooks, value: initialState, storage };
|
|
139
|
-
const { result } = (0, react_1.renderHook)(({ prehooks: p, storage: s, value: v }) => (0, _1.default)(p, v, s), { initialProps });
|
|
140
|
-
store = result.current;
|
|
141
|
-
});
|
|
142
|
-
afterAll(() => {
|
|
143
|
-
setAddSpy.mockRestore();
|
|
144
|
-
setDeleteSpy.mockRestore();
|
|
145
|
-
ImmutableConnectSpy.mockRestore();
|
|
146
|
-
});
|
|
147
|
-
describe('resetState', () => {
|
|
148
|
-
beforeAll(() => {
|
|
149
|
-
prehooks.resetState.mockClear();
|
|
150
|
-
setStateSpy.mockClear();
|
|
151
|
-
storage.getItem.mockClear();
|
|
152
|
-
store.resetState(ConnectionMock);
|
|
153
|
-
});
|
|
154
|
-
test('obtains initial state from storage', () => {
|
|
155
|
-
expect(storage.getItem).toHaveBeenCalled();
|
|
156
|
-
});
|
|
157
|
-
test('runs the avaiable prehook', () => {
|
|
158
|
-
expect(prehooks.resetState).toHaveBeenCalled();
|
|
159
|
-
});
|
|
160
|
-
test('resets the state if prehook evaluates to true', () => {
|
|
161
|
-
// prehook.resetState had been mocked to return true
|
|
162
|
-
// please see 'prehooks effects' describe block for alternate scenario
|
|
163
|
-
expect(setStateSpy).toHaveBeenCalled();
|
|
164
|
-
});
|
|
165
|
-
describe('with no arguments', () => {
|
|
166
|
-
test('runs the available prehook with an empty update data', () => {
|
|
167
|
-
expect(prehooks.resetState.mock.calls[0][0]).toEqual({});
|
|
168
|
-
});
|
|
169
|
-
test('attempts to update current state with an empty update data', () => {
|
|
170
|
-
expect(setStateSpy.mock.calls[0][0]).toEqual({});
|
|
171
|
-
});
|
|
172
|
-
});
|
|
173
|
-
describe('with arguments', () => {
|
|
174
|
-
let stateKey0, resetData;
|
|
175
|
-
beforeAll(() => {
|
|
176
|
-
prehooks.resetState.mockClear();
|
|
177
|
-
setStateSpy.mockClear();
|
|
178
|
-
stateKey0 = Object.keys(initialState)[0];
|
|
179
|
-
resetData = { [stateKey0]: { [constants_1.REPLACE_TAG]: initialState[stateKey0] } };
|
|
180
|
-
store.resetState(ConnectionMock, [stateKey0]);
|
|
181
|
-
});
|
|
182
|
-
test('runs the available prehook with update data corresponding to resetState argument', () => {
|
|
183
|
-
expect(prehooks.resetState.mock.calls[0][0]).toEqual(resetData);
|
|
184
|
-
});
|
|
185
|
-
test('merges the update data into current state', () => {
|
|
186
|
-
expect(setStateSpy.mock.calls[0][0]).toEqual(resetData);
|
|
187
|
-
});
|
|
188
|
-
describe('containing the `' + constants_1.FULL_STATE_SELECTOR + '` path', () => {
|
|
189
|
-
let initialState, storageCloneMockImpl, storageGetItemMockImpl;
|
|
190
|
-
beforeAll(() => {
|
|
191
|
-
storageCloneMockImpl = storage.clone.getMockImplementation();
|
|
192
|
-
storageGetItemMockImpl = storage.getItem.getMockImplementation();
|
|
193
|
-
prehooks.resetState.mockClear();
|
|
194
|
-
setStateSpy.mockClear();
|
|
195
|
-
initialState = { ...initialState, b: { z: expect.anything() } };
|
|
196
|
-
storage.clone.mockReset().mockReturnValue(initialState);
|
|
197
|
-
storage.getItem.mockReset().mockReturnValue(initialState);
|
|
198
|
-
const { result } = (0, react_1.renderHook)(({ prehooks: p, storage: s, value: v }) => (0, _1.default)(p, v, s), { initialProps: { prehooks, storage, value: initialState } });
|
|
199
|
-
const store = result.current;
|
|
200
|
-
store.resetState(ConnectionMock, ['a', constants_1.FULL_STATE_SELECTOR, 'b.z']);
|
|
201
|
-
});
|
|
202
|
-
afterAll(() => {
|
|
203
|
-
storage.clone.mockReset().mockImplementation(storageCloneMockImpl);
|
|
204
|
-
storage.getItem.mockReset().mockImplementation(storageGetItemMockImpl);
|
|
205
|
-
});
|
|
206
|
-
test('runs the available prehook with update data equaling the initial state', () => {
|
|
207
|
-
expect(prehooks.resetState.mock.calls[0][0])
|
|
208
|
-
.toEqual({ [constants_1.REPLACE_TAG]: initialState });
|
|
209
|
-
});
|
|
210
|
-
test('merges the initial state into current state', () => {
|
|
211
|
-
expect(setStateSpy.mock.calls[0][0])
|
|
212
|
-
.toEqual({ [constants_1.REPLACE_TAG]: initialState });
|
|
213
|
-
});
|
|
214
|
-
});
|
|
215
|
-
});
|
|
216
|
-
describe('path arguments not occurring in intial state', () => {
|
|
217
|
-
let nonInitStatePaths, resetData;
|
|
218
|
-
beforeAll(() => {
|
|
219
|
-
prehooks.resetState.mockClear();
|
|
220
|
-
setStateSpy.mockClear();
|
|
221
|
-
nonInitStatePaths = [
|
|
222
|
-
'a',
|
|
223
|
-
'dsdfd.adfsdff',
|
|
224
|
-
'dsdfd.sfgrwfg'
|
|
225
|
-
];
|
|
226
|
-
resetData = {
|
|
227
|
-
a: { [constants_1.REPLACE_TAG]: initialState.a },
|
|
228
|
-
dsdfd: { [constants_1.DELETE_TAG]: ['adfsdff', 'sfgrwfg'] }
|
|
229
|
-
};
|
|
230
|
-
store.resetState(ConnectionMock, nonInitStatePaths);
|
|
231
|
-
});
|
|
232
|
-
test('are deleted from current state', () => {
|
|
233
|
-
expect(setStateSpy.mock.calls[0][0]).toEqual(resetData);
|
|
234
|
-
});
|
|
235
|
-
});
|
|
236
|
-
describe('with paths containing the `' + constants_1.FULL_STATE_SELECTOR + '` path where initial state is empty', () => {
|
|
237
|
-
let storageCloneMockImpl, storageGetItemMockImpl;
|
|
238
|
-
beforeAll(() => {
|
|
239
|
-
storageCloneMockImpl = storage.clone.getMockImplementation();
|
|
240
|
-
storageGetItemMockImpl = storage.getItem.getMockImplementation();
|
|
241
|
-
prehooks.resetState.mockClear();
|
|
242
|
-
setStateSpy.mockClear();
|
|
243
|
-
storage.clone.mockReset().mockReturnValue();
|
|
244
|
-
storage.getItem.mockReset().mockReturnValue();
|
|
245
|
-
const { result } = (0, react_1.renderHook)(({ prehooks: p, storage: s }) => (0, _1.default)(p, undefined, s), { initialProps: { prehooks, storage } });
|
|
246
|
-
const store = result.current;
|
|
247
|
-
store.resetState(ConnectionMock, ['a', constants_1.FULL_STATE_SELECTOR, 'b.z']);
|
|
248
|
-
});
|
|
249
|
-
afterAll(() => {
|
|
250
|
-
storage.clone.mockReset().mockImplementation(storageCloneMockImpl);
|
|
251
|
-
storage.getItem.mockReset().mockImplementation(storageGetItemMockImpl);
|
|
252
|
-
});
|
|
253
|
-
test('empties the current state', () => {
|
|
254
|
-
expect(setStateSpy.mock.calls[0][0]).toEqual(constants_1.CLEAR_TAG);
|
|
255
|
-
});
|
|
256
|
-
});
|
|
257
|
-
});
|
|
258
|
-
describe('setState', () => {
|
|
259
|
-
describe('normal operations', () => {
|
|
260
|
-
beforeAll(() => {
|
|
261
|
-
prehooks.setState.mockClear();
|
|
262
|
-
setStateSpy.mockClear();
|
|
263
|
-
store.setState(ConnectionMock);
|
|
264
|
-
});
|
|
265
|
-
test('runs the avaiable prehook', () => {
|
|
266
|
-
expect(prehooks.setState).toHaveBeenCalled();
|
|
267
|
-
});
|
|
268
|
-
test('sets the state if prehook evaluates to true', () => {
|
|
269
|
-
// prehook.setState had been mocked to return true
|
|
270
|
-
// please see 'prehooks effects' describe block for alternate scenario
|
|
271
|
-
expect(setStateSpy).toHaveBeenCalled();
|
|
272
|
-
});
|
|
273
|
-
});
|
|
274
|
-
describe('payload', () => {
|
|
275
|
-
beforeEach(() => { setStateSpy.mockClear(); });
|
|
276
|
-
test('can be a single change object', () => {
|
|
277
|
-
const payload = { a: expect.anything() };
|
|
278
|
-
store.setState(ConnectionMock, payload);
|
|
279
|
-
expect(setStateSpy.mock.calls[0][0]).toEqual(payload);
|
|
280
|
-
});
|
|
281
|
-
test('can be an array of change objects', () => {
|
|
282
|
-
const payload = [
|
|
283
|
-
{ a: expect.anything() },
|
|
284
|
-
{ x: expect.anything() }
|
|
285
|
-
];
|
|
286
|
-
store.setState(ConnectionMock, payload);
|
|
287
|
-
expect(setStateSpy.mock.calls[0][0]).toEqual(payload);
|
|
288
|
-
});
|
|
289
|
-
});
|
|
290
|
-
describe('payload translation for compatibility with the cache', () => {
|
|
291
|
-
beforeEach(() => { setStateSpy.mockClear(); });
|
|
292
|
-
test('returns empty payload as-is', () => {
|
|
293
|
-
store.setState(ConnectionMock);
|
|
294
|
-
expect(setStateSpy.mock.calls[0][0]).toEqual(undefined);
|
|
295
|
-
setStateSpy.mockClear();
|
|
296
|
-
store.setState(ConnectionMock, null);
|
|
297
|
-
expect(setStateSpy.mock.calls[0][0]).toEqual(null);
|
|
298
|
-
});
|
|
299
|
-
test('returns non top-level ' + constants_1.FULL_STATE_SELECTOR + ' key bearing payload as-is', () => {
|
|
300
|
-
const payload = {
|
|
301
|
-
a: expect.anything(),
|
|
302
|
-
b: {
|
|
303
|
-
[constants_1.FULL_STATE_SELECTOR]: expect.anything()
|
|
304
|
-
}
|
|
305
|
-
};
|
|
306
|
-
store.setState(ConnectionMock, payload);
|
|
307
|
-
expect(setStateSpy.mock.calls[0][0]).toEqual(payload);
|
|
308
|
-
});
|
|
309
|
-
test('converts all top-level' + constants_1.FULL_STATE_SELECTOR + ' payload keys only', () => {
|
|
310
|
-
const asIsPayload = {
|
|
311
|
-
a: expect.anything(),
|
|
312
|
-
q: {
|
|
313
|
-
[constants_1.FULL_STATE_SELECTOR]: expect.anything()
|
|
314
|
-
}
|
|
315
|
-
};
|
|
316
|
-
store.setState(ConnectionMock, {
|
|
317
|
-
[constants_1.FULL_STATE_SELECTOR]: expect.anything(),
|
|
318
|
-
...asIsPayload
|
|
319
|
-
});
|
|
320
|
-
expect(setStateSpy.mock.calls[0][0]).toEqual({
|
|
321
|
-
[constants_1.GLOBAL_SELECTOR]: expect.anything(),
|
|
322
|
-
...asIsPayload
|
|
323
|
-
});
|
|
324
|
-
});
|
|
325
|
-
test('converts any payload bearing top-level ' + constants_1.FULL_STATE_SELECTOR + ' keys amongst a payload list', () => {
|
|
326
|
-
store.setState(ConnectionMock, [{
|
|
327
|
-
[constants_1.FULL_STATE_SELECTOR]: expect.anything(),
|
|
328
|
-
a: expect.anything()
|
|
329
|
-
}, {
|
|
330
|
-
a: expect.anything()
|
|
331
|
-
}, {
|
|
332
|
-
z: expect.anything(),
|
|
333
|
-
k: expect.anything(),
|
|
334
|
-
[constants_1.FULL_STATE_SELECTOR]: expect.anything(),
|
|
335
|
-
a: expect.anything()
|
|
336
|
-
}, {
|
|
337
|
-
s: expect.anything(),
|
|
338
|
-
t: {
|
|
339
|
-
[constants_1.FULL_STATE_SELECTOR]: expect.anything()
|
|
340
|
-
}
|
|
341
|
-
}, {
|
|
342
|
-
l: [[constants_1.FULL_STATE_SELECTOR]],
|
|
343
|
-
p: expect.anything()
|
|
344
|
-
}]);
|
|
345
|
-
expect(setStateSpy.mock.calls[0][0]).toEqual([{
|
|
346
|
-
[constants_1.GLOBAL_SELECTOR]: expect.anything(),
|
|
347
|
-
a: expect.anything()
|
|
348
|
-
}, {
|
|
349
|
-
a: expect.anything()
|
|
350
|
-
}, {
|
|
351
|
-
z: expect.anything(),
|
|
352
|
-
k: expect.anything(),
|
|
353
|
-
[constants_1.GLOBAL_SELECTOR]: expect.anything(),
|
|
354
|
-
a: expect.anything()
|
|
355
|
-
}, {
|
|
356
|
-
s: expect.anything(),
|
|
357
|
-
t: {
|
|
358
|
-
[constants_1.FULL_STATE_SELECTOR]: expect.anything()
|
|
359
|
-
}
|
|
360
|
-
}, {
|
|
361
|
-
l: [[constants_1.FULL_STATE_SELECTOR]],
|
|
362
|
-
p: expect.anything()
|
|
363
|
-
}]);
|
|
364
|
-
});
|
|
365
|
-
});
|
|
366
|
-
});
|
|
367
|
-
describe('subscribe', () => {
|
|
368
|
-
const LISTENER = 'LISTENER STUB';
|
|
369
|
-
let result;
|
|
370
|
-
beforeAll(() => {
|
|
371
|
-
setAddSpy.mockClear();
|
|
372
|
-
setDeleteSpy.mockClear();
|
|
373
|
-
result = store.subscribe(LISTENER);
|
|
374
|
-
});
|
|
375
|
-
test('adds a new subscriber', () => {
|
|
376
|
-
expect(setAddSpy).toHaveBeenCalled();
|
|
377
|
-
expect(setAddSpy).toHaveBeenCalledWith(LISTENER);
|
|
378
|
-
});
|
|
379
|
-
test('returns a function to unsub the new subscriber', () => {
|
|
380
|
-
expect(result).toBeInstanceOf(Function);
|
|
381
|
-
expect(setDeleteSpy).not.toHaveBeenCalled();
|
|
382
|
-
result();
|
|
383
|
-
expect(setDeleteSpy).toHaveBeenCalledWith(LISTENER);
|
|
384
|
-
});
|
|
385
|
-
});
|
|
386
|
-
});
|
|
387
|
-
describe('prehooks effects', () => {
|
|
388
|
-
let ConnectionMock, ImmutableConnectSpy, setStateSpy, store;
|
|
389
|
-
beforeAll(() => {
|
|
390
|
-
jest.clearAllMocks();
|
|
391
|
-
setStateSpy = jest.fn();
|
|
392
|
-
ConnectionMock = {
|
|
393
|
-
disconnect: noop,
|
|
394
|
-
get: expect.anything,
|
|
395
|
-
set: setStateSpy
|
|
396
|
-
};
|
|
397
|
-
ImmutableConnectSpy = jest
|
|
398
|
-
.spyOn(auto_immutable_1.default.prototype, 'connect')
|
|
399
|
-
.mockReturnValue(ConnectionMock);
|
|
400
|
-
store = (0, react_1.renderHook)(({ prehooks: p, storage: s, value: v }) => (0, _1.default)(p, v, s), {
|
|
401
|
-
initialProps: {
|
|
402
|
-
prehooks: {
|
|
403
|
-
resetState: jest.fn().mockReturnValue(false),
|
|
404
|
-
setState: jest.fn().mockReturnValue(false)
|
|
405
|
-
},
|
|
406
|
-
storage,
|
|
407
|
-
value: initialState
|
|
408
|
-
}
|
|
409
|
-
}).result.current;
|
|
410
|
-
});
|
|
411
|
-
afterAll(() => { ImmutableConnectSpy.mockRestore(); });
|
|
412
|
-
describe('resetState #2', () => {
|
|
413
|
-
test('will not reset the state if prehook evaluates to false', () => {
|
|
414
|
-
// prehooks.resetState had been mocked to return false
|
|
415
|
-
store.resetState(ConnectionMock);
|
|
416
|
-
expect(setStateSpy).not.toHaveBeenCalled();
|
|
417
|
-
});
|
|
418
|
-
test('throws if return type is not boolean', () => {
|
|
419
|
-
const { result } = (0, react_1.renderHook)(({ prehooks: p, storage: s, value: v }) => (0, _1.default)(p, v, s), {
|
|
420
|
-
initialProps: {
|
|
421
|
-
prehooks: {
|
|
422
|
-
resetState: noop,
|
|
423
|
-
setState: () => true
|
|
424
|
-
},
|
|
425
|
-
storage,
|
|
426
|
-
value: initialState
|
|
427
|
-
}
|
|
428
|
-
});
|
|
429
|
-
expect(() => result.current.resetState(ConnectionMock, expect.anything()))
|
|
430
|
-
.toThrow('`resetState` prehook must return a boolean value.');
|
|
431
|
-
});
|
|
432
|
-
});
|
|
433
|
-
describe('setState #2', () => {
|
|
434
|
-
test('will not set the state if prehook evaluates to false', () => {
|
|
435
|
-
// prehooks.setState had been mocked to return false
|
|
436
|
-
store.setState();
|
|
437
|
-
expect(setStateSpy).not.toHaveBeenCalled();
|
|
438
|
-
});
|
|
439
|
-
test('throws if return type is not boolean', () => {
|
|
440
|
-
const { result } = (0, react_1.renderHook)(({ prehooks: p, storage: s, value: v }) => (0, _1.default)(p, v, s), {
|
|
441
|
-
initialProps: {
|
|
442
|
-
prehooks: {
|
|
443
|
-
resetState: () => true,
|
|
444
|
-
setState: noop
|
|
445
|
-
},
|
|
446
|
-
storage,
|
|
447
|
-
value: initialState
|
|
448
|
-
}
|
|
449
|
-
});
|
|
450
|
-
expect(() => result.current.setState(ConnectionMock, expect.anything()))
|
|
451
|
-
.toThrow('`setState` prehook must return a boolean value.');
|
|
452
|
-
});
|
|
453
|
-
});
|
|
454
|
-
});
|
|
455
|
-
});
|
|
456
|
-
});
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import '@testing-library/jest-dom';
|
|
2
|
-
/**
|
|
3
|
-
* @typedef {import('@testing-library/react-hooks').Renderer<TProps>} Renderer
|
|
4
|
-
* @template TProps
|
|
5
|
-
*/
|
|
6
|
-
/**
|
|
7
|
-
* @typedef {import('@testing-library/react-hooks').RenderHookResult<TProps, TValue, TRenderer>} RenderHookResult
|
|
8
|
-
* @template TProps
|
|
9
|
-
* @template TValue
|
|
10
|
-
* @template {Renderer<TProps>} TRenderer
|
|
11
|
-
*/
|