Skip to content

Commit f85abda

Browse files
feat(clerk-js,clerk-react,vue): Introduce development modal to enable organizations (#7159)
Co-authored-by: Alex Carpenter <[email protected]>
1 parent 89af093 commit f85abda

File tree

29 files changed

+1373
-222
lines changed

29 files changed

+1373
-222
lines changed

.changeset/flat-ravens-call.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
---
2+
'@clerk/clerk-js': minor
3+
'@clerk/shared': minor
4+
'@clerk/clerk-react': minor
5+
'@clerk/vue': minor
6+
---
7+
8+
Introduce in-app development prompt to enable the Organizations feature
9+
10+
In development instances, when using organization components or hooks for the first time, developers will see a prompt to enable the Organizations feature directly in their app, eliminating the need to visit the Clerk Dashboard.

packages/clerk-js/bundlewatch.config.json

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
{
22
"files": [
33
{ "path": "./dist/clerk.js", "maxSize": "840KB" },
4-
{ "path": "./dist/clerk.browser.js", "maxSize": "81KB" },
5-
{ "path": "./dist/clerk.channel.browser.js", "maxSize": "81KB" },
6-
{ "path": "./dist/clerk.legacy.browser.js", "maxSize": "123KB" },
4+
{ "path": "./dist/clerk.browser.js", "maxSize": "83KB" },
5+
{ "path": "./dist/clerk.channel.browser.js", "maxSize": "83KB" },
6+
{ "path": "./dist/clerk.legacy.browser.js", "maxSize": "127KB" },
77
{ "path": "./dist/clerk.headless*.js", "maxSize": "65KB" },
8-
{ "path": "./dist/ui-common*.js", "maxSize": "117.1KB" },
8+
{ "path": "./dist/ui-common*.js", "maxSize": "119KB" },
99
{ "path": "./dist/ui-common*.legacy.*.js", "maxSize": "122KB" },
1010
{ "path": "./dist/vendors*.js", "maxSize": "47KB" },
1111
{ "path": "./dist/coinbase*.js", "maxSize": "38KB" },
@@ -23,6 +23,7 @@
2323
{ "path": "./dist/onetap*.js", "maxSize": "1KB" },
2424
{ "path": "./dist/waitlist*.js", "maxSize": "1.5KB" },
2525
{ "path": "./dist/keylessPrompt*.js", "maxSize": "6.5KB" },
26+
{ "path": "./dist/enableOrganizationsPrompt*.js", "maxSize": "6.5KB" },
2627
{ "path": "./dist/pricingTable*.js", "maxSize": "4.02KB" },
2728
{ "path": "./dist/checkout*.js", "maxSize": "8.82KB" },
2829
{ "path": "./dist/up-billing-page*.js", "maxSize": "3.0KB" },

packages/clerk-js/src/core/__tests__/clerk.test.ts

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2508,4 +2508,128 @@ describe('Clerk singleton', () => {
25082508
});
25092509
});
25102510
});
2511+
2512+
describe('__internal_attemptToEnableEnvironmentSetting', () => {
2513+
describe('for organizations', () => {
2514+
it('does not open prompt if organizations is enabled in development', async () => {
2515+
mockEnvironmentFetch.mockReturnValue(
2516+
Promise.resolve({
2517+
userSettings: mockUserSettings,
2518+
displayConfig: mockDisplayConfig,
2519+
isSingleSession: () => false,
2520+
isProduction: () => false,
2521+
isDevelopmentOrStaging: () => true,
2522+
organizationSettings: {
2523+
enabled: true,
2524+
},
2525+
}),
2526+
);
2527+
2528+
const sut = new Clerk(productionPublishableKey);
2529+
2530+
const __internal_openEnableOrganizationsPromptSpy = vi.fn();
2531+
sut.__internal_openEnableOrganizationsPrompt = __internal_openEnableOrganizationsPromptSpy;
2532+
2533+
await sut.load();
2534+
2535+
const result = await sut.__internal_attemptToEnableEnvironmentSetting({
2536+
for: 'organizations',
2537+
caller: 'OrganizationSwitcher',
2538+
});
2539+
2540+
expect(result?.isEnabled).toBe(true);
2541+
expect(__internal_openEnableOrganizationsPromptSpy).not.toHaveBeenCalled();
2542+
});
2543+
2544+
it('does not open prompt if organizations is enabled in production', async () => {
2545+
mockEnvironmentFetch.mockReturnValue(
2546+
Promise.resolve({
2547+
userSettings: mockUserSettings,
2548+
displayConfig: mockDisplayConfig,
2549+
isSingleSession: () => false,
2550+
isProduction: () => true,
2551+
isDevelopmentOrStaging: () => true,
2552+
organizationSettings: {
2553+
enabled: true,
2554+
},
2555+
}),
2556+
);
2557+
2558+
const sut = new Clerk(productionPublishableKey);
2559+
2560+
const __internal_openEnableOrganizationsPromptSpy = vi.fn();
2561+
sut.__internal_openEnableOrganizationsPrompt = __internal_openEnableOrganizationsPromptSpy;
2562+
2563+
await sut.load();
2564+
2565+
const result = await sut.__internal_attemptToEnableEnvironmentSetting({
2566+
for: 'organizations',
2567+
caller: 'OrganizationSwitcher',
2568+
});
2569+
2570+
expect(result?.isEnabled).toBe(true);
2571+
expect(__internal_openEnableOrganizationsPromptSpy).not.toHaveBeenCalled();
2572+
});
2573+
2574+
it('opens prompt if organizations is disabled in development', async () => {
2575+
mockEnvironmentFetch.mockReturnValue(
2576+
Promise.resolve({
2577+
userSettings: mockUserSettings,
2578+
displayConfig: mockDisplayConfig,
2579+
isSingleSession: () => false,
2580+
isProduction: () => false,
2581+
isDevelopmentOrStaging: () => true,
2582+
organizationSettings: {
2583+
enabled: false,
2584+
},
2585+
}),
2586+
);
2587+
2588+
const sut = new Clerk(developmentPublishableKey);
2589+
2590+
const __internal_openEnableOrganizationsPromptSpy = vi.fn();
2591+
sut.__internal_openEnableOrganizationsPrompt = __internal_openEnableOrganizationsPromptSpy;
2592+
2593+
await sut.load();
2594+
2595+
const result = await sut.__internal_attemptToEnableEnvironmentSetting({
2596+
for: 'organizations',
2597+
caller: 'OrganizationSwitcher',
2598+
});
2599+
2600+
expect(result?.isEnabled).toBe(false);
2601+
expect(__internal_openEnableOrganizationsPromptSpy).toHaveBeenCalled();
2602+
});
2603+
2604+
it('does not open prompt if organizations is disabled in production', async () => {
2605+
mockEnvironmentFetch.mockReturnValue(
2606+
Promise.resolve({
2607+
userSettings: mockUserSettings,
2608+
displayConfig: mockDisplayConfig,
2609+
isSingleSession: () => false,
2610+
isProduction: () => false,
2611+
isDevelopmentOrStaging: () => true,
2612+
organizationSettings: {
2613+
enabled: false,
2614+
},
2615+
}),
2616+
);
2617+
2618+
const sut = new Clerk(productionPublishableKey);
2619+
2620+
const __internal_openEnableOrganizationsPromptSpy = vi.fn();
2621+
sut.__internal_openEnableOrganizationsPrompt = __internal_openEnableOrganizationsPromptSpy;
2622+
2623+
await sut.load();
2624+
2625+
const result = await sut.__internal_attemptToEnableEnvironmentSetting({
2626+
for: 'organizations',
2627+
caller: 'OrganizationSwitcher',
2628+
});
2629+
2630+
expect(result?.isEnabled).toBe(false);
2631+
expect(__internal_openEnableOrganizationsPromptSpy).not.toHaveBeenCalled();
2632+
});
2633+
});
2634+
});
25112635
});

0 commit comments

Comments
 (0)