@blac/core 2.0.0-rc-16 → 2.0.0-rc.1

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.
Files changed (157) hide show
  1. package/dist/.tsbuildinfo +1 -0
  2. package/dist/Blac.d.ts +246 -0
  3. package/dist/Blac.d.ts.map +1 -0
  4. package/dist/Blac.js +624 -0
  5. package/dist/Blac.js.map +1 -0
  6. package/dist/Bloc.d.ts +41 -0
  7. package/dist/Bloc.d.ts.map +1 -0
  8. package/dist/Bloc.js +140 -0
  9. package/dist/Bloc.js.map +1 -0
  10. package/dist/BlocBase.d.ts +110 -0
  11. package/dist/BlocBase.d.ts.map +1 -0
  12. package/dist/BlocBase.js +287 -0
  13. package/dist/BlocBase.js.map +1 -0
  14. package/dist/Cubit.d.ts +25 -0
  15. package/dist/Cubit.d.ts.map +1 -0
  16. package/dist/Cubit.js +64 -0
  17. package/dist/Cubit.js.map +1 -0
  18. package/dist/adapter/BlacAdapter.d.ts +67 -0
  19. package/dist/adapter/BlacAdapter.d.ts.map +1 -0
  20. package/dist/adapter/BlacAdapter.js +263 -0
  21. package/dist/adapter/BlacAdapter.js.map +1 -0
  22. package/dist/adapter/ProxyFactory.d.ts +50 -0
  23. package/dist/adapter/ProxyFactory.d.ts.map +1 -0
  24. package/dist/adapter/ProxyFactory.js +150 -0
  25. package/dist/adapter/ProxyFactory.js.map +1 -0
  26. package/{src/adapter/index.ts → dist/adapter/index.d.ts} +1 -0
  27. package/dist/adapter/index.d.ts.map +1 -0
  28. package/dist/adapter/index.js +19 -0
  29. package/dist/adapter/index.js.map +1 -0
  30. package/dist/errors/BlacError.d.ts +38 -0
  31. package/dist/errors/BlacError.d.ts.map +1 -0
  32. package/dist/errors/BlacError.js +55 -0
  33. package/dist/errors/BlacError.js.map +1 -0
  34. package/dist/errors/ErrorManager.d.ts +39 -0
  35. package/dist/errors/ErrorManager.d.ts.map +1 -0
  36. package/dist/errors/ErrorManager.js +91 -0
  37. package/dist/errors/ErrorManager.js.map +1 -0
  38. package/dist/errors/handleError.d.ts +24 -0
  39. package/dist/errors/handleError.d.ts.map +1 -0
  40. package/dist/errors/handleError.js +62 -0
  41. package/dist/errors/handleError.js.map +1 -0
  42. package/dist/errors/index.d.ts +5 -0
  43. package/dist/errors/index.d.ts.map +1 -0
  44. package/dist/errors/index.js +13 -0
  45. package/dist/errors/index.js.map +1 -0
  46. package/{src/events.ts → dist/events.d.ts} +4 -2
  47. package/dist/events.d.ts.map +1 -0
  48. package/dist/events.js +17 -0
  49. package/dist/events.js.map +1 -0
  50. package/dist/index.cjs +38 -0
  51. package/{src/index.ts → dist/index.d.ts} +1 -10
  52. package/dist/index.d.ts.map +1 -0
  53. package/dist/index.js +38 -0
  54. package/dist/index.js.map +1 -0
  55. package/dist/lifecycle/BlocLifecycle.d.ts +51 -0
  56. package/dist/lifecycle/BlocLifecycle.d.ts.map +1 -0
  57. package/dist/lifecycle/BlocLifecycle.js +123 -0
  58. package/dist/lifecycle/BlocLifecycle.js.map +1 -0
  59. package/dist/lifecycle/index.d.ts +2 -0
  60. package/dist/lifecycle/index.d.ts.map +1 -0
  61. package/dist/lifecycle/index.js +18 -0
  62. package/dist/lifecycle/index.js.map +1 -0
  63. package/dist/plugins/BlocPluginRegistry.d.ts +58 -0
  64. package/dist/plugins/BlocPluginRegistry.d.ts.map +1 -0
  65. package/dist/plugins/BlocPluginRegistry.js +201 -0
  66. package/dist/plugins/BlocPluginRegistry.js.map +1 -0
  67. package/dist/plugins/SystemPluginRegistry.d.ts +79 -0
  68. package/dist/plugins/SystemPluginRegistry.d.ts.map +1 -0
  69. package/dist/plugins/SystemPluginRegistry.js +184 -0
  70. package/dist/plugins/SystemPluginRegistry.js.map +1 -0
  71. package/{src/plugins/index.ts → dist/plugins/index.d.ts} +1 -5
  72. package/dist/plugins/index.d.ts.map +1 -0
  73. package/dist/plugins/index.js +26 -0
  74. package/dist/plugins/index.js.map +1 -0
  75. package/dist/plugins/types.d.ts +103 -0
  76. package/dist/plugins/types.d.ts.map +1 -0
  77. package/dist/plugins/types.js +3 -0
  78. package/dist/plugins/types.js.map +1 -0
  79. package/dist/subscription/SubscriptionManager.d.ts +67 -0
  80. package/dist/subscription/SubscriptionManager.d.ts.map +1 -0
  81. package/dist/subscription/SubscriptionManager.js +317 -0
  82. package/dist/subscription/SubscriptionManager.js.map +1 -0
  83. package/{src/subscription/index.ts → dist/subscription/index.d.ts} +1 -0
  84. package/dist/subscription/index.d.ts.map +1 -0
  85. package/dist/subscription/index.js +19 -0
  86. package/dist/subscription/index.js.map +1 -0
  87. package/dist/subscription/types.d.ts +65 -0
  88. package/dist/subscription/types.d.ts.map +1 -0
  89. package/dist/subscription/types.js +3 -0
  90. package/dist/subscription/types.js.map +1 -0
  91. package/dist/testing.d.ts +33 -0
  92. package/dist/testing.d.ts.map +1 -0
  93. package/dist/testing.js +68 -0
  94. package/dist/testing.js.map +1 -0
  95. package/{src/types.ts → dist/types.d.ts} +11 -28
  96. package/dist/types.d.ts.map +1 -0
  97. package/dist/types.js +3 -0
  98. package/dist/types.js.map +1 -0
  99. package/dist/utils/BatchingManager.d.ts +28 -0
  100. package/dist/utils/BatchingManager.d.ts.map +1 -0
  101. package/dist/utils/BatchingManager.js +48 -0
  102. package/dist/utils/BatchingManager.js.map +1 -0
  103. package/dist/utils/RerenderLogger.d.ts +60 -0
  104. package/dist/utils/RerenderLogger.d.ts.map +1 -0
  105. package/dist/utils/RerenderLogger.js +205 -0
  106. package/dist/utils/RerenderLogger.js.map +1 -0
  107. package/dist/utils/generateInstanceId.d.ts +11 -0
  108. package/dist/utils/generateInstanceId.d.ts.map +1 -0
  109. package/dist/utils/generateInstanceId.js +50 -0
  110. package/dist/utils/generateInstanceId.js.map +1 -0
  111. package/dist/utils/shallowEqual.d.ts +9 -0
  112. package/dist/utils/shallowEqual.d.ts.map +1 -0
  113. package/dist/utils/shallowEqual.js +35 -0
  114. package/dist/utils/shallowEqual.js.map +1 -0
  115. package/dist/utils/uuid.d.ts +10 -0
  116. package/dist/utils/uuid.d.ts.map +1 -0
  117. package/dist/utils/uuid.js +24 -0
  118. package/dist/utils/uuid.js.map +1 -0
  119. package/package.json +19 -6
  120. package/src/Blac.ts +0 -802
  121. package/src/Bloc.ts +0 -180
  122. package/src/BlocBase.ts +0 -398
  123. package/src/Cubit.ts +0 -68
  124. package/src/__tests__/Blac.config.test.ts +0 -79
  125. package/src/__tests__/Bloc.event.test.ts +0 -394
  126. package/src/__tests__/BlocBase.subscription.test.ts +0 -349
  127. package/src/__tests__/Cubit.test.ts +0 -462
  128. package/src/__tests__/memory-leaks.test.ts +0 -383
  129. package/src/__tests__/plugins.test.ts +0 -464
  130. package/src/adapter/BlacAdapter.ts +0 -467
  131. package/src/adapter/ProxyFactory.ts +0 -249
  132. package/src/adapter/__tests__/BlacAdapter.test.ts +0 -555
  133. package/src/adapter/__tests__/ProxyFactory.test.ts +0 -655
  134. package/src/errors/BlacError.ts +0 -69
  135. package/src/errors/ErrorManager.ts +0 -101
  136. package/src/errors/handleError.ts +0 -114
  137. package/src/errors/index.ts +0 -13
  138. package/src/lifecycle/BlocLifecycle.ts +0 -156
  139. package/src/lifecycle/index.ts +0 -1
  140. package/src/plugins/BlocPluginRegistry.ts +0 -240
  141. package/src/plugins/SystemPluginRegistry.ts +0 -242
  142. package/src/plugins/__tests__/BlocPluginRegistry.test.ts +0 -450
  143. package/src/plugins/__tests__/SystemPluginRegistry.test.ts +0 -404
  144. package/src/plugins/types.ts +0 -129
  145. package/src/subscription/README.md +0 -132
  146. package/src/subscription/SubscriptionManager.ts +0 -395
  147. package/src/subscription/__tests__/SubscriptionManager.test.ts +0 -355
  148. package/src/subscription/types.ts +0 -90
  149. package/src/testing.ts +0 -246
  150. package/src/utils/BatchingManager.ts +0 -59
  151. package/src/utils/RerenderLogger.ts +0 -265
  152. package/src/utils/__tests__/generateInstanceId.test.ts +0 -104
  153. package/src/utils/__tests__/shallowEqual.test.ts +0 -171
  154. package/src/utils/__tests__/uuid.test.ts +0 -144
  155. package/src/utils/generateInstanceId.ts +0 -54
  156. package/src/utils/shallowEqual.ts +0 -40
  157. package/src/utils/uuid.ts +0 -22
@@ -1,79 +0,0 @@
1
- import { describe, it, expect, beforeEach, afterEach } from 'vitest';
2
- import { Blac, BlacConfig } from '../index';
3
-
4
- describe('Blac.config', () => {
5
- const originalConfig = { ...Blac.config };
6
-
7
- beforeEach(() => {
8
- // Reset to default config before each test
9
- Blac.setConfig({
10
- proxyDependencyTracking: true,
11
- });
12
- });
13
-
14
- afterEach(() => {
15
- // Restore original config after tests
16
- Blac.setConfig(originalConfig);
17
- });
18
-
19
- describe('setConfig', () => {
20
- it('should have default configuration', () => {
21
- expect(Blac.config).toEqual({
22
- proxyDependencyTracking: true,
23
- });
24
- });
25
-
26
- it('should update configuration with partial config', () => {
27
- Blac.setConfig({ proxyDependencyTracking: false });
28
-
29
- expect(Blac.config).toEqual({
30
- proxyDependencyTracking: false,
31
- });
32
- });
33
-
34
- it('should merge configuration properly', () => {
35
- // First set to false
36
- Blac.setConfig({ proxyDependencyTracking: false });
37
-
38
- // Then set empty config - should keep false
39
- Blac.setConfig({});
40
-
41
- expect(Blac.config).toEqual({
42
- proxyDependencyTracking: false,
43
- });
44
- });
45
-
46
- it('should throw error for invalid proxyDependencyTracking type', () => {
47
- expect(() => {
48
- Blac.setConfig({ proxyDependencyTracking: 'true' as any });
49
- }).toThrow('BlacConfig.proxyDependencyTracking must be a boolean');
50
- });
51
-
52
- it('should return a copy of config, not the original', () => {
53
- const config1 = Blac.config;
54
- const config2 = Blac.config;
55
-
56
- expect(config1).not.toBe(config2);
57
- expect(config1).toEqual(config2);
58
- });
59
-
60
- it('should not allow direct modification of config', () => {
61
- const config = Blac.config as any;
62
- config.proxyDependencyTracking = false;
63
-
64
- // Original config should remain unchanged
65
- expect(Blac.config.proxyDependencyTracking).toBe(true);
66
- });
67
- });
68
-
69
- describe('config type exports', () => {
70
- it('should allow typed config usage', () => {
71
- const testConfig: Partial<BlacConfig> = {
72
- proxyDependencyTracking: false,
73
- };
74
-
75
- Blac.setConfig(testConfig);
76
- expect(Blac.config.proxyDependencyTracking).toBe(false);
77
- });
78
- });
79
- });
@@ -1,394 +0,0 @@
1
- import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
2
- import { Bloc } from '../Bloc';
3
- import { Blac } from '../Blac';
4
-
5
- // Define test events
6
- class IncrementEvent {
7
- constructor(public amount: number = 1) {}
8
- }
9
-
10
- class AsyncIncrementEvent {
11
- constructor(
12
- public amount: number,
13
- public delay: number,
14
- ) {}
15
- }
16
-
17
- class DecrementEvent {
18
- constructor(public amount: number = 1) {}
19
- }
20
-
21
- class ErrorEvent {
22
- constructor(public message: string) {}
23
- }
24
-
25
- class CriticalErrorEvent extends Error {
26
- name = 'CriticalError';
27
- constructor(message: string) {
28
- super(message);
29
- }
30
- }
31
-
32
- // Test Bloc implementation
33
- class CounterBloc extends Bloc<
34
- number,
35
- IncrementEvent | AsyncIncrementEvent | DecrementEvent | ErrorEvent
36
- > {
37
- constructor(initialValue = 0) {
38
- super(initialValue);
39
-
40
- // Register event handlers
41
- this.on(IncrementEvent, (event, emit) => {
42
- emit(this.state + event.amount);
43
- });
44
-
45
- this.on(AsyncIncrementEvent, async (event, emit) => {
46
- await new Promise((resolve) => setTimeout(resolve, event.delay));
47
- emit(this.state + event.amount);
48
- });
49
-
50
- this.on(DecrementEvent, (event, emit) => {
51
- emit(this.state - event.amount);
52
- });
53
-
54
- this.on(ErrorEvent, (event, emit) => {
55
- throw new Error(event.message);
56
- });
57
- }
58
- }
59
-
60
- // Bloc with critical error handling
61
- class CriticalErrorBloc extends Bloc<string> {
62
- constructor() {
63
- super('initial');
64
-
65
- this.on(CriticalErrorEvent, (event) => {
66
- throw event;
67
- });
68
- }
69
- }
70
-
71
- describe('Bloc Event Handling', () => {
72
- let bloc: CounterBloc;
73
- let blacInstance: Blac;
74
-
75
- beforeEach(() => {
76
- blacInstance = new Blac({ __unsafe_ignore_singleton: true });
77
- Blac.enableLog = false; // Disable logging for tests
78
- bloc = blacInstance.getBloc(CounterBloc);
79
- });
80
-
81
- afterEach(() => {
82
- vi.clearAllMocks();
83
- });
84
-
85
- describe('Event Handler Registration', () => {
86
- it('should register event handlers with on() method', () => {
87
- expect(bloc.eventHandlers.size).toBe(4); // 4 handlers registered
88
- expect(bloc.eventHandlers.has(IncrementEvent)).toBe(true);
89
- expect(bloc.eventHandlers.has(AsyncIncrementEvent)).toBe(true);
90
- expect(bloc.eventHandlers.has(DecrementEvent)).toBe(true);
91
- expect(bloc.eventHandlers.has(ErrorEvent)).toBe(true);
92
- });
93
-
94
- it('should overwrite existing handler when registering same event type', () => {
95
- const originalHandler = bloc.eventHandlers.get(IncrementEvent);
96
-
97
- // Register new handler for same event
98
- const newHandler = vi.fn();
99
- (bloc as any).on(IncrementEvent, newHandler);
100
-
101
- expect(bloc.eventHandlers.get(IncrementEvent)).toBe(newHandler);
102
- expect(bloc.eventHandlers.get(IncrementEvent)).not.toBe(originalHandler);
103
- });
104
-
105
- it('should handle events with proper type inference', async () => {
106
- const observer = vi.fn();
107
- bloc.subscribe(observer);
108
-
109
- await bloc.add(new IncrementEvent(5));
110
-
111
- expect(observer).toHaveBeenCalledWith(5);
112
- expect(bloc.state).toBe(5);
113
- });
114
- });
115
-
116
- describe('Event Queue and Sequential Processing', () => {
117
- it('should queue events and process them sequentially', async () => {
118
- const observer = vi.fn();
119
- bloc.subscribe(observer);
120
-
121
- // Add multiple events rapidly
122
- const promises = [
123
- bloc.add(new IncrementEvent(1)),
124
- bloc.add(new IncrementEvent(2)),
125
- bloc.add(new IncrementEvent(3)),
126
- ];
127
-
128
- await Promise.all(promises);
129
-
130
- // Should be called 3 times with sequential state updates
131
- expect(observer).toHaveBeenCalledTimes(3);
132
- expect(observer).toHaveBeenNthCalledWith(1, 1);
133
- expect(observer).toHaveBeenNthCalledWith(2, 3);
134
- expect(observer).toHaveBeenNthCalledWith(3, 6);
135
- expect(bloc.state).toBe(6);
136
- });
137
-
138
- it('should process async events in order', async () => {
139
- const observer = vi.fn();
140
- bloc.subscribe(observer);
141
-
142
- // Add async events with different delays
143
- const promises = [
144
- bloc.add(new AsyncIncrementEvent(1, 50)),
145
- bloc.add(new AsyncIncrementEvent(2, 10)),
146
- bloc.add(new AsyncIncrementEvent(3, 30)),
147
- ];
148
-
149
- await Promise.all(promises);
150
-
151
- // Despite different delays, events should process in order
152
- expect(observer).toHaveBeenCalledTimes(3);
153
- expect(observer).toHaveBeenNthCalledWith(1, 1);
154
- expect(observer).toHaveBeenNthCalledWith(2, 3);
155
- expect(observer).toHaveBeenNthCalledWith(3, 6);
156
- });
157
-
158
- it('should handle mixed sync and async events', async () => {
159
- const observer = vi.fn();
160
- bloc.subscribe(observer);
161
-
162
- const promises = [
163
- bloc.add(new IncrementEvent(1)),
164
- bloc.add(new AsyncIncrementEvent(2, 20)),
165
- bloc.add(new DecrementEvent(1)),
166
- bloc.add(new AsyncIncrementEvent(3, 10)),
167
- ];
168
-
169
- await Promise.all(promises);
170
-
171
- expect(observer).toHaveBeenCalledTimes(4);
172
- expect(bloc.state).toBe(5); // 0 + 1 + 2 - 1 + 3 = 5
173
- });
174
- });
175
-
176
- describe('Error Handling', () => {
177
- it('should handle errors in event handlers gracefully', async () => {
178
- const errorSpy = vi.spyOn(Blac, 'error').mockImplementation(() => {});
179
- const observer = vi.fn();
180
- bloc.subscribe(observer);
181
-
182
- await bloc.add(new ErrorEvent('Test error'));
183
-
184
- // Error should be logged but not crash the bloc
185
- expect(errorSpy).toHaveBeenCalled();
186
- expect(observer).not.toHaveBeenCalled(); // No state change
187
- expect(bloc.state).toBe(0); // State unchanged
188
-
189
- // Bloc should still be functional
190
- await bloc.add(new IncrementEvent(1));
191
- expect(bloc.state).toBe(1);
192
- });
193
-
194
- it('should re-throw critical errors', async () => {
195
- const criticalBloc = new CriticalErrorBloc();
196
-
197
- await expect(
198
- criticalBloc.add(new CriticalErrorEvent('Critical failure')),
199
- ).rejects.toThrow('Critical failure');
200
- });
201
-
202
- it('should log warning for unhandled events', async () => {
203
- const warnSpy = vi.spyOn(Blac, 'warn').mockImplementation(() => {});
204
-
205
- // Create event without handler
206
- class UnhandledEvent {}
207
-
208
- await bloc.add(new UnhandledEvent() as any);
209
-
210
- expect(warnSpy).toHaveBeenCalledWith(
211
- expect.stringContaining('No handler registered'),
212
- expect.any(String),
213
- expect.any(Array),
214
- expect.any(String),
215
- expect.any(UnhandledEvent),
216
- );
217
- });
218
- });
219
-
220
- describe('Event Context and Metadata', () => {
221
- it('should pass event instance to state change notifications', async () => {
222
- const observer = vi.fn();
223
- bloc.subscribe(observer);
224
-
225
- const event = new IncrementEvent(10);
226
- await bloc.add(event);
227
-
228
- expect(observer).toHaveBeenCalledWith(10);
229
- });
230
-
231
- it('should maintain correct state context during handler execution', async () => {
232
- let capturedStates: number[] = [];
233
-
234
- // Custom bloc that captures state during handler
235
- class StateCapturingBloc extends Bloc<number> {
236
- constructor() {
237
- super(0);
238
-
239
- this.on(IncrementEvent, (event, emit) => {
240
- capturedStates.push(this.state); // Capture current state
241
- emit(this.state + event.amount);
242
- });
243
- }
244
- }
245
-
246
- const capturingBloc = new StateCapturingBloc();
247
-
248
- await capturingBloc.add(new IncrementEvent(1));
249
- await capturingBloc.add(new IncrementEvent(2));
250
- await capturingBloc.add(new IncrementEvent(3));
251
-
252
- expect(capturedStates).toEqual([0, 1, 3]); // State at time of each handler
253
- expect(capturingBloc.state).toBe(6);
254
- });
255
- });
256
-
257
- describe('Edge Cases', () => {
258
- it('should handle empty event queue gracefully', async () => {
259
- // Process empty queue should not throw
260
- await (bloc as any)._processEventQueue();
261
- expect(bloc.state).toBe(0);
262
- });
263
-
264
- it('should handle rapid event additions during processing', async () => {
265
- const observer = vi.fn();
266
- bloc.subscribe(observer);
267
-
268
- // Custom bloc that adds more events during processing
269
- class ChainReactionBloc extends Bloc<number> {
270
- constructor() {
271
- super(0);
272
-
273
- this.on(IncrementEvent, async (event, emit) => {
274
- emit(this.state + event.amount);
275
-
276
- // Add another event during processing
277
- if (this.state < 5) {
278
- await this.add(new IncrementEvent(1));
279
- }
280
- });
281
- }
282
- }
283
-
284
- const chainBloc = new ChainReactionBloc();
285
- const chainObserver = vi.fn();
286
- chainBloc.subscribe(chainObserver);
287
-
288
- await chainBloc.add(new IncrementEvent(1));
289
-
290
- // Should process all chained events
291
- expect(chainBloc.state).toBe(5);
292
- expect(chainObserver).toHaveBeenCalledTimes(5);
293
- });
294
-
295
- it('should handle event handler that emits multiple times', async () => {
296
- class MultiEmitBloc extends Bloc<number[]> {
297
- constructor() {
298
- super([]);
299
-
300
- this.on(IncrementEvent, (event, emit) => {
301
- // Emit multiple state updates
302
- for (let i = 1; i <= event.amount; i++) {
303
- emit([...this.state, i]);
304
- }
305
- });
306
- }
307
- }
308
-
309
- const multiBloc = new MultiEmitBloc();
310
- const observer = vi.fn();
311
- multiBloc.subscribe(observer);
312
-
313
- await multiBloc.add(new IncrementEvent(3));
314
-
315
- expect(observer).toHaveBeenCalledTimes(3);
316
- expect(multiBloc.state).toEqual([1, 2, 3]);
317
- });
318
-
319
- it('should handle events with constructor-less classes', async () => {
320
- // Event without explicit constructor
321
- class SimpleEvent {}
322
-
323
- class SimpleBloc extends Bloc<string> {
324
- constructor() {
325
- super('initial');
326
- this.on(SimpleEvent, (event, emit) => {
327
- emit('handled');
328
- });
329
- }
330
- }
331
-
332
- const simpleBloc = new SimpleBloc();
333
- await simpleBloc.add(new SimpleEvent() as any);
334
-
335
- expect(simpleBloc.state).toBe('handled');
336
- });
337
-
338
- it('should prevent state updates after disposal is initiated', async () => {
339
- const observer = vi.fn();
340
- bloc.subscribe(observer);
341
- const errorSpy = vi.spyOn(Blac, 'error').mockImplementation(() => {});
342
-
343
- // Start async event processing
344
- const promise = bloc.add(new AsyncIncrementEvent(5, 50));
345
-
346
- // Dispose bloc while event is processing
347
- setTimeout(() => bloc.dispose(), 25);
348
-
349
- await promise;
350
-
351
- // State should not be updated after disposal
352
- expect(bloc.state).toBe(0);
353
- // Error should be logged about attempted state update on disposed bloc
354
- expect(errorSpy).toHaveBeenCalledWith(
355
- expect.stringContaining('Attempted state update on'),
356
- );
357
- });
358
- });
359
-
360
- describe('Performance Considerations', () => {
361
- it('should handle large event queues efficiently', async () => {
362
- const eventCount = 1000;
363
- const promises: Promise<void>[] = [];
364
-
365
- for (let i = 0; i < eventCount; i++) {
366
- promises.push(bloc.add(new IncrementEvent(1)));
367
- }
368
-
369
- const startTime = performance.now();
370
- await Promise.all(promises);
371
- const endTime = performance.now();
372
-
373
- expect(bloc.state).toBe(eventCount);
374
- expect(endTime - startTime).toBeLessThan(1000); // Should process quickly
375
- });
376
-
377
- it('should not leak memory with event references', async () => {
378
- const events: any[] = [];
379
-
380
- // Create many events
381
- for (let i = 0; i < 100; i++) {
382
- const event = new IncrementEvent(1);
383
- events.push(event);
384
- await bloc.add(event);
385
- }
386
-
387
- // Clear event array
388
- events.length = 0;
389
-
390
- // Events should be garbage collectible after processing
391
- expect((bloc as any)._eventQueue.length).toBe(0);
392
- });
393
- });
394
- });