Skip to content

Commit

Permalink
Merge branch 'main' into rob/eco-302-move-environment-variable-logic-…
Browse files Browse the repository at this point in the history
…into-clerkshared
  • Loading branch information
wobsoriano authored Feb 5, 2025
2 parents 01ba102 + 74a43c0 commit 71ff504
Show file tree
Hide file tree
Showing 67 changed files with 1,015 additions and 346 deletions.
3 changes: 2 additions & 1 deletion integration/models/applicationConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,8 @@ export const applicationConfig = () => {
[...env.privateVariables]
.filter(([_, v]) => v)
.map(([k, v]) => `${envFormatters.private(k)}=${v}`)
.join('\n'),
.join('\n') +
'\n',
);
};
return defaultWriter;
Expand Down
7 changes: 6 additions & 1 deletion integration/presets/envs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,16 @@ export const instanceKeys = getInstanceKeys();

const base = environmentConfig()
.setEnvVariable('public', 'CLERK_TELEMETRY_DISABLED', true)
.setEnvVariable('public', 'CLERK_KEYLESS_DISABLED', true)
.setEnvVariable('public', 'CLERK_SIGN_IN_URL', '/sign-in')
.setEnvVariable('public', 'CLERK_SIGN_UP_URL', '/sign-up')
.setEnvVariable('public', 'CLERK_JS_URL', constants.E2E_APP_CLERK_JS || 'http://localhost:18211/clerk.browser.js');

const withKeyless = base.clone().setEnvVariable('public', 'CLERK_ENABLE_KEYLESS', true);
const withKeyless = base
.clone()
// Creates keyless applications in our staging database.
.setEnvVariable('private', 'CLERK_API_URL', 'https://api.clerkstage.dev')
.setEnvVariable('public', 'CLERK_KEYLESS_DISABLED', false);

const withEmailCodes = base
.clone()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export default function Home() {
<SignInButton
mode='modal'
forceRedirectUrl='/protected'
signUpForceRedirectUrl='/protected'
>
Sign in button (force)
</SignInButton>
Expand All @@ -20,6 +21,7 @@ export default function Home() {
<SignUpButton
mode='modal'
forceRedirectUrl='/protected'
signInForceRedirectUrl='/protected'
>
Sign up button (force)
</SignUpButton>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import { UserButton } from '@clerk/clerk-react';
import { useContext } from 'react';
import { PageContext, 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');
const [notifications, setNotifications] = React.useState(false);
const [language, setLanguage] = React.useState('en');

return (
<PageContextProvider>
<UserButton fallback={<>Loading user button</>}>
<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>
</PageContextProvider>
);
}
5 changes: 5 additions & 0 deletions integration/templates/react-vite/src/main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import SignUp from './sign-up';
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 UserButtonCustomTrigger from './custom-user-button-trigger';
import UserButton from './user-button';
import Waitlist from './waitlist';
Expand Down Expand Up @@ -75,6 +76,10 @@ const router = createBrowserRouter([
path: '/custom-user-button',
element: <UserButtonCustom />,
},
{
path: '/custom-user-button-dynamic-labels',
element: <UserButtonCustomDynamicLabels />,
},
{
path: '/custom-user-button-trigger',
element: <UserButtonCustomTrigger />,
Expand Down
55 changes: 55 additions & 0 deletions integration/tests/custom-pages.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { createTestUtils, testAgainstRunningApps } from '../testUtils';
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';

async function waitForMountedComponent(
component: 'UserButton' | 'UserProfile',
Expand Down Expand Up @@ -320,5 +321,59 @@ testAgainstRunningApps({ withPattern: ['react.vite.withEmailCodes'] })(
await pendingDialog;
});
});

test.describe('User Button with dynamic labels', () => {
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_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];

// 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');
});
});
},
);
14 changes: 8 additions & 6 deletions integration/tests/next-quickstart-keyless.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,15 @@ const mockClaimedInstanceEnvironmentCall = async (page: Page) => {
test.describe('Keyless mode @quickstart', () => {
test.describe.configure({ mode: 'serial' });
let app: Application;
let dashboardUrl = 'https://dashboard.clerk.com/';

test.beforeAll(async () => {
app = await commonSetup.commit();
await app.setup();
await app.withEnv(appConfigs.envs.withKeyless);
if (appConfigs.envs.withKeyless.privateVariables.get('CLERK_API_URL')?.includes('clerkstage')) {
dashboardUrl = 'https://dashboard.clerkstage.dev/';
}
await app.dev();
});

Expand Down Expand Up @@ -74,7 +78,7 @@ test.describe('Keyless mode @quickstart', () => {

await newPage.waitForLoadState();
await newPage.waitForURL(url => {
const urlToReturnTo = 'https://dashboard.clerk.com/apps/claim?token=';
const urlToReturnTo = `${dashboardUrl}apps/claim?token=`;
return (
url.pathname === '/apps/claim/sign-in' &&
url.searchParams.get('sign_in_force_redirect_url')?.startsWith(urlToReturnTo) &&
Expand Down Expand Up @@ -102,11 +106,9 @@ test.describe('Keyless mode @quickstart', () => {
]);

await newPage.waitForLoadState();
await newPage.waitForURL(url =>
url.href.startsWith(
'https://dashboard.clerk.com/sign-in?redirect_url=https%3A%2F%2Fdashboard.clerk.com%2Fapps%2Fapp_',
),
);
await newPage.waitForURL(url => {
return url.href.startsWith(`${dashboardUrl}sign-in?redirect_url=${encodeURIComponent(dashboardUrl)}apps%2Fapp_`);
});
});

test('Claimed application with keys inside .env, on dismiss, keyless prompt is removed.', async ({
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@
"typescript-eslint": "8.21.0",
"uuid": "8.3.2",
"verdaccio": "^5.26.3",
"vitest": "3.0.2",
"vitest": "3.0.5",
"yalc": "1.0.0-pre.53",
"zx": "catalog:repo"
},
Expand Down
8 changes: 8 additions & 0 deletions packages/chrome-extension/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
# Change Log

## 2.2.7

### Patch Changes

- Updated dependencies [[`5c26eef22cd296366bbd21b4d04a4f87d74fc284`](https://github.com/clerk/javascript/commit/5c26eef22cd296366bbd21b4d04a4f87d74fc284), [`0fa449cd09c9973297464a14f785895e3ddcab4d`](https://github.com/clerk/javascript/commit/0fa449cd09c9973297464a14f785895e3ddcab4d), [`68b89170a2d4c475e37056e6d5b59c497c45cfb3`](https://github.com/clerk/javascript/commit/68b89170a2d4c475e37056e6d5b59c497c45cfb3), [`b6b8a1207e706ee2a305e11b941f4c32c69d5922`](https://github.com/clerk/javascript/commit/b6b8a1207e706ee2a305e11b941f4c32c69d5922)]:
- @clerk/clerk-js@5.52.1
- @clerk/clerk-react@5.22.11

## 2.2.6

### Patch Changes
Expand Down
2 changes: 1 addition & 1 deletion packages/chrome-extension/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@clerk/chrome-extension",
"version": "2.2.6",
"version": "2.2.7",
"description": "Clerk SDK for Chrome extensions",
"keywords": [
"auth",
Expand Down
10 changes: 10 additions & 0 deletions packages/clerk-js/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
# Change Log

## 5.52.1

### Patch Changes

- Add virtual routing deprecation warning. ([#5072](https://github.com/clerk/javascript/pull/5072)) by [@alexcarpenter](https://github.com/alexcarpenter)

- Ensure only one action is open per section within `UserProfile`. ([#5030](https://github.com/clerk/javascript/pull/5030)) by [@alexcarpenter](https://github.com/alexcarpenter)

- Prevent infinite loop when the client is blocked ([#5083](https://github.com/clerk/javascript/pull/5083)) by [@anagstef](https://github.com/anagstef)

## 5.52.0

### Minor Changes
Expand Down
2 changes: 1 addition & 1 deletion packages/clerk-js/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@clerk/clerk-js",
"version": "5.52.0",
"version": "5.52.1",
"description": "Clerk JS library",
"keywords": [
"clerk",
Expand Down
25 changes: 17 additions & 8 deletions packages/clerk-js/src/core/clerk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1493,15 +1493,24 @@ export class Clerk implements ClerkInterface {
if (!this.client || !this.session) {
return;
}
const newClient = await Client.getOrCreateInstance().fetch();
this.updateClient(newClient);
if (this.session) {
return;
}
if (opts.broadcast) {
this.#broadcastSignOutEvent();
try {
const newClient = await Client.getOrCreateInstance().fetch();
this.updateClient(newClient);
if (this.session) {
return;
}
if (opts.broadcast) {
this.#broadcastSignOutEvent();
}
return this.setActive({ session: null });
} catch (err) {
// Handle the 403 Forbidden
if (err.status === 403) {
return this.setActive({ session: null });
} else {
throw err;
}
}
return this.setActive({ session: null });
};

public authenticateWithGoogleOneTap = async (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { useEnabledThirdPartyProviders } from '../../hooks';
import { useRouter } from '../../router';
import { handleError, sleep } from '../../utils';

const ConnectMenuButton = (props: { strategy: OAuthStrategy }) => {
const ConnectMenuButton = (props: { strategy: OAuthStrategy; onClick?: () => void }) => {
const { strategy } = props;
const card = useCardState();
const { user } = useUser();
Expand Down Expand Up @@ -95,7 +95,7 @@ const ConnectMenuButton = (props: { strategy: OAuthStrategy }) => {
);
};

export const AddConnectedAccount = () => {
export const AddConnectedAccount = ({ onClick }: { onClick?: () => void }) => {
const { user } = useUser();
const { strategies } = useEnabledThirdPartyProviders();

Expand All @@ -114,6 +114,7 @@ export const AddConnectedAccount = () => {
<ProfileSection.ActionMenu
triggerLocalizationKey={localizationKeys('userProfile.start.connectedAccountsSection.primaryButton')}
id='connectedAccounts'
onClick={onClick}
>
{unconnectedStrategies.map(strategy => (
<ConnectMenuButton
Expand Down
Loading

0 comments on commit 71ff504

Please sign in to comment.