Skip to content

Commit db3f1a9

Browse files
authored
fix(ui): Add missing noop methods to unsafeMetadata field in SignUpStart (#8500)
1 parent 4c44aa6 commit db3f1a9

3 files changed

Lines changed: 68 additions & 1 deletion

File tree

.changeset/wild-insects-design.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@clerk/ui": patch
3+
---
4+
5+
Fixed unhandled TypeError when `unsafeMetadata` is passed to `<SignUp />`

packages/ui/src/components/SignUp/SignUpStart.tsx

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -259,7 +259,15 @@ function SignUpStartInternal(): JSX.Element {
259259
}, [] as Array<FormControlState>);
260260

261261
if (unsafeMetadata) {
262-
fieldsToSubmit.push({ id: 'unsafeMetadata', value: unsafeMetadata } as any);
262+
const noop = () => {};
263+
fieldsToSubmit.push({
264+
id: 'unsafeMetadata',
265+
value: unsafeMetadata,
266+
clearFeedback: noop,
267+
setValue: noop,
268+
onChange: noop,
269+
setError: noop,
270+
} as any);
263271
}
264272

265273
if (fields.ticket || hasExistingSignUpWithTicket) {

packages/ui/src/components/SignUp/__tests__/SignUpStart.test.tsx

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { ClerkAPIResponseError } from '@clerk/shared/error';
12
import { OAUTH_PROVIDERS } from '@clerk/shared/oauth';
23
import type { SignUpResource } from '@clerk/shared/types';
34
import { describe, expect, it, vi } from 'vitest';
@@ -522,4 +523,57 @@ describe('SignUpStart', () => {
522523
await waitFor(() => screen.getByText(/create your account/i));
523524
});
524525
});
526+
527+
describe('unsafeMetadata', () => {
528+
it('does not throw when signUp.create rejects with an API error', async () => {
529+
Object.defineProperty(window, 'location', {
530+
writable: true,
531+
value: { href: 'http://localhost/sign-up' },
532+
});
533+
534+
let unhandledError: unknown = null;
535+
const onUnhandledRejection = (reason: unknown) => {
536+
unhandledError = reason;
537+
};
538+
process.on('unhandledRejection', onUnhandledRejection);
539+
540+
const { wrapper, fixtures, props } = await createFixtures(f => {
541+
f.withEmailAddress({ required: true });
542+
f.withPassword({ required: true });
543+
});
544+
fixtures.signUp.create.mockRejectedValueOnce(
545+
new ClerkAPIResponseError('Error', {
546+
data: [
547+
{
548+
code: 'form_password_pwned',
549+
long_message: 'Password has been found in an online data breach.',
550+
message: 'Password has been found in an online data breach.',
551+
meta: { param_name: 'password' },
552+
},
553+
],
554+
status: 422,
555+
}),
556+
);
557+
props.setProps({ unsafeMetadata: { foo: 'bar' } });
558+
559+
const { userEvent } = render(
560+
<CardStateProvider>
561+
<SignUpStart />
562+
</CardStateProvider>,
563+
{ wrapper },
564+
);
565+
566+
await userEvent.type(screen.getByLabelText(/email address/i), 'test@example.com');
567+
await userEvent.type(screen.getByPlaceholderText(/create a password/i), 'password123');
568+
await userEvent.click(screen.getByText(/continue/i));
569+
570+
await waitFor(() => expect(fixtures.signUp.create).toHaveBeenCalled());
571+
await screen.findByTestId('form-feedback-error');
572+
// Flush pending microtasks so any unhandled rejection event has a chance to fire.
573+
await new Promise(resolve => setTimeout(resolve, 0));
574+
575+
process.off('unhandledRejection', onUnhandledRejection);
576+
expect(unhandledError).toBeNull();
577+
});
578+
});
525579
});

0 commit comments

Comments
 (0)