From ea5621660aaf4606a876f415ac1018451876a77d Mon Sep 17 00:00:00 2001 From: panteliselef Date: Thu, 4 Jan 2024 13:56:46 +0200 Subject: [PATCH 1/2] 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 (cherry picked from commit 38d8b3e8a0387bcf0b9c8d16e3bbfcfe9b643ca2) --- .changeset/thirty-cooks-cheer.md | 5 + .../__tests__/useCoreOrganization.test.tsx | 204 ++++++++++++++++++ .../src/react/hooks/useOrganization.tsx | 4 +- 3 files changed, 211 insertions(+), 2 deletions(-) create mode 100644 .changeset/thirty-cooks-cheer.md diff --git a/.changeset/thirty-cooks-cheer.md b/.changeset/thirty-cooks-cheer.md new file mode 100644 index 00000000000..9537a0a571e --- /dev/null +++ b/.changeset/thirty-cooks-cheer.md @@ -0,0 +1,5 @@ +--- +'@clerk/shared': patch +--- + +Fixes a bug where Invitations from `useOrganization` incorrectly depended on options for memberships. diff --git a/packages/clerk-js/src/ui/hooks/__tests__/useCoreOrganization.test.tsx b/packages/clerk-js/src/ui/hooks/__tests__/useCoreOrganization.test.tsx index ea437599892..aafff2133f6 100644 --- a/packages/clerk-js/src/ui/hooks/__tests__/useCoreOrganization.test.tsx +++ b/packages/clerk-js/src/ui/hooks/__tests__/useCoreOrganization.test.tsx @@ -3,6 +3,7 @@ import { describe } from '@jest/globals'; import { act, bindCreateFixtures, renderHook, waitFor } from '../../../testUtils'; import { createFakeDomain, + createFakeOrganizationInvitation, createFakeOrganizationMembershipRequest, } from '../../components/OrganizationProfile/__tests__/utils'; import { createFakeUserOrganizationMembership } from '../../components/OrganizationSwitcher/__tests__/utlis'; @@ -15,6 +16,9 @@ const defaultRenderer = () => domains: { pageSize: 2, }, + invitations: { + pageSize: 2, + }, membershipRequests: { pageSize: 2, }, @@ -427,4 +431,204 @@ describe('useOrganization', () => { }); }); }); + + describe('invitations', () => { + it('fetch with pages', async () => { + const { wrapper, fixtures } = await createFixtures(f => { + f.withOrganizations(); + f.withUser({ + email_addresses: ['test@clerk.com'], + organization_memberships: [{ name: 'Org1', role: 'basic_member' }], + }); + }); + + fixtures.clerk.organization?.getInvitations.mockReturnValue( + Promise.resolve({ + data: [ + createFakeOrganizationInvitation({ + id: '1', + emailAddress: 'admin1@clerk.com', + organizationId: '1', + createdAt: new Date('2022-01-01'), + }), + createFakeOrganizationInvitation({ + id: '2', + emailAddress: 'member2@clerk.com', + organizationId: '1', + createdAt: new Date('2022-01-01'), + }), + ], + total_count: 4, + }), + ); + const { result } = renderHook(defaultRenderer, { wrapper }); + expect(result.current.invitations?.isLoading).toBe(true); + expect(result.current.invitations?.isFetching).toBe(true); + expect(result.current.invitations?.count).toBe(0); + + await waitFor(() => expect(result.current.invitations?.isLoading).toBe(false)); + + expect(result.current.invitations?.isFetching).toBe(false); + expect(result.current.invitations?.count).toBe(4); + expect(result.current.invitations?.page).toBe(1); + expect(result.current.invitations?.pageCount).toBe(2); + expect(result.current.invitations?.hasNextPage).toBe(true); + + fixtures.clerk.organization?.getInvitations.mockReturnValue( + Promise.resolve({ + data: [ + createFakeOrganizationInvitation({ + id: '3', + emailAddress: 'admin3@clerk.com', + organizationId: '1', + createdAt: new Date('2022-01-01'), + }), + createFakeOrganizationInvitation({ + id: '4', + emailAddress: 'member4@clerk.com', + organizationId: '1', + createdAt: new Date('2022-01-01'), + }), + ], + total_count: 4, + }), + ); + + act(() => result.current.invitations?.fetchNext?.()); + + await waitFor(() => expect(result.current.invitations?.isLoading).toBe(true)); + await waitFor(() => expect(result.current.invitations?.isLoading).toBe(false)); + + expect(result.current.invitations?.page).toBe(2); + expect(result.current.invitations?.hasNextPage).toBe(false); + expect(result.current.invitations?.data).toEqual( + expect.arrayContaining([ + expect.not.objectContaining({ + id: '1', + }), + expect.not.objectContaining({ + id: '2', + }), + expect.objectContaining({ + organizationId: '1', + id: '3', + emailAddress: 'admin3@clerk.com', + }), + expect.objectContaining({ + organizationId: '1', + id: '4', + emailAddress: 'member4@clerk.com', + }), + ]), + ); + }); + + it('infinite fetch', async () => { + const { wrapper, fixtures } = await createFixtures(f => { + f.withOrganizations(); + f.withUser({ + email_addresses: ['test@clerk.com'], + organization_memberships: [{ name: 'Org1', role: 'basic_member' }], + }); + }); + + fixtures.clerk.organization?.getInvitations.mockReturnValueOnce( + Promise.resolve({ + data: [ + createFakeOrganizationInvitation({ + id: '1', + emailAddress: 'admin1@clerk.com', + organizationId: '1', + createdAt: new Date('2022-01-01'), + }), + createFakeOrganizationInvitation({ + id: '2', + emailAddress: 'member2@clerk.com', + organizationId: '1', + createdAt: new Date('2022-01-01'), + }), + ], + total_count: 4, + }), + ); + const { result } = renderHook( + () => + useOrganization({ + invitations: { + pageSize: 2, + infinite: true, + }, + }), + { wrapper }, + ); + expect(result.current.invitations?.isLoading).toBe(true); + expect(result.current.invitations?.isFetching).toBe(true); + + await waitFor(() => expect(result.current.invitations?.isLoading).toBe(false)); + expect(result.current.invitations?.isFetching).toBe(false); + + fixtures.clerk.organization?.getInvitations.mockReturnValueOnce( + Promise.resolve({ + data: [ + createFakeOrganizationInvitation({ + id: '1', + emailAddress: 'admin1@clerk.com', + organizationId: '1', + createdAt: new Date('2022-01-01'), + }), + createFakeOrganizationInvitation({ + id: '2', + emailAddress: 'member2@clerk.com', + organizationId: '1', + createdAt: new Date('2022-01-01'), + }), + ], + total_count: 4, + }), + ); + + fixtures.clerk.organization?.getInvitations.mockReturnValueOnce( + Promise.resolve({ + data: [ + createFakeOrganizationInvitation({ + id: '3', + emailAddress: 'admin3@clerk.com', + organizationId: '1', + createdAt: new Date('2022-01-01'), + }), + createFakeOrganizationInvitation({ + id: '4', + emailAddress: 'member4@clerk.com', + organizationId: '1', + createdAt: new Date('2022-01-01'), + }), + ], + total_count: 4, + }), + ); + + act(() => result.current.invitations?.fetchNext?.()); + + await waitFor(() => expect(result.current.invitations?.isFetching).toBe(true)); + expect(result.current.invitations?.isLoading).toBe(false); + + await waitFor(() => expect(result.current.invitations?.isFetching).toBe(false)); + expect(result.current.invitations?.data).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + id: '1', + }), + expect.objectContaining({ + id: '2', + }), + expect.objectContaining({ + id: '3', + }), + expect.objectContaining({ + id: '4', + }), + ]), + ); + }); + }); }); diff --git a/packages/shared/src/react/hooks/useOrganization.tsx b/packages/shared/src/react/hooks/useOrganization.tsx index 15a6f776bde..181297d55d6 100644 --- a/packages/shared/src/react/hooks/useOrganization.tsx +++ b/packages/shared/src/react/hooks/useOrganization.tsx @@ -282,8 +282,8 @@ export const useOrganization: UseOrganization = params => { }, organization?.getInvitations, { - keepPreviousData: membersSafeValues.keepPreviousData, - infinite: membersSafeValues.infinite, + keepPreviousData: invitationsSafeValues.keepPreviousData, + infinite: invitationsSafeValues.infinite, enabled: !!invitationsParams, }, { From ba49daf0066c1e70c5d62454657422e01802f51c Mon Sep 17 00:00:00 2001 From: panteliselef Date: Thu, 4 Jan 2024 15:45:58 +0200 Subject: [PATCH 2/2] fix(clerk-js): Use useCoreOrganization --- .../src/ui/hooks/__tests__/useCoreOrganization.test.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/clerk-js/src/ui/hooks/__tests__/useCoreOrganization.test.tsx b/packages/clerk-js/src/ui/hooks/__tests__/useCoreOrganization.test.tsx index aafff2133f6..6f41f4910c9 100644 --- a/packages/clerk-js/src/ui/hooks/__tests__/useCoreOrganization.test.tsx +++ b/packages/clerk-js/src/ui/hooks/__tests__/useCoreOrganization.test.tsx @@ -553,7 +553,7 @@ describe('useOrganization', () => { ); const { result } = renderHook( () => - useOrganization({ + useCoreOrganization({ invitations: { pageSize: 2, infinite: true,