From d41dad14a1c823652ea0a12c4698847b490a03a3 Mon Sep 17 00:00:00 2001 From: Jeff Avallone Date: Wed, 16 Jan 2019 20:09:04 -0500 Subject: [PATCH] Adding install prompt link in the header --- .../Header/__snapshots__/test.js.snap | 6 ++ src/components/Header/index.js | 4 + .../InstallPrompt/__snapshots__/test.js.snap | 16 ++++ src/components/InstallPrompt/index.js | 53 +++++++++++ src/components/InstallPrompt/test.js | 88 +++++++++++++++++++ src/globals.module.css | 8 ++ src/locales/en-AC.yaml | 2 + src/locales/en.yaml | 2 + 8 files changed, 179 insertions(+) create mode 100644 src/components/InstallPrompt/__snapshots__/test.js.snap create mode 100644 src/components/InstallPrompt/index.js create mode 100644 src/components/InstallPrompt/test.js diff --git a/src/components/Header/__snapshots__/test.js.snap b/src/components/Header/__snapshots__/test.js.snap index 432f7ea..36cf455 100644 --- a/src/components/Header/__snapshots__/test.js.snap +++ b/src/components/Header/__snapshots__/test.js.snap @@ -39,6 +39,9 @@ exports[`Header rendering 1`] = ` +
  • + +
  • @@ -87,6 +90,9 @@ exports[`Header rendering with no banner 1`] = `
  • +
  • + +
  • diff --git a/src/components/Header/index.js b/src/components/Header/index.js index 9ac7529..10c7558 100644 --- a/src/components/Header/index.js +++ b/src/components/Header/index.js @@ -6,6 +6,7 @@ import { withNamespaces, Trans } from 'react-i18next'; import GitlabIcon from 'react-feather/dist/icons/gitlab'; import LocaleSwitcher from 'components/LocaleSwitcher'; +import InstallPrompt from 'components/InstallPrompt'; import style from './style.module.css'; @@ -31,6 +32,9 @@ export const Header = ({ banner }) => ( Privacy Policy
  • +
  • + +
  • diff --git a/src/components/InstallPrompt/__snapshots__/test.js.snap b/src/components/InstallPrompt/__snapshots__/test.js.snap new file mode 100644 index 0000000..08d3585 --- /dev/null +++ b/src/components/InstallPrompt/__snapshots__/test.js.snap @@ -0,0 +1,16 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`InstallPrompt rendering 1`] = `""`; + +exports[`InstallPrompt rendering after an install prompt has been requested 1`] = `""`; + +exports[`InstallPrompt rendering after an install prompt has been requested 2`] = ` + + + Add to Home Screen + + +`; diff --git a/src/components/InstallPrompt/index.js b/src/components/InstallPrompt/index.js new file mode 100644 index 0000000..261c188 --- /dev/null +++ b/src/components/InstallPrompt/index.js @@ -0,0 +1,53 @@ +import React from 'react'; +import { withNamespaces, Trans } from 'react-i18next'; + +class InstallPrompt extends React.PureComponent { + state = { + installPrompt: null + } + + componentDidMount() { + window.addEventListener('beforeinstallprompt', this.handleInstallPrompt); + } + + componentWillUnmount() { + window.removeEventListener('beforeinstallprompt', this.handleInstallPrompt); + } + + handleInstallPrompt = event => { + this.setState({ + installPrompt: event + }); + } + + handleInstall = async event => { + event.preventDefault(); + + const { installPrompt } = this.state; + + try { + installPrompt.prompt(); + await installPrompt.userChoice; + } + catch { + // User cancelled install + } + + this.setState({ installPrompt: null }); + } + + render() { + const { installPrompt } = this.state; + + if (!installPrompt) { + return null; + } + + return + Add to Home Screen + ; + } +} + +export { InstallPrompt }; +export default withNamespaces()(InstallPrompt); diff --git a/src/components/InstallPrompt/test.js b/src/components/InstallPrompt/test.js new file mode 100644 index 0000000..e0fc673 --- /dev/null +++ b/src/components/InstallPrompt/test.js @@ -0,0 +1,88 @@ +import React from 'react'; +import { shallow } from 'enzyme'; + +import { InstallPrompt } from 'components/InstallPrompt'; + +describe('InstallPrompt', () => { + test('rendering', () => { + const component = shallow( + + ); + expect(component).toMatchSnapshot(); + }); + + test('rendering after an install prompt has been requested', () => { + const component = shallow( + + ); + expect(component).toMatchSnapshot(); + + component.instance().handleInstallPrompt({ + prompt: jest.fn() + }); + + expect(component).toMatchSnapshot(); + }); + + test('adding and removing event listener', () => { + jest.spyOn(window, 'addEventListener'); + jest.spyOn(window, 'removeEventListener'); + + const component = shallow( + + ); + const handleInstallPrompt = component.instance().handleInstallPrompt; + + expect(window.addEventListener).toHaveBeenCalledWith( + 'beforeinstallprompt', + handleInstallPrompt); + + component.unmount(); + + expect(window.removeEventListener).toHaveBeenCalledWith( + 'beforeinstallprompt', + handleInstallPrompt); + }); + + test('accepting install prompt', async () => { + const component = shallow( + + ); + const promptObj = { + prompt: jest.fn(), + userChoice: Promise.resolve() + }; + const eventObj = { preventDefault: jest.fn() }; + + component.instance().handleInstallPrompt(promptObj); + component.find('a').simulate('click', eventObj); + + // Allow async code to run + await new Promise(resolve => setTimeout(resolve)); + + expect(eventObj.preventDefault).toHaveBeenCalled(); + expect(promptObj.prompt).toHaveBeenCalled(); + expect(component.state('installPrompt')).toBeNull(); + }); + + test('rejecting install prompt', async () => { + const component = shallow( + + ); + const promptObj = { + prompt: jest.fn(), + userChoice: Promise.reject() + }; + const eventObj = { preventDefault: jest.fn() }; + + component.instance().handleInstallPrompt(promptObj); + component.find('a').simulate('click', eventObj); + + // Allow async code to run + await new Promise(resolve => setTimeout(resolve)); + + expect(eventObj.preventDefault).toHaveBeenCalled(); + expect(promptObj.prompt).toHaveBeenCalled(); + expect(component.state('installPrompt')).toBeNull(); + }); +}); diff --git a/src/globals.module.css b/src/globals.module.css index 61b8f7b..38bf9ab 100644 --- a/src/globals.module.css +++ b/src/globals.module.css @@ -46,6 +46,10 @@ padding-right: var(--list-separator-width); } + & li:empty { + display: none; + } + & li:before { content: '//'; padding: 0 0.5rem; @@ -71,6 +75,10 @@ padding-left: var(--list-separator-width); } + & li:empty { + display: none; + } + & li:after { content: '//'; padding: 0 0.5rem; diff --git a/src/locales/en-AC.yaml b/src/locales/en-AC.yaml index be26725..16f5bc2 100644 --- a/src/locales/en-AC.yaml +++ b/src/locales/en-AC.yaml @@ -65,3 +65,5 @@ DOWNLOAD PNG "Loading...": | LOADING... +"Add to Home Screen": | + ADD TO HOME SCREEN diff --git a/src/locales/en.yaml b/src/locales/en.yaml index b185462..19b5905 100644 --- a/src/locales/en.yaml +++ b/src/locales/en.yaml @@ -65,3 +65,5 @@ Download PNG "Loading...": | Loading... +"Add to Home Screen": | + Add to Home Screen