Skip to content

Commit 891c9b0

Browse files
authored
Merge pull request #20095 from mozilla/fxa-12989
feat(settings): Add SigninCachedPage customizations
2 parents b481375 + 7782c29 commit 891c9b0

10 files changed

Lines changed: 137 additions & 17 deletions

File tree

libs/shared/cms/src/__generated__/gql.ts

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

libs/shared/cms/src/__generated__/graphql.ts

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

libs/shared/cms/src/lib/queries/relying-party/factories.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,15 @@ export const RelyingPartyResultFactory = (
127127
pageTitle: faker.string.sample(),
128128
splitLayout: faker.datatype.boolean(),
129129
},
130+
SigninCachedPage: {
131+
logoUrl: faker.internet.url(),
132+
logoAltText: faker.internet.url(),
133+
headline: faker.string.sample(),
134+
description: faker.string.sample(),
135+
primaryButtonText: faker.string.sample(),
136+
pageTitle: faker.string.sample(),
137+
splitLayout: faker.datatype.boolean(),
138+
},
130139
SigninTokenCodePage: {
131140
logoUrl: faker.internet.url(),
132141
logoAltText: faker.internet.url(),

libs/shared/cms/src/lib/queries/relying-party/query.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,15 @@ export const relyingPartyQuery = graphql(`
8282
pageTitle
8383
splitLayout
8484
}
85+
SigninCachedPage {
86+
logoUrl
87+
logoAltText
88+
headline
89+
description
90+
primaryButtonText
91+
pageTitle
92+
splitLayout
93+
}
8594
SigninTokenCodePage {
8695
headline
8796
description

libs/shared/cms/src/lib/queries/relying-party/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ export interface RelyingPartyResult {
6060
SignupConfirmCodePage: Page;
6161
SignupConfirmedSyncPage: Page;
6262
SigninPage: Page;
63+
SigninCachedPage?: Page;
6364
SigninTokenCodePage?: Page;
6465
SigninUnblockCodePage?: Page;
6566
shared: Shared;

packages/fxa-settings/src/models/integrations/relier-interfaces.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ export interface RelierCmsInfo {
103103
SignupConfirmedSyncPage?: PageRelierCmsInfo;
104104

105105
SigninPage: PageRelierCmsInfo;
106+
SigninCachedPage?: PageRelierCmsInfo;
106107
SigninTotpCodePage?: PageRelierCmsInfo;
107108
SigninTokenCodePage?: PageRelierCmsInfo;
108109
SigninUnblockCodePage?: PageRelierCmsInfo;

packages/fxa-settings/src/pages/Signin/container.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -573,7 +573,10 @@ const SigninContainer = ({
573573
}
574574

575575
const cmsInfo = integration.getCmsInfo();
576-
const splitLayout = cmsInfo?.SigninPage?.splitLayout;
576+
// sessionToken is a necessary precondition for showing the cached page
577+
const splitLayout = sessionToken
578+
? (cmsInfo?.SigninCachedPage?.splitLayout ?? cmsInfo?.SigninPage?.splitLayout)
579+
: cmsInfo?.SigninPage?.splitLayout;
577580

578581
// TODO: if validationError is 'email', in content-server we show "Bad request email param"
579582
// For now, just redirect to index-first, until FXA-8289 is done

packages/fxa-settings/src/pages/Signin/index.stories.tsx

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,22 @@ export const SignInWithCmsCachedCredentialsSplitLayout = storyWithProps({
123123
}),
124124
});
125125

126+
export const SignInWithCmsCachedPage = storyWithProps({
127+
sessionToken: MOCK_SESSION_TOKEN,
128+
integration: createMockSigninOAuthIntegration({
129+
wantsKeys: false,
130+
cmsInfo: {
131+
...MOCK_CMS_INFO,
132+
SigninCachedPage: {
133+
headline: 'Welcome back',
134+
description: 'Continue to your Mozilla account',
135+
primaryButtonText: 'Continue',
136+
pageTitle: 'Welcome back',
137+
},
138+
},
139+
}),
140+
});
141+
126142
export const SignInRelayNoPasswordlessSupport = storyWithProps({
127143
integration: createMockSigninOAuthNativeIntegration({
128144
service: OAuthNativeServices.Relay,

packages/fxa-settings/src/pages/Signin/index.test.tsx

Lines changed: 80 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1581,17 +1581,18 @@ describe('Signin component', () => {
15811581
hasPassword: false,
15821582
});
15831583

1584-
// the specific case here is the falsy condition of the above ternary
1585-
// so, we make sure our mock headline is NOT in the document as a guard against
1586-
// snapshotting the wrong render.
1587-
expect(
1588-
screen.queryByText(cmsProps.cmsInfo.SigninPage.headline)
1589-
).not.toBeInTheDocument();
1590-
15911584
const cmsLogo = screen.getByRole('img', {
15921585
name: cmsProps.cmsInfo.shared.logoAltText,
15931586
});
15941587
expect(cmsLogo).toMatchSnapshot();
1588+
1589+
// When no SigninCachedPage is set, the non-password path falls back
1590+
// to SigninPage headline and description
1591+
expect(
1592+
screen.getByRole('heading', {
1593+
name: cmsProps.cmsInfo.SigninPage.headline,
1594+
})
1595+
).toBeInTheDocument();
15951596
});
15961597

15971598
it('renders the CMS-styled submit button', () => {
@@ -1621,5 +1622,77 @@ describe('Signin component', () => {
16211622

16221623
expect(additionalInfo).toBeInTheDocument();
16231624
});
1625+
1626+
describe('SigninCachedPage CMS config', () => {
1627+
const cachedCmsProps = {
1628+
cmsInfo: {
1629+
...MOCK_CMS_INFO,
1630+
SigninCachedPage: {
1631+
headline: 'Welcome back',
1632+
description: 'Continue to your Mozilla account',
1633+
primaryButtonText: 'Continue',
1634+
pageTitle: 'Welcome back',
1635+
},
1636+
},
1637+
};
1638+
1639+
it('renders cached CMS headline and description for cached user', () => {
1640+
render({
1641+
integration: createMockSigninWebIntegration(cachedCmsProps),
1642+
sessionToken: MOCK_SESSION_TOKEN,
1643+
hasPassword: true,
1644+
});
1645+
1646+
expect(
1647+
screen.getByRole('heading', { name: 'Welcome back' })
1648+
).toBeInTheDocument();
1649+
expect(
1650+
screen.getByText('Continue to your Mozilla account')
1651+
).toBeInTheDocument();
1652+
});
1653+
1654+
it('renders cached CMS button text for cached user', () => {
1655+
render({
1656+
integration: createMockSigninWebIntegration(cachedCmsProps),
1657+
sessionToken: MOCK_SESSION_TOKEN,
1658+
hasPassword: true,
1659+
});
1660+
1661+
expect(
1662+
screen.getByRole('button', { name: 'Continue' })
1663+
).toBeInTheDocument();
1664+
});
1665+
1666+
it('falls back to SigninPage CMS config when SigninCachedPage is not set', () => {
1667+
render({
1668+
integration: createMockSigninWebIntegration(cmsProps),
1669+
sessionToken: MOCK_SESSION_TOKEN,
1670+
hasPassword: true,
1671+
});
1672+
1673+
expect(
1674+
screen.getByRole('heading', {
1675+
name: cmsProps.cmsInfo.SigninPage.headline,
1676+
})
1677+
).toBeInTheDocument();
1678+
});
1679+
1680+
it('uses SigninPage CMS config for non-cached user even when SigninCachedPage is set', () => {
1681+
render({
1682+
integration: createMockSigninWebIntegration(cachedCmsProps),
1683+
hasPassword: true,
1684+
sessionToken: undefined,
1685+
});
1686+
1687+
expect(
1688+
screen.getByRole('heading', {
1689+
name: cachedCmsProps.cmsInfo.SigninPage.headline,
1690+
})
1691+
).toBeInTheDocument();
1692+
expect(
1693+
screen.queryByRole('heading', { name: 'Welcome back' })
1694+
).not.toBeInTheDocument();
1695+
});
1696+
});
16241697
});
16251698
});

packages/fxa-settings/src/pages/Signin/index.tsx

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -360,8 +360,13 @@ const Signin = ({
360360
);
361361

362362
const cmsInfo = integration.getCmsInfo();
363-
const title = cmsInfo?.SigninPage.pageTitle;
364-
const splitLayout = cmsInfo?.SigninPage.splitLayout;
363+
const cachedPageCms = cmsInfo?.SigninCachedPage;
364+
const signinPageCms = cmsInfo?.SigninPage;
365+
// Use cached page config when available and user has cached account, else fall back to SigninPage
366+
const activePageCms =
367+
!isPasswordNeeded && cachedPageCms ? cachedPageCms : signinPageCms;
368+
const title = activePageCms?.pageTitle;
369+
const splitLayout = activePageCms?.splitLayout;
365370
const additionalAccessibilityInfo =
366371
cmsInfo?.shared.additionalAccessibilityInfo;
367372

@@ -383,8 +388,8 @@ const Signin = ({
383388
{...{
384389
cmsLogoUrl: cmsInfo?.shared.logoUrl,
385390
cmsLogoAltText: cmsInfo?.shared.logoAltText,
386-
cmsHeadline: cmsInfo?.SigninPage.headline,
387-
cmsDescription: cmsInfo?.SigninPage.description,
391+
cmsHeadline: activePageCms?.headline,
392+
cmsDescription: activePageCms?.description,
388393
cmsHeadlineFontSize: cmsInfo?.shared.headlineFontSize,
389394
cmsHeadlineTextColor: cmsInfo?.shared.headlineTextColor,
390395
}}
@@ -400,6 +405,8 @@ const Signin = ({
400405
serviceName,
401406
cmsLogoUrl: cmsInfo?.shared.logoUrl,
402407
cmsLogoAltText: cmsInfo?.shared.logoAltText,
408+
cmsHeadline: activePageCms?.headline,
409+
cmsDescription: activePageCms?.description,
403410
cmsHeadlineFontSize: cmsInfo?.shared.headlineFontSize,
404411
cmsHeadlineTextColor: cmsInfo?.shared.headlineTextColor,
405412
}}
@@ -489,6 +496,7 @@ const Signin = ({
489496
type="submit"
490497
disabled={signinLoading}
491498
buttonColor={cmsInfo?.shared.buttonColor}
499+
buttonText={activePageCms?.primaryButtonText}
492500
>
493501
Sign in
494502
</CmsButtonWithFallback>

0 commit comments

Comments
 (0)