@blac/core 2.0.0-rc-13 → 2.0.0-rc-16
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 +10 -15
- package/src/Blac.ts +38 -71
- package/src/Bloc.ts +8 -9
- package/src/BlocBase.ts +246 -540
- package/src/Cubit.ts +1 -16
- package/src/__tests__/Blac.config.test.ts +10 -17
- package/src/__tests__/Bloc.event.test.ts +27 -52
- package/src/__tests__/BlocBase.subscription.test.ts +349 -0
- package/src/__tests__/Cubit.test.ts +39 -50
- package/src/__tests__/memory-leaks.test.ts +383 -0
- package/src/__tests__/plugins.test.ts +107 -97
- package/src/adapter/BlacAdapter.ts +347 -207
- package/src/adapter/ProxyFactory.ts +196 -255
- package/src/adapter/__tests__/BlacAdapter.test.ts +71 -77
- package/src/adapter/__tests__/ProxyFactory.test.ts +1 -1
- package/src/adapter/index.ts +0 -1
- package/src/errors/BlacError.ts +69 -0
- package/src/errors/ErrorManager.ts +101 -0
- package/src/errors/handleError.ts +114 -0
- package/src/errors/index.ts +13 -0
- package/src/events.ts +7 -1
- package/src/index.ts +7 -1
- package/src/lifecycle/BlocLifecycle.ts +156 -0
- package/src/lifecycle/index.ts +1 -0
- package/src/plugins/BlocPluginRegistry.ts +71 -51
- package/src/plugins/SystemPluginRegistry.ts +63 -13
- package/src/plugins/__tests__/BlocPluginRegistry.test.ts +450 -0
- package/src/plugins/__tests__/SystemPluginRegistry.test.ts +404 -0
- package/src/plugins/types.ts +32 -3
- package/src/subscription/README.md +132 -0
- package/src/subscription/SubscriptionManager.ts +395 -0
- package/src/subscription/__tests__/SubscriptionManager.test.ts +355 -0
- package/src/subscription/index.ts +2 -0
- package/src/subscription/types.ts +90 -0
- package/src/testing.ts +31 -37
- package/src/types.ts +4 -21
- package/src/utils/BatchingManager.ts +59 -0
- package/src/utils/RerenderLogger.ts +265 -0
- package/src/utils/__tests__/generateInstanceId.test.ts +104 -0
- package/src/utils/__tests__/shallowEqual.test.ts +171 -0
- package/src/utils/__tests__/uuid.test.ts +144 -0
- package/src/utils/generateInstanceId.ts +54 -0
- package/src/utils/shallowEqual.ts +1 -1
- package/README.md +0 -329
- package/dist/index.cjs.js +0 -11
- package/dist/index.cjs.js.map +0 -1
- package/dist/index.d.ts +0 -1078
- package/dist/index.es.js +0 -1992
- package/dist/index.es.js.map +0 -1
- package/src/BlacObserver.ts +0 -189
- package/src/__tests__/BlocBase.lifecycle.test.ts +0 -441
- package/src/__tests__/props.test.ts +0 -256
- package/src/adapter/ConsumerTracker.ts +0 -241
- package/src/adapter/__tests__/ConsumerTracker.test.ts +0 -562
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { describe, it, expect, vi, beforeEach
|
|
1
|
+
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
2
2
|
import { Blac } from '../Blac';
|
|
3
3
|
import { Cubit } from '../Cubit';
|
|
4
4
|
import { Bloc } from '../Bloc';
|
|
5
|
-
import { BlacPlugin, BlocPlugin, PluginCapabilities
|
|
5
|
+
import { BlacPlugin, BlocPlugin, PluginCapabilities } from '../plugins';
|
|
6
6
|
import { BlocBase } from '../BlocBase';
|
|
7
7
|
|
|
8
8
|
// Test Cubit
|
|
@@ -10,7 +10,7 @@ class CounterCubit extends Cubit<number> {
|
|
|
10
10
|
constructor() {
|
|
11
11
|
super(0);
|
|
12
12
|
}
|
|
13
|
-
|
|
13
|
+
|
|
14
14
|
increment = () => this.emit(this.state + 1);
|
|
15
15
|
decrement = () => this.emit(this.state - 1);
|
|
16
16
|
setValue = (value: number) => this.emit(value);
|
|
@@ -29,7 +29,7 @@ class SetValue extends CounterEvent {
|
|
|
29
29
|
class CounterBloc extends Bloc<number, CounterEvent> {
|
|
30
30
|
constructor() {
|
|
31
31
|
super(0);
|
|
32
|
-
|
|
32
|
+
|
|
33
33
|
this.on(Increment, (event, emit) => emit(this.state + 1));
|
|
34
34
|
this.on(Decrement, (event, emit) => emit(this.state - 1));
|
|
35
35
|
this.on(SetValue, (event, emit) => emit(event.value));
|
|
@@ -41,31 +41,41 @@ class TestLoggingPlugin implements BlacPlugin {
|
|
|
41
41
|
readonly name = 'logging';
|
|
42
42
|
readonly version = '1.0.0';
|
|
43
43
|
private logLevel: 'debug' | 'info' | 'warn' | 'error';
|
|
44
|
-
|
|
45
|
-
constructor(
|
|
44
|
+
|
|
45
|
+
constructor(
|
|
46
|
+
options: { logLevel?: 'debug' | 'info' | 'warn' | 'error' } = {},
|
|
47
|
+
) {
|
|
46
48
|
this.logLevel = options.logLevel || 'info';
|
|
47
49
|
}
|
|
48
|
-
|
|
50
|
+
|
|
49
51
|
onBlocCreated(bloc: BlocBase<any>): void {
|
|
50
52
|
this.log('debug', `Bloc created: ${bloc._name}:${bloc._id}`);
|
|
51
53
|
}
|
|
52
|
-
|
|
53
|
-
onStateChanged(
|
|
54
|
+
|
|
55
|
+
onStateChanged(
|
|
56
|
+
bloc: BlocBase<any>,
|
|
57
|
+
previousState: any,
|
|
58
|
+
currentState: any,
|
|
59
|
+
): void {
|
|
54
60
|
this.log('debug', `State changed in ${bloc._name}:${bloc._id}`, {
|
|
55
61
|
previousState,
|
|
56
|
-
currentState
|
|
62
|
+
currentState,
|
|
57
63
|
});
|
|
58
64
|
}
|
|
59
|
-
|
|
60
|
-
private log(
|
|
65
|
+
|
|
66
|
+
private log(
|
|
67
|
+
level: 'debug' | 'info' | 'warn' | 'error',
|
|
68
|
+
message: string,
|
|
69
|
+
data?: any,
|
|
70
|
+
): void {
|
|
61
71
|
const levels = ['debug', 'info', 'warn', 'error'];
|
|
62
72
|
const currentLevelIndex = levels.indexOf(this.logLevel);
|
|
63
73
|
const messageLevelIndex = levels.indexOf(level);
|
|
64
|
-
|
|
74
|
+
|
|
65
75
|
if (messageLevelIndex >= currentLevelIndex) {
|
|
66
76
|
const timestamp = new Date().toISOString();
|
|
67
77
|
const logMessage = `[BlaC] [${timestamp}] ${message}`;
|
|
68
|
-
|
|
78
|
+
|
|
69
79
|
switch (level) {
|
|
70
80
|
case 'debug':
|
|
71
81
|
console.debug(logMessage, data);
|
|
@@ -98,14 +108,14 @@ class TestPersistencePlugin<TState> implements BlocPlugin<TState> {
|
|
|
98
108
|
transformState: true,
|
|
99
109
|
interceptEvents: false,
|
|
100
110
|
persistData: true,
|
|
101
|
-
accessMetadata: false
|
|
111
|
+
accessMetadata: false,
|
|
102
112
|
};
|
|
103
|
-
|
|
113
|
+
|
|
104
114
|
private storage: StorageAdapter;
|
|
105
115
|
private key: string;
|
|
106
116
|
private saveDebounceMs: number;
|
|
107
117
|
private saveTimer?: any;
|
|
108
|
-
|
|
118
|
+
|
|
109
119
|
constructor(options: {
|
|
110
120
|
key: string;
|
|
111
121
|
storage?: StorageAdapter;
|
|
@@ -115,20 +125,20 @@ class TestPersistencePlugin<TState> implements BlocPlugin<TState> {
|
|
|
115
125
|
this.storage = options.storage || new MockStorage();
|
|
116
126
|
this.saveDebounceMs = options.saveDebounceMs ?? 100;
|
|
117
127
|
}
|
|
118
|
-
|
|
119
|
-
onAttach(bloc: BlocBase<TState
|
|
128
|
+
|
|
129
|
+
onAttach(bloc: BlocBase<TState>): void {
|
|
120
130
|
const savedData = this.storage.getItem(this.key);
|
|
121
131
|
if (savedData) {
|
|
122
132
|
const restoredState = JSON.parse(savedData);
|
|
123
133
|
(bloc as any)._state = restoredState;
|
|
124
134
|
}
|
|
125
135
|
}
|
|
126
|
-
|
|
136
|
+
|
|
127
137
|
onStateChange(previousState: TState, currentState: TState): void {
|
|
128
138
|
if (this.saveTimer) {
|
|
129
139
|
clearTimeout(this.saveTimer);
|
|
130
140
|
}
|
|
131
|
-
|
|
141
|
+
|
|
132
142
|
if (this.saveDebounceMs > 0) {
|
|
133
143
|
this.saveTimer = setTimeout(() => {
|
|
134
144
|
this.storage.setItem(this.key, JSON.stringify(currentState));
|
|
@@ -147,14 +157,14 @@ class TestValidationPlugin<T> implements BlocPlugin<T> {
|
|
|
147
157
|
transformState: true,
|
|
148
158
|
interceptEvents: false,
|
|
149
159
|
persistData: false,
|
|
150
|
-
accessMetadata: false
|
|
160
|
+
accessMetadata: false,
|
|
151
161
|
};
|
|
152
|
-
|
|
162
|
+
|
|
153
163
|
constructor(private validator: (state: T) => boolean | string) {}
|
|
154
|
-
|
|
164
|
+
|
|
155
165
|
transformState(previousState: T, nextState: T): T {
|
|
156
166
|
const result = this.validator(nextState);
|
|
157
|
-
|
|
167
|
+
|
|
158
168
|
if (result === true) {
|
|
159
169
|
return nextState;
|
|
160
170
|
} else if (result === false) {
|
|
@@ -170,15 +180,15 @@ class TestValidationPlugin<T> implements BlocPlugin<T> {
|
|
|
170
180
|
// Mock storage
|
|
171
181
|
class MockStorage implements StorageAdapter {
|
|
172
182
|
private store = new Map<string, string>();
|
|
173
|
-
|
|
183
|
+
|
|
174
184
|
getItem(key: string): string | null {
|
|
175
185
|
return this.store.get(key) || null;
|
|
176
186
|
}
|
|
177
|
-
|
|
187
|
+
|
|
178
188
|
setItem(key: string, value: string): void {
|
|
179
189
|
this.store.set(key, value);
|
|
180
190
|
}
|
|
181
|
-
|
|
191
|
+
|
|
182
192
|
removeItem(key: string): void {
|
|
183
193
|
this.store.delete(key);
|
|
184
194
|
}
|
|
@@ -188,120 +198,120 @@ describe('New Plugin System', () => {
|
|
|
188
198
|
beforeEach(() => {
|
|
189
199
|
Blac.resetInstance();
|
|
190
200
|
});
|
|
191
|
-
|
|
201
|
+
|
|
192
202
|
describe('System Plugins (BlacPlugin)', () => {
|
|
193
203
|
it('should register and execute system plugins', () => {
|
|
194
204
|
const onBlocCreated = vi.fn();
|
|
195
205
|
const onStateChanged = vi.fn();
|
|
196
|
-
|
|
206
|
+
|
|
197
207
|
const plugin: BlacPlugin = {
|
|
198
208
|
name: 'test-system-plugin',
|
|
199
209
|
version: '1.0.0',
|
|
200
210
|
onBlocCreated,
|
|
201
|
-
onStateChanged
|
|
211
|
+
onStateChanged,
|
|
202
212
|
};
|
|
203
|
-
|
|
213
|
+
|
|
204
214
|
Blac.instance.plugins.add(plugin);
|
|
205
|
-
|
|
215
|
+
|
|
206
216
|
const cubit = Blac.getBloc(CounterCubit);
|
|
207
217
|
expect(onBlocCreated).toHaveBeenCalledWith(cubit);
|
|
208
|
-
|
|
218
|
+
|
|
209
219
|
cubit.increment();
|
|
210
220
|
expect(onStateChanged).toHaveBeenCalledWith(cubit, 0, 1);
|
|
211
221
|
});
|
|
212
|
-
|
|
222
|
+
|
|
213
223
|
it('should handle plugin errors gracefully', () => {
|
|
214
224
|
const errorPlugin: BlacPlugin = {
|
|
215
225
|
name: 'error-plugin',
|
|
216
226
|
version: '1.0.0',
|
|
217
227
|
onBlocCreated: () => {
|
|
218
228
|
throw new Error('Plugin error');
|
|
219
|
-
}
|
|
229
|
+
},
|
|
220
230
|
};
|
|
221
|
-
|
|
231
|
+
|
|
222
232
|
Blac.instance.plugins.add(errorPlugin);
|
|
223
|
-
|
|
233
|
+
|
|
224
234
|
// Should not throw when creating bloc
|
|
225
235
|
expect(() => Blac.getBloc(CounterCubit)).not.toThrow();
|
|
226
236
|
});
|
|
227
|
-
|
|
237
|
+
|
|
228
238
|
it('should execute bootstrap hooks', () => {
|
|
229
239
|
const beforeBootstrap = vi.fn();
|
|
230
240
|
const afterBootstrap = vi.fn();
|
|
231
|
-
|
|
241
|
+
|
|
232
242
|
const plugin: BlacPlugin = {
|
|
233
243
|
name: 'bootstrap-plugin',
|
|
234
244
|
version: '1.0.0',
|
|
235
245
|
beforeBootstrap,
|
|
236
|
-
afterBootstrap
|
|
246
|
+
afterBootstrap,
|
|
237
247
|
};
|
|
238
|
-
|
|
248
|
+
|
|
239
249
|
Blac.resetInstance();
|
|
240
250
|
Blac.instance.plugins.add(plugin);
|
|
241
251
|
Blac.instance.bootstrap();
|
|
242
|
-
|
|
252
|
+
|
|
243
253
|
expect(beforeBootstrap).toHaveBeenCalled();
|
|
244
254
|
expect(afterBootstrap).toHaveBeenCalled();
|
|
245
255
|
});
|
|
246
|
-
|
|
256
|
+
|
|
247
257
|
it('should track metrics', () => {
|
|
248
258
|
const plugin: BlacPlugin = {
|
|
249
259
|
name: 'metrics-plugin',
|
|
250
260
|
version: '1.0.0',
|
|
251
261
|
onBlocCreated: () => {
|
|
252
262
|
// Do something
|
|
253
|
-
}
|
|
263
|
+
},
|
|
254
264
|
};
|
|
255
|
-
|
|
265
|
+
|
|
256
266
|
Blac.instance.plugins.add(plugin);
|
|
257
267
|
Blac.getBloc(CounterCubit);
|
|
258
|
-
|
|
268
|
+
|
|
259
269
|
const metrics = Blac.instance.plugins.getMetrics('metrics-plugin');
|
|
260
270
|
expect(metrics).toBeDefined();
|
|
261
271
|
expect(metrics?.get('onBlocCreated')).toBeDefined();
|
|
262
272
|
expect(metrics?.get('onBlocCreated')?.executionCount).toBe(1);
|
|
263
273
|
});
|
|
264
274
|
});
|
|
265
|
-
|
|
275
|
+
|
|
266
276
|
describe('Bloc Plugins (BlocPlugin)', () => {
|
|
267
277
|
it('should attach plugins to specific blocs', () => {
|
|
268
278
|
const onAttach = vi.fn();
|
|
269
279
|
const onStateChange = vi.fn();
|
|
270
|
-
|
|
280
|
+
|
|
271
281
|
const plugin: BlocPlugin<number> = {
|
|
272
282
|
name: 'test-bloc-plugin',
|
|
273
283
|
version: '1.0.0',
|
|
274
284
|
onAttach,
|
|
275
|
-
onStateChange
|
|
285
|
+
onStateChange,
|
|
276
286
|
};
|
|
277
|
-
|
|
287
|
+
|
|
278
288
|
const cubit = new CounterCubit();
|
|
279
289
|
cubit.addPlugin(plugin);
|
|
280
|
-
|
|
290
|
+
|
|
281
291
|
// Activate the bloc
|
|
282
292
|
Blac.activateBloc(cubit as any);
|
|
283
|
-
|
|
293
|
+
|
|
284
294
|
expect(onAttach).toHaveBeenCalledWith(cubit);
|
|
285
|
-
|
|
295
|
+
|
|
286
296
|
cubit.increment();
|
|
287
297
|
expect(onStateChange).toHaveBeenCalledWith(0, 1);
|
|
288
298
|
});
|
|
289
|
-
|
|
299
|
+
|
|
290
300
|
it('should transform state through plugins', () => {
|
|
291
301
|
const transformPlugin: BlocPlugin<number> = {
|
|
292
302
|
name: 'double-plugin',
|
|
293
303
|
version: '1.0.0',
|
|
294
|
-
transformState: (prev, next) => next * 2
|
|
304
|
+
transformState: (prev, next) => next * 2,
|
|
295
305
|
};
|
|
296
|
-
|
|
306
|
+
|
|
297
307
|
const cubit = new CounterCubit();
|
|
298
308
|
cubit.addPlugin(transformPlugin);
|
|
299
309
|
Blac.activateBloc(cubit as any);
|
|
300
|
-
|
|
310
|
+
|
|
301
311
|
cubit.setValue(5);
|
|
302
312
|
expect(cubit.state).toBe(10); // 5 * 2
|
|
303
313
|
});
|
|
304
|
-
|
|
314
|
+
|
|
305
315
|
it('should transform events through plugins', () => {
|
|
306
316
|
const transformPlugin: BlocPlugin<number, CounterEvent> = {
|
|
307
317
|
name: 'event-doubler',
|
|
@@ -311,21 +321,21 @@ describe('New Plugin System', () => {
|
|
|
311
321
|
return new SetValue(event.value * 2);
|
|
312
322
|
}
|
|
313
323
|
return event;
|
|
314
|
-
}
|
|
324
|
+
},
|
|
315
325
|
};
|
|
316
|
-
|
|
326
|
+
|
|
317
327
|
const bloc = new CounterBloc();
|
|
318
328
|
bloc.addPlugin(transformPlugin);
|
|
319
329
|
Blac.activateBloc(bloc as any);
|
|
320
|
-
|
|
330
|
+
|
|
321
331
|
bloc.add(new SetValue(5));
|
|
322
|
-
|
|
332
|
+
|
|
323
333
|
// Wait for event processing
|
|
324
334
|
setTimeout(() => {
|
|
325
335
|
expect(bloc.state).toBe(10); // 5 * 2
|
|
326
336
|
}, 10);
|
|
327
337
|
});
|
|
328
|
-
|
|
338
|
+
|
|
329
339
|
it('should respect plugin capabilities', () => {
|
|
330
340
|
const readOnlyPlugin: BlocPlugin<number> = {
|
|
331
341
|
name: 'read-only',
|
|
@@ -335,120 +345,120 @@ describe('New Plugin System', () => {
|
|
|
335
345
|
transformState: false,
|
|
336
346
|
interceptEvents: false,
|
|
337
347
|
persistData: false,
|
|
338
|
-
accessMetadata: false
|
|
348
|
+
accessMetadata: false,
|
|
339
349
|
},
|
|
340
350
|
transformState: () => {
|
|
341
351
|
throw new Error('Should not be called');
|
|
342
352
|
},
|
|
343
|
-
onStateChange: vi.fn()
|
|
353
|
+
onStateChange: vi.fn(),
|
|
344
354
|
};
|
|
345
|
-
|
|
355
|
+
|
|
346
356
|
const cubit = new CounterCubit();
|
|
347
357
|
cubit.addPlugin(readOnlyPlugin);
|
|
348
358
|
Blac.activateBloc(cubit as any);
|
|
349
|
-
|
|
359
|
+
|
|
350
360
|
cubit.increment();
|
|
351
361
|
expect(cubit.state).toBe(1); // Transform not applied
|
|
352
362
|
expect(readOnlyPlugin.onStateChange).toHaveBeenCalled();
|
|
353
363
|
});
|
|
354
364
|
});
|
|
355
|
-
|
|
365
|
+
|
|
356
366
|
describe('Example Plugins', () => {
|
|
357
367
|
it('should log with TestLoggingPlugin', () => {
|
|
358
368
|
const consoleSpy = vi.spyOn(console, 'debug');
|
|
359
|
-
|
|
369
|
+
|
|
360
370
|
const plugin = new TestLoggingPlugin({ logLevel: 'debug' });
|
|
361
371
|
Blac.instance.plugins.add(plugin);
|
|
362
|
-
|
|
372
|
+
|
|
363
373
|
const cubit = Blac.getBloc(CounterCubit);
|
|
364
374
|
cubit.increment();
|
|
365
|
-
|
|
375
|
+
|
|
366
376
|
expect(consoleSpy).toHaveBeenCalledWith(
|
|
367
377
|
expect.stringContaining('Bloc created'),
|
|
368
|
-
undefined
|
|
378
|
+
undefined,
|
|
369
379
|
);
|
|
370
|
-
|
|
380
|
+
|
|
371
381
|
consoleSpy.mockRestore();
|
|
372
382
|
});
|
|
373
|
-
|
|
383
|
+
|
|
374
384
|
it('should persist state with TestPersistencePlugin', () => {
|
|
375
385
|
const storage = new MockStorage();
|
|
376
386
|
storage.setItem('counter', '42');
|
|
377
|
-
|
|
387
|
+
|
|
378
388
|
const plugin = new TestPersistencePlugin<number>({
|
|
379
389
|
key: 'counter',
|
|
380
390
|
storage,
|
|
381
|
-
saveDebounceMs: 0
|
|
391
|
+
saveDebounceMs: 0,
|
|
382
392
|
});
|
|
383
|
-
|
|
393
|
+
|
|
384
394
|
const cubit = new CounterCubit();
|
|
385
395
|
cubit.addPlugin(plugin);
|
|
386
396
|
Blac.activateBloc(cubit as any);
|
|
387
|
-
|
|
397
|
+
|
|
388
398
|
// Should restore from storage
|
|
389
399
|
expect(cubit.state).toBe(42);
|
|
390
|
-
|
|
400
|
+
|
|
391
401
|
// Should save new state
|
|
392
402
|
cubit.setValue(100);
|
|
393
|
-
|
|
403
|
+
|
|
394
404
|
// Wait for debounced save
|
|
395
405
|
setTimeout(() => {
|
|
396
406
|
expect(storage.getItem('counter')).toBe('100');
|
|
397
407
|
}, 10);
|
|
398
408
|
});
|
|
399
|
-
|
|
409
|
+
|
|
400
410
|
it('should validate state with TestValidationPlugin', () => {
|
|
401
411
|
const validator = (state: number) => {
|
|
402
412
|
if (state < 0) return 'Value must be non-negative';
|
|
403
413
|
if (state > 100) return 'Value must not exceed 100';
|
|
404
414
|
return true;
|
|
405
415
|
};
|
|
406
|
-
|
|
416
|
+
|
|
407
417
|
const plugin = new TestValidationPlugin(validator);
|
|
408
|
-
|
|
418
|
+
|
|
409
419
|
const cubit = new CounterCubit();
|
|
410
420
|
cubit.addPlugin(plugin);
|
|
411
421
|
Blac.activateBloc(cubit as any);
|
|
412
|
-
|
|
422
|
+
|
|
413
423
|
cubit.setValue(-5);
|
|
414
424
|
expect(cubit.state).toBe(0); // Rejected
|
|
415
|
-
|
|
425
|
+
|
|
416
426
|
cubit.setValue(50);
|
|
417
427
|
expect(cubit.state).toBe(50); // Accepted
|
|
418
|
-
|
|
428
|
+
|
|
419
429
|
cubit.setValue(150);
|
|
420
430
|
expect(cubit.state).toBe(50); // Rejected
|
|
421
431
|
});
|
|
422
432
|
});
|
|
423
|
-
|
|
433
|
+
|
|
424
434
|
describe('Plugin Composition', () => {
|
|
425
435
|
it('should compose multiple bloc plugins', () => {
|
|
426
436
|
const storage = new MockStorage();
|
|
427
|
-
|
|
437
|
+
|
|
428
438
|
const persistencePlugin = new TestPersistencePlugin<number>({
|
|
429
439
|
key: 'validated-counter',
|
|
430
440
|
storage,
|
|
431
|
-
saveDebounceMs: 0
|
|
441
|
+
saveDebounceMs: 0,
|
|
432
442
|
});
|
|
433
|
-
|
|
443
|
+
|
|
434
444
|
const validationPlugin = new TestValidationPlugin<number>(
|
|
435
|
-
(state) => state >= 0 && state <= 10
|
|
445
|
+
(state) => state >= 0 && state <= 10,
|
|
436
446
|
);
|
|
437
|
-
|
|
447
|
+
|
|
438
448
|
const cubit = new CounterCubit();
|
|
439
449
|
cubit.addPlugin(validationPlugin);
|
|
440
450
|
cubit.addPlugin(persistencePlugin);
|
|
441
451
|
Blac.activateBloc(cubit as any);
|
|
442
|
-
|
|
452
|
+
|
|
443
453
|
cubit.setValue(5);
|
|
444
454
|
expect(cubit.state).toBe(5);
|
|
445
|
-
|
|
455
|
+
|
|
446
456
|
cubit.setValue(15);
|
|
447
457
|
expect(cubit.state).toBe(5); // Validation rejected
|
|
448
|
-
|
|
458
|
+
|
|
449
459
|
setTimeout(() => {
|
|
450
460
|
expect(storage.getItem('validated-counter')).toBe('5');
|
|
451
461
|
}, 10);
|
|
452
462
|
});
|
|
453
463
|
});
|
|
454
|
-
});
|
|
464
|
+
});
|