forked from Expensify/react-native-onyx
-
Notifications
You must be signed in to change notification settings - Fork 0
/
LocalForageProviderTest.js
137 lines (116 loc) · 5.27 KB
/
LocalForageProviderTest.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
import _ from 'underscore';
import LocalForageProviderMock from '../../../../lib/storage/providers/LocalForage';
import createDeferredTask from '../../../../lib/createDeferredTask';
import waitForPromisesToResolve from '../../../utils/waitForPromisesToResolve';
describe('storage/providers/LocalForage', () => {
const SAMPLE_ITEMS = [
['string', 'Plain String'],
['array', ['Mixed', {array: [{id: 1}, {id: 2}]}]],
['true', true],
['false', false],
['object', {id: 'Object', nested: {content: 'Nested object'}}],
['number', 100],
];
// For some reason fake timers cause promises to hang
beforeAll(() => jest.useRealTimers());
beforeEach(() => {
jest.clearAllMocks();
LocalForageProviderMock.clear();
LocalForageProviderMock.clear.mockClear();
});
it('multiSet', () => {
// Given multiple pairs to be saved in storage
const pairs = SAMPLE_ITEMS.slice();
// When they are saved
return LocalForageProviderMock.multiSet(pairs).then(() => {
// We expect a call to localForage.setItem for each pair
_.each(pairs, ([key, value]) => expect(LocalForageProviderMock.setItem).toHaveBeenCalledWith(key, value));
});
});
it('multiGet', () => {
// Given we have some data in storage
LocalForageProviderMock.multiSet(SAMPLE_ITEMS);
return waitForPromisesToResolve().then(() => {
// Then multi get should retrieve them
const keys = _.map(SAMPLE_ITEMS, _.head);
return LocalForageProviderMock.multiGet(keys)
.then(pairs => expect(pairs).toEqual(expect.arrayContaining(SAMPLE_ITEMS)));
});
});
it('multiMerge', () => {
// Given existing data in storage
const USER_1 = {
name: 'Tom',
age: 30,
traits: {hair: 'brown'},
};
const USER_2 = {
name: 'Sarah',
age: 25,
traits: {hair: 'black'},
};
LocalForageProviderMock.multiSet([['@USER_1', USER_1], ['@USER_2', USER_2]]);
return waitForPromisesToResolve().then(() => {
LocalForageProviderMock.localForageSet.mockClear();
// Given deltas matching existing structure
const USER_1_DELTA = {
age: 31,
traits: {eyes: 'blue'},
};
const USER_2_DELTA = {
age: 26,
traits: {hair: 'green'},
};
// When data is merged to storage
return LocalForageProviderMock.multiMerge([
['@USER_1', USER_1_DELTA],
['@USER_2', USER_2_DELTA],
]).then(() => {
// Then each existing item should be set with the merged content
expect(LocalForageProviderMock.localForageSet).toHaveBeenNthCalledWith(1,
'@USER_1', {
name: 'Tom',
age: 31,
traits: {
hair: 'brown',
eyes: 'blue',
},
});
expect(LocalForageProviderMock.localForageSet).toHaveBeenNthCalledWith(2,
'@USER_2', {
name: 'Sarah',
age: 26,
traits: {
hair: 'green',
},
});
});
});
});
it('clear', () => {
// We're creating a Promise which we programatically control when to resolve.
const task = createDeferredTask();
// We configure localforage.setItem to return this promise the first time it's called and to otherwise return resolved promises
LocalForageProviderMock.setItem = jest.fn()
.mockReturnValue(Promise.resolve()) // Default behavior
.mockReturnValueOnce(task.promise); // First call behavior
// Make 5 StorageProvider.setItem calls - this adds 5 items to the queue and starts executing the first localForage.setItem
for (let i = 0; i < 5; i++) {
LocalForageProviderMock.setItem(`key${i}`, `value${i}`);
}
// At this point,`localForage.setItem` should have been called once, but we control when it resolves, and we'll keep it unresolved.
// This simulates the 1st localForage.setItem taking a random time.
// We then call StorageProvider.clear() while the first localForage.setItem isn't completed yet.
LocalForageProviderMock.clear();
// Any calls that follow this would have been queued - so we don't expect more than 1 `localForage.setItem` call after the
// first one resolves.
task.resolve();
// waitForPromisesToResolve() makes jest wait for any promises (even promises returned as the result of a promise) to resolve.
// If StorageProvider.clear() does not abort the queue, more localForage.setItem calls would be executed because they would
// be sitting in the setItemQueue
return waitForPromisesToResolve().then(() => {
expect(LocalForageProviderMock.localForageSet).toHaveBeenCalledTimes(0);
expect(LocalForageProviderMock.clear).toHaveBeenCalledTimes(1);
});
});
});