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('');
+    });
+});