diff --git a/__tests__/src/components/WindowTopBar.test.js b/__tests__/src/components/WindowTopBar.test.js index 86cc567291eeb31e5d1136fd1663c6109df3e5d8..8782060b6c8271bb2c90da9ebdf0cc153a1ad3db 100644 --- a/__tests__/src/components/WindowTopBar.test.js +++ b/__tests__/src/components/WindowTopBar.test.js @@ -1,50 +1,74 @@ import React from 'react'; import { shallow } from 'enzyme'; -import WindowTopBar from '../../../src/components/WindowTopBar'; + +import Typography from '@material-ui/core/Typography'; +import Button from '@material-ui/core/Button'; +import IconButton from '@material-ui/core/IconButton'; +import MenuIcon from '@material-ui/icons/Menu'; +import Toolbar from '@material-ui/core/Toolbar'; + +import WindowTopMenuButton from '../../../src/containers/WindowTopMenuButton'; +import WindowTopBarButtons from '../../../src/containers/WindowTopBarButtons'; import WindowIcon from '../../../src/containers/WindowIcon'; +import WindowTopBar from '../../../src/components/WindowTopBar'; -const manifestFixture = { - manifestation: { - getLabel: () => [{ value: 'Fixture Label' }], - }, -}; +/** create wrapper */ +function createWrapper(props) { + return shallow( + <WindowTopBar + manifestTitle="awesome manifest" + windowId="xyz" + classes={{}} + t={str => str} + removeWindow={() => {}} + toggleWindowSideBar={() => {}} + {...props} + />, + ).dive(); // unwrap HOC created by withStyles() +} describe('WindowTopBar', () => { - let topBar; - let mockRemoveWindow; - let mockToggleWindowSideBar; - - beforeEach(() => { - mockRemoveWindow = jest.fn(); - mockToggleWindowSideBar = jest.fn(); - topBar = shallow( - <WindowTopBar - manifest={manifestFixture} - windowId="foo" - removeWindow={mockRemoveWindow} - toggleWindowSideBar={mockToggleWindowSideBar} - classes={{}} - t={key => key} - />, - ).dive(); + it('renders all needed elements', () => { + const wrapper = createWrapper(); + expect(wrapper.find(Toolbar).length).toBe(1); + expect(wrapper.find(IconButton).length).toBe(1); + expect(wrapper.find(MenuIcon).length).toBe(1); + expect(wrapper.find(WindowIcon).length).toBe(1); + expect(wrapper.find(Typography).length).toBe(1); + expect(wrapper.find(WindowTopBarButtons).length).toBe(1); + expect(wrapper.find(WindowTopMenuButton).length).toBe(1); + expect(wrapper.find(Button).length).toBe(1); + }); + + it('passes correct props to <IconButton/>', () => { + const toggleWindowSideBar = jest.fn(); + const wrapper = createWrapper({ toggleWindowSideBar }); + expect(wrapper.find(IconButton).first().props().onClick).toBe(toggleWindowSideBar); + }); + + it('passes correct props to <WindowIcon/>', () => { + const wrapper = createWrapper(); + expect(wrapper.find(WindowIcon).first().props().windowId).toBe('xyz'); }); - it('renders wrapping element', () => { - expect(topBar.find('.mirador-window-top-bar').length).toBe(1); + it('passes correct props to <Typography/>', () => { + const wrapper = createWrapper(); + expect(wrapper.find(Typography).first().render().text()).toBe('awesome manifest'); }); - it('provides removeWindow() function to the close button component', () => { - expect(topBar.find('.mirador-window-close').prop('onClick')) - .toBe(mockRemoveWindow); + it('passes correct props to <WindowTopBarButtons/>', () => { + const wrapper = createWrapper(); + expect(wrapper.find(WindowTopBarButtons).first().props().windowId).toBe('xyz'); }); - it('renders a window icon', () => { - expect(topBar.find(WindowIcon).length).toBe(1); + it('passe correct props to <WindowTopMenuButton', () => { + const wrapper = createWrapper(); + expect(wrapper.find(WindowTopMenuButton).first().props().windowId).toBe('xyz'); }); - it('calls the toggleWindowSideBar prop when the menu IconButton is clicked', () => { - topBar.find('WithStyles(IconButton)').simulate('click'); - expect(mockToggleWindowSideBar).toHaveBeenCalledTimes(1); - expect(mockToggleWindowSideBar).toHaveBeenCalledWith('foo'); + it('passes correct props to <Button/>', () => { + const removeWindow = jest.fn(); + const wrapper = createWrapper({ removeWindow }); + expect(wrapper.find(Button).first().props().onClick).toBe(removeWindow); }); }); diff --git a/__tests__/src/selectors/index.test.js b/__tests__/src/selectors/index.test.js index f3b3d48e832b087e0014e6e361accd2a5b10f9d4..4b0fe519feb18d6463ca9de74e873c60feb9188e 100644 --- a/__tests__/src/selectors/index.test.js +++ b/__tests__/src/selectors/index.test.js @@ -1,10 +1,11 @@ import manifesto from 'manifesto.js'; -import manifestFixture from '../../fixtures/version-2/001.json'; +import manifestFixture001 from '../../fixtures/version-2/001.json'; import { getWindowManifest, getManifestLogo, getManifestCanvases, getThumbnailNavigationPosition, + getManifestTitle, } from '../../../src/state/selectors'; @@ -44,9 +45,9 @@ describe('getWindowManifest()', () => { describe('getManifestLogo()', () => { it('should return manifest logo id', () => { - const manifest = { manifestation: manifesto.create(manifestFixture) }; + const manifest = { manifestation: manifesto.create(manifestFixture001) }; const received = getManifestLogo(manifest); - expect(received).toEqual(manifestFixture.logo['@id']); + expect(received).toEqual(manifestFixture001.logo['@id']); }); it('should return null if manifest has no logo', () => { @@ -64,7 +65,7 @@ describe('getManifestCanvases', () => { }); it('returns canvases from the manifest', () => { - const manifest = { manifestation: manifesto.create(manifestFixture) }; + const manifest = { manifestation: manifesto.create(manifestFixture001) }; const received = getManifestCanvases(manifest); expect(received.length).toBe(1); expect(received[0].id).toBe('https://iiif.bodleian.ox.ac.uk/iiif/canvas/9cca8fdd-4a61-4429-8ac1-f648764b4d6d.json'); @@ -94,3 +95,22 @@ describe('getThumbnailNavigationPosition', () => { expect(received).toBeUndefined(); }); }); + +describe('getManifestTitle', () => { + it('should return manifest title', () => { + const manifest = { manifestation: manifesto.create(manifestFixture001) }; + const received = getManifestTitle(manifest); + expect(received).toBe('Bodleian Library Human Freaks 2 (33)'); + }); + + it('should return undefined if manifest undefined', () => { + const received = getManifestTitle(undefined); + expect(received).toBeUndefined(); + }); + + it('should return undefined if no manifestation', () => { + const manifest = {}; + const received = getManifestTitle(manifest); + expect(received).toBeUndefined(); + }); +}); diff --git a/src/components/WindowTopBar.js b/src/components/WindowTopBar.js index 46a52d0aab63a07c41a398ef4b49c0a895eb2600..a7200e9929994a389c9c994a9f3e07f7afed4730 100644 --- a/src/components/WindowTopBar.js +++ b/src/components/WindowTopBar.js @@ -17,39 +17,26 @@ import ns from '../config/css-ns'; * WindowTopBar */ class WindowTopBar extends Component { - /** - * titleContent - * - * @return {String} - */ - titleContent() { - const { manifest } = this.props; - if (manifest && manifest.manifestation) { - return manifest.manifestation.getLabel().map(label => label.value)[0]; - } - return ''; - } - /** * render * @return */ render() { const { - removeWindow, windowId, classes, toggleWindowSideBar, t, + removeWindow, windowId, classes, toggleWindowSideBar, t, manifestTitle, } = this.props; return ( <Toolbar disableGutters className={classNames(classes.reallyDense, ns('window-top-bar'))} variant="dense"> <IconButton aria-label={t('toggleWindowSideBar')} color="inherit" - onClick={() => toggleWindowSideBar(windowId)} + onClick={toggleWindowSideBar} > <MenuIcon /> </IconButton> <WindowIcon windowId={windowId} /> <Typography variant="h3" noWrap color="inherit" className={classes.typographyBody}> - {this.titleContent()} + {manifestTitle} </Typography> <WindowTopBarButtons windowId={windowId} /> <WindowTopMenuButton className={ns('window-menu-btn')} windowId={windowId} /> @@ -60,17 +47,16 @@ class WindowTopBar extends Component { } WindowTopBar.propTypes = { - manifest: PropTypes.object, // eslint-disable-line react/forbid-prop-types + manifestTitle: PropTypes.string, removeWindow: PropTypes.func.isRequired, windowId: PropTypes.string.isRequired, classes: PropTypes.object.isRequired, // eslint-disable-line react/forbid-prop-types - toggleWindowSideBar: PropTypes.func, + toggleWindowSideBar: PropTypes.func.isRequired, t: PropTypes.func, }; WindowTopBar.defaultProps = { - manifest: null, - toggleWindowSideBar: () => {}, + manifestTitle: '', t: key => key, }; diff --git a/src/containers/WindowTopBar.js b/src/containers/WindowTopBar.js index 0bc54458ae7b4ef4712ece6e2f422459c746b68e..1d193b101f5f425ea21d5de7a37248d3509ab0b4 100644 --- a/src/containers/WindowTopBar.js +++ b/src/containers/WindowTopBar.js @@ -3,20 +3,26 @@ import { connect } from 'react-redux'; import { withNamespaces } from 'react-i18next'; import * as actions from '../state/actions'; import miradorWithPlugins from '../lib/miradorWithPlugins'; +import { getWindowManifest, getManifestTitle } from '../state/selectors'; import WindowTopBar from '../components/WindowTopBar'; +/** mapStateToProps */ +const mapStateToProps = (state, { windowId }) => ({ + manifestTitle: getManifestTitle(getWindowManifest(state, windowId)), +}); + /** * mapDispatchToProps - used to hook up connect to action creators * @memberof ManifestListItem * @private */ -const mapDispatchToProps = (dispatch, props) => ({ - removeWindow: () => dispatch(actions.removeWindow(props.windowId)), - toggleWindowSideBar: () => dispatch(actions.toggleWindowSideBar(props.windowId)), +const mapDispatchToProps = (dispatch, { windowId }) => ({ + removeWindow: () => dispatch(actions.removeWindow(windowId)), + toggleWindowSideBar: () => dispatch(actions.toggleWindowSideBar(windowId)), }); const enhance = compose( - connect(null, mapDispatchToProps), + connect(mapStateToProps, mapDispatchToProps), miradorWithPlugins, withNamespaces(), // further HOC go here diff --git a/src/state/selectors/index.js b/src/state/selectors/index.js index 7cc2c24eca30ff1640fd5ac163fb46ee0975b5a5..1c46754826edf65274a15be24fd347d8548db66d 100644 --- a/src/state/selectors/index.js +++ b/src/state/selectors/index.js @@ -43,3 +43,14 @@ export function getThumbnailNavigationPosition(state, windowId) { return state.windows[windowId] && state.windows[windowId].thumbnailNavigationPosition; } + +/** +* Return manifest title +* @param {object} manifest +* @return {String} +*/ +export function getManifestTitle(manifest) { + return manifest + && manifest.manifestation + && manifest.manifestation.getLabel().map(label => label.value)[0]; +}