Skip to content

Commit 3ef744b

Browse files
authored
Merge pull request #292 from clerkinc/custom_support_email
feat(clerk-js): Add supportEmail property option
2 parents 3a4bf80 + 71eff74 commit 3ef744b

File tree

8 files changed

+139
-5
lines changed

8 files changed

+139
-5
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import { renderHook } from '@clerk/shared/testUtils';
2+
3+
const mockUseOptions = jest.fn();
4+
5+
import { useSupportEmail } from './useSupportEmail';
6+
7+
jest.mock('ui/contexts', () => {
8+
return {
9+
useCoreClerk: () => {
10+
return {
11+
frontendApi: 'clerk.clerk.dev',
12+
};
13+
},
14+
useOptions: mockUseOptions,
15+
};
16+
});
17+
18+
describe('useSupportEmail', () => {
19+
test('should use custom email when provided', () => {
20+
mockUseOptions.mockImplementationOnce(() => ({ supportEmail: 'test@email.com' }));
21+
const { result } = renderHook(() => useSupportEmail());
22+
23+
expect(result.current).toBe('test@email.com');
24+
});
25+
26+
test('should fallback to default when supportEmail is not provided in options', () => {
27+
mockUseOptions.mockImplementationOnce(() => ({ supportEmail: undefined }));
28+
const { result } = renderHook(() => useSupportEmail());
29+
30+
expect(result.current).toBe('support@clerk.dev');
31+
});
32+
});

packages/clerk-js/src/ui/hooks/useSupportEmail.ts

+4-2
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,20 @@
11
import React from 'react';
22

33
import { buildEmailAddress } from '../../utils';
4-
import { useCoreClerk } from '../contexts';
4+
import { useCoreClerk, useOptions } from '../contexts';
55

66
export function useSupportEmail(): string {
77
const Clerk = useCoreClerk();
8+
const { supportEmail } = useOptions();
89

910
const supportDomain = React.useMemo(
1011
() =>
12+
supportEmail ||
1113
buildEmailAddress({
1214
localPart: 'support',
1315
frontendApi: Clerk.frontendApi,
1416
}),
15-
[Clerk.frontendApi],
17+
[Clerk.frontendApi, supportEmail],
1618
);
1719

1820
return supportDomain;

packages/clerk-js/src/ui/signIn/SignInFactorOne.test.tsx

+1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ jest.mock('ui/contexts', () => {
1717
useSignInContext: jest.fn(),
1818
useCoreClerk: jest.fn(),
1919
useCoreSignIn: jest.fn(),
20+
useOptions: jest.fn(() => ({ supportEmail: undefined })),
2021
};
2122
});
2223

packages/clerk-js/src/ui/signIn/SignInStart.test.tsx

+1
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ jest.mock('ui/contexts', () => {
5353
useCoreClerk: jest.fn(() => ({
5454
setActive: mockSetActive,
5555
})),
56+
useOptions: jest.fn(() => ({ supportEmail: undefined })),
5657
};
5758
});
5859

packages/clerk-js/src/ui/signIn/strategies/All.test.tsx

+16-2
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ import { SignInFactor } from '@clerk/types';
33
import { Session } from 'core/resources';
44
import React from 'react';
55

6+
const mockUseOptions = jest.fn(() => ({}));
7+
68
import { All } from './All';
79

810
jest.mock('ui/contexts', () => {
@@ -13,6 +15,7 @@ jest.mock('ui/contexts', () => {
1315
frontendAPI: 'clerk.clerk.dev',
1416
},
1517
})),
18+
useOptions: mockUseOptions,
1619
useEnvironment: jest.fn(() => ({
1720
displayConfig: {
1821
theme: {
@@ -65,7 +68,18 @@ describe('<All/>', () => {
6568
},
6669
];
6770

68-
it('renders the All sign in methods', async () => {
71+
it('renders the All sign in methods', () => {
72+
const tree = renderJSON(
73+
<All
74+
factors={factors}
75+
selectFactor={jest.fn()}
76+
/>,
77+
);
78+
expect(tree).toMatchSnapshot();
79+
});
80+
81+
it('renders the All sign in methods with custom support email', () => {
82+
mockUseOptions.mockImplementationOnce(() => ({ supportEmail: 'test@test.com' }));
6983
const tree = renderJSON(
7084
<All
7185
factors={factors}
@@ -75,7 +89,7 @@ describe('<All/>', () => {
7589
expect(tree).toMatchSnapshot();
7690
});
7791

78-
it('triggers selectStrategy callback on click', async () => {
92+
it('triggers selectStrategy callback on click', () => {
7993
const mockSelectStrategy = jest.fn();
8094
render(
8195
<All

packages/clerk-js/src/ui/signIn/strategies/All.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ import React from 'react';
44
import { Separator } from 'ui/common';
55
import { useSupportEmail } from 'ui/hooks/useSupportEmail';
66
import { allStrategiesButtonsComparator } from 'ui/signIn/strategies/factorSortingUtils';
7-
import { factorHasLocalStrategy } from '../utils';
87

8+
import { factorHasLocalStrategy } from '../utils';
99
import { OAuth } from './OAuth';
1010

1111
export function getButtonLabel(factor: SignInFactor): string {

packages/clerk-js/src/ui/signIn/strategies/__snapshots__/All.test.tsx.snap

+82
Original file line numberDiff line numberDiff line change
@@ -81,3 +81,85 @@ Array [
8181
</div>,
8282
]
8383
`;
84+
85+
exports[`<All/> renders the All sign in methods with custom support email 1`] = `
86+
Array [
87+
<div
88+
className="cl-oauth-button-group"
89+
>
90+
<button
91+
className="button outline primary cl-oauth-button"
92+
disabled={false}
93+
onClick={[Function]}
94+
style={
95+
Object {
96+
"display": "flex",
97+
}
98+
}
99+
>
100+
<img
101+
alt="Google"
102+
src="https://images.clerk.dev/static/google.svg"
103+
/>
104+
<span>
105+
Sign in with Google
106+
</span>
107+
</button>
108+
<button
109+
className="button outline primary cl-oauth-button"
110+
disabled={false}
111+
onClick={[Function]}
112+
style={
113+
Object {
114+
"display": "flex",
115+
}
116+
}
117+
>
118+
<img
119+
alt="Facebook"
120+
src="https://images.clerk.dev/static/facebook.svg"
121+
/>
122+
<span>
123+
Sign in with Facebook
124+
</span>
125+
</button>
126+
</div>,
127+
<div
128+
className="cl-auth-form-separator"
129+
/>,
130+
<button
131+
className="button solid primary cl-primary-button"
132+
onClick={[Function]}
133+
>
134+
Send magic link to +1*********9
135+
</button>,
136+
<button
137+
className="button solid primary cl-primary-button"
138+
onClick={[Function]}
139+
>
140+
Email code to j***@e*****.com
141+
</button>,
142+
<button
143+
className="button solid primary cl-primary-button"
144+
onClick={[Function]}
145+
>
146+
Send code to +1*********9
147+
</button>,
148+
<button
149+
className="button solid primary cl-primary-button"
150+
onClick={[Function]}
151+
>
152+
Sign in with your password
153+
</button>,
154+
<div
155+
className="cl-auth-form-link cl-auth-trouble-link"
156+
>
157+
<a
158+
href="mailto:test@test.com"
159+
title="Contact support"
160+
>
161+
I am having trouble signing in
162+
</a>
163+
</div>,
164+
]
165+
`;

packages/types/src/clerk.ts

+2
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,8 @@ export interface ClerkOptions {
294294
polling?: boolean;
295295
selectInitialSession?: (client: ClientResource) => ActiveSessionResource | null;
296296
theme?: ClerkThemeOptions;
297+
/** Optional support email for display in authentication screens */
298+
supportEmail?: string;
297299
}
298300

299301
export interface Resources {

0 commit comments

Comments
 (0)