Skip to content
This repository has been archived by the owner on Mar 13, 2024. It is now read-only.

Commit

Permalink
[MM-10569] Invite links won't work in mobile browser when the user is…
Browse files Browse the repository at this point in the history
… asked if they want to download the app (#1919)

* fixes issue with first-time mobile viewers being indirected to sign up page incorrectly

get components under test

fix eslint error and update snapshots

* change onclick to use redirect url param instead of history.goBack()
  • Loading branch information
mickmister authored and lieut-data committed Nov 7, 2018
1 parent 48d24bf commit 5f6f5d5
Show file tree
Hide file tree
Showing 7 changed files with 326 additions and 11 deletions.
24 changes: 19 additions & 5 deletions components/get_android_app/get_android_app.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,24 @@

import React from 'react';
import {FormattedMessage} from 'react-intl';
import {Link} from 'react-router-dom';
import PropTypes from 'prop-types';

import {useSafeUrl} from 'utils/url';
import MattermostIcon from 'images/favicon/android-chrome-192x192.png';
import Nexus6Mockup from 'images/nexus-6p-mockup.png';

export default function GetAndroidApp({androidAppDownloadLink}) {
export default function GetAndroidApp({androidAppDownloadLink, history, location}) {
const onContinue = (e) => {
e.preventDefault();

const redirectTo = (new URLSearchParams(location.search)).get('redirect_to');
if (redirectTo) {
history.push(redirectTo);
} else {
history.push('/');
}
};

return (
<div className='get-app get-android-app'>
<h1 className='get-app__header'>
Expand Down Expand Up @@ -41,7 +51,7 @@ export default function GetAndroidApp({androidAppDownloadLink}) {
</div>
</div>
<a
className='btn btn-primary get-android-app__continue'
className='btn btn-primary get-android-app__app-store-link'
href={useSafeUrl(androidAppDownloadLink)}
>
<FormattedMessage
Expand All @@ -59,12 +69,16 @@ export default function GetAndroidApp({androidAppDownloadLink}) {
defaultMessage='Or {link}'
values={{
link: (
<Link to='/'>
<a
onClick={onContinue}
className='get-android-app__continue'
>

<FormattedMessage
id='get_app.continueWithBrowserLink'
defaultMessage='continue with browser'
/>
</Link>
</a>
),
}}
/>
Expand Down
22 changes: 18 additions & 4 deletions components/get_ios_app/get_ios_app.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,24 @@

import React from 'react';
import {FormattedMessage} from 'react-intl';
import {Link} from 'react-router-dom';
import PropTypes from 'prop-types';

import {useSafeUrl} from 'utils/url';
import AppStoreButton from 'images/app-store-button.png';
import IPhone6Mockup from 'images/iphone-6-mockup.png';

export default function GetIosApp({iosAppDownloadLink}) {
export default function GetIosApp({iosAppDownloadLink, history, location}) {
const onContinue = (e) => {
e.preventDefault();

const redirectTo = (new URLSearchParams(location.search)).get('redirect_to');
if (redirectTo) {
history.push(redirectTo);
} else {
history.push('/');
}
};

return (
<div className='get-app get-ios-app'>
<h1 className='get-app__header'>
Expand Down Expand Up @@ -52,12 +62,16 @@ export default function GetIosApp({iosAppDownloadLink}) {
defaultMessage='Or {link}'
values={{
link: (
<Link to='/'>
<a
onClick={onContinue}
className='get-ios-app__continue'
>

<FormattedMessage
id='get_app.continueWithBrowserLink'
defaultMessage='continue with browser'
/>
</Link>
</a>
),
}}
/>
Expand Down
4 changes: 2 additions & 2 deletions components/root/root.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -201,10 +201,10 @@ export default class Root extends React.Component {

// redirect to the mobile landing page if the user hasn't seen it before
if (iosDownloadLink && UserAgent.isIosWeb() && !BrowserStore.hasSeenLandingPage() && !toResetPasswordScreen) {
this.props.history.push('/get_ios_app');
this.props.history.push('/get_ios_app?redirect_to=' + encodeURIComponent(this.props.location.pathname) + encodeURIComponent(this.props.location.search));
BrowserStore.setLandingPageSeen(true);
} else if (androidDownloadLink && UserAgent.isAndroidWeb() && !BrowserStore.hasSeenLandingPage() && !toResetPasswordScreen) {
this.props.history.push('/get_android_app');
this.props.history.push('/get_android_app?redirect_to=' + encodeURIComponent(this.props.location.pathname) + encodeURIComponent(this.props.location.search));
BrowserStore.setLandingPageSeen(true);
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`components/GetAndroidApp should match snapshot 1`] = `
<div
className="get-app get-android-app"
>
<h1
className="get-app__header"
>
<FormattedMessage
defaultMessage="Mattermost works best if you switch to our Android app"
id="get_app.androidHeader"
values={Object {}}
/>
</h1>
<hr />
<div>
<img
className="get-android-app__icon"
src="mockup.png"
/>
<div
className="get-android-app__app-info"
>
<span
className="get-android-app__app-name"
>
<FormattedMessage
defaultMessage="Mattermost for Android"
id="get_app.androidAppName"
values={Object {}}
/>
</span>
<span
className="get-android-app__app-creator"
>
<FormattedMessage
defaultMessage="Mattermost, Inc"
id="get_app.mattermostInc"
values={Object {}}
/>
</span>
</div>
</div>
<a
className="btn btn-primary get-android-app__app-store-link"
href="https://about.mattermost.com/mattermost-android-app"
>
<FormattedMessage
defaultMessage="Continue"
id="get_app.continue"
values={Object {}}
/>
</a>
<img
className="get-app__screenshot"
src="mockup.png"
/>
<span
className="get-app__continue-with-browser"
>
<FormattedMessage
defaultMessage="Or {link}"
id="get_app.continueWithBrowser"
values={
Object {
"link": <a
className="get-android-app__continue"
onClick={[Function]}
>
<FormattedMessage
defaultMessage="continue with browser"
id="get_app.continueWithBrowserLink"
values={Object {}}
/>
</a>,
}
}
/>
</span>
</div>
`;
65 changes: 65 additions & 0 deletions tests/components/get_android_app/get_android_app.test.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.

import React from 'react';
import {shallow} from 'enzyme';

import {mountWithIntl} from 'tests/helpers/intl-test-helper.jsx';
import GetAndroidApp from 'components/get_android_app/get_android_app.jsx';

jest.mock('images/favicon/android-chrome-192x192.png', () => 'favicon.png');
jest.mock('images/nexus-6p-mockup.png', () => 'mockup.png');

describe('components/GetAndroidApp', () => {
test('should match snapshot', () => {
const wrapper = shallow(
<GetAndroidApp
androidAppDownloadLink={'https://about.mattermost.com/mattermost-android-app'}
/>
);
expect(wrapper).toMatchSnapshot();
});

test('should contain the download link', () => {
const wrapper = shallow(
<GetAndroidApp
androidAppDownloadLink={'https://about.mattermost.com/mattermost-android-app'}
/>
);

const link = wrapper.find('.get-android-app__app-store-link');
expect(link.prop('href')).toEqual('https://about.mattermost.com/mattermost-android-app');
});

test('should redirect if the user chooses to stay in the browser. Redirect url param is present', () => {
const push = jest.fn();
const wrapper = mountWithIntl(
<GetAndroidApp
androidAppDownloadLink={'https://about.mattermost.com/mattermost-android-app'}
history={{push}}
location={{search: '?redirect_to=last_page'}}
/>
);
expect(push).not.toHaveBeenCalled();

const link = wrapper.find('.get-android-app__continue');
link.simulate('click');
expect(push).toHaveBeenCalledWith('last_page');
});

test('should redirect if the user chooses to stay in the browser. Redirect url param is not present', () => {
const push = jest.fn();
const wrapper = mountWithIntl(
<GetAndroidApp
androidAppDownloadLink={'https://about.mattermost.com/mattermost-android-app'}
history={{push}}
location={{search: ''}}
/>
);
expect(push).not.toHaveBeenCalled();

const link = wrapper.find('.get-android-app__continue');
link.simulate('click');
expect(push).toHaveBeenCalledWith('/');
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`components/GetIosApp should match snapshot 1`] = `
<div
className="get-app get-ios-app"
>
<h1
className="get-app__header"
>
<FormattedMessage
defaultMessage="Mattermost works best if you switch to our iPhone app"
id="get_app.iosHeader"
values={Object {}}
/>
</h1>
<hr />
<a
className="get-ios-app__app-store-link"
href="https://about.mattermost.com/mattermost-ios-app"
rel="noopener noreferrer"
>
<img
src="mockup.png"
/>
</a>
<img
className="get-app__screenshot"
src="mockup.png"
/>
<h2
className="get-ios-app__already-have-it"
>
<FormattedMessage
defaultMessage="Already have it?"
id="get_app.alreadyHaveIt"
values={Object {}}
/>
</h2>
<a
className="btn btn-primary get-ios-app__open-mattermost"
href="mattermost:https://"
>
<FormattedMessage
defaultMessage="Open Mattermost"
id="get_app.openMattermost"
values={Object {}}
/>
</a>
<span
className="get-app__continue-with-browser"
>
<FormattedMessage
defaultMessage="Or {link}"
id="get_app.continueWithBrowser"
values={
Object {
"link": <a
className="get-ios-app__continue"
onClick={[Function]}
>
<FormattedMessage
defaultMessage="continue with browser"
id="get_app.continueWithBrowserLink"
values={Object {}}
/>
</a>,
}
}
/>
</span>
</div>
`;
Loading

0 comments on commit 5f6f5d5

Please sign in to comment.