@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.
- package/dist/.tsbuildinfo +1 -0
- package/dist/Blac.d.ts +246 -0
- package/dist/Blac.d.ts.map +1 -0
- package/dist/Blac.js +624 -0
- package/dist/Blac.js.map +1 -0
- package/dist/Bloc.d.ts +41 -0
- package/dist/Bloc.d.ts.map +1 -0
- package/dist/Bloc.js +140 -0
- package/dist/Bloc.js.map +1 -0
- package/dist/BlocBase.d.ts +110 -0
- package/dist/BlocBase.d.ts.map +1 -0
- package/dist/BlocBase.js +287 -0
- package/dist/BlocBase.js.map +1 -0
- package/dist/Cubit.d.ts +25 -0
- package/dist/Cubit.d.ts.map +1 -0
- package/dist/Cubit.js +64 -0
- package/dist/Cubit.js.map +1 -0
- package/dist/adapter/BlacAdapter.d.ts +67 -0
- package/dist/adapter/BlacAdapter.d.ts.map +1 -0
- package/dist/adapter/BlacAdapter.js +263 -0
- package/dist/adapter/BlacAdapter.js.map +1 -0
- package/dist/adapter/ProxyFactory.d.ts +50 -0
- package/dist/adapter/ProxyFactory.d.ts.map +1 -0
- package/dist/adapter/ProxyFactory.js +150 -0
- package/dist/adapter/ProxyFactory.js.map +1 -0
- package/{src/adapter/index.ts → dist/adapter/index.d.ts} +1 -0
- package/dist/adapter/index.d.ts.map +1 -0
- package/dist/adapter/index.js +19 -0
- package/dist/adapter/index.js.map +1 -0
- package/dist/errors/BlacError.d.ts +38 -0
- package/dist/errors/BlacError.d.ts.map +1 -0
- package/dist/errors/BlacError.js +55 -0
- package/dist/errors/BlacError.js.map +1 -0
- package/dist/errors/ErrorManager.d.ts +39 -0
- package/dist/errors/ErrorManager.d.ts.map +1 -0
- package/dist/errors/ErrorManager.js +91 -0
- package/dist/errors/ErrorManager.js.map +1 -0
- package/dist/errors/handleError.d.ts +24 -0
- package/dist/errors/handleError.d.ts.map +1 -0
- package/dist/errors/handleError.js +62 -0
- package/dist/errors/handleError.js.map +1 -0
- package/dist/errors/index.d.ts +5 -0
- package/dist/errors/index.d.ts.map +1 -0
- package/dist/errors/index.js +13 -0
- package/dist/errors/index.js.map +1 -0
- package/{src/events.ts → dist/events.d.ts} +4 -2
- package/dist/events.d.ts.map +1 -0
- package/dist/events.js +17 -0
- package/dist/events.js.map +1 -0
- package/dist/index.cjs +38 -0
- package/{src/index.ts → dist/index.d.ts} +1 -10
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +38 -0
- package/dist/index.js.map +1 -0
- package/dist/lifecycle/BlocLifecycle.d.ts +51 -0
- package/dist/lifecycle/BlocLifecycle.d.ts.map +1 -0
- package/dist/lifecycle/BlocLifecycle.js +123 -0
- package/dist/lifecycle/BlocLifecycle.js.map +1 -0
- package/dist/lifecycle/index.d.ts +2 -0
- package/dist/lifecycle/index.d.ts.map +1 -0
- package/dist/lifecycle/index.js +18 -0
- package/dist/lifecycle/index.js.map +1 -0
- package/dist/plugins/BlocPluginRegistry.d.ts +58 -0
- package/dist/plugins/BlocPluginRegistry.d.ts.map +1 -0
- package/dist/plugins/BlocPluginRegistry.js +201 -0
- package/dist/plugins/BlocPluginRegistry.js.map +1 -0
- package/dist/plugins/SystemPluginRegistry.d.ts +79 -0
- package/dist/plugins/SystemPluginRegistry.d.ts.map +1 -0
- package/dist/plugins/SystemPluginRegistry.js +184 -0
- package/dist/plugins/SystemPluginRegistry.js.map +1 -0
- package/{src/plugins/index.ts → dist/plugins/index.d.ts} +1 -5
- package/dist/plugins/index.d.ts.map +1 -0
- package/dist/plugins/index.js +26 -0
- package/dist/plugins/index.js.map +1 -0
- package/dist/plugins/types.d.ts +103 -0
- package/dist/plugins/types.d.ts.map +1 -0
- package/dist/plugins/types.js +3 -0
- package/dist/plugins/types.js.map +1 -0
- package/dist/subscription/SubscriptionManager.d.ts +67 -0
- package/dist/subscription/SubscriptionManager.d.ts.map +1 -0
- package/dist/subscription/SubscriptionManager.js +317 -0
- package/dist/subscription/SubscriptionManager.js.map +1 -0
- package/{src/subscription/index.ts → dist/subscription/index.d.ts} +1 -0
- package/dist/subscription/index.d.ts.map +1 -0
- package/dist/subscription/index.js +19 -0
- package/dist/subscription/index.js.map +1 -0
- package/dist/subscription/types.d.ts +65 -0
- package/dist/subscription/types.d.ts.map +1 -0
- package/dist/subscription/types.js +3 -0
- package/dist/subscription/types.js.map +1 -0
- package/dist/testing.d.ts +33 -0
- package/dist/testing.d.ts.map +1 -0
- package/dist/testing.js +68 -0
- package/dist/testing.js.map +1 -0
- package/{src/types.ts → dist/types.d.ts} +11 -28
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/BatchingManager.d.ts +28 -0
- package/dist/utils/BatchingManager.d.ts.map +1 -0
- package/dist/utils/BatchingManager.js +48 -0
- package/dist/utils/BatchingManager.js.map +1 -0
- package/dist/utils/RerenderLogger.d.ts +60 -0
- package/dist/utils/RerenderLogger.d.ts.map +1 -0
- package/dist/utils/RerenderLogger.js +205 -0
- package/dist/utils/RerenderLogger.js.map +1 -0
- package/dist/utils/generateInstanceId.d.ts +11 -0
- package/dist/utils/generateInstanceId.d.ts.map +1 -0
- package/dist/utils/generateInstanceId.js +50 -0
- package/dist/utils/generateInstanceId.js.map +1 -0
- package/dist/utils/shallowEqual.d.ts +9 -0
- package/dist/utils/shallowEqual.d.ts.map +1 -0
- package/dist/utils/shallowEqual.js +35 -0
- package/dist/utils/shallowEqual.js.map +1 -0
- package/dist/utils/uuid.d.ts +10 -0
- package/dist/utils/uuid.d.ts.map +1 -0
- package/dist/utils/uuid.js +24 -0
- package/dist/utils/uuid.js.map +1 -0
- package/package.json +19 -6
- package/src/Blac.ts +0 -802
- package/src/Bloc.ts +0 -180
- package/src/BlocBase.ts +0 -398
- package/src/Cubit.ts +0 -68
- package/src/__tests__/Blac.config.test.ts +0 -79
- package/src/__tests__/Bloc.event.test.ts +0 -394
- package/src/__tests__/BlocBase.subscription.test.ts +0 -349
- package/src/__tests__/Cubit.test.ts +0 -462
- package/src/__tests__/memory-leaks.test.ts +0 -383
- package/src/__tests__/plugins.test.ts +0 -464
- package/src/adapter/BlacAdapter.ts +0 -467
- package/src/adapter/ProxyFactory.ts +0 -249
- package/src/adapter/__tests__/BlacAdapter.test.ts +0 -555
- package/src/adapter/__tests__/ProxyFactory.test.ts +0 -655
- package/src/errors/BlacError.ts +0 -69
- package/src/errors/ErrorManager.ts +0 -101
- package/src/errors/handleError.ts +0 -114
- package/src/errors/index.ts +0 -13
- package/src/lifecycle/BlocLifecycle.ts +0 -156
- package/src/lifecycle/index.ts +0 -1
- package/src/plugins/BlocPluginRegistry.ts +0 -240
- package/src/plugins/SystemPluginRegistry.ts +0 -242
- package/src/plugins/__tests__/BlocPluginRegistry.test.ts +0 -450
- package/src/plugins/__tests__/SystemPluginRegistry.test.ts +0 -404
- package/src/plugins/types.ts +0 -129
- package/src/subscription/README.md +0 -132
- package/src/subscription/SubscriptionManager.ts +0 -395
- package/src/subscription/__tests__/SubscriptionManager.test.ts +0 -355
- package/src/subscription/types.ts +0 -90
- package/src/testing.ts +0 -246
- package/src/utils/BatchingManager.ts +0 -59
- package/src/utils/RerenderLogger.ts +0 -265
- package/src/utils/__tests__/generateInstanceId.test.ts +0 -104
- package/src/utils/__tests__/shallowEqual.test.ts +0 -171
- package/src/utils/__tests__/uuid.test.ts +0 -144
- package/src/utils/generateInstanceId.ts +0 -54
- package/src/utils/shallowEqual.ts +0 -40
- package/src/utils/uuid.ts +0 -22
|
@@ -1,383 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
|
|
2
|
-
import { Blac } from '../Blac';
|
|
3
|
-
import { Cubit } from '../Cubit';
|
|
4
|
-
import { Bloc } from '../Bloc';
|
|
5
|
-
import { BlacAdapter } from '../adapter/BlacAdapter';
|
|
6
|
-
|
|
7
|
-
// Helper to force garbage collection if available
|
|
8
|
-
const forceGC = () => {
|
|
9
|
-
if ((global as any).gc) {
|
|
10
|
-
(global as any).gc();
|
|
11
|
-
}
|
|
12
|
-
};
|
|
13
|
-
|
|
14
|
-
// Helper to wait for WeakRef cleanup
|
|
15
|
-
const waitForCleanup = async (checkFn: () => boolean, maxWait = 1000) => {
|
|
16
|
-
const start = Date.now();
|
|
17
|
-
while (Date.now() - start < maxWait) {
|
|
18
|
-
forceGC();
|
|
19
|
-
await new Promise((resolve) => setTimeout(resolve, 10));
|
|
20
|
-
if (checkFn()) return true;
|
|
21
|
-
}
|
|
22
|
-
return false;
|
|
23
|
-
};
|
|
24
|
-
|
|
25
|
-
// Test state class
|
|
26
|
-
class TestState {
|
|
27
|
-
constructor(public value: number) {}
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
// Test Cubit
|
|
31
|
-
class TestCubit extends Cubit<TestState> {
|
|
32
|
-
constructor() {
|
|
33
|
-
super(new TestState(0));
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
increment = () => {
|
|
37
|
-
this.emit(new TestState(this.state.value + 1));
|
|
38
|
-
};
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
// Test event
|
|
42
|
-
class IncrementEvent {
|
|
43
|
-
constructor(public amount: number) {}
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
// Test Bloc
|
|
47
|
-
class TestBloc extends Bloc<TestState, IncrementEvent> {
|
|
48
|
-
constructor() {
|
|
49
|
-
super(new TestState(0));
|
|
50
|
-
this.on(IncrementEvent, this.handleIncrement);
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
handleIncrement = (
|
|
54
|
-
event: IncrementEvent,
|
|
55
|
-
emit: (state: TestState) => void,
|
|
56
|
-
) => {
|
|
57
|
-
emit(new TestState(this.state.value + event.amount));
|
|
58
|
-
};
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
describe('Memory Leak Tests', () => {
|
|
62
|
-
let blac: Blac;
|
|
63
|
-
|
|
64
|
-
beforeEach(() => {
|
|
65
|
-
blac = Blac.getInstance();
|
|
66
|
-
Blac.enableLog = false; // Disable logging for tests
|
|
67
|
-
vi.useFakeTimers();
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
afterEach(() => {
|
|
71
|
-
vi.useRealTimers();
|
|
72
|
-
Blac.resetInstance();
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
describe('WeakRef Cleanup', () => {
|
|
76
|
-
it('should support component WeakRefs for automatic cleanup', async () => {
|
|
77
|
-
const cubit = blac.getBloc(TestCubit);
|
|
78
|
-
let component: any = { id: 'test-component' };
|
|
79
|
-
const weakRef = new WeakRef(component);
|
|
80
|
-
|
|
81
|
-
// Subscribe with component reference
|
|
82
|
-
const unsubscribe = cubit.subscribeComponent(weakRef, () => {});
|
|
83
|
-
expect(cubit.subscriptionCount).toBe(1);
|
|
84
|
-
|
|
85
|
-
// Verify the subscription works
|
|
86
|
-
const callback = vi.fn();
|
|
87
|
-
cubit.subscribeComponent(weakRef, callback);
|
|
88
|
-
cubit.increment();
|
|
89
|
-
expect(callback).toHaveBeenCalled();
|
|
90
|
-
|
|
91
|
-
// Clean up
|
|
92
|
-
unsubscribe();
|
|
93
|
-
});
|
|
94
|
-
|
|
95
|
-
it('should handle multiple subscriptions with weak references', async () => {
|
|
96
|
-
const cubit = blac.getBloc(TestCubit);
|
|
97
|
-
const component1 = { id: 'component-1' };
|
|
98
|
-
const component2 = { id: 'component-2' };
|
|
99
|
-
const component3 = { id: 'component-3' };
|
|
100
|
-
|
|
101
|
-
// Add subscriptions with weak refs
|
|
102
|
-
const unsub1 = cubit.subscribeComponent(
|
|
103
|
-
new WeakRef(component1),
|
|
104
|
-
() => {},
|
|
105
|
-
);
|
|
106
|
-
const unsub2 = cubit.subscribeComponent(
|
|
107
|
-
new WeakRef(component2),
|
|
108
|
-
() => {},
|
|
109
|
-
);
|
|
110
|
-
const unsub3 = cubit.subscribeComponent(
|
|
111
|
-
new WeakRef(component3),
|
|
112
|
-
() => {},
|
|
113
|
-
);
|
|
114
|
-
|
|
115
|
-
expect(cubit.subscriptionCount).toBe(3);
|
|
116
|
-
|
|
117
|
-
// Remove some subscriptions
|
|
118
|
-
unsub1();
|
|
119
|
-
unsub2();
|
|
120
|
-
|
|
121
|
-
expect(cubit.subscriptionCount).toBe(1);
|
|
122
|
-
|
|
123
|
-
// Clean up remaining
|
|
124
|
-
unsub3();
|
|
125
|
-
expect(cubit.subscriptionCount).toBe(0);
|
|
126
|
-
});
|
|
127
|
-
});
|
|
128
|
-
|
|
129
|
-
describe('Bloc Instance Disposal', () => {
|
|
130
|
-
it('should dispose non-keepAlive blocs when no consumers remain', async () => {
|
|
131
|
-
const cubit = blac.getBloc(TestCubit);
|
|
132
|
-
const adapter = new BlacAdapter(
|
|
133
|
-
{ blocConstructor: TestCubit, componentRef: { current: {} } },
|
|
134
|
-
{},
|
|
135
|
-
);
|
|
136
|
-
|
|
137
|
-
// Subscribe and unsubscribe
|
|
138
|
-
adapter.mount();
|
|
139
|
-
const unsubscribe = adapter.createSubscription({ onChange: () => {} });
|
|
140
|
-
expect(cubit.subscriptionCount).toBe(1);
|
|
141
|
-
|
|
142
|
-
unsubscribe();
|
|
143
|
-
adapter.unmount();
|
|
144
|
-
|
|
145
|
-
// Wait for disposal
|
|
146
|
-
await vi.runAllTimersAsync();
|
|
147
|
-
|
|
148
|
-
// Bloc should be disposed
|
|
149
|
-
expect(cubit.isDisposed).toBe(true);
|
|
150
|
-
});
|
|
151
|
-
|
|
152
|
-
it('should not dispose keepAlive blocs when no consumers remain', async () => {
|
|
153
|
-
class KeepAliveCubit extends TestCubit {
|
|
154
|
-
static keepAlive = true;
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
const cubit = blac.getBloc(KeepAliveCubit);
|
|
158
|
-
const adapter = new BlacAdapter(
|
|
159
|
-
{ blocConstructor: KeepAliveCubit, componentRef: { current: {} } },
|
|
160
|
-
{},
|
|
161
|
-
);
|
|
162
|
-
|
|
163
|
-
// Subscribe and unsubscribe
|
|
164
|
-
adapter.mount();
|
|
165
|
-
const unsubscribe = adapter.createSubscription({ onChange: () => {} });
|
|
166
|
-
expect(cubit.subscriptionCount).toBe(1);
|
|
167
|
-
|
|
168
|
-
unsubscribe();
|
|
169
|
-
|
|
170
|
-
// Wait for potential disposal
|
|
171
|
-
await vi.runAllTimersAsync();
|
|
172
|
-
|
|
173
|
-
// Bloc should still be active
|
|
174
|
-
expect(cubit.isDisposed).toBe(false);
|
|
175
|
-
});
|
|
176
|
-
});
|
|
177
|
-
|
|
178
|
-
describe('Memory Pressure Scenarios', () => {
|
|
179
|
-
it('should handle rapid subscription addition/removal without leaks', async () => {
|
|
180
|
-
const cubit = blac.getBloc(TestCubit);
|
|
181
|
-
const unsubscribes: (() => void)[] = [];
|
|
182
|
-
|
|
183
|
-
// Add many subscriptions
|
|
184
|
-
for (let i = 0; i < 1000; i++) {
|
|
185
|
-
const unsub = cubit.subscribe(() => {});
|
|
186
|
-
unsubscribes.push(unsub);
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
expect(cubit.subscriptionCount).toBe(1000);
|
|
190
|
-
|
|
191
|
-
// Remove half the subscriptions
|
|
192
|
-
for (let i = 0; i < 500; i++) {
|
|
193
|
-
unsubscribes[i]();
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
expect(cubit.subscriptionCount).toBe(500);
|
|
197
|
-
|
|
198
|
-
// Remove remaining subscriptions
|
|
199
|
-
for (let i = 500; i < 1000; i++) {
|
|
200
|
-
unsubscribes[i]();
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
expect(cubit.subscriptionCount).toBe(0);
|
|
204
|
-
});
|
|
205
|
-
|
|
206
|
-
it('should handle concurrent bloc creation and disposal', async () => {
|
|
207
|
-
const adapters: BlacAdapter<typeof TestBloc>[] = [];
|
|
208
|
-
const unsubscribes: (() => void)[] = [];
|
|
209
|
-
|
|
210
|
-
// Create many blocs through adapters
|
|
211
|
-
for (let i = 0; i < 100; i++) {
|
|
212
|
-
const adapter = new BlacAdapter(
|
|
213
|
-
{ blocConstructor: TestBloc, componentRef: { current: {} } },
|
|
214
|
-
{ instanceId: `test-bloc-${i}` },
|
|
215
|
-
);
|
|
216
|
-
adapters.push(adapter);
|
|
217
|
-
adapter.mount();
|
|
218
|
-
const unsub = adapter.createSubscription({ onChange: () => {} });
|
|
219
|
-
unsubscribes.push(unsub);
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
// Unsubscribe all and unmount
|
|
223
|
-
unsubscribes.forEach((unsub) => unsub());
|
|
224
|
-
adapters.forEach((adapter) => adapter.unmount());
|
|
225
|
-
|
|
226
|
-
// Wait for disposal
|
|
227
|
-
await vi.runAllTimersAsync();
|
|
228
|
-
|
|
229
|
-
// All blocs should be disposed
|
|
230
|
-
for (const adapter of adapters) {
|
|
231
|
-
expect(adapter.blocInstance.isDisposed).toBe(true);
|
|
232
|
-
}
|
|
233
|
-
});
|
|
234
|
-
});
|
|
235
|
-
|
|
236
|
-
describe('Proxy and Cache Cleanup', () => {
|
|
237
|
-
it('should not leak memory through proxy caches', async () => {
|
|
238
|
-
const { ProxyFactory } = await import('../adapter/ProxyFactory');
|
|
239
|
-
const { createStateProxy, getStats, resetStats } = ProxyFactory;
|
|
240
|
-
const stats = getStats();
|
|
241
|
-
const initialProxyCount = stats.stateProxiesCreated || 0;
|
|
242
|
-
|
|
243
|
-
// Create many proxied states
|
|
244
|
-
for (let i = 0; i < 100; i++) {
|
|
245
|
-
const cubit = new TestCubit();
|
|
246
|
-
const proxy = createStateProxy({
|
|
247
|
-
target: cubit.state,
|
|
248
|
-
consumerRef: { current: {} },
|
|
249
|
-
consumerTracker: {
|
|
250
|
-
trackAccess: () => {},
|
|
251
|
-
} as any,
|
|
252
|
-
});
|
|
253
|
-
// Access properties to trigger proxy creation
|
|
254
|
-
const _ = proxy.value;
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
// Proxies should have been created
|
|
258
|
-
const newStats = getStats();
|
|
259
|
-
expect(newStats.stateProxiesCreated || 0).toBeGreaterThan(
|
|
260
|
-
initialProxyCount,
|
|
261
|
-
);
|
|
262
|
-
|
|
263
|
-
// Clear stats
|
|
264
|
-
resetStats();
|
|
265
|
-
const clearedStats = getStats();
|
|
266
|
-
expect(clearedStats.stateProxiesCreated || 0).toBe(0);
|
|
267
|
-
});
|
|
268
|
-
});
|
|
269
|
-
|
|
270
|
-
describe('Event Queue Memory Management', () => {
|
|
271
|
-
it('should not accumulate events in queue indefinitely', async () => {
|
|
272
|
-
const bloc = blac.getBloc(TestBloc);
|
|
273
|
-
|
|
274
|
-
// Add many events rapidly
|
|
275
|
-
for (let i = 0; i < 1000; i++) {
|
|
276
|
-
bloc.add(new IncrementEvent(1));
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
// Wait for processing
|
|
280
|
-
await vi.runAllTimersAsync();
|
|
281
|
-
|
|
282
|
-
// Queue should be empty after processing
|
|
283
|
-
expect((bloc as any)._eventQueue.length).toBe(0);
|
|
284
|
-
});
|
|
285
|
-
|
|
286
|
-
it('should handle disposal during event processing', async () => {
|
|
287
|
-
const bloc = blac.getBloc(TestBloc);
|
|
288
|
-
const adapter = new BlacAdapter(
|
|
289
|
-
{ blocConstructor: TestBloc, componentRef: { current: {} } },
|
|
290
|
-
{},
|
|
291
|
-
);
|
|
292
|
-
|
|
293
|
-
// Subscribe
|
|
294
|
-
adapter.mount();
|
|
295
|
-
const unsubscribe = adapter.createSubscription({ onChange: () => {} });
|
|
296
|
-
|
|
297
|
-
// Add events and immediately dispose
|
|
298
|
-
for (let i = 0; i < 10; i++) {
|
|
299
|
-
bloc.add(new IncrementEvent(1));
|
|
300
|
-
}
|
|
301
|
-
|
|
302
|
-
unsubscribe();
|
|
303
|
-
adapter.unmount();
|
|
304
|
-
|
|
305
|
-
// Wait for disposal
|
|
306
|
-
await vi.runAllTimersAsync();
|
|
307
|
-
|
|
308
|
-
// Bloc should be disposed and queue cleared
|
|
309
|
-
expect(bloc.isDisposed).toBe(true);
|
|
310
|
-
expect((bloc as any)._eventQueue.length).toBe(0);
|
|
311
|
-
});
|
|
312
|
-
});
|
|
313
|
-
|
|
314
|
-
describe('Disposal State Transitions', () => {
|
|
315
|
-
it('should handle concurrent disposal requests safely', async () => {
|
|
316
|
-
const cubit = blac.getBloc(TestCubit);
|
|
317
|
-
const adapter = new BlacAdapter(
|
|
318
|
-
{ blocConstructor: TestCubit, componentRef: { current: {} } },
|
|
319
|
-
{},
|
|
320
|
-
);
|
|
321
|
-
|
|
322
|
-
// Add multiple consumers
|
|
323
|
-
adapter.mount();
|
|
324
|
-
const unsub1 = adapter.createSubscription({ onChange: () => {} });
|
|
325
|
-
const adapter2 = new BlacAdapter(
|
|
326
|
-
{ blocConstructor: TestCubit, componentRef: { current: {} } },
|
|
327
|
-
{},
|
|
328
|
-
);
|
|
329
|
-
adapter2.mount();
|
|
330
|
-
const unsub2 = adapter2.createSubscription({ onChange: () => {} });
|
|
331
|
-
|
|
332
|
-
// Remove consumers concurrently
|
|
333
|
-
await Promise.all([
|
|
334
|
-
(async () => {
|
|
335
|
-
unsub1();
|
|
336
|
-
adapter.unmount();
|
|
337
|
-
})(),
|
|
338
|
-
(async () => {
|
|
339
|
-
unsub2();
|
|
340
|
-
adapter2.unmount();
|
|
341
|
-
})(),
|
|
342
|
-
]);
|
|
343
|
-
|
|
344
|
-
// Wait for disposal
|
|
345
|
-
await vi.runAllTimersAsync();
|
|
346
|
-
|
|
347
|
-
// Should be disposed exactly once
|
|
348
|
-
expect(cubit.isDisposed).toBe(true);
|
|
349
|
-
});
|
|
350
|
-
|
|
351
|
-
it('should prevent state updates after disposal', async () => {
|
|
352
|
-
const cubit = blac.getBloc(TestCubit);
|
|
353
|
-
const adapter = new BlacAdapter(
|
|
354
|
-
{ blocConstructor: TestCubit, componentRef: { current: {} } },
|
|
355
|
-
{},
|
|
356
|
-
);
|
|
357
|
-
|
|
358
|
-
// Subscribe and start disposal
|
|
359
|
-
adapter.mount();
|
|
360
|
-
const unsub = adapter.createSubscription({ onChange: () => {} });
|
|
361
|
-
unsub();
|
|
362
|
-
adapter.unmount();
|
|
363
|
-
|
|
364
|
-
// Wait for disposal to complete
|
|
365
|
-
await vi.runAllTimersAsync();
|
|
366
|
-
|
|
367
|
-
expect(cubit.isDisposed).toBe(true);
|
|
368
|
-
|
|
369
|
-
// Try to update state after disposal
|
|
370
|
-
const callback = vi.fn();
|
|
371
|
-
const unsubscribe = cubit.subscribe(callback);
|
|
372
|
-
|
|
373
|
-
// State should not change
|
|
374
|
-
const initialState = cubit.state;
|
|
375
|
-
cubit.increment();
|
|
376
|
-
|
|
377
|
-
// State should remain unchanged
|
|
378
|
-
expect(cubit.state).toBe(initialState);
|
|
379
|
-
expect(callback).not.toHaveBeenCalled();
|
|
380
|
-
unsubscribe();
|
|
381
|
-
});
|
|
382
|
-
});
|
|
383
|
-
});
|