From 799e037f39f5622750ba714f7a15830dc649e53f Mon Sep 17 00:00:00 2001
From: panteliselef
Date: Mon, 14 Apr 2025 14:28:03 +0300
Subject: [PATCH 1/5] wip
---
integration/models/longRunningApplication.ts | 2 ++
integration/presets/envs.ts | 8 ++++++++
integration/presets/longRunningApps.ts | 1 +
.../next-app-router/src/app/api/settings/route.ts | 2 +-
.../src/app/settings/auth-protect/page.tsx | 2 +-
.../next-app-router/src/app/settings/rsc-protect/page.tsx | 2 +-
.../next-app-router/src/app/settings/useAuth-has/page.tsx | 2 +-
integration/templates/next-app-router/src/middleware.ts | 2 +-
integration/tests/protect.test.ts | 6 +++++-
packages/testing/src/common/setup.ts | 4 ++--
packages/testing/src/common/types.ts | 2 ++
11 files changed, 25 insertions(+), 8 deletions(-)
diff --git a/integration/models/longRunningApplication.ts b/integration/models/longRunningApplication.ts
index 52c4ac4b6d3..de9eaa90559 100644
--- a/integration/models/longRunningApplication.ts
+++ b/integration/models/longRunningApplication.ts
@@ -62,6 +62,7 @@ export const longRunningApplication = (params: LongRunningApplicationParams) =>
try {
const publishableKey = params.env.publicVariables.get('CLERK_PUBLISHABLE_KEY');
const secretKey = params.env.privateVariables.get('CLERK_SECRET_KEY');
+ const apiUrl = params.env.privateVariables.get('CLERK_API_URL');
const { instanceType, frontendApi: frontendApiUrl } = parsePublishableKey(publishableKey);
if (instanceType !== 'development') {
@@ -71,6 +72,7 @@ export const longRunningApplication = (params: LongRunningApplicationParams) =>
publishableKey,
frontendApiUrl,
secretKey,
+ apiUrl,
dotenv: false,
});
}
diff --git a/integration/presets/envs.ts b/integration/presets/envs.ts
index 8254244547f..2ce9b117ee7 100644
--- a/integration/presets/envs.ts
+++ b/integration/presets/envs.ts
@@ -144,6 +144,13 @@ const withSessionTasks = base
.setEnvVariable('public', 'CLERK_PUBLISHABLE_KEY', instanceKeys.get('with-session-tasks').pk)
.setEnvVariable('private', 'CLERK_ENCRYPTION_KEY', constants.E2E_CLERK_ENCRYPTION_KEY || 'a-key');
+const withBillingStaging = base
+ .clone()
+ .setId('withBillingStaging')
+ .setEnvVariable('private', 'CLERK_API_URL', 'https://api.clerkstage.dev')
+ .setEnvVariable('private', 'CLERK_SECRET_KEY', instanceKeys.get('with-billing-staging').sk)
+ .setEnvVariable('public', 'CLERK_PUBLISHABLE_KEY', instanceKeys.get('with-billing-staging').pk);
+
export const envs = {
base,
withKeyless,
@@ -165,4 +172,5 @@ export const envs = {
withSignInOrUpEmailLinksFlow,
withSignInOrUpwithRestrictedModeFlow,
withSessionTasks,
+ withBillingStaging,
} as const;
diff --git a/integration/presets/longRunningApps.ts b/integration/presets/longRunningApps.ts
index dabfbf72327..3f5a9cba354 100644
--- a/integration/presets/longRunningApps.ts
+++ b/integration/presets/longRunningApps.ts
@@ -42,6 +42,7 @@ export const createLongRunningApps = () => {
config: next.appRouter,
env: envs.withSessionTasks,
},
+ { id: 'next.appRouter.withBillingStaging', config: next.appRouter, env: envs.withBillingStaging },
{
id: 'next.appRouter.withLegalConsent',
config: next.appRouter,
diff --git a/integration/templates/next-app-router/src/app/api/settings/route.ts b/integration/templates/next-app-router/src/app/api/settings/route.ts
index 8e6d46017e6..895ccf2b2bb 100644
--- a/integration/templates/next-app-router/src/app/api/settings/route.ts
+++ b/integration/templates/next-app-router/src/app/api/settings/route.ts
@@ -1,6 +1,6 @@
import { auth } from '@clerk/nextjs/server';
export async function GET() {
- const { userId } = await auth.protect((has: any) => has({ role: 'admin' }) || has({ role: 'org:editor' }));
+ const { userId } = await auth.protect((has: any) => has({ role: 'org:admin' }) || has({ role: 'org:editor' }));
return new Response(JSON.stringify({ userId }));
}
diff --git a/integration/templates/next-app-router/src/app/settings/auth-protect/page.tsx b/integration/templates/next-app-router/src/app/settings/auth-protect/page.tsx
index c7f9b76b514..4a8aec1143e 100644
--- a/integration/templates/next-app-router/src/app/settings/auth-protect/page.tsx
+++ b/integration/templates/next-app-router/src/app/settings/auth-protect/page.tsx
@@ -1,6 +1,6 @@
import { auth } from '@clerk/nextjs/server';
export default async function Page() {
- await auth.protect({ role: 'admin' });
+ await auth.protect({ role: 'org:admin' });
return User has access
;
}
diff --git a/integration/templates/next-app-router/src/app/settings/rsc-protect/page.tsx b/integration/templates/next-app-router/src/app/settings/rsc-protect/page.tsx
index 889e6e18fd3..9e21b23d034 100644
--- a/integration/templates/next-app-router/src/app/settings/rsc-protect/page.tsx
+++ b/integration/templates/next-app-router/src/app/settings/rsc-protect/page.tsx
@@ -3,7 +3,7 @@ import { Protect } from '@clerk/nextjs';
export default function Page() {
return (
User is not admin
}
>
User has access
diff --git a/integration/templates/next-app-router/src/app/settings/useAuth-has/page.tsx b/integration/templates/next-app-router/src/app/settings/useAuth-has/page.tsx
index 14b2dbb1eef..36d5fd0774c 100644
--- a/integration/templates/next-app-router/src/app/settings/useAuth-has/page.tsx
+++ b/integration/templates/next-app-router/src/app/settings/useAuth-has/page.tsx
@@ -6,7 +6,7 @@ export default function Page() {
if (!isLoaded) {
return Loading
;
}
- if (!has({ role: 'admin' })) {
+ if (!has({ role: 'org:admin' })) {
return User is not admin
;
}
return User has access
;
diff --git a/integration/templates/next-app-router/src/middleware.ts b/integration/templates/next-app-router/src/middleware.ts
index 24c94de0e8e..7ccdcc1934b 100644
--- a/integration/templates/next-app-router/src/middleware.ts
+++ b/integration/templates/next-app-router/src/middleware.ts
@@ -18,7 +18,7 @@ export default clerkMiddleware(async (auth, req) => {
}
if (isAdminRoute(req)) {
- await auth.protect({ role: 'admin' });
+ await auth.protect({ role: 'org:admin' });
}
if (isCSPRoute(req)) {
diff --git a/integration/tests/protect.test.ts b/integration/tests/protect.test.ts
index 2d85ae33221..647ead518ff 100644
--- a/integration/tests/protect.test.ts
+++ b/integration/tests/protect.test.ts
@@ -5,7 +5,9 @@ import { appConfigs } from '../presets';
import type { FakeOrganization, FakeUser } from '../testUtils';
import { createTestUtils, testAgainstRunningApps } from '../testUtils';
-testAgainstRunningApps({ withEnv: [appConfigs.envs.withCustomRoles] })('authorization @nextjs', ({ app }) => {
+testAgainstRunningApps({
+ withEnv: [appConfigs.envs.withCustomRoles, appConfigs.envs.withBillingStaging],
+})('authorization @nextjs', ({ app }) => {
test.describe.configure({ mode: 'serial' });
let fakeAdmin: FakeUser;
@@ -40,6 +42,8 @@ testAgainstRunningApps({ withEnv: [appConfigs.envs.withCustomRoles] })('authoriz
await u.po.signIn.waitForMounted();
await u.po.signIn.signInWithEmailAndInstantPassword({ email: fakeAdmin.email, password: fakeAdmin.password });
await u.po.expect.toBeSignedIn();
+ const jwtVersion = await page.evaluate(() => window.Clerk.session?.lastActiveToken?.jwt?.claims?.v);
+ expect(jwtVersion).toBe(app.env.id === 'withBillingStaging' ? 2 : undefined);
await u.po.organizationSwitcher.goTo();
await u.po.organizationSwitcher.waitForMounted();
diff --git a/packages/testing/src/common/setup.ts b/packages/testing/src/common/setup.ts
index 90397df5252..4ed0d30790d 100644
--- a/packages/testing/src/common/setup.ts
+++ b/packages/testing/src/common/setup.ts
@@ -5,7 +5,7 @@ import dotenv from 'dotenv';
import type { ClerkSetupOptions, ClerkSetupReturn } from './types';
export const fetchEnvVars = async (options?: ClerkSetupOptions): Promise => {
- const { debug = false, dotenv: loadDotEnv = true, ...rest } = options || {};
+ const { debug = false, dotenv: loadDotEnv = true, apiUrl: apiUrlProp, ...rest } = options || {};
const log = (msg: string) => {
if (debug) {
@@ -48,7 +48,7 @@ export const fetchEnvVars = async (options?: ClerkSetupOptions): Promise
Date: Mon, 14 Apr 2025 15:08:40 +0300
Subject: [PATCH 2/5] changeset
---
.changeset/purple-falcons-behave.md | 2 ++
1 file changed, 2 insertions(+)
create mode 100644 .changeset/purple-falcons-behave.md
diff --git a/.changeset/purple-falcons-behave.md b/.changeset/purple-falcons-behave.md
new file mode 100644
index 00000000000..a845151cc84
--- /dev/null
+++ b/.changeset/purple-falcons-behave.md
@@ -0,0 +1,2 @@
+---
+---
From a334f5fa50e5da2b607847e7962b64b84ab23e3f Mon Sep 17 00:00:00 2001
From: panteliselef
Date: Mon, 14 Apr 2025 15:13:47 +0300
Subject: [PATCH 3/5] add changeset for testing
---
.changeset/silly-spies-cut.md | 5 +++++
packages/testing/src/common/types.ts | 5 +++++
2 files changed, 10 insertions(+)
create mode 100644 .changeset/silly-spies-cut.md
diff --git a/.changeset/silly-spies-cut.md b/.changeset/silly-spies-cut.md
new file mode 100644
index 00000000000..448d18a5ba8
--- /dev/null
+++ b/.changeset/silly-spies-cut.md
@@ -0,0 +1,5 @@
+---
+'@clerk/testing': patch
+---
+
+Accept `apiUrl` from `clerkSetup()`.
diff --git a/packages/testing/src/common/types.ts b/packages/testing/src/common/types.ts
index 4f56906da4a..a67116579c9 100644
--- a/packages/testing/src/common/types.ts
+++ b/packages/testing/src/common/types.ts
@@ -29,6 +29,11 @@ export type ClerkSetupOptions = {
*/
secretKey?: string;
+ /*
+ * The backend API URL
+ * If not provided, the library will look for the key in the following environment variables:
+ * - CLERK_API_URL
+ */
apiUrl?: string;
/*
From 009156905df0b4206340802eb49cdcc00070390e Mon Sep 17 00:00:00 2001
From: panteliselef
Date: Tue, 15 Apr 2025 10:17:20 +0300
Subject: [PATCH 4/5] remove types from testing package
---
.changeset/silly-spies-cut.md | 3 ---
integration/models/longRunningApplication.ts | 1 +
packages/testing/src/common/setup.ts | 4 ++--
packages/testing/src/common/types.ts | 7 -------
4 files changed, 3 insertions(+), 12 deletions(-)
diff --git a/.changeset/silly-spies-cut.md b/.changeset/silly-spies-cut.md
index 448d18a5ba8..a845151cc84 100644
--- a/.changeset/silly-spies-cut.md
+++ b/.changeset/silly-spies-cut.md
@@ -1,5 +1,2 @@
---
-'@clerk/testing': patch
---
-
-Accept `apiUrl` from `clerkSetup()`.
diff --git a/integration/models/longRunningApplication.ts b/integration/models/longRunningApplication.ts
index de9eaa90559..b7e17ced2df 100644
--- a/integration/models/longRunningApplication.ts
+++ b/integration/models/longRunningApplication.ts
@@ -72,6 +72,7 @@ export const longRunningApplication = (params: LongRunningApplicationParams) =>
publishableKey,
frontendApiUrl,
secretKey,
+ // @ts-expect-error apiUrl is not a typed option for clerkSetup, but it is accepted at runtime.
apiUrl,
dotenv: false,
});
diff --git a/packages/testing/src/common/setup.ts b/packages/testing/src/common/setup.ts
index 4ed0d30790d..36214347116 100644
--- a/packages/testing/src/common/setup.ts
+++ b/packages/testing/src/common/setup.ts
@@ -5,7 +5,7 @@ import dotenv from 'dotenv';
import type { ClerkSetupOptions, ClerkSetupReturn } from './types';
export const fetchEnvVars = async (options?: ClerkSetupOptions): Promise => {
- const { debug = false, dotenv: loadDotEnv = true, apiUrl: apiUrlProp, ...rest } = options || {};
+ const { debug = false, dotenv: loadDotEnv = true, ...rest } = options || {};
const log = (msg: string) => {
if (debug) {
@@ -48,7 +48,7 @@ export const fetchEnvVars = async (options?: ClerkSetupOptions): Promise
Date: Wed, 16 Apr 2025 10:47:06 +0300
Subject: [PATCH 5/5] access safe
---
packages/testing/src/common/setup.ts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/packages/testing/src/common/setup.ts b/packages/testing/src/common/setup.ts
index 36214347116..480170e82fa 100644
--- a/packages/testing/src/common/setup.ts
+++ b/packages/testing/src/common/setup.ts
@@ -48,7 +48,7 @@ export const fetchEnvVars = async (options?: ClerkSetupOptions): Promise