Skip to content

Commit 770db0d

Browse files
authored
Merge pull request #40 from clerkinc/usersettings_#
Replace AuthConfig with UserSettings in #
2 parents 0106ed8 + 65d98e0 commit 770db0d

File tree

7 files changed

+292
-219
lines changed

7 files changed

+292
-219
lines changed

packages/clerk-js/src/ui/#/#.test.tsx

+1-5
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,7 @@ jest.mock('ui/contexts', () => {
2727
displayConfig: {
2828
homeUrl: 'https://www.bbc.com',
2929
},
30-
authConfig: {
31-
identificationStrategies: ['email_address', 'oauth_google'],
32-
firstFactors: ['email_address', 'oauth_google'],
33-
singleSessionMode: true,
34-
} as Partial<AuthConfig>,
30+
authConfig: { singleSessionMode: true } as Partial<AuthConfig>,
3531
} as Partial<EnvironmentResource>),
3632
),
3733
withCoreSessionSwitchGuard: (a: any) => a,

packages/clerk-js/src/ui/#/#Start.test.tsx

+74-37
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ import {
66
waitFor,
77
} from '@clerk/shared/testUtils';
88
import { titleize } from '@clerk/shared/utils/string';
9-
import { Session } from 'core/resources';
10-
import { AuthConfig } from 'core/resources/AuthConfig';
9+
import { UserSettingsJSON } from '@clerk/types';
10+
import { Session, UserSettings } from 'core/resources/internal';
1111
import React from 'react';
1212
import { useCore# } from 'ui/contexts';
1313

@@ -17,8 +17,7 @@ const navigateMock = jest.fn();
1717
const mockCreateRequest = jest.fn();
1818
const mockSetSession = jest.fn();
1919
const mockAuthenticateWithRedirect = jest.fn();
20-
const mockIdentificationRequirements = jest.fn();
21-
let mockAuthConfig: Partial<AuthConfig>;
20+
let mockUserSettings: UserSettings;
2221

2322
const oldWindowLocation = window.location;
2423
const setWindowQueryParams = (params: Array<[string, string]>) => {
@@ -62,7 +61,8 @@ jest.mock('ui/contexts', () => {
6261
applicationName: 'My test app',
6362
after#Url: 'http://test.host',
6463
},
65-
authConfig: mockAuthConfig,
64+
userSettings: mockUserSettings,
65+
authConfig: { singleSessionMode: false },
6666
})),
6767
};
6868
});
@@ -79,9 +79,9 @@ describe('<#Start/>', () => {
7979
const { location } = window;
8080

8181
beforeEach(() => {
82-
mockIdentificationRequirements.mockImplementation(() => [
83-
['email_address', 'oauth_google', 'oauth_facebook'],
84-
]);
82+
// mockIdentificationRequirements.mockImplementation(() => [
83+
// ['email_address', 'oauth_google', 'oauth_facebook'],
84+
// ]);
8585

8686
mockCreateRequest.mockImplementation(() =>
8787
Promise.resolve({
@@ -94,13 +94,38 @@ describe('<#Start/>', () => {
9494
}),
9595
);
9696

97-
mockAuthConfig = {
98-
username: 'on',
99-
firstName: 'required',
100-
lastName: 'required',
101-
password: 'required',
102-
identificationRequirements: mockIdentificationRequirements(),
103-
};
97+
mockUserSettings = new UserSettings({
98+
attributes: {
99+
username: {
100+
enabled: true,
101+
},
102+
first_name: {
103+
enabled: true,
104+
required: true,
105+
},
106+
last_name: {
107+
enabled: true,
108+
required: true,
109+
},
110+
password: {
111+
enabled: true,
112+
required: true,
113+
},
114+
email_address: {
115+
enabled: true,
116+
},
117+
},
118+
social: {
119+
oauth_google: {
120+
enabled: true,
121+
strategy: 'oauth_google',
122+
},
123+
oauth_facebook: {
124+
enabled: true,
125+
strategy: 'oauth_facebook',
126+
},
127+
},
128+
} as UserSettingsJSON);
104129
});
105130

106131
afterEach(() => {
@@ -111,22 +136,19 @@ describe('<#Start/>', () => {
111136
global.window.location = location;
112137
});
113138

114-
it('renders the # start screen', async () => {
139+
it('renders the # start screen', () => {
115140
const tree = renderJSON(<#Start />);
116141
expect(tree).toMatchSnapshot();
117142
});
118143

119144
it('renders the start screen, types the name, email, and password and creates a # attempt', async () => {
120145
render(<#Start />);
121146

122-
await userEvent.type(screen.getByLabelText('First name'), 'John');
123-
await userEvent.type(screen.getByLabelText('Last name'), 'Doe');
124-
await userEvent.type(screen.getByLabelText('Username'), 'jdoe');
125-
await userEvent.type(
126-
screen.getByLabelText('Email address'),
127-
'jdoe@example.com',
128-
);
129-
await userEvent.type(screen.getByLabelText('Password'), 'p@ssW0rd');
147+
userEvent.type(screen.getByLabelText('First name'), 'John');
148+
userEvent.type(screen.getByLabelText('Last name'), 'Doe');
149+
userEvent.type(screen.getByLabelText('Username'), 'jdoe');
150+
userEvent.type(screen.getByLabelText('Email address'), 'jdoe@example.com');
151+
userEvent.type(screen.getByLabelText('Password'), 'p@ssW0rd');
130152

131153
userEvent.click(screen.getByRole('button', { name: '#' }));
132154

@@ -170,7 +192,7 @@ describe('<#Start/>', () => {
170192
},
171193
);
172194

173-
it('renders the external account verification error if available', async () => {
195+
it('renders the external account verification error if available', () => {
174196
const errorMsg =
175197
'You cannot # with sokratis.vidros@gmail.com since this is an invitation-only application';
176198

@@ -194,14 +216,24 @@ describe('<#Start/>', () => {
194216
expect(mockCreateRequest).toHaveBeenNthCalledWith(1, {});
195217
});
196218

197-
it('only renders the SSO buttons if no other method is supported', async () => {
198-
mockIdentificationRequirements.mockImplementation(() => [
199-
['oauth_google', 'oauth_facebook'],
200-
]);
201-
mockAuthConfig = {
202-
username: 'off',
203-
identificationRequirements: mockIdentificationRequirements(),
204-
};
219+
it('only renders the SSO buttons if no other method is supported', () => {
220+
mockUserSettings = new UserSettings({
221+
attributes: {
222+
username: {
223+
enabled: false,
224+
},
225+
},
226+
social: {
227+
oauth_google: {
228+
enabled: true,
229+
strategy: 'oauth_google',
230+
},
231+
oauth_facebook: {
232+
enabled: true,
233+
strategy: 'oauth_facebook',
234+
},
235+
},
236+
} as UserSettingsJSON);
205237

206238
render(<#Start />);
207239
screen.getByRole('button', { name: /Google/ });
@@ -212,7 +244,7 @@ describe('<#Start/>', () => {
212244
});
213245

214246
describe('when the user does not grant access to their Facebook account', () => {
215-
it('renders the external account verification error if available', async () => {
247+
it('renders the external account verification error if available', () => {
216248
const errorMsg = 'You did not grant access to your Facebook account';
217249

218250
(useCore# as jest.Mock).mockImplementation(() => {
@@ -296,9 +328,14 @@ describe('<#Start/>', () => {
296328
});
297329

298330
it('does not render the phone number field', async () => {
299-
mockIdentificationRequirements.mockImplementation(() => [
300-
['phone_number'],
301-
]);
331+
mockUserSettings = new UserSettings({
332+
attributes: {
333+
phone_number: {
334+
enabled: true,
335+
required: true,
336+
},
337+
},
338+
} as UserSettingsJSON);
302339

303340
const { container } = render(<#Start />);
304341
const labels = container.querySelectorAll('label');

packages/clerk-js/src/ui/#/#Start.tsx

+9-10
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { Control } from '@clerk/shared/components/control';
22
import { Form } from '@clerk/shared/components/form';
33
import { Input } from '@clerk/shared/components/input';
44
import { PhoneInput } from '@clerk/shared/components/phoneInput';
5-
import { OAuthStrategy, #Resource, Web3Strategy } from '@clerk/types';
5+
import { #Resource } from '@clerk/types';
66
import React from 'react';
77
import type { FieldState } from 'ui/common';
88
import {
@@ -29,17 +29,14 @@ import { getClerkQueryParam } from 'utils/getClerkQueryParam';
2929
import { SignInLink } from './SignInLink';
3030
import { #OAuth } from './#OAuth';
3131
import { #Web3 } from './#Web3';
32-
import {
33-
determineFirstPartyFields,
34-
determineOauthOptions,
35-
determineWeb3Options,
36-
} from './utils';
32+
import { determineFirstPartyFields } from './utils';
3733

3834
type ActiveIdentifier = 'emailAddress' | 'phoneNumber';
3935

4036
function _#Start(): JSX.Element {
4137
const { navigate } = useNavigate();
4238
const environment = useEnvironment();
39+
const { userSettings } = environment;
4340
const { setSession } = useCoreClerk();
4441
const { navigateAfter# } = use#Context();
4542
const [emailOrPhoneActive, setEmailOrPhoneActive] =
@@ -62,10 +59,12 @@ function _#Start(): JSX.Element {
6259

6360
const [error, setError] = React.useState<string | undefined>();
6461
const hasInvitationToken = !!formFields.invitationToken.value;
62+
6563
const fields = determineFirstPartyFields(environment, hasInvitationToken);
66-
const oauthOptions = determineOauthOptions(environment) as OAuthStrategy[];
67-
const web3Options = determineWeb3Options(environment) as Web3Strategy[];
68-
const handleInvitationFlow = async () => {
64+
const oauthOptions = userSettings.socialProviderStrategies;
65+
const web3Options = userSettings.web3FirstFactors;
66+
67+
const handleInvitationFlow = () => {
6968
const token = formFields.invitationToken.value;
7069
if (!token) {
7170
return;
@@ -149,7 +148,7 @@ function _#Start(): JSX.Element {
149148
}
150149
};
151150

152-
const complete#Flow = async (su: #Resource) => {
151+
const complete#Flow = (su: #Resource) => {
153152
if (su.status === 'complete') {
154153
return setSession(su.createdSessionId, navigateAfter#);
155154
} else if (

packages/clerk-js/src/ui/#/#Verify.test.tsx

+60-19
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
import { noop, render, renderJSON } from '@clerk/shared/testUtils';
22
import {
3+
AttributeData,
34
SessionResource,
4-
SignInStrategyName,
55
#Resource,
6+
UserSettingsJSON,
67
} from '@clerk/types';
8+
import { UserSettings } from 'core/resources/internal';
79
import React from 'react';
810

911
import {
@@ -25,7 +27,7 @@ const mockStartMagicLinkFlow = jest.fn(() => {
2527
},
2628
} as any as #Resource);
2729
});
28-
let mockFirstFactors: SignInStrategyName[];
30+
let mockEmailAddressAttribute: Partial<AttributeData>;
2931
let mockDisabledStrategies: string[] = [];
3032

3133
jest.mock('ui/router/RouteContext');
@@ -37,16 +39,42 @@ jest.mock('ui/contexts', () => {
3739
applicationName: 'My test app',
3840
after#Url: 'http://test.host',
3941
},
40-
authConfig: {
41-
username: 'on',
42-
firstName: 'required',
43-
lastName: 'required',
44-
password: 'required',
45-
firstFactors: mockFirstFactors,
46-
identificationRequirements: [
47-
['email_address', 'phone_address', 'oauth_google', 'oauth_facebook'],
48-
],
49-
},
42+
userSettings: new UserSettings({
43+
attributes: {
44+
first_name: {
45+
enabled: true,
46+
required: false,
47+
},
48+
last_name: {
49+
enabled: true,
50+
required: false,
51+
},
52+
password: {
53+
enabled: true,
54+
required: false,
55+
},
56+
username: {
57+
enabled: true,
58+
required: false,
59+
},
60+
email_address: mockEmailAddressAttribute,
61+
},
62+
social: {
63+
oauth_google: {
64+
enabled: true,
65+
required: false,
66+
authenticatable: false,
67+
strategy: 'oauth_google',
68+
},
69+
oauth_facebook: {
70+
enabled: true,
71+
required: false,
72+
authenticatable: false,
73+
strategy: 'oauth_facebook',
74+
},
75+
},
76+
} as unknown as UserSettingsJSON),
77+
authConfig: { singleSessionMode: false },
5078
})),
5179
useCoreSession: () => {
5280
return { id: 'sess_id' } as SessionResource;
@@ -105,20 +133,33 @@ describe('<#Verify/>', () => {
105133
});
106134

107135
describe('verify email address', () => {
108-
it('renders the # verification form', async () => {
109-
mockFirstFactors = ['email_code', 'phone_code', 'password'];
136+
it('renders the # verification form', () => {
137+
mockEmailAddressAttribute = {
138+
enabled: true,
139+
first_factors: ['email_code'],
140+
verifications: ['email_code'],
141+
};
142+
// mockFirstFactors = ['email_code', 'phone_code', 'password'];
110143
const tree = renderJSON(<#VerifyEmailAddress />);
111144
expect(tree).toMatchSnapshot();
112145
});
113146

114-
it('renders the # verification form but prefers email_link if exists', async () => {
115-
mockFirstFactors = ['email_code', 'phone_code', 'password', 'email_link'];
147+
it('renders the # verification form but prefers email_link if exists', () => {
148+
mockEmailAddressAttribute = {
149+
enabled: true,
150+
first_factors: ['email_link'],
151+
verifications: ['email_link'],
152+
};
116153
const tree = renderJSON(<#VerifyEmailAddress />);
117154
expect(tree).toMatchSnapshot();
118155
});
119156

120-
it('can skip disabled verification strategies', async () => {
121-
mockFirstFactors = ['email_code', 'phone_code', 'password', 'email_link'];
157+
it('can skip disabled verification strategies', () => {
158+
mockEmailAddressAttribute = {
159+
enabled: true,
160+
first_factors: ['email_link'],
161+
verifications: ['email_link'],
162+
};
122163
mockDisabledStrategies = ['email_link'];
123164
const { container } = render(<#VerifyEmailAddress />);
124165
expect(container.querySelector('.cl-otp-input')).not.toBeNull();
@@ -131,7 +172,7 @@ describe('<#Verify/>', () => {
131172
});
132173

133174
describe('verify phone number', () => {
134-
it('renders the # verification form', async () => {
175+
it('renders the # verification form', () => {
135176
const tree = renderJSON(<#VerifyPhoneNumber />);
136177
expect(tree).toMatchSnapshot();
137178
});

0 commit comments

Comments
 (0)