diff --git a/.travis.yml b/.travis.yml
index 33c4de439700bd708bdd20c6e783e63d97992dc0..13ccbc30b19e7a92ed2c25a39bf0f5037daa651a 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -11,12 +11,9 @@ node_js:
 cache:
   directories:
   - node_modules
-env:
-  global:
-  - NODE_ENV=production
 install:
-- npm --production=false install
-- npm --production=false update
+- npm install
+- npm update
 before_deploy:
 - npm --no-git-tag-version version 0.1.0-prerelease.$(date +%Y%m%d%H%M%S)
 - git config --global user.email $(git log --pretty=format:"%ae" -n1)
@@ -39,4 +36,3 @@ deploy:
   skip_cleanup: true
   email: $NPM_EMAIL
   api_key: $NPM_TOKEN
-
diff --git a/package.json b/package.json
index 8399f51fced1d1f2b28f9be56fda55bd3a88e953..344cac12623e1879a588c09d6d3d543957ff2ebc 100644
--- a/package.json
+++ b/package.json
@@ -10,7 +10,7 @@
     "i18n:msgs": "node ./scripts/generate-locale-messages.js",
     "i18n:src": "babel src > tmp.js && rimraf tmp.js && ./scripts/build-i18n-source.js ./translations/messages/ ./translations/",
     "start": "npm run i18n:msgs && webpack-dev-server",
-    "test": "npm run test:lint && npm run build && npm run test:unit && npm run test:integration",
+    "test": "npm run test:lint && npm run test:unit && NODE_ENV=production npm run build && npm run test:integration",
     "test:integration": "jest --runInBand test[\\\\/]integration",
     "test:lint": "eslint . --ext .js,.jsx",
     "test:unit": "jest test[\\\\/]unit",
@@ -24,8 +24,8 @@
     "url": "git+ssh://git@github.com/LLK/scratch-gui.git"
   },
   "peerDependencies": {
-    "react": "^15.6.1",
-    "react-dom": "^15.6.1"
+    "react": "^16.0.0",
+    "react-dom": "^16.0.0"
   },
   "devDependencies": {
     "autoprefixer": "^7.1.3",
@@ -43,7 +43,8 @@
     "classnames": "2.2.5",
     "copy-webpack-plugin": "^4.0.1",
     "css-loader": "^0.28.7",
-    "enzyme": "^2.8.2",
+    "enzyme": "^3.1.0",
+    "enzyme-adapter-react-16": "1.0.1",
     "eslint": "^4.7.1",
     "eslint-config-scratch": "^5.0.0",
     "eslint-plugin-import": "^2.7.0",
@@ -65,18 +66,19 @@
     "postcss-loader": "^2.0.5",
     "postcss-simple-vars": "^4.0.0",
     "prop-types": "^15.5.10",
-    "react": "15.6.1",
-    "react-contextmenu": "2.7.0",
-    "react-dom": "15.6.1",
+    "raf": "^3.4.0",
+    "react": "16.0.0",
+    "react-contextmenu": "2.8.0",
+    "react-dom": "16.0.0",
     "react-draggable": "3.0.3",
     "react-intl": "2.4.0",
     "react-intl-redux": "0.6.0",
-    "react-modal": "2.3.1",
+    "react-modal": "3.0.0",
     "react-redux": "5.0.6",
-    "react-responsive": "1.3.4",
+    "react-responsive": "2.0.0",
     "react-style-proptype": "3.0.0",
     "react-tabs": "2.1.0",
-    "react-test-renderer": "^15.5.4",
+    "react-test-renderer": "16.0.0",
     "redux": "3.7.0",
     "redux-mock-store": "^1.2.3",
     "redux-throttle": "0.1.1",
@@ -98,6 +100,10 @@
     "xhr": "2.4.0"
   },
   "jest": {
+    "setupFiles": [
+      "raf/polyfill",
+      "<rootDir>/test/helpers/enzyme-setup.js"
+    ],
     "testPathIgnorePatterns": [
       "src/test.js"
     ],
diff --git a/test/helpers/enzyme-setup.js b/test/helpers/enzyme-setup.js
new file mode 100644
index 0000000000000000000000000000000000000000..5374f679d38ef65d773fdc12133032aae63c37b5
--- /dev/null
+++ b/test/helpers/enzyme-setup.js
@@ -0,0 +1,4 @@
+import Enzyme from 'enzyme';
+import Adapter from 'enzyme-adapter-react-16';
+
+Enzyme.configure({adapter: new Adapter()});
diff --git a/test/unit/containers/sound-editor.test.jsx b/test/unit/containers/sound-editor.test.jsx
index 325488a250249f9a426926fb56ab367b519b4cae..63199ef01e6f6fffebd49ea2cb0397d1dbb47887 100644
--- a/test/unit/containers/sound-editor.test.jsx
+++ b/test/unit/containers/sound-editor.test.jsx
@@ -63,7 +63,7 @@ describe('Sound Editor Container', () => {
                 store={store}
             />
         );
-        const component = wrapper.find(SoundEditorComponent);
+        let component = wrapper.find(SoundEditorComponent);
         // Ensure rendering doesn't start playing any sounds
         expect(mockAudioBufferPlayer.instance.play.mock.calls).toEqual([]);
         expect(mockAudioBufferPlayer.instance.stop.mock.calls).toEqual([]);
@@ -73,9 +73,13 @@ describe('Sound Editor Container', () => {
 
         // Mock the audio buffer player calling onUpdate
         mockAudioBufferPlayer.instance.onUpdate(0.5);
+        wrapper.update();
+        component = wrapper.find(SoundEditorComponent);
         expect(component.props().playhead).toEqual(0.5);
 
         component.props().onStop();
+        wrapper.update();
+        component = wrapper.find(SoundEditorComponent);
         expect(mockAudioBufferPlayer.instance.stop).toHaveBeenCalled();
         expect(component.props().playhead).toEqual(null);
     });
@@ -87,13 +91,17 @@ describe('Sound Editor Container', () => {
                 store={store}
             />
         );
-        const component = wrapper.find(SoundEditorComponent);
+        let component = wrapper.find(SoundEditorComponent);
 
         component.props().onActivateTrim();
+        wrapper.update();
+        component = wrapper.find(SoundEditorComponent);
         expect(component.props().trimStart).not.toEqual(null);
         expect(component.props().trimEnd).not.toEqual(null);
 
         component.props().onActivateTrim();
+        wrapper.update();
+        component = wrapper.find(SoundEditorComponent);
         expect(vm.updateSoundBuffer).toHaveBeenCalled();
         expect(component.props().trimStart).toEqual(null);
         expect(component.props().trimEnd).toEqual(null);
@@ -223,7 +231,7 @@ describe('Sound Editor Container', () => {
                 store={store}
             />
         );
-        const component = wrapper.find(SoundEditorComponent);
+        let component = wrapper.find(SoundEditorComponent);
         // Undo and redo should be disabled initially
         expect(component.prop('canUndo')).toEqual(false);
         expect(component.prop('canRedo')).toEqual(false);
@@ -232,27 +240,34 @@ describe('Sound Editor Container', () => {
         component.props().onActivateTrim(); // Activate trimming
         component.props().onActivateTrim(); // Submit new samples by calling again
         wrapper.update();
+        component = wrapper.find(SoundEditorComponent);
         expect(component.prop('canUndo')).toEqual(true);
         expect(component.prop('canRedo')).toEqual(false);
 
         // Undoing should make it possible to redo and not possible to undo again
         component.props().onUndo();
         wrapper.update();
+        component = wrapper.find(SoundEditorComponent);
         expect(component.prop('canUndo')).toEqual(false);
         expect(component.prop('canRedo')).toEqual(true);
 
         // Redoing should make it possible to undo and not possible to redo again
         component.props().onRedo();
         wrapper.update();
+        component = wrapper.find(SoundEditorComponent);
         expect(component.prop('canUndo')).toEqual(true);
         expect(component.prop('canRedo')).toEqual(false);
 
         // New submission should clear the redo stack
         component.props().onUndo(); // Undo to go back to a state where redo is enabled
         wrapper.update();
+        component = wrapper.find(SoundEditorComponent);
         expect(component.prop('canRedo')).toEqual(true);
         component.props().onActivateTrim(); // Activate trimming
         component.props().onActivateTrim(); // Submit new samples by calling again
+
+        wrapper.update();
+        component = wrapper.find(SoundEditorComponent);
         expect(component.prop('canRedo')).toEqual(false);
     });
 });
diff --git a/test/unit/util/project-loader-hoc.test.jsx b/test/unit/util/project-loader-hoc.test.jsx
index 964894c4369441e328e6e365f97631d3736f15b6..d61352d3630c51a81c5da5d612da89ab65038a2a 100644
--- a/test/unit/util/project-loader-hoc.test.jsx
+++ b/test/unit/util/project-loader-hoc.test.jsx
@@ -45,7 +45,7 @@ describe('ProjectLoaderHOC', () => {
         const before = mounted.find('div').text();
         ProjectLoader.load = jest.fn((id, cb) => cb(null, id));
         window.location.hash = `#winning`;
-        mounted.node.updateProject();
+        mounted.instance().updateProject();
         expect(mounted.find('div').text()).not.toEqual(before);
     });
 });