Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: clerk/javascript
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: @clerk/themes@2.2.18
Choose a base ref
...
head repository: clerk/javascript
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: @clerk/themes@2.2.19
Choose a head ref

Commits on Feb 13, 2025

  1. feat(clerk-js,shared,nextjs,react-router,clerk-react,remix): Introduc…

    …e `EmailLinkErrorCodeStatus` (#5142)
    alexcarpenter authored Feb 13, 2025
    Copy the full SHA
    d76c469 View commit details
  2. Copy the full SHA
    6e67503 View commit details
  3. chore(repo): Add missing changeset for tanstack-start EmailLinkErrorC…

    …odeStatus (#5151)
    
    Co-authored-by: panteliselef <panteliselef@outlook.com>
    alexcarpenter and panteliselef authored Feb 13, 2025
    Copy the full SHA
    ee2375c View commit details
  4. fix(clerk-js): Update web3 signUpContinueUrl when in combined flow (#…

    …5141)
    
    Co-authored-by: Vaggelis Yfantis <vaggelisyfantis@gmail.com>
    alexcarpenter and octoper authored Feb 13, 2025
    Copy the full SHA
    3fac683 View commit details
  5. Copy the full SHA
    b15ec60 View commit details
  6. fix(nextjs): Update clerkMiddleware request callback to accept an a…

    …sync function (#5154)
    
    Co-authored-by: Jack Adam <jackadam@improbable.io>
    LauraBeatris and itsjxck authored Feb 13, 2025
    Copy the full SHA
    ccf4836 View commit details
  7. Copy the full SHA
    62200fa View commit details
  8. Copy the full SHA
    e9c6d79 View commit details
  9. Copy the full SHA
    35059df View commit details

Commits on Feb 14, 2025

  1. chore(shared): Update dependency esbuild to v0.25.0 [SECURITY] (#5132)

    Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
    renovate[bot] authored Feb 14, 2025
    Copy the full SHA
    80e6ba0 View commit details
  2. Copy the full SHA
    14fd729 View commit details
  3. Copy the full SHA
    a9b0087 View commit details
  4. Copy the full SHA
    c0ecbe4 View commit details
  5. Copy the full SHA
    f59491e View commit details
  6. Copy the full SHA
    8daa94a View commit details
  7. Copy the full SHA
    74868fa View commit details
  8. Copy the full SHA
    92d17d7 View commit details

Commits on Feb 16, 2025

  1. fix(repo): Update dependency zod to ^3.24.2 (#5181)

    Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
    renovate[bot] authored Feb 16, 2025
    Copy the full SHA
    8f2b3f7 View commit details
  2. fix(repo): Update dependency next to v14.2.24 (#5180)

    Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
    Co-authored-by: panteliselef <panteliselef@outlook.com>
    renovate[bot] and panteliselef authored Feb 16, 2025
    Copy the full SHA
    5521a71 View commit details

Commits on Feb 17, 2025

  1. chore(astro): Update dependency astro to ^5.2.6 (#5174)

    Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
    Co-authored-by: Lennart <lekoarts@gmail.com>
    renovate[bot] and LekoArts authored Feb 17, 2025
    Copy the full SHA
    ea188fe View commit details
  2. chore(clerk-js): Update [DEV] minor & patch dependencies to ^1.2.3 (#…

    …5175)
    
    Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
    Co-authored-by: panteliselef <panteliselef@outlook.com>
    renovate[bot] and panteliselef authored Feb 17, 2025
    Copy the full SHA
    8def478 View commit details
  3. chore(repo): Update common TypeScript types (#5178)

    Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
    Co-authored-by: Lennart <lekoarts@gmail.com>
    renovate[bot] and LekoArts authored Feb 17, 2025
    Copy the full SHA
    062438a View commit details
  4. chore(nextjs): Update dependency next to ^14.2.24 (#5177)

    Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
    Co-authored-by: panteliselef <panteliselef@outlook.com>
    renovate[bot] and panteliselef authored Feb 17, 2025
    Copy the full SHA
    d255ea5 View commit details
  5. Copy the full SHA
    a4bf420 View commit details
  6. Copy the full SHA
    cab9408 View commit details

Commits on Feb 18, 2025

  1. chore(localizations): Add missing fi-FI translations for legalConsent (

    …#5103)
    
    Co-authored-by: panteliselef <panteliselef@outlook.com>
    severi and panteliselef authored Feb 18, 2025
    Copy the full SHA
    4001e03 View commit details
  2. fix(clerk-react): Prevent UserProfileModal re-render in `<UserButto…

    …n />` with custom props (#5145)
    nikospapcom authored Feb 18, 2025
    Copy the full SHA
    30f6f38 View commit details
  3. ci(repo): Version packages (#5149)

    Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
    clerk-cookie and github-actions[bot] authored Feb 18, 2025
    Copy the full SHA
    93acb6f View commit details
Showing with 1,712 additions and 562 deletions.
  1. +1 −1 .lintstagedrc.json
  2. +2 −1 integration/templates/next-app-router/src/app/sign-in-or-up/[[...catchall]]/page.tsx
  3. +1 −0 integration/templates/next-app-router/src/app/sign-up/[[...catchall]]/page.tsx
  4. +68 −0 integration/templates/react-vite/src/custom-user-button/with-dynamic-label-and-custom-pages.tsx
  5. +1 −19 integration/templates/react-vite/src/custom-user-button/with-dynamic-labels.tsx
  6. +5 −0 integration/templates/react-vite/src/main.tsx
  7. +24 −0 integration/testUtils/usersService.ts
  8. +68 −0 integration/tests/custom-pages.test.ts
  9. +2 −2 integration/tests/nuxt/middleware.test.ts
  10. +1 −1 integration/tests/sign-in-or-up-component.test.ts
  11. +12 −0 integration/tests/sign-out-smoke.test.ts
  12. +71 −0 integration/tests/unsafeMetadata.test.ts
  13. +1 −1 package.json
  14. +9 −0 packages/agent-toolkit/CHANGELOG.md
  15. +2 −2 packages/agent-toolkit/package.json
  16. +9 −0 packages/astro/CHANGELOG.md
  17. +2 −2 packages/astro/package.json
  18. +8 −0 packages/backend/CHANGELOG.md
  19. +1 −1 packages/backend/package.json
  20. +9 −0 packages/chrome-extension/CHANGELOG.md
  21. +1 −1 packages/chrome-extension/package.json
  22. +34 −0 packages/clerk-js/CHANGELOG.md
  23. +1 −1 packages/clerk-js/bundlewatch.config.json
  24. +3 −4 packages/clerk-js/package.json
  25. +5 −5 packages/clerk-js/src/core/__tests__/clerk.test.ts
  26. +9 −1 packages/clerk-js/src/core/auth/AuthCookieService.ts
  27. +52 −16 packages/clerk-js/src/core/clerk.ts
  28. +1 −0 packages/clerk-js/src/core/resources/Error.ts
  29. +0 −1 packages/clerk-js/src/ui/Components.tsx
  30. +3 −3 packages/clerk-js/src/ui/common/EmailLinkVerify.tsx
  31. +1 −0 packages/clerk-js/src/ui/components/SignIn/SignIn.tsx
  32. +1 −1 packages/clerk-js/src/ui/components/SignIn/SignInSocialButtons.tsx
  33. +3 −3 packages/clerk-js/src/ui/components/SignUp/__tests__/SignUpEmailLinkFlowComplete.test.tsx
  34. +7 −5 packages/clerk-js/src/ui/components/UserProfile/EmailsSection.tsx
  35. +1 −1 packages/clerk-js/src/ui/components/UserVerification/AlternativeMethods.tsx
  36. +1 −1 packages/clerk-js/src/ui/elements/VerificationCodeCard.tsx
  37. +36 −0 packages/clerk-js/src/utils/offlineScheduler.ts
  38. +1 −4 packages/clerk-js/src/utils/pageLifecycle.ts
  39. +9 −0 packages/elements/CHANGELOG.md
  40. +2 −2 packages/elements/examples/nextjs/package.json
  41. +1 −1 packages/elements/package.json
  42. +8 −0 packages/expo-passkeys/CHANGELOG.md
  43. +1 −1 packages/expo-passkeys/package.json
  44. +10 −0 packages/expo/CHANGELOG.md
  45. +1 −1 packages/expo/package.json
  46. +9 −0 packages/express/CHANGELOG.md
  47. +1 −1 packages/express/package.json
  48. +9 −0 packages/fastify/CHANGELOG.md
  49. +1 −1 packages/fastify/package.json
  50. +9 −0 packages/localizations/CHANGELOG.md
  51. +1 −1 packages/localizations/package.json
  52. +6 −5 packages/localizations/src/fi-FI.ts
  53. +35 −0 packages/nextjs/CHANGELOG.md
  54. +2 −2 packages/nextjs/package.json
  55. +2 −0 packages/nextjs/src/app-router/client/ClerkProvider.tsx
  56. +3 −3 packages/nextjs/src/app-router/client/useInternalNavFun.ts
  57. +1 −0 packages/nextjs/src/client-boundary/hooks.ts
  58. +1 −0 packages/nextjs/src/errors.ts
  59. +13 −3 packages/nextjs/src/global.d.ts
  60. +58 −22 packages/nextjs/src/server/__tests__/clerkMiddleware.test.ts
  61. +3 −3 packages/nextjs/src/server/clerkMiddleware.ts
  62. +61 −0 packages/nuxt/CHANGELOG.md
  63. +5 −1 packages/nuxt/package.json
  64. +8 −0 packages/nuxt/src/runtime/errors.ts
  65. +16 −0 packages/nuxt/src/runtime/server/errors.ts
  66. +11 −0 packages/nuxt/src/runtime/server/getAuth.ts
  67. +1 −0 packages/nuxt/src/runtime/server/index.ts
  68. +1 −0 packages/nuxt/tsup.config.ts
  69. +19 −0 packages/react-router/CHANGELOG.md
  70. +1 −1 packages/react-router/package.json
  71. +1 −0 packages/react-router/src/errors.ts
  72. +19 −0 packages/react/CHANGELOG.md
  73. +1 −1 packages/react/package.json
  74. +24 −3 packages/react/src/components/ClerkHostRenderer.tsx
  75. +1 −0 packages/react/src/errors.ts
  76. +19 −0 packages/remix/CHANGELOG.md
  77. +1 −1 packages/remix/package.json
  78. +1 −0 packages/remix/src/errors.ts
  79. +20 −0 packages/shared/CHANGELOG.md
  80. +4 −3 packages/shared/package.json
  81. +31 −0 packages/shared/src/__tests__/organization.test.ts
  82. +7 −0 packages/shared/src/error.ts
  83. +16 −0 packages/shared/src/organization.ts
  84. +1 −9 packages/shared/src/react/hooks/useOrganization.tsx
  85. +5 −4 packages/shared/src/telemetry/events/component-mounted.ts
  86. +21 −0 packages/tanstack-start/CHANGELOG.md
  87. +1 −1 packages/tanstack-start/package.json
  88. +1 −0 packages/tanstack-start/src/errors.ts
  89. +11 −0 packages/testing/CHANGELOG.md
  90. +1 −1 packages/testing/package.json
  91. +13 −0 packages/testing/src/cypress/setupClerkTestingToken.ts
  92. +7 −0 packages/themes/CHANGELOG.md
  93. +1 −1 packages/themes/package.json
  94. +6 −0 packages/types/CHANGELOG.md
  95. +1 −1 packages/types/package.json
  96. +1 −3 packages/types/src/snapshots.ts
  97. +3 −1 packages/types/src/telemetry.ts
  98. +8 −0 packages/types/src/utils.ts
  99. +10 −0 packages/ui/CHANGELOG.md
  100. +1 −1 packages/ui/package.json
  101. +1 −1 packages/ui/theme-builder/package.json
  102. +43 −0 packages/vue/CHANGELOG.md
  103. +5 −1 packages/vue/package.json
  104. +1 −9 packages/vue/src/composables/useOrganization.ts
  105. +8 −0 packages/vue/src/errors.ts
  106. +1 −1 packages/vue/tsup.config.ts
  107. +650 −395 pnpm-lock.yaml
2 changes: 1 addition & 1 deletion .lintstagedrc.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{
"*.{mjs,js,jsx,ts,tsx}": ["pnpm eslint --fix", "pnpm prettier --write"],
"*.{mjs,js,jsx,ts,tsx,vue}": ["pnpm eslint --fix", "pnpm prettier --write"],
"*.{json,md,mdx}": ["pnpm prettier --write"]
}
Original file line number Diff line number Diff line change
@@ -5,9 +5,10 @@ export default function Page() {
<div>
<SignIn
routing={'path'}
path={'/sign-in'}
path={'/sign-in-or-up'}
signUpUrl={'/sign-up'}
fallback={<>Loading sign in</>}
unsafeMetadata={{ position: 'goalie' }}
withSignUp
/>
</div>
Original file line number Diff line number Diff line change
@@ -8,6 +8,7 @@ export default function Page() {
path={'/sign-up'}
signInUrl={'/sign-in'}
fallback={<>Loading sign up</>}
unsafeMetadata={{ position: 'goalie' }}
/>
</div>
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import { UserButton } from '@clerk/clerk-react';
import { PageContextProvider } from '../PageContext.tsx';
import React from 'react';

export default function Page() {
const [open, setIsOpen] = React.useState(false);
const [theme, setTheme] = React.useState('light');
const [notifications, setNotifications] = React.useState(false);
const [language, setLanguage] = React.useState('en');

return (
<PageContextProvider>
<UserButton
fallback={<>Loading user button</>}
userProfileProps={{ appearance: { elements: { modalBackdrop: { zIndex: '100' } } } }}
>
<UserButton.MenuItems>
<UserButton.Action
label={`Chat is ${open ? 'ON' : 'OFF'}`}
labelIcon={<span>🌐</span>}
onClick={() => setIsOpen(!open)}
/>
<UserButton.Action
label={`Theme: ${theme === 'light' ? '☀️ Light' : '🌙 Dark'}`}
labelIcon={<span>🌐</span>}
onClick={() => setTheme(t => (t === 'light' ? 'dark' : 'light'))}
/>
<UserButton.Action
label={`Notifications ${notifications ? '🔔 ON' : '🔕 OFF'}`}
labelIcon={<span>🌐</span>}
onClick={() => setNotifications(n => !n)}
/>
<UserButton.Action
label={`Language: ${language.toUpperCase()}`}
labelIcon={<span>🌍</span>}
onClick={() => setLanguage(l => (l === 'en' ? 'es' : 'en'))}
/>
<UserButton.Action label={'manageAccount'} />
<UserButton.Action label={'signOut'} />
<UserButton.Link
href={'http://clerk.com'}
label={'Visit Clerk'}
labelIcon={<span>🌐</span>}
/>

<UserButton.Link
href={'/user'}
label={'Visit User page'}
labelIcon={<span>🌐</span>}
/>

<UserButton.Action
label={'Custom Alert'}
labelIcon={<span>🔔</span>}
onClick={() => alert('custom-alert')}
/>
</UserButton.MenuItems>
<UserButton.UserProfilePage
label='Notifications Page'
url='notifications'
labelIcon={<span>🔔</span>}
>
<h1 data-page='notifications-page'>Notifications page</h1>
</UserButton.UserProfilePage>
</UserButton>
</PageContextProvider>
);
}
Original file line number Diff line number Diff line change
@@ -1,25 +1,7 @@
import { UserButton } from '@clerk/clerk-react';
import { useContext } from 'react';
import { PageContext, PageContextProvider } from '../PageContext.tsx';
import { PageContextProvider } from '../PageContext.tsx';
import React from 'react';

function Page1() {
const { counter, setCounter } = useContext(PageContext);

return (
<>
<h1 data-page={1}>Page 1</h1>
<p data-page={1}>Counter: {counter}</p>
<button
data-page={1}
onClick={() => setCounter(a => a + 1)}
>
Update
</button>
</>
);
}

export default function Page() {
const [open, setIsOpen] = React.useState(false);
const [theme, setTheme] = React.useState('light');
5 changes: 5 additions & 0 deletions integration/templates/react-vite/src/main.tsx
Original file line number Diff line number Diff line change
@@ -11,6 +11,7 @@ import UserProfile from './user';
import UserProfileCustom from './custom-user-profile';
import UserButtonCustom from './custom-user-button';
import UserButtonCustomDynamicLabels from './custom-user-button/with-dynamic-labels.tsx';
import UserButtonCustomDynamicLabelsAndCustomPages from './custom-user-button/with-dynamic-label-and-custom-pages.tsx';
import UserButtonCustomTrigger from './custom-user-button-trigger';
import UserButton from './user-button';
import Waitlist from './waitlist';
@@ -85,6 +86,10 @@ const router = createBrowserRouter([
path: '/custom-user-button-dynamic-labels',
element: <UserButtonCustomDynamicLabels />,
},
{
path: '/custom-user-button-dynamic-labels-and-custom-pages',
element: <UserButtonCustomDynamicLabelsAndCustomPages />,
},
{
path: '/custom-user-button-trigger',
element: <UserButtonCustomTrigger />,
24 changes: 24 additions & 0 deletions integration/testUtils/usersService.ts
Original file line number Diff line number Diff line change
@@ -55,6 +55,7 @@ export type UserService = {
createBapiUser: (fakeUser: FakeUser) => Promise<User>;
deleteIfExists: (opts: { id?: string; email?: string }) => Promise<void>;
createFakeOrganization: (userId: string) => Promise<FakeOrganization>;
getUser: (opts: { id?: string; email?: string }) => Promise<User | undefined>;
};

/**
@@ -116,6 +117,29 @@ export const createUserService = (clerkClient: ClerkClient) => {

await clerkClient.users.deleteUser(id);
},
getUser: async (opts: { id?: string; email?: string }) => {
if (opts.id) {
try {
const user = await clerkClient.users.getUser(opts.id);
return user;
} catch (err) {
console.log(`Error fetching user "${opts.id}": ${err.message}`);
return;
}
}

if (opts.email) {
const { data: users } = await clerkClient.users.getUserList({ emailAddress: [opts.email] });
if (users.length > 0) {
return users[0];
} else {
console.log(`User "${opts.email}" does not exist!`);
return;
}
}

throw new Error('Either id or email must be provided');
},
createFakeOrganization: async userId => {
const name = faker.animal.dog();
const organization = await clerkClient.organizations.createOrganization({
68 changes: 68 additions & 0 deletions integration/tests/custom-pages.test.ts
Original file line number Diff line number Diff line change
@@ -8,6 +8,7 @@ const CUSTOM_PROFILE_PAGE = '/custom-user-profile';
const CUSTOM_BUTTON_PAGE = '/custom-user-button';
const CUSTOM_BUTTON_TRIGGER_PAGE = '/custom-user-button-trigger';
const CUSTOM_BUTTON_DYNAMIC_LABELS_PAGE = '/custom-user-button-dynamic-labels';
const CUSTOM_BUTTON_DYNAMIC_LABELS_AND_CUSTOM_PAGES_PAGE = '/custom-user-button-dynamic-labels-and-custom-pages';

async function waitForMountedComponent(
component: 'UserButton' | 'UserProfile',
@@ -375,5 +376,72 @@ testAgainstRunningApps({ withPattern: ['react.vite.withEmailCodes'] })(
await expect(languageButton).toHaveText('🌍Language: EN');
});
});

test.describe('User Button with dynamic labels and custom page', () => {
test('click Chat is OFF and ensure that state has been changed', async ({ page, context }) => {
const u = createTestUtils({ app, page, context });
await u.po.signIn.goTo();
await u.po.signIn.waitForMounted();
await u.po.signIn.signInWithEmailAndInstantPassword({ email: fakeUser.email, password: fakeUser.password });
await u.po.expect.toBeSignedIn();

await u.page.goToRelative(CUSTOM_BUTTON_DYNAMIC_LABELS_AND_CUSTOM_PAGES_PAGE);
await u.po.userButton.waitForMounted();
await u.po.userButton.toggleTrigger();
await u.po.userButton.waitForPopover();

const pagesContainer = u.page.locator('div.cl-userButtonPopoverActions__multiSession').first();
const buttons = await pagesContainer.locator('button').all();

expect(buttons.length).toBe(9);

const expectedTexts = [
'🌐Chat is OFF',
'🌐Theme: ☀️ Light',
'🌐Notifications 🔕 OFF',
'🌍Language: EN',
'Manage account',
'Sign out',
'🌐Visit Clerk',
'🌐Visit User page',
'🔔Custom Alert',
];

for (let i = 0; i < buttons.length; i++) {
await expect(buttons[i]).toHaveText(expectedTexts[i]);
}

const chatButton = buttons[0];
const notificationsButton = buttons[2];
const languageButton = buttons[3];
const manageAccountButton = buttons[4];

// Test chat toggle
await chatButton.click();
await u.po.userButton.toggleTrigger();
await u.po.userButton.waitForPopover();
await expect(chatButton).toHaveText('🌐Chat is ON');
await expect(languageButton).toHaveText('🌍Language: EN');

await notificationsButton.click();
await u.po.userButton.toggleTrigger();
await u.po.userButton.waitForPopover();
await expect(notificationsButton).toHaveText('🌐Notifications 🔔 ON');
await expect(chatButton).toHaveText('🌐Chat is ON');
await expect(languageButton).toHaveText('🌍Language: EN');

await manageAccountButton.click();
await u.po.userProfile.waitForMounted();

const userProfilePageButtons = await u.page.locator('button.cl-navbarButton__custom-page-0').all();
const [notificationsPage] = userProfilePageButtons;
await expect(notificationsPage.locator('div.cl-navbarButtonIcon__custom-page-0')).toHaveText('🔔');

await notificationsPage.click();

const orderSent = page.locator('h1[data-page="notifications-page"]');
await orderSent.waitFor({ state: 'attached' });
});
});
},
);
4 changes: 2 additions & 2 deletions integration/tests/nuxt/middleware.test.ts
Original file line number Diff line number Diff line change
@@ -24,10 +24,10 @@ test.describe('custom middleware @nuxt', () => {
)
.addFile(
'server/middleware/clerk.js',
() => `import { clerkMiddleware, createRouteMatcher } from '@clerk/nuxt/server';
() => `import { clerkMiddleware, createRouteMatcher, getAuth } from '@clerk/nuxt/server';
export default clerkMiddleware((event) => {
const { userId } = event.context.auth
const { userId } = getAuth(event);
const isProtectedRoute = createRouteMatcher(['/api/me']);
if (!userId && isProtectedRoute(event)) {
2 changes: 1 addition & 1 deletion integration/tests/sign-in-or-up-component.test.ts
Original file line number Diff line number Diff line change
@@ -22,6 +22,6 @@ test.describe('sign-in-or-up component initialization flow @nextjs', () => {
test('flows are combined', async ({ page, context }) => {
const u = createTestUtils({ app, page, context });
await u.page.goToRelative('/sign-in-or-up');
await expect(u.page.getByText(`Don’t have an account?`)).toBeHidden();
await expect(u.page.getByText(`Continue to`)).toBeVisible();
});
});
12 changes: 12 additions & 0 deletions integration/tests/sign-out-smoke.test.ts
Original file line number Diff line number Diff line change
@@ -22,6 +22,18 @@ testAgainstRunningApps({ withEnv: [appConfigs.envs.withEmailCodes] })('sign out

test('sign out through all open tabs at once', async ({ page, context }) => {
const mainTab = createTestUtils({ app, page, context });
await mainTab.page.addInitScript(() => {
/**
* Playwright may define connection incorrectly, we are overriding to null
*/
if (
navigator.onLine &&
// @ts-expect-error Cannot find `connection`
(navigator?.connection?.rtt === 0 || navigator?.downlink?.rtt === 0)
) {
Object.defineProperty(Object.getPrototypeOf(navigator), 'connection', { value: null });
}
});
await mainTab.po.signIn.goTo();
await mainTab.po.signIn.setIdentifier(fakeUser.email);
await mainTab.po.signIn.continue();
71 changes: 71 additions & 0 deletions integration/tests/unsafeMetadata.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import { expect, test } from '@playwright/test';

import { appConfigs } from '../presets';
import { createTestUtils, testAgainstRunningApps } from '../testUtils';

testAgainstRunningApps({ withEnv: [appConfigs.envs.withEmailCodes] })('unsafeMetadata @nextjs', ({ app }) => {
test.describe.configure({ mode: 'parallel' });

test.afterAll(async () => {
await app.teardown();
});

test('sign up persists unsafeMetadata', async ({ page, context }) => {
const u = createTestUtils({ app, page, context });
const fakeUser = u.services.users.createFakeUser({
fictionalEmail: true,
withPhoneNumber: true,
withUsername: true,
});

// Go to sign up page
await u.po.signUp.goTo();

// Fill in sign up form
await u.po.signUp.signUpWithEmailAndPassword({
email: fakeUser.email,
password: fakeUser.password,
});

// Verify email
await u.po.signUp.enterTestOtpCode();

// Check if user is signed in
await u.po.expect.toBeSignedIn();

const user = await u.services.users.getUser({ email: fakeUser.email });
expect(user?.unsafeMetadata).toEqual({ position: 'goalie' });

await fakeUser.deleteIfExists();
});

test('combined sign up persists unsafeMetadata', async ({ page, context }) => {
const u = createTestUtils({ app, page, context });
const fakeUser = u.services.users.createFakeUser({
fictionalEmail: true,
withPassword: true,
withUsername: true,
});

await u.page.goToRelative('/sign-in-or-up');
await u.po.signIn.setIdentifier(fakeUser.username);
await u.po.signIn.continue();
await u.page.waitForAppUrl('/sign-in-or-up/create');

const prefilledUsername = u.po.signUp.getUsernameInput();
await expect(prefilledUsername).toHaveValue(fakeUser.username);

await u.po.signUp.setEmailAddress(fakeUser.email);
await u.po.signUp.setPassword(fakeUser.password);
await u.po.signUp.continue();

await u.po.signUp.enterTestOtpCode();

await u.po.expect.toBeSignedIn();

const user = await u.services.users.getUser({ email: fakeUser.email });
expect(user?.unsafeMetadata).toEqual({ position: 'goalie' });

await fakeUser.deleteIfExists();
});
});
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -75,7 +75,7 @@
"@testing-library/user-event": "^14.5.2",
"@types/cross-spawn": "^6.0.3",
"@types/jest": "^29.3.1",
"@types/node": "^22.13.1",
"@types/node": "^22.13.4",
"@types/react": "catalog:react",
"@types/react-dom": "catalog:react",
"@vitest/coverage-v8": "3.0.2",
9 changes: 9 additions & 0 deletions packages/agent-toolkit/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
# @clerk/agent-toolkit

## 0.0.3

### Patch Changes

- Updated dependencies [[`d76c4699990b8477745c2584b1b98d5c92f9ace6`](https://github.com/clerk/javascript/commit/d76c4699990b8477745c2584b1b98d5c92f9ace6), [`a9b0087fca3f427f65907b358d9b5bc0c95921d8`](https://github.com/clerk/javascript/commit/a9b0087fca3f427f65907b358d9b5bc0c95921d8), [`92d17d7c087470b262fa5407cb6720fe6b17d333`](https://github.com/clerk/javascript/commit/92d17d7c087470b262fa5407cb6720fe6b17d333)]:
- @clerk/shared@2.22.0
- @clerk/types@4.46.1
- @clerk/backend@1.24.2

## 0.0.2

### Patch Changes
Loading