diff --git a/src/pages/__snapshots__/index.test.js.snap b/src/pages/__snapshots__/index.test.js.snap index 3a71349..dd7b1c0 100644 --- a/src/pages/__snapshots__/index.test.js.snap +++ b/src/pages/__snapshots__/index.test.js.snap @@ -42,6 +42,94 @@ exports[`Index Page rendering 1`] = ` `; +exports[`Index Page rendering after an install prompt has been requested 1`] = ` + + + + + +`; + +exports[`Index Page rendering after an install prompt has been requested 2`] = ` + + + + + + +`; + exports[`Index Page rendering with an expression on the URL 1`] = ` diff --git a/src/pages/index.js b/src/pages/index.js index a215ea4..cb72eee 100644 --- a/src/pages/index.js +++ b/src/pages/index.js @@ -6,6 +6,7 @@ import URLSearchParams from '@ungap/url-search-params'; import Metadata from 'components/Metadata'; import Message from 'components/Message'; import App from 'components/App'; +import InstallPrompt from 'components/InstallPrompt'; export const query = graphql` query IndexPageQuery { @@ -40,6 +41,10 @@ const readURLHash = (location, defaultSyntax) => { }; class IndexPage extends React.PureComponent { + state={ + installPrompt: null + } + static propTypes = { location: PropTypes.object, data: PropTypes.shape({ @@ -55,7 +60,37 @@ class IndexPage extends React.PureComponent { }) } + componentDidMount() { + window.addEventListener('beforeinstallprompt', this.handleInstallPrompt); + } + + componentWillUnmount() { + window.removeEventListener('beforeinstallprompt', this.handleInstallPrompt); + } + + handleInstallPrompt = event => { + event.preventDefault(); + + this.setState({ + installPrompt: event + }); + } + + handleInstallReject = () => { + this.setState({ installPrompt: null }); + } + + handleInstallAccept = () => { + const { installPrompt } = this.state; + + this.setState({ installPrompt: null }); + installPrompt.prompt(); + } + render() { + const { + installPrompt + } = this.state; const { location, data: { site: { siteMetadata } } @@ -75,6 +110,9 @@ class IndexPage extends React.PureComponent { + { installPrompt && } ; } } diff --git a/src/pages/index.test.js b/src/pages/index.test.js index 6c909f1..473e72a 100644 --- a/src/pages/index.test.js +++ b/src/pages/index.test.js @@ -32,4 +32,73 @@ describe('Index Page', () => { ); expect(component).toMatchSnapshot(); }); + + test('rendering after an install prompt has been requested', () => { + const component = shallow( + + ); + expect(component).toMatchSnapshot(); + + component.instance().handleInstallPrompt({ + preventDefault: jest.fn(), + prompt: jest.fn() + }); + + expect(component).toMatchSnapshot(); + }); + + test('removing event listener on umount', () => { + jest.spyOn(window, 'addEventListener'); + jest.spyOn(window, 'removeEventListener'); + + const component = shallow( + + ); + + expect(window.addEventListener).toHaveBeenCalledWith( + 'beforeinstallprompt', + expect.any(Function)); + + component.unmount(); + + expect(window.removeEventListener).toHaveBeenCalledWith( + 'beforeinstallprompt', + expect.any(Function)); + }); + + test('rejecting install prompt', () => { + const component = shallow( + + ); + const instance = component.instance(); + const installEvent = { + preventDefault: jest.fn(), + prompt: jest.fn() + }; + + instance.handleInstallPrompt(installEvent); + + instance.handleInstallReject(); + + expect(installEvent.prompt).not.toHaveBeenCalled(); + expect(component.state('installPrompt')).toEqual(null); + }); + + test('accepting install prompt', () => { + const component = shallow( + + ); + const instance = component.instance(); + const installEvent = { + preventDefault: jest.fn(), + prompt: jest.fn() + }; + + instance.handleInstallPrompt(installEvent); + + instance.handleInstallAccept(); + + expect(installEvent.prompt).toHaveBeenCalled(); + expect(component.state('installPrompt')).toEqual(null); + }); });