|
| 1 | +import { Endpoint } from '@data-client/endpoint'; |
1 | 2 | import nock from 'nock'; |
2 | 3 | import { computed, defineComponent, h, nextTick, reactive } from 'vue'; |
3 | 4 |
|
4 | | -import { CoolerArticleResource } from '../../../../__tests__/new'; |
| 5 | +import { |
| 6 | + CoolerArticleResource, |
| 7 | + CoolerArticle, |
| 8 | +} from '../../../../__tests__/new'; |
5 | 9 | import useSuspense from '../consumers/useSuspense'; |
6 | 10 | import { renderDataCompose, mountDataClient } from '../test'; |
7 | 11 |
|
@@ -289,4 +293,64 @@ describe('vue useSuspense()', () => { |
289 | 293 |
|
290 | 294 | cleanup(); |
291 | 295 | }); |
| 296 | + |
| 297 | + it('should initiate second fetch when props change even if first promise never resolves', async () => { |
| 298 | + let fetchInitialCalled = false; |
| 299 | + let fetchFinalCalled = false; |
| 300 | + let resolveInitial: ((value: any) => void) | undefined; |
| 301 | + let resolveFinal: ((value: any) => void) | undefined; |
| 302 | + |
| 303 | + // Create custom endpoint with controllable promises |
| 304 | + const ControlledEndpoint = new Endpoint( |
| 305 | + ({ id }: { id: number }) => { |
| 306 | + if (id === payload.id) { |
| 307 | + fetchInitialCalled = true; |
| 308 | + // Initial fetch - manually controlled |
| 309 | + return new Promise(resolve => { |
| 310 | + resolveInitial = resolve; |
| 311 | + }); |
| 312 | + } else if (id === payload2.id) { |
| 313 | + fetchFinalCalled = true; |
| 314 | + // Final fetch - manually controlled |
| 315 | + return new Promise(resolve => { |
| 316 | + resolveFinal = resolve; |
| 317 | + }); |
| 318 | + } |
| 319 | + throw new Error(`Unexpected id: ${id}`); |
| 320 | + }, |
| 321 | + { schema: CoolerArticle, name: 'ControlledEndpoint' }, |
| 322 | + ); |
| 323 | + |
| 324 | + const props = reactive({ id: payload.id }); |
| 325 | + |
| 326 | + // Start the composable (don't await yet since initial fetch needs manual resolution) |
| 327 | + const setupPromise = renderDataCompose( |
| 328 | + (props: { id: number }) => |
| 329 | + useSuspense( |
| 330 | + ControlledEndpoint, |
| 331 | + computed(() => ({ id: props.id })), |
| 332 | + ), |
| 333 | + { props }, |
| 334 | + ); |
| 335 | + |
| 336 | + // Wait for initial fetch to be called |
| 337 | + expect(fetchInitialCalled).toBe(true); |
| 338 | + |
| 339 | + props.id = payload2.id; |
| 340 | + await nextTick(); |
| 341 | + |
| 342 | + resolveFinal?.(payload2); |
| 343 | + |
| 344 | + // Resolve the initial fetch so renderDataCompose completes |
| 345 | + resolveInitial?.(payload); |
| 346 | + |
| 347 | + const { result, cleanup } = await setupPromise; |
| 348 | + const articleRef = await result; |
| 349 | + |
| 350 | + // The data should now be from the final fetch (payload2) |
| 351 | + expect(articleRef.value?.title).toBe(payload2.title); |
| 352 | + expect(articleRef.value?.content).toBe(payload2.content); |
| 353 | + |
| 354 | + cleanup(); |
| 355 | + }); |
292 | 356 | }); |
0 commit comments