Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ export function useFxAStatus(integration: FxAStatusIntegration) {
const [supportsKeysOptionalLogin, setSupportsKeysOptionalLogin] =
useState<boolean>(false);
const [supportsCanLinkAccountUid, setSupportsCanLinkAccountUid] =
useState<boolean>(false);
useState<boolean | undefined>(undefined);

useEffect(() => {
// This sends a web channel message to the browser to prompt a response
Expand Down
4 changes: 2 additions & 2 deletions packages/fxa-settings/src/lib/hooks/useFxAStatus/mocks.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ import { getSyncEngineIds, syncEngineConfigs } from '../../sync-engines';
export function mockUseFxAStatus({
offeredSyncEnginesOverride,
supportsKeysOptionalLogin = false,
supportsCanLinkAccountUid = false,
supportsCanLinkAccountUid,
}: {
offeredSyncEnginesOverride?: ReturnType<typeof getSyncEngineIds>;
supportsKeysOptionalLogin?: boolean;
supportsCanLinkAccountUid?: boolean;
supportsCanLinkAccountUid?: boolean | undefined;
} = {}) {
const offeredSyncEngineConfigs = syncEngineConfigs;
const offeredSyncEngines =
Expand Down
70 changes: 69 additions & 1 deletion packages/fxa-settings/src/pages/Index/container.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import * as IndexModule from './index';
import * as ReactUtils from 'fxa-react/lib/utils';
import * as cache from '../../lib/cache';

import React from 'react';
import { waitFor } from '@testing-library/react';
import { LocationProvider } from '@reach/router';
import { useValidatedQueryParams } from '../../lib/hooks/useValidate';
Expand Down Expand Up @@ -971,6 +970,75 @@ describe('IndexContainer', () => {
expect(currentIndexProps?.errorBannerMessage).toBeDefined();
});
});

describe('useFxAStatusResult.supportsCanLinkAccountUid and processEmailSubmission', () => {
beforeEach(() => {
jest.spyOn(cache, 'currentAccount').mockReturnValue({
uid: 'abc123',
email: MOCK_EMAIL,
lastLogin: Date.now(),
});
});

it('shows loading spinner and does not call fxaCanLinkAccount when supportsCanLinkAccountUid is undefined', async () => {
mockUseFxAStatusResult = mockUseFxAStatus({
supportsCanLinkAccountUid: undefined,
});

const { getByText } = renderWithLocalizationProvider(
<LocationProvider>
<IndexContainer
integration={integration}
serviceName={MozServices.FirefoxSync}
useFxAStatusResult={mockUseFxAStatusResult}
/>
</LocationProvider>
);

expect(getByText('LoadingSpinner')).toBeInTheDocument();
expect(firefox.fxaCanLinkAccount).not.toHaveBeenCalled();
});

it('does not call fxaCanLinkAccount when supportsCanLinkAccountUid is true', async () => {
mockUseFxAStatusResult = mockUseFxAStatus({
supportsCanLinkAccountUid: true,
});

renderWithLocalizationProvider(
<LocationProvider>
<IndexContainer
integration={integration}
serviceName={MozServices.FirefoxSync}
useFxAStatusResult={mockUseFxAStatusResult}
/>
</LocationProvider>
);

await waitFor(() => {
expect(firefox.fxaCanLinkAccount).not.toHaveBeenCalled();
});
});

it('calls fxaCanLinkAccount when supportsCanLinkAccountUid is false', async () => {
mockUseFxAStatusResult = mockUseFxAStatus({
supportsCanLinkAccountUid: false,
});

renderWithLocalizationProvider(
<LocationProvider>
<IndexContainer
integration={integration}
serviceName={MozServices.FirefoxSync}
useFxAStatusResult={mockUseFxAStatusResult}
/>
</LocationProvider>
);

await waitFor(() => {
expect(firefox.fxaCanLinkAccount).toHaveBeenCalled();
});
});
});
});
});
});
15 changes: 12 additions & 3 deletions packages/fxa-settings/src/pages/Index/container.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -271,12 +271,20 @@ const IndexContainer = ({
if (isUnsupportedContext(integration.data.context)) {
hardNavigate('/update_firefox', {}, true);
} else if (shouldTrySuggestedEmail && !attemptedEmailAutoSubmit.current) {
// Without this, can_link_account can fire multiple times due to calling it in a `useEffect`,
// causing multiple sync warnings to be displayed. This ensures it is called once.
attemptedEmailAutoSubmit.current = true;
// Must be in an async function or else `setIsLoading(false)` can be called prematurely with
// the next render, before async actions in `processEmailSubmission` have finished
(async () => {
if (integration.isSync() || integration.isFirefoxNonSync()) {
// Wait for this to resolve before calling 'processEmailSubmission'.
// Otherwise, a merge warning may show on email-first for newer Fx versions
// that support "can link account" by UID.
if (useFxAStatusResult.supportsCanLinkAccountUid === undefined) {
return;
}
}
// Without this, can_link_account can fire multiple times due to calling it in a `useEffect`,
// causing multiple sync warnings to be displayed. This ensures it is called once.
attemptedEmailAutoSubmit.current = true;
await processEmailSubmission(suggestedEmail, false);
})();
} else {
Expand All @@ -290,6 +298,7 @@ const IndexContainer = ({
shouldTrySuggestedEmail,
integration.data.context,
integration,
useFxAStatusResult.supportsCanLinkAccountUid,
]);

useEffect(() => {
Expand Down
Loading