diff --git a/src/components/navigation/www/navigation.jsx b/src/components/navigation/www/navigation.jsx index 90d34bcad..98f68cead 100644 --- a/src/components/navigation/www/navigation.jsx +++ b/src/components/navigation/www/navigation.jsx @@ -18,7 +18,6 @@ const LoginDropdown = require('../../login/login-dropdown.jsx'); const CanceledDeletionModal = require('../../login/canceled-deletion-modal.jsx'); const NavigationBox = require('../base/navigation.jsx'); const Registration = require('../../registration/registration.jsx'); -const Scratch3Registration = require('../../registration/scratch3-registration.jsx'); const AccountNav = require('./accountnav.jsx'); require('./navigation.scss'); @@ -28,6 +27,7 @@ class Navigation extends React.Component { super(props); bindAll(this, [ 'getProfileUrl', + 'handleClickRegistration', 'handleSearchSubmit' ]); this.state = { @@ -78,6 +78,13 @@ class Navigation extends React.Component { if (!this.props.user) return; return `/users/${this.props.user.username}/`; } + handleClickRegistration (event) { + if (this.props.useScratch3Registration) { + this.props.navigateToRegistration(event); + } else { + this.props.handleOpenRegistration(event); + } + } handleSearchSubmit (formData) { let targetUrl = '/search/projects'; if (formData.q) { @@ -189,9 +196,12 @@ class Navigation extends React.Component { className="link right join" key="join" > + {/* there's no css class registrationLink -- this is + just to make the link findable for testing */} @@ -214,18 +224,10 @@ class Navigation extends React.Component { ]) : [] } - {this.props.registrationOpen && ( - this.props.useScratch3Registration ? ( - - ) : ( - - ) + {this.props.registrationOpen && !this.props.useScratch3Registration && ( + )} @@ -243,6 +245,7 @@ Navigation.propTypes = { handleToggleAccountNav: PropTypes.func, handleToggleLoginOpen: PropTypes.func, intl: intlShape, + navigateToRegistration: PropTypes.func, permissions: PropTypes.shape({ admin: PropTypes.bool, social: PropTypes.bool, @@ -305,14 +308,24 @@ const mapDispatchToProps = dispatch => ({ event.preventDefault(); dispatch(navigationActions.toggleLoginOpen()); }, + navigateToRegistration: event => { + event.preventDefault(); + navigationActions.navigateToRegistration(); + }, setMessageCount: newCount => { dispatch(messageCountActions.setCount(newCount)); } }); +// Allow incoming props to override redux-provided props. Used to mock in tests. +const mergeProps = (stateProps, dispatchProps, ownProps) => Object.assign( + {}, stateProps, dispatchProps, ownProps +); + const ConnectedNavigation = connect( mapStateToProps, - mapDispatchToProps + mapDispatchToProps, + mergeProps )(Navigation); module.exports = injectIntl(ConnectedNavigation); diff --git a/src/redux/navigation.js b/src/redux/navigation.js index a7ff091a8..591833208 100644 --- a/src/redux/navigation.js +++ b/src/redux/navigation.js @@ -92,6 +92,10 @@ module.exports.setSearchTerm = searchTerm => ({ searchTerm: searchTerm }); +module.exports.navigateToRegistration = () => { + window.location = '/join'; +}; + module.exports.handleCompleteRegistration = createProject => (dispatch => { if (createProject) { window.location = '/projects/editor/?tutorial=getStarted'; diff --git a/test/unit/components/navigation.test.jsx b/test/unit/components/navigation.test.jsx new file mode 100644 index 000000000..0072dc4cd --- /dev/null +++ b/test/unit/components/navigation.test.jsx @@ -0,0 +1,70 @@ +const React = require('react'); +const {shallowWithIntl} = require('../../helpers/intl-helpers.jsx'); +import configureStore from 'redux-mock-store'; +const Navigation = require('../../../src/components/navigation/www/navigation.jsx'); +const sessionActions = require('../../../src/redux/session.js'); + +describe('Navigation', () => { + const mockStore = configureStore(); + let store; + + beforeEach(() => { + store = null; + }); + + const getNavigationWrapper = props => { + const wrapper = shallowWithIntl( + + , {context: {store}} + ); + return wrapper + .dive() // unwrap redux connect(injectIntl(JoinFlow)) + .dive(); // unwrap injectIntl(JoinFlow) + }; + + test('when using old join flow, clicking Join Scratch attemps to open registration', () => { + store = mockStore({ + navigation: { + useScratch3Registration: false + }, + session: { + status: sessionActions.Status.FETCHED + }, + messageCount: { + messageCount: 0 + } + }); + const props = { + handleOpenRegistration: jest.fn() + }; + const navWrapper = getNavigationWrapper(props); + const navInstance = navWrapper.instance(); + + navWrapper.find('a.registrationLink').simulate('click'); + expect(navInstance.props.handleOpenRegistration).toHaveBeenCalled(); + }); + + test('when using new join flow, clicking Join Scratch attemps to navigate to registration', () => { + store = mockStore({ + navigation: { + useScratch3Registration: true + }, + session: { + status: sessionActions.Status.FETCHED + }, + messageCount: { + messageCount: 0 + } + }); + const props = { + navigateToRegistration: jest.fn() + }; + const navWrapper = getNavigationWrapper(props); + const navInstance = navWrapper.instance(); + + navWrapper.find('a.registrationLink').simulate('click'); + expect(navInstance.props.navigateToRegistration).toHaveBeenCalled(); + }); +});