diff --git a/src/containers/sb-file-uploader.jsx b/src/containers/sb-file-uploader.jsx index 0fcf90b0291e5faf0987da61c7fbb94090449021..88903526169ffce308eac9c9ac7512a1340366ff 100644 --- a/src/containers/sb-file-uploader.jsx +++ b/src/containers/sb-file-uploader.jsx @@ -47,6 +47,13 @@ class SBFileUploader extends React.Component { 'handleClick' ]); } + getProjectTitleFromFilename (fileInputFilename) { + if (!fileInputFilename) return ''; + // only parse title from files like "filename.sb2" or "filename.sb3" + const matches = fileInputFilename.match(/^(.*)\.sb[23]$/); + if (!matches) return ''; + return matches[1].substring(0, 100); // truncate project title to max 100 chars + } // called when user has finished selecting a file to upload handleChange (e) { // Remove the hash if any (without triggering a hash change event or a reload) @@ -76,15 +83,8 @@ class SBFileUploader extends React.Component { if (thisFileInput.files) { // Don't attempt to load if no file was selected this.props.onLoadingStarted(); reader.readAsArrayBuffer(thisFileInput.files[0]); - // extract the title from the file and set it as current project title - if (thisFileInput.files[0].name) { - // only parse title from files like "filename.sb2" or "filename.sb3" - const matches = thisFileInput.files[0].name.match(/^(.*)\.sb[23]$/); - if (matches) { - const truncatedProjectTitle = matches[1].substring(0, 100); - this.props.onUpdateProjectTitle(truncatedProjectTitle); - } - } + const uploadedProjectTitle = this.getProjectTitleFromFilename(thisFileInput.files[0].name); + this.props.onUpdateProjectTitle(uploadedProjectTitle); } } handleClick () { @@ -137,7 +137,13 @@ const mapDispatchToProps = dispatch => ({ } }); +// Allow incoming props to override redux-provided props. Used to mock in tests. +const mergeProps = (stateProps, dispatchProps, ownProps) => Object.assign( + {}, stateProps, dispatchProps, ownProps +); + export default connect( mapStateToProps, - mapDispatchToProps + mapDispatchToProps, + mergeProps )(injectIntl(SBFileUploader)); diff --git a/test/unit/containers/sb-file-uploader.test.jsx b/test/unit/containers/sb-file-uploader.test.jsx new file mode 100644 index 0000000000000000000000000000000000000000..2bdd908155e668292bbfbe80c42cd5d8e4e93d42 --- /dev/null +++ b/test/unit/containers/sb-file-uploader.test.jsx @@ -0,0 +1,67 @@ +import React from 'react'; +import {Provider} from 'react-redux'; +import {mountWithIntl, shallowWithIntl, componentWithIntl} from '../../helpers/intl-helpers.jsx'; +import configureStore from 'redux-mock-store'; +import SBFileUploader from '../../../src/containers/sb-file-uploader.jsx'; + +describe('SBFileUploader', () => { + const mockStore = configureStore(); + let onLoadingFinished; + let onLoadingStarted; + let onUpdateProjectTitle; + let store; + + // Wrap this in a function so it gets test specific states and can be reused. + const getContainer = function () { + return ( + <SBFileUploader + store={store} + onLoadingFinished={onLoadingFinished} + onLoadingStarted={onLoadingStarted} + onUpdateProjectTitle={onUpdateProjectTitle} + > + {(renderFileInput, loadProject) => ( + <div + onClick={loadProject} + /> + )} + </SBFileUploader> + ); + }; + + beforeEach(() => { + store = mockStore({ + scratchGui: { + projectState: {} + } + }); + onUpdateProjectTitle = jest.fn(); + onLoadingFinished = jest.fn(); + onLoadingStarted = jest.fn(); + }); + + test('correctly sets title with .sb3 filename', () => { + const component = mountWithIntl(getContainer()); + const instance = component.instance(); + const projectName = instance.getProjectTitleFromFilename('my project is great.sb3'); + expect(projectName).toBe('my project is great'); + }); + + test('correctly sets title with .sb3 filename', () => { + const component = componentWithIntl(getContainer()); + const projectName = component.getProjectTitleFromFilename('my project is great.sb3'); + expect(projectName).toBe('my project is great'); + }); + + test('sets blank title with .sb filename', () => { + const component = componentWithIntl(getContainer()); + const projectName = component.getProjectTitleFromFilename('my project is great.sb'); + expect(projectName).toBe(''); + }); + + test('sets blank title with filename with no extension', () => { + const component = componentWithIntl(getContainer()); + const projectName = component.getProjectTitleFromFilename('my project is great'); + expect(projectName).toBe(''); + }); +});