diff --git a/packages/fxa-settings/src/pages/Pair/AuthComplete/index.test.tsx b/packages/fxa-settings/src/pages/Pair/AuthComplete/index.test.tsx
index 1b1729a96c6..124d06a6031 100644
--- a/packages/fxa-settings/src/pages/Pair/AuthComplete/index.test.tsx
+++ b/packages/fxa-settings/src/pages/Pair/AuthComplete/index.test.tsx
@@ -3,9 +3,9 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
import React from 'react';
-import { screen } from '@testing-library/react';
+import { screen, waitFor } from '@testing-library/react';
import { renderWithLocalizationProvider } from 'fxa-react/lib/test-utils/localizationProvider';
-import AuthComplete, { viewName } from '.';
+import AuthComplete, { PAIR_DEVICE_INFO_KEY, viewName } from '.';
import { MOCK_METADATA_UNKNOWN_LOCATION } from '../../../components/DeviceInfoBlock/mocks';
import { usePageViewEvent } from '../../../lib/metrics';
import { REACT_ENTRYPOINT } from '../../../constants';
@@ -86,6 +86,7 @@ describe('AuthComplete page', () => {
);
mockIntegration = new PAI();
mockIntegration.data = { entrypoint: undefined };
+ sessionStorage.clear();
});
it('calls complete() on mount and destroy() on unmount', () => {
@@ -96,6 +97,46 @@ describe('AuthComplete page', () => {
unmount();
expect(mockIntegration.destroy).toHaveBeenCalled();
});
+
+ it('restores device info from sessionStorage after refresh', () => {
+ const cachedInfo = {
+ deviceFamily: 'Firefox',
+ deviceOS: 'Windows',
+ ipAddress: '1.2.3.4',
+ };
+ sessionStorage.setItem(PAIR_DEVICE_INFO_KEY, JSON.stringify(cachedInfo));
+
+ renderWithLocalizationProvider(
+
+ );
+
+ expect(screen.getByRole('heading', { level: 2 })).toHaveTextContent(
+ 'You are now syncing with: Firefox on Windows'
+ );
+ expect(mockIntegration.getSupplicantMetadata).not.toHaveBeenCalled();
+ });
+
+ it('persists fetched device info to sessionStorage', async () => {
+ const fetchedInfo = {
+ deviceFamily: 'Firefox',
+ deviceOS: 'Android',
+ ipAddress: '1.2.3.4',
+ };
+ mockIntegration.getSupplicantMetadata.mockResolvedValue(fetchedInfo);
+
+ renderWithLocalizationProvider(
+
+ );
+
+ await waitFor(() =>
+ expect(sessionStorage.getItem(PAIR_DEVICE_INFO_KEY)).toBe(
+ JSON.stringify(fetchedInfo)
+ )
+ );
+ expect(screen.getByRole('heading', { level: 2 })).toHaveTextContent(
+ 'You are now syncing with: Firefox on Android'
+ );
+ });
});
describe('Send Tab variant', () => {
diff --git a/packages/fxa-settings/src/pages/Pair/AuthComplete/index.tsx b/packages/fxa-settings/src/pages/Pair/AuthComplete/index.tsx
index 26d730f36d4..443cf2d26f8 100644
--- a/packages/fxa-settings/src/pages/Pair/AuthComplete/index.tsx
+++ b/packages/fxa-settings/src/pages/Pair/AuthComplete/index.tsx
@@ -19,6 +19,8 @@ import { isSendTabEntrypoint } from '../../../lib/utilities';
export const viewName = 'pair.auth.complete';
+export const PAIR_DEVICE_INFO_KEY = 'pair.supp.device-info';
+
type AuthCompleteProps = {
suppDeviceInfo?: RemoteMetadata;
supportsFirefoxView?: boolean;
@@ -37,7 +39,15 @@ const AuthComplete = ({
usePageViewEvent(viewName, REACT_ENTRYPOINT);
const ftlMsgResolver = useFtlMsgResolver();
const [deviceInfo, setDeviceInfo] = useState(
- suppDeviceInfoProp
+ () => {
+ if (suppDeviceInfoProp) return suppDeviceInfoProp;
+ try {
+ const cached = sessionStorage.getItem(PAIR_DEVICE_INFO_KEY);
+ return cached ? (JSON.parse(cached) as RemoteMetadata) : undefined;
+ } catch {
+ return undefined;
+ }
+ }
);
const authorityIntegration =
@@ -49,16 +59,21 @@ const AuthComplete = ({
const deviceOS = deviceInfo?.deviceOS || 'Unknown';
const isSendTab = isSendTabEntrypoint(integration?.data.entrypoint);
- // Fetch supplicant metadata if not provided via props
+ // Fetch supplicant metadata if not already available from props or sessionStorage
useEffect(() => {
- if (suppDeviceInfoProp) {
+ if (suppDeviceInfoProp || deviceInfo) {
return;
}
authorityIntegration
?.getSupplicantMetadata()
- .then(setDeviceInfo)
+ .then((info) => {
+ try {
+ sessionStorage.setItem(PAIR_DEVICE_INFO_KEY, JSON.stringify(info));
+ } catch {}
+ setDeviceInfo(info);
+ })
.catch(() => {});
- }, [authorityIntegration, suppDeviceInfoProp]);
+ }, [authorityIntegration, suppDeviceInfoProp, deviceInfo]);
// Signal pairing complete to Firefox on mount
useEffect(() => {