Skip to content

Commit 7103b79

Browse files
authored
Merge pull request #19802 from mozilla/FXA-12781
bug(settings): Fix extraneous sign in email
2 parents c10cdf2 + 10dd023 commit 7103b79

4 files changed

Lines changed: 97 additions & 25 deletions

File tree

packages/fxa-settings/src/components/Settings/ModalVerifySession/index.test.tsx

Lines changed: 36 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,11 @@ import 'mutationobserver-shim';
66
import React from 'react';
77
import { screen, waitFor } from '@testing-library/react';
88
import userEvent from '@testing-library/user-event';
9-
import { mockSession, renderWithRouter } from '../../../models/mocks';
9+
import {
10+
mockAuthClient,
11+
mockSession,
12+
renderWithRouter,
13+
} from '../../../models/mocks';
1014
import { Account, AppContext, Session } from '../../../models';
1115
import { ModalVerifySession } from '.';
1216
import { AuthUiErrors } from 'fxa-settings/src/lib/auth-errors/auth-errors';
@@ -18,6 +22,15 @@ const account = {
1822
} as unknown as Account;
1923

2024
const session = mockSession(false);
25+
const authClient = mockAuthClient();
26+
27+
// jest.mock('../../../models', () => ({
28+
// ...jest.requireActual('../../../models'),
29+
// useAuthClient: () => {
30+
// const authClient = mockAuthClient();
31+
// return authClient;
32+
// },
33+
// }));
2134

2235
window.console.error = jest.fn();
2336

@@ -30,7 +43,13 @@ describe('ModalVerifySession', () => {
3043
const onDismiss = jest.fn();
3144
const onError = jest.fn();
3245
renderWithRouter(
33-
<AppContext.Provider value={{ account, session }}>
46+
<AppContext.Provider
47+
value={{
48+
authClient,
49+
account,
50+
session,
51+
}}
52+
>
3453
<ModalVerifySession {...{ onDismiss, onError }} />
3554
</AppContext.Provider>
3655
);
@@ -51,8 +70,19 @@ describe('ModalVerifySession', () => {
5170
it('sends verification code on mount', async () => {
5271
const onDismiss = jest.fn();
5372
const onError = jest.fn();
73+
authClient.sessionStatus = jest.fn().mockReturnValue({
74+
state: 'unverified',
75+
details: {
76+
verified: false,
77+
accountEmailVerified: true,
78+
sessionVerified: false,
79+
sessionVerificationMeetsMinimumAAL: false,
80+
sessionVerificationMethod: 'email',
81+
},
82+
});
83+
5484
renderWithRouter(
55-
<AppContext.Provider value={{ account, session }}>
85+
<AppContext.Provider value={{ account, session, authClient }}>
5686
<ModalVerifySession {...{ onDismiss, onError }} />
5787
</AppContext.Provider>
5888
);
@@ -67,7 +97,7 @@ describe('ModalVerifySession', () => {
6797
const onDismiss = jest.fn();
6898
const onError = jest.fn();
6999
renderWithRouter(
70-
<AppContext.Provider value={{ account, session }}>
100+
<AppContext.Provider value={{ account, session, authClient }}>
71101
<ModalVerifySession {...{ onDismiss, onError }} />
72102
</AppContext.Provider>
73103
);
@@ -88,7 +118,7 @@ describe('ModalVerifySession', () => {
88118
const onDismiss = jest.fn();
89119
const onError = jest.fn();
90120
renderWithRouter(
91-
<AppContext.Provider value={{ account, session }}>
121+
<AppContext.Provider value={{ account, session, authClient }}>
92122
<ModalVerifySession {...{ onDismiss, onError }} />
93123
</AppContext.Provider>
94124
);
@@ -122,7 +152,7 @@ describe('ModalVerifySession', () => {
122152
const onDismiss = jest.fn();
123153
const onError = jest.fn();
124154
renderWithRouter(
125-
<AppContext.Provider value={{ account, session }}>
155+
<AppContext.Provider value={{ account, session, authClient }}>
126156
<ModalVerifySession {...{ onDismiss, onError }} />
127157
</AppContext.Provider>
128158
);

packages/fxa-settings/src/components/Settings/ModalVerifySession/index.tsx

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { useForm } from 'react-hook-form';
77
import Modal from '../Modal';
88
import InputText from '../../InputText';
99
import { ApolloError } from '@apollo/client';
10-
import { useAccount, useSession } from '../../../models';
10+
import { useAccount, useAuthClient, useSession } from '../../../models';
1111
import { Localized, useLocalization } from '@fluent/react';
1212
import { AuthUiErrors } from 'fxa-settings/src/lib/auth-errors/auth-errors';
1313
import { getErrorFtlId } from '../../../lib/error-utils';
@@ -28,6 +28,7 @@ export const ModalVerifySession = ({
2828
onCompleted,
2929
}: ModalProps) => {
3030
const session = useSession();
31+
const authClient = useAuthClient();
3132
const [errorText, setErrorText] = useState<string>();
3233
const hasSentVerificationCode = useRef(false);
3334
const account = useAccount();
@@ -64,17 +65,21 @@ export const ModalVerifySession = ({
6465

6566
useEffect(() => {
6667
const getStatus = async () => {
67-
// Check cache first, then do network request for session verification
68-
if (session.verified) {
68+
// Don't trust the cache for now, make an actual call.
69+
const status = await authClient.sessionStatus(session.token);
70+
if (status.details.sessionVerified) {
6971
onCompleted && onCompleted();
70-
} else if (!hasSentVerificationCode.current) {
72+
return;
73+
}
74+
75+
if (!hasSentVerificationCode.current) {
7176
hasSentVerificationCode.current = true;
7277
await session.sendVerificationCode();
7378
}
7479
};
7580

7681
getStatus();
77-
}, [session, onCompleted]);
82+
}, [session, onCompleted, authClient]);
7883

7984
// Destructure formState in advance to avoid logical operator short-circuiting
8085
// causing the isValid field to be conditionally subscribed.

packages/fxa-settings/src/components/Settings/VerifiedSessionGuard/index.test.tsx

Lines changed: 32 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import {
1212
} from '../../../models/mocks';
1313
import { Account, AppContext } from '../../../models';
1414
import { VerifiedSessionGuard } from '.';
15+
import AuthClient from 'fxa-auth-client/browser';
1516

1617
it('renders the content when verified', async () => {
1718
const account = {
@@ -22,16 +23,29 @@ it('renders the content when verified', async () => {
2223
const onDismiss = jest.fn();
2324
const onError = jest.fn();
2425

25-
await act(async () =>
26+
await act(
27+
async () =>
2628
await renderWithRouter(
2729
<AppContext.Provider
28-
value={mockAppContext({ account, session: mockSession(true, false) })}
30+
value={mockAppContext({
31+
account,
32+
session: mockSession(true, false),
33+
authClient: {
34+
sessionStatus: () => {
35+
return {
36+
details: {
37+
sessionVerified: true,
38+
},
39+
};
40+
},
41+
} as unknown as AuthClient,
42+
})}
2943
>
30-
<VerifiedSessionGuard {...{ onDismiss, onError }}>
31-
<div data-testid="children">Content</div>
32-
</VerifiedSessionGuard>
33-
</AppContext.Provider>
34-
)
44+
<VerifiedSessionGuard {...{ onDismiss, onError }}>
45+
<div data-testid="children">Content</div>
46+
</VerifiedSessionGuard>
47+
</AppContext.Provider>
48+
)
3549
);
3650

3751
expect(screen.getByTestId('children')).toBeInTheDocument();
@@ -46,14 +60,18 @@ it('renders the guard when unverified', async () => {
4660
},
4761
} as unknown as Account;
4862

49-
await act(async () => await renderWithRouter(
50-
<AppContext.Provider value={mockAppContext({ account, session: mockSession(false) })}>
51-
<VerifiedSessionGuard {...{ onDismiss, onError }}>
52-
<div>Content</div>
53-
</VerifiedSessionGuard>
54-
</AppContext.Provider>
63+
await act(
64+
async () =>
65+
await renderWithRouter(
66+
<AppContext.Provider
67+
value={mockAppContext({ account, session: mockSession(false) })}
68+
>
69+
<VerifiedSessionGuard {...{ onDismiss, onError }}>
70+
<div>Content</div>
71+
</VerifiedSessionGuard>
72+
</AppContext.Provider>
5573
)
56-
);
74+
);
5775

5876
expect(screen.getByTestId('modal-verify-session')).toBeInTheDocument();
5977
});

packages/fxa-settings/src/models/mocks.tsx

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
44

55
import React from 'react';
6+
import AuthClient from 'fxa-auth-client/browser';
67
import { AccountData, ProfileInfo, Session } from '.';
78
import { renderWithLocalizationProvider } from 'fxa-react/lib/test-utils/localizationProvider';
89
import {
@@ -122,6 +123,23 @@ export function mockSession(
122123
return session;
123124
}
124125

126+
export function mockAuthClient() {
127+
// There are plenty more methods to mock here, but this is these are the ones
128+
// that get commonly used.
129+
return {
130+
sessionStatus: jest.fn().mockReturnValue({
131+
state: 'verified',
132+
details: {
133+
verified: true,
134+
accountEmailVerified: true,
135+
sessionVerified: true,
136+
sessionVerificationMeetsMinimumAAL: true,
137+
sessionVerificationMethod: 'email',
138+
},
139+
}),
140+
} as unknown as AuthClient;
141+
}
142+
125143
export function mockSensitiveDataClient() {
126144
return new SensitiveDataClient();
127145
}
@@ -186,6 +204,7 @@ export function mockAppContext(context?: AppContextValue) {
186204
{
187205
account: MOCK_ACCOUNT,
188206
session: mockSession(),
207+
authClient: mockAuthClient(),
189208
config: getDefault(),
190209
sensitiveDataClient: mockSensitiveDataClient(),
191210
uniqueUserId: '4a9512ac-3110-43df-aa8a-958A3d210b9c3',

0 commit comments

Comments
 (0)