Skip to content

Commit

Permalink
🐛 fixed fields autocomplete not working in signin popup
Browse files Browse the repository at this point in the history
closes #16960
- replaced iframe by div for signin page
  • Loading branch information
susannakosic committed Aug 15, 2023
1 parent fd95eac commit 0ba9f94
Show file tree
Hide file tree
Showing 5 changed files with 118 additions and 100 deletions.
7 changes: 3 additions & 4 deletions apps/portal/src/components/Global.styles.js
Expand Up @@ -38,7 +38,7 @@ export const GlobalStyles = `
body {
margin: 0px;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif;
font-family: Inter, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif;
font-size: 1.6rem;
height: 100%;
line-height: 1.6em;
Expand All @@ -48,7 +48,7 @@ export const GlobalStyles = `
box-sizing: border-box;
overflow: hidden;
}
button,
button span {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif;
Expand Down Expand Up @@ -97,9 +97,8 @@ export const GlobalStyles = `
p {
font-size: 15px;
line-height: 1.5em;
margin-bottom: 24px;
}
strong {
font-weight: 600;
}
Expand Down
69 changes: 34 additions & 35 deletions apps/portal/src/components/PopupModal.js
@@ -1,4 +1,4 @@
import React from 'react';
import React, {useContext} from 'react';
import Frame from './Frame';
import {hasMode} from '../utils/check-mode';
import AppContext from '../AppContext';
Expand Down Expand Up @@ -224,6 +224,33 @@ class PopupContent extends React.Component {
}
}

const PopupContainer = ({useOverlay, children}) => {
const {member, site, brandColor} = useContext(AppContext);
const containerStyles = StylesWrapper({member});

if (hasMode(['preview'])) {
containerStyles.modalContainer.zIndex = '3999997';
}

const pageContentStyles = `
:root {
--brandcolor: ${brandColor}
}
` + getFrameStyles({site});

return (<div style={containerStyles.modalContainer}>
{useOverlay && <div style={containerStyles.frame.common} title="portal-overlay">
<style dangerouslySetInnerHTML={{__html: pageContentStyles}} />
{children}
</div>}
{!useOverlay && <Frame style={containerStyles.frame.common} title="portal-popup" head={(<>
<style dangerouslySetInnerHTML={{__html: pageContentStyles}} />
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1" /></>)} dataTestId='portal-popup-frame'>
{children}
</Frame>}
</div>);
};

export default class PopupModal extends React.Component {
static contextType = AppContext;

Expand Down Expand Up @@ -253,36 +280,12 @@ export default class PopupModal extends React.Component {
}
}

renderFrameStyles() {
const {site} = this.context;
const FrameStyle = getFrameStyles({site});
const styles = `
:root {
--brandcolor: ${this.context.brandColor}
}
` + FrameStyle;
return (
<>
<style dangerouslySetInnerHTML={{__html: styles}} />
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1" />
</>
);
}

renderFrameContainer() {
const {member, site, customSiteUrl} = this.context;
const Styles = StylesWrapper({member});
const {site, customSiteUrl, page} = this.context;
const isMobile = window.innerWidth < 480;

const frameStyle = {
...Styles.frame.common
};

let className = 'gh-portal-popup-background';
if (hasMode(['preview'])) {
Styles.modalContainer.zIndex = '3999997';
}


if (hasMode(['preview'], {customSiteUrl}) && !site.disableBackground) {
className += ' preview';
}
Expand All @@ -291,14 +294,10 @@ export default class PopupModal extends React.Component {
className += ' dev';
}

return (
<div style={Styles.modalContainer}>
<Frame style={frameStyle} title="portal-popup" head={this.renderFrameStyles()} dataTestId='portal-popup-frame'>
<div className={className} onClick = {e => this.handlePopupClose(e)}></div>
<PopupContent isMobile={isMobile} />
</Frame>
</div>
);
return (<PopupContainer useOverlay={page === 'signin'}>
<div className={className} onClick={e => this.handlePopupClose(e)}></div>
<PopupContent isMobile={isMobile} />
</PopupContainer>);
}

render() {
Expand Down
134 changes: 77 additions & 57 deletions apps/portal/src/tests/SigninFlow.test.js
Expand Up @@ -23,23 +23,27 @@ const setup = async ({site, member = null}) => {
const utils = appRender(
<App api={ghostApi} />
);

const triggerButtonFrame = await utils.findByTitle(/portal-trigger/i);
const popupFrame = utils.queryByTitle(/portal-popup/i);
const popupIframeDocument = popupFrame.contentDocument;
const emailInput = within(popupIframeDocument).queryByLabelText(/email/i);
const nameInput = within(popupIframeDocument).queryByLabelText(/name/i);
const submitButton = within(popupIframeDocument).queryByRole('button', {name: 'Continue'});
const signinButton = within(popupIframeDocument).queryByRole('button', {name: 'Sign in'});
const siteTitle = within(popupIframeDocument).queryByText(site.title);
const freePlanTitle = within(popupIframeDocument).queryByText('Free');
const monthlyPlanTitle = within(popupIframeDocument).queryByText('Monthly');
const yearlyPlanTitle = within(popupIframeDocument).queryByText('Yearly');
const fullAccessTitle = within(popupIframeDocument).queryByText('Full access');

const overlay = utils.queryByTitle(/portal-overlay/i);
const emailInput = within(overlay).queryByLabelText(/email/i);
const nameInput = within(overlay).queryByLabelText(/name/i);
const submitButton = within(overlay).queryByRole('button', {name: 'Continue'});
const signinButton = within(overlay).queryByRole('button', {name: 'Sign in'});
const siteTitle = within(overlay).queryByText(site.title);
const freePlanTitle = within(overlay).queryByText('Free');
const monthlyPlanTitle = within(overlay).queryByText('Monthly');
const yearlyPlanTitle = within(overlay).queryByText('Yearly');
const fullAccessTitle = within(overlay).queryByText('Full access');

const getIframeDocument = async () => {
const iframe = await within(utils.baseElement).findByTitle(/portal-popup/i);
return iframe.contentDocument;
};

return {
ghostApi,
popupIframeDocument,
popupFrame,
overlay,
triggerButtonFrame,
siteTitle,
emailInput,
Expand All @@ -50,7 +54,8 @@ const setup = async ({site, member = null}) => {
monthlyPlanTitle,
yearlyPlanTitle,
fullAccessTitle,
...utils
...utils,
getIframeDocument
};
};

Expand All @@ -76,22 +81,28 @@ const multiTierSetup = async ({site, member = null}) => {
);
const freeTierDescription = site.products?.find(p => p.type === 'free')?.description;
const triggerButtonFrame = await utils.findByTitle(/portal-trigger/i);
const popupFrame = utils.queryByTitle(/portal-popup/i);
const popupIframeDocument = popupFrame.contentDocument;
const emailInput = within(popupIframeDocument).queryByLabelText(/email/i);
const nameInput = within(popupIframeDocument).queryByLabelText(/name/i);
const submitButton = within(popupIframeDocument).queryByRole('button', {name: 'Continue'});
const signinButton = within(popupIframeDocument).queryByRole('button', {name: 'Sign in'});
const siteTitle = within(popupIframeDocument).queryByText(site.title);
const freePlanTitle = within(popupIframeDocument).queryAllByText(/free$/i);
const freePlanDescription = within(popupIframeDocument).queryAllByText(freeTierDescription);
const monthlyPlanTitle = within(popupIframeDocument).queryByText('Monthly');
const yearlyPlanTitle = within(popupIframeDocument).queryByText('Yearly');
const fullAccessTitle = within(popupIframeDocument).queryByText('Full access');

const overlay = utils.queryByTitle(/portal-overlay/i);

const emailInput = within(overlay).queryByLabelText(/email/i);
const nameInput = within(overlay).queryByLabelText(/name/i);
const submitButton = within(overlay).queryByRole('button', {name: 'Continue'});
const signinButton = within(overlay).queryByRole('button', {name: 'Sign in'});
const siteTitle = within(overlay).queryByText(site.title);
const freePlanTitle = within(overlay).queryAllByText(/free$/i);
const freePlanDescription = within(overlay).queryAllByText(freeTierDescription);
const monthlyPlanTitle = within(overlay).queryByText('Monthly');
const yearlyPlanTitle = within(overlay).queryByText('Yearly');
const fullAccessTitle = within(overlay).queryByText('Full access');

const getIframeDocument = async () => {
const iframe = await within(utils.baseElement).findByTitle(/portal-popup/i);
return iframe.contentDocument;
};

return {
ghostApi,
popupIframeDocument,
popupFrame,
overlay,
triggerButtonFrame,
siteTitle,
emailInput,
Expand All @@ -103,7 +114,8 @@ const multiTierSetup = async ({site, member = null}) => {
yearlyPlanTitle,
fullAccessTitle,
freePlanDescription,
...utils
...utils,
getIframeDocument
};
};

Expand All @@ -123,12 +135,11 @@ describe('Signin', () => {
});
test('with default settings', async () => {
const {
ghostApi, popupFrame, triggerButtonFrame, emailInput, nameInput, submitButton,popupIframeDocument
ghostApi, overlay, triggerButtonFrame, emailInput, nameInput, submitButton, getIframeDocument
} = await setup({
site: FixtureSite.singleTier.basic
});

expect(popupFrame).toBeInTheDocument();
expect(overlay).toBeInTheDocument();
expect(triggerButtonFrame).toBeInTheDocument();
expect(emailInput).toBeInTheDocument();
expect(nameInput).not.toBeInTheDocument();
Expand All @@ -138,23 +149,24 @@ describe('Signin', () => {

expect(emailInput).toHaveValue('jamie@example.com');

fireEvent.click(submitButton);
fireEvent.click(submitButton);

expect(ghostApi.member.sendMagicLink).toHaveBeenLastCalledWith({
email: 'jamie@example.com',
emailType: 'signin'
});

const magicLink = await within(popupIframeDocument).findByText(/Now check your email/i);
expect(magicLink).toBeInTheDocument();

const iframeDocument = await getIframeDocument();
const magicLink = await within(iframeDocument).findByText(/Now check your email/i);
expect(magicLink).toBeInTheDocument();
});

test('without name field', async () => {
const {ghostApi, popupFrame, triggerButtonFrame, emailInput, nameInput, submitButton,
popupIframeDocument} = await setup({
const {ghostApi, overlay, triggerButtonFrame, emailInput, nameInput, submitButton, getIframeDocument} = await setup({
site: FixtureSite.singleTier.withoutName
});

expect(popupFrame).toBeInTheDocument();
expect(overlay).toBeInTheDocument();
expect(triggerButtonFrame).toBeInTheDocument();
expect(emailInput).toBeInTheDocument();
expect(nameInput).not.toBeInTheDocument();
Expand All @@ -170,17 +182,18 @@ describe('Signin', () => {
emailType: 'signin'
});

const magicLink = await within(popupIframeDocument).findByText(/Now check your email/i);
const iframeDocument = await getIframeDocument();
const magicLink = await within(iframeDocument).findByText(/Now check your email/i);
expect(magicLink).toBeInTheDocument();
});

test('with only free plan', async () => {
let {ghostApi, popupFrame, triggerButtonFrame, emailInput, nameInput, submitButton,
popupIframeDocument} = await setup({
let {ghostApi, overlay, triggerButtonFrame, emailInput, nameInput, submitButton,
getIframeDocument} = await setup({
site: FixtureSite.singleTier.onlyFreePlan
});

expect(popupFrame).toBeInTheDocument();
expect(overlay).toBeInTheDocument();
expect(triggerButtonFrame).toBeInTheDocument();
expect(emailInput).toBeInTheDocument();
expect(nameInput).not.toBeInTheDocument();
Expand All @@ -196,7 +209,8 @@ describe('Signin', () => {
emailType: 'signin'
});

const magicLink = await within(popupIframeDocument).findByText(/Now check your email/i);
const iframeDocument = await getIframeDocument();
const magicLink = await within(iframeDocument).findByText(/Now check your email/i);
expect(magicLink).toBeInTheDocument();
});
});
Expand All @@ -215,12 +229,12 @@ describe('Signin', () => {
window.location = realLocation;
});
test('with default settings', async () => {
const {ghostApi, popupFrame, triggerButtonFrame, emailInput, nameInput, submitButton,
popupIframeDocument} = await multiTierSetup({
const {ghostApi, overlay, triggerButtonFrame, emailInput, nameInput, submitButton,
getIframeDocument} = await multiTierSetup({
site: FixtureSite.multipleTiers.basic
});

expect(popupFrame).toBeInTheDocument();
expect(overlay).toBeInTheDocument();
expect(triggerButtonFrame).toBeInTheDocument();
expect(emailInput).toBeInTheDocument();
expect(nameInput).not.toBeInTheDocument();
Expand All @@ -236,17 +250,19 @@ describe('Signin', () => {
emailType: 'signin'
});

const magicLink = await within(popupIframeDocument).findByText(/Now check your email/i);
const iframeDocument = await getIframeDocument();

const magicLink = await within(iframeDocument).findByText(/Now check your email/i);
expect(magicLink).toBeInTheDocument();
});

test('without name field', async () => {
const {ghostApi, popupFrame, triggerButtonFrame, emailInput, nameInput, submitButton,
popupIframeDocument} = await multiTierSetup({
const {ghostApi, overlay, triggerButtonFrame, emailInput, nameInput, submitButton,
getIframeDocument} = await multiTierSetup({
site: FixtureSite.multipleTiers.withoutName
});

expect(popupFrame).toBeInTheDocument();
expect(overlay).toBeInTheDocument();
expect(triggerButtonFrame).toBeInTheDocument();
expect(emailInput).toBeInTheDocument();
expect(nameInput).not.toBeInTheDocument();
Expand All @@ -262,17 +278,19 @@ describe('Signin', () => {
emailType: 'signin'
});

const magicLink = await within(popupIframeDocument).findByText(/Now check your email/i);
const iframeDocument = await getIframeDocument();

const magicLink = await within(iframeDocument).findByText(/Now check your email/i);
expect(magicLink).toBeInTheDocument();
});

test('with only free plan available', async () => {
let {ghostApi, popupFrame, triggerButtonFrame, emailInput, nameInput, submitButton,
popupIframeDocument} = await multiTierSetup({
let {ghostApi, overlay, triggerButtonFrame, emailInput, nameInput, submitButton,
getIframeDocument} = await multiTierSetup({
site: FixtureSite.multipleTiers.onlyFreePlan
});

expect(popupFrame).toBeInTheDocument();
expect(overlay).toBeInTheDocument();
expect(triggerButtonFrame).toBeInTheDocument();
expect(emailInput).toBeInTheDocument();
expect(nameInput).not.toBeInTheDocument();
Expand All @@ -288,7 +306,9 @@ describe('Signin', () => {
emailType: 'signin'
});

const magicLink = await within(popupIframeDocument).findByText(/Now check your email/i);
const iframeDocument = await getIframeDocument();

const magicLink = await within(iframeDocument).findByText(/Now check your email/i);
expect(magicLink).toBeInTheDocument();
});
});
Expand Down
4 changes: 2 additions & 2 deletions apps/portal/src/tests/data-attributes.test.js
Expand Up @@ -357,9 +357,9 @@ describe('Portal Data attributes:', () => {
expect(triggerButtonFrame).toBeInTheDocument();
const portalElement = document.querySelector('[data-portal]');
fireEvent.click(portalElement);
popupFrame = await utils.findByTitle(/portal-popup/i);
popupFrame = await utils.findByTitle(/portal-overlay/i);
expect(popupFrame).toBeInTheDocument();
const loginTitle = within(popupFrame.contentDocument).queryByText(/sign in/i);
const loginTitle = within(popupFrame).queryByText(/sign in/i);
expect(loginTitle).toBeInTheDocument();
});
});
Expand Down

0 comments on commit 0ba9f94

Please sign in to comment.