@esportsplus/web-storage 0.3.3 → 0.4.0
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/.github/workflows/bump.yml +2 -2
- package/.github/workflows/dependabot.yml +1 -1
- package/.github/workflows/publish.yml +2 -2
- package/build/constants.d.ts +3 -1
- package/build/constants.js +2 -0
- package/build/drivers/memory.d.ts +16 -0
- package/build/drivers/memory.js +64 -0
- package/build/drivers/sessionstorage.d.ts +19 -0
- package/build/drivers/sessionstorage.js +94 -0
- package/build/index.d.ts +12 -2
- package/build/index.js +271 -31
- package/build/types.d.ts +16 -2
- package/package.json +6 -2
- package/src/constants.ts +3 -1
- package/src/drivers/memory.ts +92 -0
- package/src/drivers/sessionstorage.ts +131 -0
- package/src/index.ts +420 -39
- package/src/types.ts +23 -2
- package/storage/feature-research.md +173 -0
- package/tests/drivers/indexeddb.ts +297 -0
- package/tests/drivers/localstorage.ts +290 -0
- package/tests/drivers/memory.ts +257 -0
- package/tests/drivers/sessionstorage.ts +290 -0
- package/tests/index.ts +1462 -0
- package/vitest.config.ts +16 -0
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
|
2
|
+
|
|
3
|
+
import { LocalStorageDriver } from '~/drivers/localstorage';
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
type TestData = { age: number; name: string; tags: string[] };
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
describe('LocalStorageDriver', () => {
|
|
10
|
+
let driver: LocalStorageDriver<TestData>;
|
|
11
|
+
|
|
12
|
+
beforeEach(() => {
|
|
13
|
+
localStorage.clear();
|
|
14
|
+
driver = new LocalStorageDriver<TestData>('test', 1);
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
describe('all', () => {
|
|
19
|
+
it('returns all stored key-value pairs', async () => {
|
|
20
|
+
await driver.set('name', 'alice');
|
|
21
|
+
await driver.set('age', 30);
|
|
22
|
+
await driver.set('tags', ['a', 'b']);
|
|
23
|
+
|
|
24
|
+
let result = await driver.all();
|
|
25
|
+
|
|
26
|
+
expect(result).toEqual({ age: 30, name: 'alice', tags: ['a', 'b'] });
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
it('returns empty object when storage is empty', async () => {
|
|
30
|
+
let result = await driver.all();
|
|
31
|
+
|
|
32
|
+
expect(result).toEqual({});
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
it('skips entries with unparseable JSON', async () => {
|
|
36
|
+
await driver.set('name', 'alice');
|
|
37
|
+
localStorage.setItem('test:1:age', '{invalid json');
|
|
38
|
+
|
|
39
|
+
let result = await driver.all();
|
|
40
|
+
|
|
41
|
+
expect(result).toEqual({ name: 'alice' });
|
|
42
|
+
});
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
describe('clear', () => {
|
|
47
|
+
it('does NOT remove keys from other drivers', async () => {
|
|
48
|
+
let other = new LocalStorageDriver<TestData>('other', 1);
|
|
49
|
+
|
|
50
|
+
await driver.set('name', 'alice');
|
|
51
|
+
await other.set('name', 'bob');
|
|
52
|
+
await driver.clear();
|
|
53
|
+
|
|
54
|
+
expect(await other.get('name')).toBe('bob');
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
it('removes all prefixed keys', async () => {
|
|
58
|
+
await driver.set('name', 'alice');
|
|
59
|
+
await driver.set('age', 30);
|
|
60
|
+
await driver.clear();
|
|
61
|
+
|
|
62
|
+
expect(await driver.count()).toBe(0);
|
|
63
|
+
expect(await driver.all()).toEqual({});
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
describe('constructor', () => {
|
|
69
|
+
it('creates with correct prefix format name:version:', async () => {
|
|
70
|
+
let d = new LocalStorageDriver<TestData>('myapp', 2);
|
|
71
|
+
|
|
72
|
+
await d.set('name', 'test');
|
|
73
|
+
|
|
74
|
+
expect(localStorage.getItem('myapp:2:name')).toBe('"test"');
|
|
75
|
+
});
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
describe('count', () => {
|
|
80
|
+
it('returns 0 when empty', async () => {
|
|
81
|
+
expect(await driver.count()).toBe(0);
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
it('returns correct count of stored items', async () => {
|
|
85
|
+
await driver.set('name', 'alice');
|
|
86
|
+
await driver.set('age', 30);
|
|
87
|
+
|
|
88
|
+
expect(await driver.count()).toBe(2);
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
describe('delete', () => {
|
|
94
|
+
it('handles deleting non-existent keys without error', async () => {
|
|
95
|
+
await expect(driver.delete(['name', 'age'])).resolves.toBeUndefined();
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
it('removes specified keys', async () => {
|
|
99
|
+
await driver.set('name', 'alice');
|
|
100
|
+
await driver.set('age', 30);
|
|
101
|
+
await driver.set('tags', ['a']);
|
|
102
|
+
await driver.delete(['name', 'tags']);
|
|
103
|
+
|
|
104
|
+
expect(await driver.get('name')).toBeUndefined();
|
|
105
|
+
expect(await driver.get('tags')).toBeUndefined();
|
|
106
|
+
expect(await driver.get('age')).toBe(30);
|
|
107
|
+
});
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
describe('keys', () => {
|
|
112
|
+
it('returns all keys without prefix', async () => {
|
|
113
|
+
await driver.set('name', 'alice');
|
|
114
|
+
await driver.set('age', 30);
|
|
115
|
+
|
|
116
|
+
let result = await driver.keys();
|
|
117
|
+
|
|
118
|
+
expect(result.sort()).toEqual(['age', 'name']);
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
it('returns empty array when empty', async () => {
|
|
122
|
+
expect(await driver.keys()).toEqual([]);
|
|
123
|
+
});
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
describe('map', () => {
|
|
128
|
+
it('iterates over all entries with correct value, key, and index', async () => {
|
|
129
|
+
await driver.set('age', 25);
|
|
130
|
+
await driver.set('name', 'alice');
|
|
131
|
+
|
|
132
|
+
let entries: { i: number; key: keyof TestData; value: TestData[keyof TestData] }[] = [];
|
|
133
|
+
|
|
134
|
+
await driver.map((value, key, i) => {
|
|
135
|
+
entries.push({ i, key, value });
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
expect(entries).toHaveLength(2);
|
|
139
|
+
|
|
140
|
+
entries.sort((a, b) => (a.key as string).localeCompare(b.key as string));
|
|
141
|
+
|
|
142
|
+
expect(entries[0]).toEqual({ i: expect.any(Number), key: 'age', value: 25 });
|
|
143
|
+
expect(entries[1]).toEqual({ i: expect.any(Number), key: 'name', value: 'alice' });
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
it('does not invoke callback on empty store', async () => {
|
|
147
|
+
let called = false;
|
|
148
|
+
|
|
149
|
+
await driver.map(() => {
|
|
150
|
+
called = true;
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
expect(called).toBe(false);
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
it('skips entries with unparseable values', async () => {
|
|
157
|
+
await driver.set('name', 'alice');
|
|
158
|
+
localStorage.setItem('test:1:age', 'not-json');
|
|
159
|
+
|
|
160
|
+
let keys: (keyof TestData)[] = [];
|
|
161
|
+
|
|
162
|
+
await driver.map((_value, key) => {
|
|
163
|
+
keys.push(key);
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
expect(keys).toEqual(['name']);
|
|
167
|
+
});
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
describe('only', () => {
|
|
172
|
+
it('returns empty Map when no keys match', async () => {
|
|
173
|
+
await driver.set('name', 'alice');
|
|
174
|
+
|
|
175
|
+
let result = await driver.only(['age', 'tags']);
|
|
176
|
+
|
|
177
|
+
expect(result.size).toBe(0);
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
it('returns Map with only requested keys', async () => {
|
|
181
|
+
await driver.set('name', 'alice');
|
|
182
|
+
await driver.set('age', 30);
|
|
183
|
+
await driver.set('tags', ['a']);
|
|
184
|
+
|
|
185
|
+
let result = await driver.only(['name', 'tags']);
|
|
186
|
+
|
|
187
|
+
expect(result.size).toBe(2);
|
|
188
|
+
expect(result.get('name')).toBe('alice');
|
|
189
|
+
expect(result.get('tags')).toEqual(['a']);
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
it('skips keys that do not exist', async () => {
|
|
193
|
+
await driver.set('name', 'alice');
|
|
194
|
+
|
|
195
|
+
let result = await driver.only(['name', 'age']);
|
|
196
|
+
|
|
197
|
+
expect(result.size).toBe(1);
|
|
198
|
+
expect(result.get('name')).toBe('alice');
|
|
199
|
+
expect(result.has('age')).toBe(false);
|
|
200
|
+
});
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
describe('prefix isolation', () => {
|
|
205
|
+
it('two drivers with different name/version do not see each other\'s data', async () => {
|
|
206
|
+
let driverA = new LocalStorageDriver<TestData>('app', 1),
|
|
207
|
+
driverB = new LocalStorageDriver<TestData>('app', 2);
|
|
208
|
+
|
|
209
|
+
await driverA.set('name', 'alice');
|
|
210
|
+
await driverB.set('name', 'bob');
|
|
211
|
+
|
|
212
|
+
expect(await driverA.get('name')).toBe('alice');
|
|
213
|
+
expect(await driverB.get('name')).toBe('bob');
|
|
214
|
+
expect(await driverA.count()).toBe(1);
|
|
215
|
+
expect(await driverB.count()).toBe(1);
|
|
216
|
+
});
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
describe('replace', () => {
|
|
221
|
+
it('replaces multiple entries at once', async () => {
|
|
222
|
+
await driver.replace([
|
|
223
|
+
['name', 'alice'],
|
|
224
|
+
['age', 30],
|
|
225
|
+
['tags', ['x', 'y']]
|
|
226
|
+
]);
|
|
227
|
+
|
|
228
|
+
expect(await driver.get('name')).toBe('alice');
|
|
229
|
+
expect(await driver.get('age')).toBe(30);
|
|
230
|
+
expect(await driver.get('tags')).toEqual(['x', 'y']);
|
|
231
|
+
});
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
|
|
235
|
+
describe('set / get', () => {
|
|
236
|
+
it('overwrites existing key', async () => {
|
|
237
|
+
await driver.set('name', 'alice');
|
|
238
|
+
await driver.set('name', 'bob');
|
|
239
|
+
|
|
240
|
+
expect(await driver.get('name')).toBe('bob');
|
|
241
|
+
expect(await driver.count()).toBe(1);
|
|
242
|
+
});
|
|
243
|
+
|
|
244
|
+
it('returns false when setItem throws', async () => {
|
|
245
|
+
let spy = vi.spyOn(localStorage, 'setItem').mockImplementationOnce(() => {
|
|
246
|
+
throw new Error('QuotaExceededError');
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
expect(await driver.set('name', 'alice')).toBe(false);
|
|
250
|
+
|
|
251
|
+
spy.mockRestore();
|
|
252
|
+
});
|
|
253
|
+
|
|
254
|
+
it('returns true on successful set', async () => {
|
|
255
|
+
expect(await driver.set('name', 'alice')).toBe(true);
|
|
256
|
+
});
|
|
257
|
+
|
|
258
|
+
it('returns undefined for non-existent key', async () => {
|
|
259
|
+
expect(await driver.get('name')).toBeUndefined();
|
|
260
|
+
});
|
|
261
|
+
|
|
262
|
+
it('sets and retrieves a number value', async () => {
|
|
263
|
+
await driver.set('age', 42);
|
|
264
|
+
|
|
265
|
+
expect(await driver.get('age')).toBe(42);
|
|
266
|
+
});
|
|
267
|
+
|
|
268
|
+
it('sets and retrieves a string value', async () => {
|
|
269
|
+
await driver.set('name', 'alice');
|
|
270
|
+
|
|
271
|
+
expect(await driver.get('name')).toBe('alice');
|
|
272
|
+
});
|
|
273
|
+
|
|
274
|
+
it('sets and retrieves an array value', async () => {
|
|
275
|
+
await driver.set('tags', ['a', 'b', 'c']);
|
|
276
|
+
|
|
277
|
+
expect(await driver.get('tags')).toEqual(['a', 'b', 'c']);
|
|
278
|
+
});
|
|
279
|
+
|
|
280
|
+
it('sets and retrieves an object value', async () => {
|
|
281
|
+
type ObjData = { meta: { nested: boolean; value: number } };
|
|
282
|
+
|
|
283
|
+
let objDriver = new LocalStorageDriver<ObjData>('obj', 1);
|
|
284
|
+
|
|
285
|
+
await objDriver.set('meta', { nested: true, value: 99 });
|
|
286
|
+
|
|
287
|
+
expect(await objDriver.get('meta')).toEqual({ nested: true, value: 99 });
|
|
288
|
+
});
|
|
289
|
+
});
|
|
290
|
+
});
|
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
import { beforeEach, describe, expect, it } from 'vitest';
|
|
2
|
+
|
|
3
|
+
import { MemoryDriver } from '~/drivers/memory';
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
type TestData = { age: number; name: string; tags: string[] };
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
describe('MemoryDriver', () => {
|
|
10
|
+
let driver: MemoryDriver<TestData>;
|
|
11
|
+
|
|
12
|
+
beforeEach(async () => {
|
|
13
|
+
driver = new MemoryDriver<TestData>('test', 1);
|
|
14
|
+
await driver.clear();
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
describe('all', () => {
|
|
19
|
+
it('returns all stored key-value pairs', async () => {
|
|
20
|
+
await driver.set('name', 'alice');
|
|
21
|
+
await driver.set('age', 30);
|
|
22
|
+
await driver.set('tags', ['a', 'b']);
|
|
23
|
+
|
|
24
|
+
let result = await driver.all();
|
|
25
|
+
|
|
26
|
+
expect(result).toEqual({ age: 30, name: 'alice', tags: ['a', 'b'] });
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
it('returns empty object when storage is empty', async () => {
|
|
30
|
+
let result = await driver.all();
|
|
31
|
+
|
|
32
|
+
expect(result).toEqual({});
|
|
33
|
+
});
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
describe('clear', () => {
|
|
38
|
+
it('removes all entries', async () => {
|
|
39
|
+
await driver.set('name', 'alice');
|
|
40
|
+
await driver.set('age', 30);
|
|
41
|
+
await driver.clear();
|
|
42
|
+
|
|
43
|
+
expect(await driver.count()).toBe(0);
|
|
44
|
+
expect(await driver.all()).toEqual({});
|
|
45
|
+
});
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
describe('constructor', () => {
|
|
50
|
+
it('creates with empty store', async () => {
|
|
51
|
+
let d = new MemoryDriver<TestData>('myapp', 2);
|
|
52
|
+
|
|
53
|
+
expect(await d.count()).toBe(0);
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
describe('count', () => {
|
|
59
|
+
it('returns 0 when empty', async () => {
|
|
60
|
+
expect(await driver.count()).toBe(0);
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
it('returns correct count of stored items', async () => {
|
|
64
|
+
await driver.set('name', 'alice');
|
|
65
|
+
await driver.set('age', 30);
|
|
66
|
+
|
|
67
|
+
expect(await driver.count()).toBe(2);
|
|
68
|
+
});
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
describe('delete', () => {
|
|
73
|
+
it('handles deleting non-existent keys without error', async () => {
|
|
74
|
+
await expect(driver.delete(['name', 'age'])).resolves.toBeUndefined();
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
it('removes specified keys', async () => {
|
|
78
|
+
await driver.set('name', 'alice');
|
|
79
|
+
await driver.set('age', 30);
|
|
80
|
+
await driver.set('tags', ['a']);
|
|
81
|
+
await driver.delete(['name', 'tags']);
|
|
82
|
+
|
|
83
|
+
expect(await driver.get('name')).toBeUndefined();
|
|
84
|
+
expect(await driver.get('tags')).toBeUndefined();
|
|
85
|
+
expect(await driver.get('age')).toBe(30);
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
describe('isolation', () => {
|
|
91
|
+
it('two drivers with different names do not share data', async () => {
|
|
92
|
+
let driverA = new MemoryDriver<TestData>('app-a', 1),
|
|
93
|
+
driverB = new MemoryDriver<TestData>('app-b', 1);
|
|
94
|
+
|
|
95
|
+
await driverA.clear();
|
|
96
|
+
await driverB.clear();
|
|
97
|
+
await driverA.set('name', 'alice');
|
|
98
|
+
await driverB.set('name', 'bob');
|
|
99
|
+
|
|
100
|
+
expect(await driverA.get('name')).toBe('alice');
|
|
101
|
+
expect(await driverB.get('name')).toBe('bob');
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
it('two drivers with same name share data', async () => {
|
|
105
|
+
let driverA = new MemoryDriver<TestData>('shared', 1),
|
|
106
|
+
driverB = new MemoryDriver<TestData>('shared', 1);
|
|
107
|
+
|
|
108
|
+
await driverA.clear();
|
|
109
|
+
await driverA.set('name', 'alice');
|
|
110
|
+
|
|
111
|
+
expect(await driverB.get('name')).toBe('alice');
|
|
112
|
+
});
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
describe('keys', () => {
|
|
117
|
+
it('returns all keys', async () => {
|
|
118
|
+
await driver.set('name', 'alice');
|
|
119
|
+
await driver.set('age', 30);
|
|
120
|
+
|
|
121
|
+
let result = await driver.keys();
|
|
122
|
+
|
|
123
|
+
expect(result.sort()).toEqual(['age', 'name']);
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
it('returns empty array when empty', async () => {
|
|
127
|
+
expect(await driver.keys()).toEqual([]);
|
|
128
|
+
});
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
describe('map', () => {
|
|
133
|
+
it('iterates over all entries with correct value, key, and index', async () => {
|
|
134
|
+
await driver.set('age', 25);
|
|
135
|
+
await driver.set('name', 'alice');
|
|
136
|
+
|
|
137
|
+
let entries: { i: number; key: keyof TestData; value: TestData[keyof TestData] }[] = [];
|
|
138
|
+
|
|
139
|
+
await driver.map((value, key, i) => {
|
|
140
|
+
entries.push({ i, key, value });
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
expect(entries).toHaveLength(2);
|
|
144
|
+
|
|
145
|
+
entries.sort((a, b) => (a.key as string).localeCompare(b.key as string));
|
|
146
|
+
|
|
147
|
+
expect(entries[0]).toEqual({ i: expect.any(Number), key: 'age', value: 25 });
|
|
148
|
+
expect(entries[1]).toEqual({ i: expect.any(Number), key: 'name', value: 'alice' });
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
it('does not invoke callback on empty store', async () => {
|
|
152
|
+
let called = false;
|
|
153
|
+
|
|
154
|
+
await driver.map(() => {
|
|
155
|
+
called = true;
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
expect(called).toBe(false);
|
|
159
|
+
});
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
describe('only', () => {
|
|
164
|
+
it('returns empty Map when no keys match', async () => {
|
|
165
|
+
await driver.set('name', 'alice');
|
|
166
|
+
|
|
167
|
+
let result = await driver.only(['age', 'tags']);
|
|
168
|
+
|
|
169
|
+
expect(result.size).toBe(0);
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
it('returns Map with only requested keys', async () => {
|
|
173
|
+
await driver.set('name', 'alice');
|
|
174
|
+
await driver.set('age', 30);
|
|
175
|
+
await driver.set('tags', ['a']);
|
|
176
|
+
|
|
177
|
+
let result = await driver.only(['name', 'tags']);
|
|
178
|
+
|
|
179
|
+
expect(result.size).toBe(2);
|
|
180
|
+
expect(result.get('name')).toBe('alice');
|
|
181
|
+
expect(result.get('tags')).toEqual(['a']);
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
it('skips keys that do not exist', async () => {
|
|
185
|
+
await driver.set('name', 'alice');
|
|
186
|
+
|
|
187
|
+
let result = await driver.only(['name', 'age']);
|
|
188
|
+
|
|
189
|
+
expect(result.size).toBe(1);
|
|
190
|
+
expect(result.get('name')).toBe('alice');
|
|
191
|
+
expect(result.has('age')).toBe(false);
|
|
192
|
+
});
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
describe('replace', () => {
|
|
197
|
+
it('replaces multiple entries at once', async () => {
|
|
198
|
+
await driver.replace([
|
|
199
|
+
['name', 'alice'],
|
|
200
|
+
['age', 30],
|
|
201
|
+
['tags', ['x', 'y']]
|
|
202
|
+
]);
|
|
203
|
+
|
|
204
|
+
expect(await driver.get('name')).toBe('alice');
|
|
205
|
+
expect(await driver.get('age')).toBe(30);
|
|
206
|
+
expect(await driver.get('tags')).toEqual(['x', 'y']);
|
|
207
|
+
});
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
|
|
211
|
+
describe('set / get', () => {
|
|
212
|
+
it('overwrites existing key', async () => {
|
|
213
|
+
await driver.set('name', 'alice');
|
|
214
|
+
await driver.set('name', 'bob');
|
|
215
|
+
|
|
216
|
+
expect(await driver.get('name')).toBe('bob');
|
|
217
|
+
expect(await driver.count()).toBe(1);
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
it('returns true on successful set', async () => {
|
|
221
|
+
expect(await driver.set('name', 'alice')).toBe(true);
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
it('returns undefined for non-existent key', async () => {
|
|
225
|
+
expect(await driver.get('name')).toBeUndefined();
|
|
226
|
+
});
|
|
227
|
+
|
|
228
|
+
it('sets and retrieves a number value', async () => {
|
|
229
|
+
await driver.set('age', 42);
|
|
230
|
+
|
|
231
|
+
expect(await driver.get('age')).toBe(42);
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
it('sets and retrieves a string value', async () => {
|
|
235
|
+
await driver.set('name', 'alice');
|
|
236
|
+
|
|
237
|
+
expect(await driver.get('name')).toBe('alice');
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
it('sets and retrieves an array value', async () => {
|
|
241
|
+
await driver.set('tags', ['a', 'b', 'c']);
|
|
242
|
+
|
|
243
|
+
expect(await driver.get('tags')).toEqual(['a', 'b', 'c']);
|
|
244
|
+
});
|
|
245
|
+
|
|
246
|
+
it('sets and retrieves an object value', async () => {
|
|
247
|
+
type ObjData = { meta: { nested: boolean; value: number } };
|
|
248
|
+
|
|
249
|
+
let objDriver = new MemoryDriver<ObjData>('obj', 1);
|
|
250
|
+
|
|
251
|
+
await objDriver.clear();
|
|
252
|
+
await objDriver.set('meta', { nested: true, value: 99 });
|
|
253
|
+
|
|
254
|
+
expect(await objDriver.get('meta')).toEqual({ nested: true, value: 99 });
|
|
255
|
+
});
|
|
256
|
+
});
|
|
257
|
+
});
|