@blac/react 2.0.0-rc-16 → 2.0.0-rc.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/dist/.tsbuildinfo +1 -0
- package/dist/index.cjs +13 -0
- package/{src/index.ts → dist/index.d.ts} +1 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js.map +1 -0
- package/dist/useBloc.d.ts +20 -0
- package/dist/useBloc.d.ts.map +1 -0
- package/dist/useBloc.js +175 -0
- package/dist/useBloc.js.map +1 -0
- package/dist/useExternalBlocStore.d.ts +31 -0
- package/dist/useExternalBlocStore.d.ts.map +1 -0
- package/dist/useExternalBlocStore.js +93 -0
- package/dist/useExternalBlocStore.js.map +1 -0
- package/package.json +24 -10
- package/src/__tests__/rerenderLogging.test.tsx +0 -257
- package/src/__tests__/useBloc.disposal.test.tsx +0 -377
- package/src/__tests__/useBloc.instanceChange.test.tsx +0 -200
- package/src/__tests__/useBloc.props.test.tsx +0 -435
- package/src/__tests__/useBloc.proxyConfig.test.tsx +0 -228
- package/src/__tests__/useBloc.staticProps.test.tsx +0 -297
- package/src/__tests__/useBloc.tracking.test.tsx +0 -202
- package/src/useBloc.ts +0 -227
- package/src/useExternalBlocStore.ts +0 -145
|
@@ -1,228 +0,0 @@
|
|
|
1
|
-
import { Blac, Cubit } from '@blac/core';
|
|
2
|
-
import { renderHook, act } from '@testing-library/react';
|
|
3
|
-
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
|
|
4
|
-
import useBloc from '../useBloc';
|
|
5
|
-
|
|
6
|
-
interface TestState {
|
|
7
|
-
count: number;
|
|
8
|
-
nested: {
|
|
9
|
-
value: string;
|
|
10
|
-
};
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
class TestCubit extends Cubit<TestState> {
|
|
14
|
-
constructor() {
|
|
15
|
-
super({ count: 0, nested: { value: 'initial' } });
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
increment = () => {
|
|
19
|
-
this.emit({ ...this.state, count: this.state.count + 1 });
|
|
20
|
-
};
|
|
21
|
-
|
|
22
|
-
updateNested = () => {
|
|
23
|
-
this.emit({ ...this.state, nested: { value: 'updated' } });
|
|
24
|
-
};
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
describe('useBloc with proxy tracking config', () => {
|
|
28
|
-
const originalConfig = { ...Blac.config };
|
|
29
|
-
|
|
30
|
-
beforeEach(() => {
|
|
31
|
-
Blac.resetInstance();
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
afterEach(() => {
|
|
35
|
-
Blac.setConfig(originalConfig);
|
|
36
|
-
Blac.resetInstance();
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
describe('when proxyDependencyTracking is enabled (default)', () => {
|
|
40
|
-
beforeEach(() => {
|
|
41
|
-
Blac.setConfig({ proxyDependencyTracking: true });
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
it('should only re-render when accessed properties change', () => {
|
|
45
|
-
const { result } = renderHook(() => useBloc(TestCubit));
|
|
46
|
-
const renderSpy = vi.fn();
|
|
47
|
-
|
|
48
|
-
// Access only count in render
|
|
49
|
-
renderHook(() => {
|
|
50
|
-
const [state] = useBloc(TestCubit);
|
|
51
|
-
renderSpy(state.count);
|
|
52
|
-
return state.count;
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
expect(renderSpy).toHaveBeenCalledTimes(1);
|
|
56
|
-
expect(renderSpy).toHaveBeenCalledWith(0);
|
|
57
|
-
|
|
58
|
-
// Update nested value (not accessed)
|
|
59
|
-
act(() => {
|
|
60
|
-
result.current[1].updateNested();
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
// Should not re-render since nested.value wasn't accessed
|
|
64
|
-
expect(renderSpy).toHaveBeenCalledTimes(1);
|
|
65
|
-
|
|
66
|
-
// Update count (accessed property)
|
|
67
|
-
act(() => {
|
|
68
|
-
result.current[1].increment();
|
|
69
|
-
});
|
|
70
|
-
|
|
71
|
-
// Should re-render since count was accessed
|
|
72
|
-
expect(renderSpy).toHaveBeenCalledTimes(2);
|
|
73
|
-
expect(renderSpy).toHaveBeenLastCalledWith(1);
|
|
74
|
-
});
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
describe('when proxyDependencyTracking is disabled', () => {
|
|
78
|
-
beforeEach(() => {
|
|
79
|
-
Blac.setConfig({ proxyDependencyTracking: false });
|
|
80
|
-
});
|
|
81
|
-
|
|
82
|
-
it('should re-render on any state change', () => {
|
|
83
|
-
const { result } = renderHook(() => useBloc(TestCubit));
|
|
84
|
-
const renderSpy = vi.fn();
|
|
85
|
-
|
|
86
|
-
// Access only count in render
|
|
87
|
-
renderHook(() => {
|
|
88
|
-
const [state] = useBloc(TestCubit);
|
|
89
|
-
renderSpy(state.count);
|
|
90
|
-
return state.count;
|
|
91
|
-
});
|
|
92
|
-
|
|
93
|
-
expect(renderSpy).toHaveBeenCalledTimes(1);
|
|
94
|
-
expect(renderSpy).toHaveBeenCalledWith(0);
|
|
95
|
-
|
|
96
|
-
// Update nested value (not accessed)
|
|
97
|
-
act(() => {
|
|
98
|
-
result.current[1].updateNested();
|
|
99
|
-
});
|
|
100
|
-
|
|
101
|
-
// Should re-render even though nested.value wasn't accessed
|
|
102
|
-
expect(renderSpy).toHaveBeenCalledTimes(2);
|
|
103
|
-
expect(renderSpy).toHaveBeenLastCalledWith(0); // count didn't change
|
|
104
|
-
|
|
105
|
-
// Update count
|
|
106
|
-
act(() => {
|
|
107
|
-
result.current[1].increment();
|
|
108
|
-
});
|
|
109
|
-
|
|
110
|
-
// Should re-render
|
|
111
|
-
expect(renderSpy).toHaveBeenCalledTimes(3);
|
|
112
|
-
expect(renderSpy).toHaveBeenLastCalledWith(1);
|
|
113
|
-
});
|
|
114
|
-
|
|
115
|
-
it('should still respect manual dependencies when provided', () => {
|
|
116
|
-
const renderSpy = vi.fn();
|
|
117
|
-
|
|
118
|
-
const { result } = renderHook(() =>
|
|
119
|
-
useBloc(TestCubit, {
|
|
120
|
-
dependencies: (bloc) => [bloc.state.count],
|
|
121
|
-
}),
|
|
122
|
-
);
|
|
123
|
-
|
|
124
|
-
// Create another hook that tracks renders
|
|
125
|
-
renderHook(() => {
|
|
126
|
-
const [state] = useBloc(TestCubit, {
|
|
127
|
-
dependencies: (bloc) => [bloc.state.count],
|
|
128
|
-
});
|
|
129
|
-
renderSpy(state);
|
|
130
|
-
return state;
|
|
131
|
-
});
|
|
132
|
-
|
|
133
|
-
expect(renderSpy).toHaveBeenCalledTimes(1);
|
|
134
|
-
|
|
135
|
-
// Update nested value
|
|
136
|
-
act(() => {
|
|
137
|
-
result.current[1].updateNested();
|
|
138
|
-
});
|
|
139
|
-
|
|
140
|
-
// Should not re-render since dependencies only include count
|
|
141
|
-
expect(renderSpy).toHaveBeenCalledTimes(1);
|
|
142
|
-
|
|
143
|
-
// Update count
|
|
144
|
-
act(() => {
|
|
145
|
-
result.current[1].increment();
|
|
146
|
-
});
|
|
147
|
-
|
|
148
|
-
// Should re-render since count is in dependencies
|
|
149
|
-
expect(renderSpy).toHaveBeenCalledTimes(2);
|
|
150
|
-
});
|
|
151
|
-
});
|
|
152
|
-
|
|
153
|
-
describe('runtime config changes', () => {
|
|
154
|
-
it('should respect config changes for new hooks', () => {
|
|
155
|
-
// Start with proxy tracking enabled
|
|
156
|
-
Blac.setConfig({ proxyDependencyTracking: true });
|
|
157
|
-
|
|
158
|
-
// Create a new cubit instance for this test to avoid interference
|
|
159
|
-
class TestCubit2 extends Cubit<TestState> {
|
|
160
|
-
constructor() {
|
|
161
|
-
super({ count: 0, nested: { value: 'initial' } });
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
increment = () => {
|
|
165
|
-
this.emit({ ...this.state, count: this.state.count + 1 });
|
|
166
|
-
};
|
|
167
|
-
|
|
168
|
-
updateNested = () => {
|
|
169
|
-
this.emit({ ...this.state, nested: { value: 'updated' } });
|
|
170
|
-
};
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
const renderSpy1 = vi.fn();
|
|
174
|
-
|
|
175
|
-
const { result: result1 } = renderHook(() => {
|
|
176
|
-
const [state, bloc] = useBloc(TestCubit2);
|
|
177
|
-
renderSpy1(state.count);
|
|
178
|
-
return [state, bloc] as const;
|
|
179
|
-
});
|
|
180
|
-
|
|
181
|
-
expect(renderSpy1).toHaveBeenCalledTimes(1);
|
|
182
|
-
|
|
183
|
-
// Update nested value
|
|
184
|
-
act(() => {
|
|
185
|
-
result1.current[1].updateNested();
|
|
186
|
-
});
|
|
187
|
-
|
|
188
|
-
// Should not re-render since nested.value wasn't accessed (proxy tracking enabled)
|
|
189
|
-
expect(renderSpy1).toHaveBeenCalledTimes(1);
|
|
190
|
-
|
|
191
|
-
// Change config for future hooks
|
|
192
|
-
Blac.setConfig({ proxyDependencyTracking: false });
|
|
193
|
-
|
|
194
|
-
// Create new cubit class to ensure fresh instance
|
|
195
|
-
class TestCubit3 extends Cubit<TestState> {
|
|
196
|
-
constructor() {
|
|
197
|
-
super({ count: 0, nested: { value: 'initial' } });
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
increment = () => {
|
|
201
|
-
this.emit({ ...this.state, count: this.state.count + 1 });
|
|
202
|
-
};
|
|
203
|
-
|
|
204
|
-
updateNested = () => {
|
|
205
|
-
this.emit({ ...this.state, nested: { value: 'updated' } });
|
|
206
|
-
};
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
// Create new hook after config change
|
|
210
|
-
const renderSpy2 = vi.fn();
|
|
211
|
-
const { result: result2 } = renderHook(() => {
|
|
212
|
-
const [state, bloc] = useBloc(TestCubit3);
|
|
213
|
-
renderSpy2(state.count);
|
|
214
|
-
return [state, bloc] as const;
|
|
215
|
-
});
|
|
216
|
-
|
|
217
|
-
expect(renderSpy2).toHaveBeenCalledTimes(1);
|
|
218
|
-
|
|
219
|
-
// Update nested value on the new cubit
|
|
220
|
-
act(() => {
|
|
221
|
-
result2.current[1].updateNested();
|
|
222
|
-
});
|
|
223
|
-
|
|
224
|
-
// Should re-render even though nested.value wasn't accessed (proxy tracking disabled)
|
|
225
|
-
expect(renderSpy2).toHaveBeenCalledTimes(2);
|
|
226
|
-
});
|
|
227
|
-
});
|
|
228
|
-
});
|
|
@@ -1,297 +0,0 @@
|
|
|
1
|
-
import { Blac, Cubit } from '@blac/core';
|
|
2
|
-
import { renderHook } from '@testing-library/react';
|
|
3
|
-
import { describe, expect, it, vi, beforeEach } from 'vitest';
|
|
4
|
-
import useBloc from '../useBloc';
|
|
5
|
-
|
|
6
|
-
// Test components
|
|
7
|
-
interface UserDetailsProps {
|
|
8
|
-
userId: string;
|
|
9
|
-
page: number;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
interface UserDetailsState {
|
|
13
|
-
user: { id: string; name: string } | null;
|
|
14
|
-
loading: boolean;
|
|
15
|
-
page: number;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
class UserDetailsCubit extends Cubit<UserDetailsState> {
|
|
19
|
-
props: ConstructorParameters<typeof UserDetailsCubit>[0];
|
|
20
|
-
|
|
21
|
-
constructor(props: UserDetailsProps) {
|
|
22
|
-
super({ user: null, loading: false, page: props.page });
|
|
23
|
-
this.props = props;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
loadUser = () => {
|
|
27
|
-
this.emit({ ...this.state, loading: true });
|
|
28
|
-
// Simulate API call
|
|
29
|
-
setTimeout(() => {
|
|
30
|
-
this.emit({
|
|
31
|
-
...this.state,
|
|
32
|
-
user: { id: this.props!.userId, name: `User ${this.props!.userId}` },
|
|
33
|
-
loading: false,
|
|
34
|
-
});
|
|
35
|
-
}, 10);
|
|
36
|
-
};
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
interface SearchProps {
|
|
40
|
-
query: string;
|
|
41
|
-
filters?: { category?: string; minPrice?: number; tags?: string[] };
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
interface SearchState {
|
|
45
|
-
results: string[];
|
|
46
|
-
loading: boolean;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
class SearchCubit extends Cubit<SearchState> {
|
|
50
|
-
constructor(props: SearchProps) {
|
|
51
|
-
super({ results: [], loading: false });
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
describe('useBloc staticProps integration', () => {
|
|
56
|
-
beforeEach(() => {
|
|
57
|
-
Blac.resetInstance();
|
|
58
|
-
vi.clearAllMocks();
|
|
59
|
-
});
|
|
60
|
-
|
|
61
|
-
describe('staticProps with instanceId', () => {
|
|
62
|
-
it('should use explicit instanceId when provided with staticProps', () => {
|
|
63
|
-
const { result: result1 } = renderHook(() =>
|
|
64
|
-
useBloc(UserDetailsCubit, {
|
|
65
|
-
staticProps: { userId: 'user123', page: 1 },
|
|
66
|
-
instanceId: 'user123',
|
|
67
|
-
}),
|
|
68
|
-
);
|
|
69
|
-
|
|
70
|
-
const { result: result2 } = renderHook(() =>
|
|
71
|
-
useBloc(UserDetailsCubit, {
|
|
72
|
-
staticProps: { userId: 'user123', page: 2 }, // Different page
|
|
73
|
-
instanceId: 'user123', // Same instanceId
|
|
74
|
-
}),
|
|
75
|
-
);
|
|
76
|
-
|
|
77
|
-
// Both should have the same instanceId
|
|
78
|
-
expect(result1.current[1]._id).toBe('user123');
|
|
79
|
-
expect(result2.current[1]._id).toBe('user123');
|
|
80
|
-
|
|
81
|
-
// Note: In React Testing Library, each renderHook creates a separate component tree,
|
|
82
|
-
// so they won't share the same instance. In a real app, they would.
|
|
83
|
-
expect(result1.current[1]._id).toBe(result2.current[1]._id);
|
|
84
|
-
});
|
|
85
|
-
|
|
86
|
-
it('should create different instances with different instanceIds', () => {
|
|
87
|
-
const { result: result1 } = renderHook(() =>
|
|
88
|
-
useBloc(UserDetailsCubit, {
|
|
89
|
-
staticProps: { userId: 'user123', page: 1 },
|
|
90
|
-
instanceId: 'user123',
|
|
91
|
-
}),
|
|
92
|
-
);
|
|
93
|
-
|
|
94
|
-
const { result: result2 } = renderHook(() =>
|
|
95
|
-
useBloc(UserDetailsCubit, {
|
|
96
|
-
staticProps: { userId: 'user456', page: 1 },
|
|
97
|
-
instanceId: 'user456',
|
|
98
|
-
}),
|
|
99
|
-
);
|
|
100
|
-
|
|
101
|
-
// Should have different IDs
|
|
102
|
-
expect(result1.current[1]._id).toBe('user123');
|
|
103
|
-
expect(result2.current[1]._id).toBe('user456');
|
|
104
|
-
expect(result1.current[1]._id).not.toBe(result2.current[1]._id);
|
|
105
|
-
});
|
|
106
|
-
});
|
|
107
|
-
|
|
108
|
-
describe('staticProps without instanceId (auto-generation)', () => {
|
|
109
|
-
it('should generate instanceId from primitive staticProps values', () => {
|
|
110
|
-
const { result: result1 } = renderHook(() =>
|
|
111
|
-
useBloc(SearchCubit, {
|
|
112
|
-
staticProps: { query: 'test', filters: { category: 'books' } },
|
|
113
|
-
}),
|
|
114
|
-
);
|
|
115
|
-
|
|
116
|
-
const { result: result2 } = renderHook(() =>
|
|
117
|
-
useBloc(SearchCubit, {
|
|
118
|
-
staticProps: { query: 'test', filters: { category: 'movies' } },
|
|
119
|
-
}),
|
|
120
|
-
);
|
|
121
|
-
|
|
122
|
-
// Should have generated ID from the query primitive
|
|
123
|
-
expect(result1.current[1]._id).toBe('query:test');
|
|
124
|
-
expect(result2.current[1]._id).toBe('query:test');
|
|
125
|
-
|
|
126
|
-
// They have the same generated ID
|
|
127
|
-
expect(result1.current[1]._id).toBe(result2.current[1]._id);
|
|
128
|
-
});
|
|
129
|
-
|
|
130
|
-
it('should create different instances for different primitive values', () => {
|
|
131
|
-
const { result: result1 } = renderHook(() =>
|
|
132
|
-
useBloc(SearchCubit, {
|
|
133
|
-
staticProps: { query: 'test1' },
|
|
134
|
-
}),
|
|
135
|
-
);
|
|
136
|
-
|
|
137
|
-
const { result: result2 } = renderHook(() =>
|
|
138
|
-
useBloc(SearchCubit, {
|
|
139
|
-
staticProps: { query: 'test2' },
|
|
140
|
-
}),
|
|
141
|
-
);
|
|
142
|
-
|
|
143
|
-
// Should have different generated IDs
|
|
144
|
-
expect(result1.current[1]._id).toBe('query:test1');
|
|
145
|
-
expect(result2.current[1]._id).toBe('query:test2');
|
|
146
|
-
expect(result1.current[1]._id).not.toBe(result2.current[1]._id);
|
|
147
|
-
});
|
|
148
|
-
|
|
149
|
-
it('should ignore non-primitive values when generating instanceId', () => {
|
|
150
|
-
const filters = { category: 'books', tags: ['fiction', 'bestseller'] };
|
|
151
|
-
|
|
152
|
-
const { result: result1 } = renderHook(() =>
|
|
153
|
-
useBloc(SearchCubit, {
|
|
154
|
-
staticProps: { query: 'test', filters }, // filters has an array
|
|
155
|
-
}),
|
|
156
|
-
);
|
|
157
|
-
|
|
158
|
-
const { result: result2 } = renderHook(() =>
|
|
159
|
-
useBloc(SearchCubit, {
|
|
160
|
-
staticProps: {
|
|
161
|
-
query: 'test',
|
|
162
|
-
filters: { ...filters, tags: ['different'] },
|
|
163
|
-
},
|
|
164
|
-
}),
|
|
165
|
-
);
|
|
166
|
-
|
|
167
|
-
// Both should generate the same ID (only 'query' is used)
|
|
168
|
-
expect(result1.current[1]._id).toBe('query:test');
|
|
169
|
-
expect(result2.current[1]._id).toBe('query:test');
|
|
170
|
-
});
|
|
171
|
-
});
|
|
172
|
-
|
|
173
|
-
describe('InstanceId usage', () => {
|
|
174
|
-
it('should use instanceId option', () => {
|
|
175
|
-
const { result } = renderHook(() =>
|
|
176
|
-
useBloc(UserDetailsCubit, {
|
|
177
|
-
staticProps: { userId: 'user123', page: 1 },
|
|
178
|
-
instanceId: 'custom-id',
|
|
179
|
-
}),
|
|
180
|
-
);
|
|
181
|
-
|
|
182
|
-
expect(result.current[1]._id).toBe('custom-id');
|
|
183
|
-
});
|
|
184
|
-
|
|
185
|
-
it('should use instanceId option with static props', () => {
|
|
186
|
-
const { result } = renderHook(() =>
|
|
187
|
-
useBloc(UserDetailsCubit, {
|
|
188
|
-
staticProps: { userId: 'user123', page: 1 },
|
|
189
|
-
instanceId: 'user123',
|
|
190
|
-
}),
|
|
191
|
-
);
|
|
192
|
-
|
|
193
|
-
const [state, bloc] = result.current;
|
|
194
|
-
expect(state.page).toBe(1);
|
|
195
|
-
expect(bloc).toBeDefined();
|
|
196
|
-
expect(bloc._id).toBe('user123');
|
|
197
|
-
});
|
|
198
|
-
|
|
199
|
-
it('should use explicit instanceId when provided', () => {
|
|
200
|
-
const { result } = renderHook(() =>
|
|
201
|
-
useBloc(UserDetailsCubit, {
|
|
202
|
-
staticProps: { userId: 'new', page: 2 },
|
|
203
|
-
instanceId: 'new-id',
|
|
204
|
-
}),
|
|
205
|
-
);
|
|
206
|
-
|
|
207
|
-
// Should use the instanceId
|
|
208
|
-
expect(result.current[1]._id).toBe('new-id');
|
|
209
|
-
|
|
210
|
-
// Should use staticProps
|
|
211
|
-
expect(result.current[1].props).toEqual({ userId: 'new', page: 2 });
|
|
212
|
-
});
|
|
213
|
-
});
|
|
214
|
-
|
|
215
|
-
describe('Complex scenarios', () => {
|
|
216
|
-
it('should handle mixed primitive types in staticProps', () => {
|
|
217
|
-
interface ConfigProps {
|
|
218
|
-
enabled: boolean;
|
|
219
|
-
maxRetries: number;
|
|
220
|
-
apiKey: string;
|
|
221
|
-
debugInfo?: { level: string };
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
class ConfigCubit extends Cubit<{ config: ConfigProps | null }> {
|
|
225
|
-
constructor(props: ConfigProps) {
|
|
226
|
-
super({ config: props });
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
const { result: result1 } = renderHook(() =>
|
|
231
|
-
useBloc(ConfigCubit, {
|
|
232
|
-
staticProps: {
|
|
233
|
-
enabled: true,
|
|
234
|
-
maxRetries: 3,
|
|
235
|
-
apiKey: 'abc123',
|
|
236
|
-
debugInfo: { level: 'verbose' }, // This should be ignored
|
|
237
|
-
},
|
|
238
|
-
}),
|
|
239
|
-
);
|
|
240
|
-
|
|
241
|
-
const { result: result2 } = renderHook(() =>
|
|
242
|
-
useBloc(ConfigCubit, {
|
|
243
|
-
staticProps: {
|
|
244
|
-
enabled: true,
|
|
245
|
-
maxRetries: 3,
|
|
246
|
-
apiKey: 'abc123',
|
|
247
|
-
debugInfo: { level: 'quiet' }, // Different object, but should still match
|
|
248
|
-
},
|
|
249
|
-
}),
|
|
250
|
-
);
|
|
251
|
-
|
|
252
|
-
// Should generate the same ID from primitives
|
|
253
|
-
const expectedId = 'apiKey:abc123|enabled:true|maxRetries:3';
|
|
254
|
-
expect(result1.current[1]._id).toBe(expectedId);
|
|
255
|
-
expect(result2.current[1]._id).toBe(expectedId);
|
|
256
|
-
});
|
|
257
|
-
|
|
258
|
-
it('should handle null and undefined in staticProps', () => {
|
|
259
|
-
interface OptionalProps {
|
|
260
|
-
required: string;
|
|
261
|
-
optional?: string;
|
|
262
|
-
nullable: string | null;
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
class OptionalCubit extends Cubit<{ data: any }> {
|
|
266
|
-
constructor(props: OptionalProps) {
|
|
267
|
-
super({ data: props });
|
|
268
|
-
}
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
const { result: result1 } = renderHook(() =>
|
|
272
|
-
useBloc(OptionalCubit, {
|
|
273
|
-
staticProps: {
|
|
274
|
-
required: 'test',
|
|
275
|
-
optional: undefined,
|
|
276
|
-
nullable: null,
|
|
277
|
-
},
|
|
278
|
-
}),
|
|
279
|
-
);
|
|
280
|
-
|
|
281
|
-
const { result: result2 } = renderHook(() =>
|
|
282
|
-
useBloc(OptionalCubit, {
|
|
283
|
-
staticProps: {
|
|
284
|
-
required: 'test',
|
|
285
|
-
optional: undefined,
|
|
286
|
-
nullable: null,
|
|
287
|
-
},
|
|
288
|
-
}),
|
|
289
|
-
);
|
|
290
|
-
|
|
291
|
-
// Should generate the same ID including null/undefined
|
|
292
|
-
const expectedId = 'nullable:null|optional:undefined|required:test';
|
|
293
|
-
expect(result1.current[1]._id).toBe(expectedId);
|
|
294
|
-
expect(result2.current[1]._id).toBe(expectedId);
|
|
295
|
-
});
|
|
296
|
-
});
|
|
297
|
-
});
|