Skip to content

Commit 38d8b3e

Browse files
authored
fix(shared): Invitations depends on wrong options (useOrganization) (#2472)
* fix(shared): Invitations depends on wrong options (useOrganization) * fix(shared): Invitations is depending on wrong options * test(clerk-js): Add unit test * chore(clerk-js): Update changeset
1 parent 124d9f3 commit 38d8b3e

File tree

3 files changed

+211
-2
lines changed

3 files changed

+211
-2
lines changed

.changeset/thirty-cooks-cheer.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@clerk/shared': patch
3+
---
4+
5+
Fixes a bug where Invitations from `useOrganization` incorrectly depended on options for memberships.

packages/clerk-js/src/ui/hooks/__tests__/useCoreOrganization.test.tsx

+204
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { describe } from '@jest/globals';
44
import { act, renderHook, waitFor } from '../../../testUtils';
55
import {
66
createFakeDomain,
7+
createFakeOrganizationInvitation,
78
createFakeOrganizationMembershipRequest,
89
} from '../../components/OrganizationProfile/__tests__/utils';
910
import { createFakeUserOrganizationMembership } from '../../components/OrganizationSwitcher/__tests__/utlis';
@@ -16,6 +17,9 @@ const defaultRenderer = () =>
1617
domains: {
1718
pageSize: 2,
1819
},
20+
invitations: {
21+
pageSize: 2,
22+
},
1923
membershipRequests: {
2024
pageSize: 2,
2125
},
@@ -403,4 +407,204 @@ describe('useOrganization', () => {
403407
);
404408
});
405409
});
410+
411+
describe('invitations', () => {
412+
it('fetch with pages', async () => {
413+
const { wrapper, fixtures } = await createFixtures(f => {
414+
f.withOrganizations();
415+
f.withUser({
416+
email_addresses: ['test@clerk.com'],
417+
organization_memberships: [{ name: 'Org1', role: 'basic_member' }],
418+
});
419+
});
420+
421+
fixtures.clerk.organization?.getInvitations.mockReturnValue(
422+
Promise.resolve({
423+
data: [
424+
createFakeOrganizationInvitation({
425+
id: '1',
426+
emailAddress: 'admin1@clerk.com',
427+
organizationId: '1',
428+
createdAt: new Date('2022-01-01'),
429+
}),
430+
createFakeOrganizationInvitation({
431+
id: '2',
432+
emailAddress: 'member2@clerk.com',
433+
organizationId: '1',
434+
createdAt: new Date('2022-01-01'),
435+
}),
436+
],
437+
total_count: 4,
438+
}),
439+
);
440+
const { result } = renderHook(defaultRenderer, { wrapper });
441+
expect(result.current.invitations?.isLoading).toBe(true);
442+
expect(result.current.invitations?.isFetching).toBe(true);
443+
expect(result.current.invitations?.count).toBe(0);
444+
445+
await waitFor(() => expect(result.current.invitations?.isLoading).toBe(false));
446+
447+
expect(result.current.invitations?.isFetching).toBe(false);
448+
expect(result.current.invitations?.count).toBe(4);
449+
expect(result.current.invitations?.page).toBe(1);
450+
expect(result.current.invitations?.pageCount).toBe(2);
451+
expect(result.current.invitations?.hasNextPage).toBe(true);
452+
453+
fixtures.clerk.organization?.getInvitations.mockReturnValue(
454+
Promise.resolve({
455+
data: [
456+
createFakeOrganizationInvitation({
457+
id: '3',
458+
emailAddress: 'admin3@clerk.com',
459+
organizationId: '1',
460+
createdAt: new Date('2022-01-01'),
461+
}),
462+
createFakeOrganizationInvitation({
463+
id: '4',
464+
emailAddress: 'member4@clerk.com',
465+
organizationId: '1',
466+
createdAt: new Date('2022-01-01'),
467+
}),
468+
],
469+
total_count: 4,
470+
}),
471+
);
472+
473+
act(() => result.current.invitations?.fetchNext?.());
474+
475+
await waitFor(() => expect(result.current.invitations?.isLoading).toBe(true));
476+
await waitFor(() => expect(result.current.invitations?.isLoading).toBe(false));
477+
478+
expect(result.current.invitations?.page).toBe(2);
479+
expect(result.current.invitations?.hasNextPage).toBe(false);
480+
expect(result.current.invitations?.data).toEqual(
481+
expect.arrayContaining([
482+
expect.not.objectContaining({
483+
id: '1',
484+
}),
485+
expect.not.objectContaining({
486+
id: '2',
487+
}),
488+
expect.objectContaining({
489+
organizationId: '1',
490+
id: '3',
491+
emailAddress: 'admin3@clerk.com',
492+
}),
493+
expect.objectContaining({
494+
organizationId: '1',
495+
id: '4',
496+
emailAddress: 'member4@clerk.com',
497+
}),
498+
]),
499+
);
500+
});
501+
502+
it('infinite fetch', async () => {
503+
const { wrapper, fixtures } = await createFixtures(f => {
504+
f.withOrganizations();
505+
f.withUser({
506+
email_addresses: ['test@clerk.com'],
507+
organization_memberships: [{ name: 'Org1', role: 'basic_member' }],
508+
});
509+
});
510+
511+
fixtures.clerk.organization?.getInvitations.mockReturnValueOnce(
512+
Promise.resolve({
513+
data: [
514+
createFakeOrganizationInvitation({
515+
id: '1',
516+
emailAddress: 'admin1@clerk.com',
517+
organizationId: '1',
518+
createdAt: new Date('2022-01-01'),
519+
}),
520+
createFakeOrganizationInvitation({
521+
id: '2',
522+
emailAddress: 'member2@clerk.com',
523+
organizationId: '1',
524+
createdAt: new Date('2022-01-01'),
525+
}),
526+
],
527+
total_count: 4,
528+
}),
529+
);
530+
const { result } = renderHook(
531+
() =>
532+
useOrganization({
533+
invitations: {
534+
pageSize: 2,
535+
infinite: true,
536+
},
537+
}),
538+
{ wrapper },
539+
);
540+
expect(result.current.invitations?.isLoading).toBe(true);
541+
expect(result.current.invitations?.isFetching).toBe(true);
542+
543+
await waitFor(() => expect(result.current.invitations?.isLoading).toBe(false));
544+
expect(result.current.invitations?.isFetching).toBe(false);
545+
546+
fixtures.clerk.organization?.getInvitations.mockReturnValueOnce(
547+
Promise.resolve({
548+
data: [
549+
createFakeOrganizationInvitation({
550+
id: '1',
551+
emailAddress: 'admin1@clerk.com',
552+
organizationId: '1',
553+
createdAt: new Date('2022-01-01'),
554+
}),
555+
createFakeOrganizationInvitation({
556+
id: '2',
557+
emailAddress: 'member2@clerk.com',
558+
organizationId: '1',
559+
createdAt: new Date('2022-01-01'),
560+
}),
561+
],
562+
total_count: 4,
563+
}),
564+
);
565+
566+
fixtures.clerk.organization?.getInvitations.mockReturnValueOnce(
567+
Promise.resolve({
568+
data: [
569+
createFakeOrganizationInvitation({
570+
id: '3',
571+
emailAddress: 'admin3@clerk.com',
572+
organizationId: '1',
573+
createdAt: new Date('2022-01-01'),
574+
}),
575+
createFakeOrganizationInvitation({
576+
id: '4',
577+
emailAddress: 'member4@clerk.com',
578+
organizationId: '1',
579+
createdAt: new Date('2022-01-01'),
580+
}),
581+
],
582+
total_count: 4,
583+
}),
584+
);
585+
586+
act(() => result.current.invitations?.fetchNext?.());
587+
588+
await waitFor(() => expect(result.current.invitations?.isFetching).toBe(true));
589+
expect(result.current.invitations?.isLoading).toBe(false);
590+
591+
await waitFor(() => expect(result.current.invitations?.isFetching).toBe(false));
592+
expect(result.current.invitations?.data).toEqual(
593+
expect.arrayContaining([
594+
expect.objectContaining({
595+
id: '1',
596+
}),
597+
expect.objectContaining({
598+
id: '2',
599+
}),
600+
expect.objectContaining({
601+
id: '3',
602+
}),
603+
expect.objectContaining({
604+
id: '4',
605+
}),
606+
]),
607+
);
608+
});
609+
});
406610
});

packages/shared/src/react/hooks/useOrganization.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -246,8 +246,8 @@ export const useOrganization: UseOrganization = params => {
246246
},
247247
organization?.getInvitations,
248248
{
249-
keepPreviousData: membersSafeValues.keepPreviousData,
250-
infinite: membersSafeValues.infinite,
249+
keepPreviousData: invitationsSafeValues.keepPreviousData,
250+
infinite: invitationsSafeValues.infinite,
251251
enabled: !!invitationsParams,
252252
},
253253
{

0 commit comments

Comments
 (0)