Uh oh!
There was an error while loading. Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork 470
feat(clerk-js): Detect locale from browser and send it to FAPI if exists during sign-in (i18n)#7011
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Uh oh!
There was an error while loading. Please reload this page.
feat(clerk-js): Detect locale from browser and send it to FAPI if exists during sign-in (i18n)
#7011
Changes from all commits
216056cbbc986ab5a358635b45c2f500017c781372File filter
Filter by extension
Conversations
Uh oh!
There was an error while loading. Please reload this page.
Jump to
Uh oh!
There was an error while loading. Please reload this page.
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| --- | ||
| '@clerk/clerk-js': patch | ||
| --- | ||
| Add support for automatically sending the browser locale during the sign-in flow | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,39 +1,95 @@ | ||
| import { describe, expect, it, vi } from 'vitest'; | ||
| import { afterEach, beforeAll, describe, expect, it, vi } from 'vitest'; | ||
| import { BaseResource } from '../internal'; | ||
| import { SignIn } from '../SignIn'; | ||
| describe('SignIn', () => { | ||
| describe('signIn.create', () => { | ||
| afterEach(() => { | ||
| vi.clearAllMocks(); | ||
| vi.unstubAllGlobals(); | ||
| }); | ||
| it('includes locale in request body when navigator.language is available', async () => { | ||
| vi.stubGlobal('navigator', { language: 'fr-FR' }); | ||
| const mockFetch = vi.fn().mockResolvedValue({ | ||
| client: null, | ||
| response: { id: 'signin_123', status: 'needs_first_factor' }, | ||
| }); | ||
| BaseResource._fetch = mockFetch; | ||
| const signIn = new SignIn(); | ||
| await signIn.create({ identifier: 'user@example.com' }); | ||
| expect(mockFetch).toHaveBeenCalledWith( | ||
| expect.objectContaining({ | ||
| method: 'POST', | ||
| path: '/client/sign_ins', | ||
| body: { | ||
| identifier: 'user@example.com', | ||
| locale: 'fr-FR', | ||
| }, | ||
| }), | ||
| ); | ||
| }); | ||
| it('excludes locale from request body when navigator.language is empty', async () => { | ||
| vi.stubGlobal('navigator', { language: '' }); | ||
| const mockFetch = vi.fn().mockResolvedValue({ | ||
| client: null, | ||
| response: { id: 'signin_123', status: 'needs_first_factor' }, | ||
| }); | ||
| BaseResource._fetch = mockFetch; | ||
| const signIn = new SignIn(); | ||
| await signIn.create({ identifier: 'user@example.com' }); | ||
| expect(mockFetch).toHaveBeenCalledWith( | ||
| expect.objectContaining({ | ||
| method: 'POST', | ||
| path: '/client/sign_ins', | ||
| body: { | ||
| identifier: 'user@example.com', | ||
| }, | ||
| }), | ||
| ); | ||
| }); | ||
| }); | ||
| describe('SignInFuture', () => { | ||
| describe('selectFirstFactor', () => { | ||
| const signInCreatedJSON = { | ||
| id: 'test_id', | ||
| supported_first_factors: [ | ||
| { strategy: 'email_code', emailAddressId: 'email_address_0', safe_identifier: 'test+abc@clerk.com' }, | ||
| { strategy: 'email_code', emailAddressId: 'email_address_1', safe_identifier: 'test@clerk.com' }, | ||
| { strategy: 'phone_code', phoneNumberId: 'phone_number_1', safe_identifier: '+301234567890' }, | ||
| ], | ||
| }; | ||
| const firstFactorPreparedJSON = {}; | ||
| BaseResource._fetch = vi.fn().mockImplementation(({ method, path, body }) => { | ||
| if (method === 'POST' && path === '/client/sign_ins') { | ||
| return Promise.resolve({ | ||
| client: null, | ||
| response: { ...signInCreatedJSON, identifier: body.identifier }, | ||
| }); | ||
| } | ||
| if (method === 'POST' && path === '/client/sign_ins/test_id/prepare_first_factor') { | ||
| return Promise.resolve({ | ||
| client: null, | ||
| response: firstFactorPreparedJSON, | ||
| }); | ||
| } | ||
| throw new Error('Unexpected call to BaseResource._fetch'); | ||
| beforeAll(() => { | ||
| const signInCreatedJSON = { | ||
ContributorAuthor There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. with new tests and mocks, this was source of failing tests. So I just added moved the into the beforeAll function so we can have more control over order and scope | ||
| id: 'test_id', | ||
| supported_first_factors: [ | ||
| { strategy: 'email_code', emailAddressId: 'email_address_0', safe_identifier: 'test+abc@clerk.com' }, | ||
| { strategy: 'email_code', emailAddressId: 'email_address_1', safe_identifier: 'test@clerk.com' }, | ||
| { strategy: 'phone_code', phoneNumberId: 'phone_number_1', safe_identifier: '+301234567890' }, | ||
| ], | ||
| }; | ||
| const firstFactorPreparedJSON = {}; | ||
| BaseResource._fetch = vi.fn().mockImplementation(({ method, path, body }) => { | ||
| if (method === 'POST' && path === '/client/sign_ins') { | ||
| return Promise.resolve({ | ||
| client: null, | ||
| response: { ...signInCreatedJSON, identifier: body.identifier }, | ||
| }); | ||
| } | ||
| if (method === 'POST' && path === '/client/sign_ins/test_id/prepare_first_factor') { | ||
| return Promise.resolve({ | ||
| client: null, | ||
| response: firstFactorPreparedJSON, | ||
| }); | ||
| } | ||
| throw new Error('Unexpected call to BaseResource._fetch'); | ||
| }); | ||
| }); | ||
| it('should select correct first factor by email address', async () => { | ||
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
since there is no change (even backwards compatible) to the sdk api for users, I think we have a
patchhere -- open to make it aminoras well