Skip to content

Commit 90e0a3a

Browse files
fix(navigation): refresh organization destination after creation
1 parent e9a4fb7 commit 90e0a3a

2 files changed

Lines changed: 68 additions & 8 deletions

File tree

‎apps/sim/hooks/queries/organization.test.tsx‎

Lines changed: 63 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,25 @@ import { createRoot, type Root } from 'react-dom/client'
88
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
99
import { ApiClientError } from '@/lib/api/client/errors'
1010

11-
const { mockGetFullOrganization, mockListOrganizations, mockRequestJson, featureFlags } =
12-
vi.hoisted(() => ({
13-
mockGetFullOrganization: vi.fn(),
14-
mockListOrganizations: vi.fn(),
15-
mockRequestJson: vi.fn(),
16-
featureFlags: { organizations: true },
17-
}))
11+
const {
12+
mockGetFullOrganization,
13+
mockListOrganizations,
14+
mockSetActiveOrganization,
15+
mockRefresh,
16+
mockRequestJson,
17+
featureFlags,
18+
} = vi.hoisted(() => ({
19+
mockGetFullOrganization: vi.fn(),
20+
mockListOrganizations: vi.fn(),
21+
mockSetActiveOrganization: vi.fn(),
22+
mockRefresh: vi.fn(),
23+
mockRequestJson: vi.fn(),
24+
featureFlags: { organizations: true },
25+
}))
26+
27+
vi.mock('next/navigation', () => ({
28+
useRouter: () => ({ refresh: mockRefresh }),
29+
}))
1830

1931
vi.mock('@/lib/core/config/env-flags', () => ({
2032
get isOrganizationsEnabled() {
@@ -31,6 +43,7 @@ vi.mock('@/lib/auth/auth-client', () => ({
3143
organization: {
3244
getFullOrganization: mockGetFullOrganization,
3345
list: mockListOrganizations,
46+
setActive: mockSetActiveOrganization,
3447
},
3548
subscription: {
3649
list: vi.fn(),
@@ -49,6 +62,7 @@ import {
4962
} from '@/lib/api/contracts/subscription'
5063
import {
5164
organizationKeys,
65+
useCreateOrganization,
5266
useOrganization,
5367
useOrganizationBilling,
5468
useOrganizationList,
@@ -199,6 +213,48 @@ describe('organization identity transitions', () => {
199213
expect(signal).toBeInstanceOf(AbortSignal)
200214
})
201215

216+
it.each([true, false])(
217+
'refreshes the server layout after organization activation settles (success=%s)',
218+
async (success) => {
219+
mockRequestJson.mockResolvedValue({ organizationId: 'new-organization' })
220+
const activation = createDeferred<{ error: { message: string } | null }>()
221+
mockSetActiveOrganization.mockReturnValue(activation.promise)
222+
let mutation: ReturnType<typeof useCreateOrganization>
223+
function CreationProbe() {
224+
mutation = useCreateOrganization()
225+
return null
226+
}
227+
228+
await act(async () => {
229+
root.render(
230+
<QueryClientProvider client={queryClient}>
231+
<CreationProbe />
232+
</QueryClientProvider>
233+
)
234+
})
235+
let pending: Promise<unknown>
236+
await act(async () => {
237+
pending = mutation.mutateAsync({ name: 'New organization' })
238+
})
239+
expect(mockSetActiveOrganization).toHaveBeenCalledWith({
240+
organizationId: 'new-organization',
241+
})
242+
expect(mockRefresh).not.toHaveBeenCalled()
243+
244+
await act(async () => {
245+
if (success) {
246+
activation.resolve({ error: null })
247+
await pending
248+
} else {
249+
const rejection = expect(pending).rejects.toThrow('Activation failed')
250+
activation.resolve({ error: { message: 'Activation failed' } })
251+
await rejection
252+
}
253+
})
254+
expect(mockRefresh).toHaveBeenCalledOnce()
255+
}
256+
)
257+
202258
it('does not call the organization plugin when organizations are disabled', async () => {
203259
featureFlags.organizations = false
204260
await act(async () =>

‎apps/sim/hooks/queries/organization.ts‎

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {
77
useQuery,
88
useQueryClient,
99
} from '@tanstack/react-query'
10+
import { useRouter } from 'next/navigation'
1011
import { ApiClientError } from '@/lib/api/client/errors'
1112
import { requestJson } from '@/lib/api/client/request'
1213
import type { ContractBodyInput } from '@/lib/api/contracts'
@@ -605,6 +606,7 @@ type CreateOrganizationParams = Pick<
605606

606607
export function useCreateOrganization() {
607608
const queryClient = useQueryClient()
609+
const router = useRouter()
608610

609611
return useMutation({
610612
mutationFn: async ({ name, slug }: CreateOrganizationParams) => {
@@ -615,15 +617,17 @@ export function useCreateOrganization() {
615617
},
616618
})
617619

618-
await client.organization.setActive({
620+
const { error } = await client.organization.setActive({
619621
organizationId: data.organizationId,
620622
})
623+
if (error) throw new Error(error.message || 'Failed to activate organization')
621624

622625
return data
623626
},
624627
onSettled: () => {
625628
queryClient.invalidateQueries({ queryKey: organizationKeys.lists() })
626629
queryClient.invalidateQueries({ queryKey: workspaceKeys.lists() })
630+
router.refresh()
627631
},
628632
})
629633
}

0 commit comments

Comments
 (0)