From b9c6f3fb44200e134fee8c545a6cff47625d2d1b Mon Sep 17 00:00:00 2001 From: Paul Kaplan Date: Mon, 31 Jul 2017 15:22:17 -0400 Subject: [PATCH 1/2] Add trimming and tests to the sound editor --- .../audio-trimmer/audio-trimmer.jsx | 70 ++-- src/components/sound-editor/icon--trim.svg | 1 + src/components/sound-editor/sound-editor.css | 21 +- src/components/sound-editor/sound-editor.jsx | 55 +++- src/containers/audio-trimmer.jsx | 2 + src/containers/sound-editor.jsx | 61 +++- test/__mocks__/audio-buffer-player.js | 12 + .../__snapshots__/sound-editor.test.jsx.snap | 311 ++++++++++++++++++ test/unit/components/sound-editor.test.jsx | 63 ++++ test/unit/containers/sound-editor.test.jsx | 93 ++++++ 10 files changed, 631 insertions(+), 58 deletions(-) create mode 100644 src/components/sound-editor/icon--trim.svg create mode 100644 test/__mocks__/audio-buffer-player.js create mode 100644 test/unit/components/__snapshots__/sound-editor.test.jsx.snap create mode 100644 test/unit/components/sound-editor.test.jsx create mode 100644 test/unit/containers/sound-editor.test.jsx diff --git a/src/components/audio-trimmer/audio-trimmer.jsx b/src/components/audio-trimmer/audio-trimmer.jsx index d414f3ae2..fc216063a 100644 --- a/src/components/audio-trimmer/audio-trimmer.jsx +++ b/src/components/audio-trimmer/audio-trimmer.jsx @@ -10,23 +10,25 @@ const AudioTrimmer = props => ( className={styles.absolute} ref={props.containerRef} > - - - - - - - - + {props.trimStart !== null ? ( + + + + + + + + + - + ) : null} {props.playhead ? ( ( /> ) : null} - - - - - - - - + {props.trimEnd !== null ? ( + + + + + + + + + - + ) : null } ); @@ -63,8 +67,8 @@ AudioTrimmer.propTypes = { onTrimEndMouseDown: PropTypes.func.isRequired, onTrimStartMouseDown: PropTypes.func.isRequired, playhead: PropTypes.number, - trimEnd: PropTypes.number.isRequired, - trimStart: PropTypes.number.isRequired + trimEnd: PropTypes.number, + trimStart: PropTypes.number }; export default AudioTrimmer; diff --git a/src/components/sound-editor/icon--trim.svg b/src/components/sound-editor/icon--trim.svg new file mode 100644 index 000000000..cf64941ca --- /dev/null +++ b/src/components/sound-editor/icon--trim.svg @@ -0,0 +1 @@ +sissors diff --git a/src/components/sound-editor/sound-editor.css b/src/components/sound-editor/sound-editor.css index 0bb44f115..1d67886da 100644 --- a/src/components/sound-editor/sound-editor.css +++ b/src/components/sound-editor/sound-editor.css @@ -36,17 +36,36 @@ } .button { - width: 2rem; height: 2rem; padding: 0.25rem; outline: none; background: white; border-radius: 0.25rem; border: 1px solid #ddd; + cursor: pointer; + font-size: 0.85rem; + transition: 0.2s; } .button img { flex-grow: 1; max-width: 100%; max-height: 100%; + min-width: 1.5rem; +} + +.trim-button { + display: flex; + align-items: center; + padding-right: 10px; /* To equalize with empty whitespace from image on left */ +} + +.trim-button-active { + filter: hue-rotate(155deg); /* @todo replace blue -> red with real submit icon */ +} + +.input-group-right { + flex-grow: 1; + display: flex; + flex-direction: row-reverse; } diff --git a/src/components/sound-editor/sound-editor.jsx b/src/components/sound-editor/sound-editor.jsx index 3e379b3f5..2168ee651 100644 --- a/src/components/sound-editor/sound-editor.jsx +++ b/src/components/sound-editor/sound-editor.jsx @@ -1,26 +1,28 @@ import PropTypes from 'prop-types'; import React from 'react'; import classNames from 'classnames'; -import Box from '../box/box.jsx'; import Waveform from '../waveform/waveform.jsx'; import Label from '../forms/label.jsx'; import Input from '../forms/input.jsx'; import BufferedInputHOC from '../forms/buffered-input-hoc.jsx'; +import AudioTrimmer from '../../containers/audio-trimmer.jsx'; import styles from './sound-editor.css'; import playIcon from '../record-modal/icon--play.svg'; import stopIcon from '../record-modal/icon--stop-playback.svg'; +import trimIcon from './icon--trim.svg'; const BufferedInput = BufferedInputHOC(Input); const SoundEditor = props => ( - - - +
+
+
{props.playhead ? ( )} - - +
+
- - - - +
+
+ +
+
+
+
- - - + +
+
+
); SoundEditor.propTypes = { chunkLevels: PropTypes.arrayOf(PropTypes.number).isRequired, name: PropTypes.string.isRequired, + onActivateTrim: PropTypes.func, onChangeName: PropTypes.func.isRequired, onPlay: PropTypes.func.isRequired, + onSetTrimEnd: PropTypes.func, + onSetTrimStart: PropTypes.func, onStop: PropTypes.func.isRequired, - playhead: PropTypes.number + playhead: PropTypes.number, + trimEnd: PropTypes.number, + trimStart: PropTypes.number }; export default SoundEditor; diff --git a/src/containers/audio-trimmer.jsx b/src/containers/audio-trimmer.jsx index 07ba2154d..03e91443e 100644 --- a/src/containers/audio-trimmer.jsx +++ b/src/containers/audio-trimmer.jsx @@ -20,12 +20,14 @@ class AudioTrimmer extends React.Component { const dx = (e.clientX - this.initialX) / containerSize; const newTrim = Math.max(0, Math.min(this.props.trimEnd, this.initialTrim + dx)); this.props.onSetTrimStart(newTrim); + e.preventDefault(); } handleTrimEndMouseMove (e) { const containerSize = this.containerElement.getBoundingClientRect().width; const dx = (e.clientX - this.initialX) / containerSize; const newTrim = Math.min(1, Math.max(this.props.trimStart, this.initialTrim + dx)); this.props.onSetTrimEnd(newTrim); + e.preventDefault(); } handleTrimStartMouseUp () { window.removeEventListener('mousemove', this.handleTrimStartMouseMove); diff --git a/src/containers/sound-editor.jsx b/src/containers/sound-editor.jsx index 7706b1e98..d18678273 100644 --- a/src/containers/sound-editor.jsx +++ b/src/containers/sound-editor.jsx @@ -17,30 +17,50 @@ class SoundEditor extends React.Component { 'handleChangeName', 'handlePlay', 'handleStopPlaying', - 'handleUpdatePlayhead' + 'handleUpdatePlayhead', + 'handleActivateTrim', + 'handleUpdateTrimEnd', + 'handleUpdateTrimStart' ]); this.state = { + chunkLevels: computeChunkedRMS(this.props.samples), playhead: null, // null is not playing, [0 -> 1] is playing percent - chunkLevels: computeChunkedRMS(this.props.samples) + trimStart: null, + trimEnd: null }; } componentDidMount () { this.audioBufferPlayer = new AudioBufferPlayer(this.props.samples, this.props.sampleRate); } componentWillReceiveProps (newProps) { - if (newProps.soundIndex !== this.props.soundIndex) { - this.audioBufferPlayer.stop(); - this.audioBufferPlayer = new AudioBufferPlayer(newProps.samples, newProps.sampleRate); - this.setState({chunkLevels: computeChunkedRMS(newProps.samples)}); + if (newProps.soundId !== this.props.soundId) { // A different sound has been selected + this.resetState(newProps.samples, newProps.sampleRate); } } componentWillUnmount () { this.audioBufferPlayer.stop(); } + resetState (samples, sampleRate) { + this.audioBufferPlayer.stop(); + this.audioBufferPlayer = new AudioBufferPlayer(samples, sampleRate); + this.setState({ + chunkLevels: computeChunkedRMS(samples), + playhead: null, + trimStart: null, + trimEnd: null + }); + } + submitNewSamples (samples, sampleRate) { + this.resetState(samples, sampleRate); + this.props.onUpdateSoundBuffer( + this.props.soundIndex, + this.audioBufferPlayer.buffer + ); + } handlePlay () { this.audioBufferPlayer.play( - 0, - 1, + this.state.trimStart || 0, + this.state.trimEnd || 1, this.handleUpdatePlayhead, this.handleStoppedPlaying); } @@ -57,6 +77,23 @@ class SoundEditor extends React.Component { handleChangeName (name) { this.props.onRenameSound(this.props.soundIndex, name); } + handleActivateTrim () { + if (this.state.trimStart === null && this.state.trimEnd === null) { + this.setState({trimEnd: 0.95, trimStart: 0.05}); + } else { + const sampleCount = this.props.samples.length; + const startIndex = Math.floor(this.state.trimStart * sampleCount); + const endIndex = Math.floor(this.state.trimEnd * sampleCount); + const clippedSamples = this.props.samples.slice(startIndex, endIndex); + this.submitNewSamples(clippedSamples, this.props.sampleRate); + } + } + handleUpdateTrimEnd (trimEnd) { + this.setState({trimEnd}); + } + handleUpdateTrimStart (trimStart) { + this.setState({trimStart}); + } render () { return ( ); } @@ -79,8 +116,10 @@ class SoundEditor extends React.Component { SoundEditor.propTypes = { name: PropTypes.string.isRequired, onRenameSound: PropTypes.func.isRequired, + onUpdateSoundBuffer: PropTypes.func.isRequired, sampleRate: PropTypes.number, samples: PropTypes.instanceOf(Float32Array), + soundId: PropTypes.string, soundIndex: PropTypes.number }; @@ -88,10 +127,12 @@ const mapStateToProps = (state, {soundIndex}) => { const sound = state.vm.editingTarget.sprite.sounds[soundIndex]; const audioBuffer = state.vm.getSoundBuffer(soundIndex); return { + soundId: sound.soundId, sampleRate: audioBuffer.sampleRate, samples: audioBuffer.getChannelData(0), name: sound.name, - onRenameSound: state.vm.renameSound.bind(state.vm) + onRenameSound: state.vm.renameSound.bind(state.vm), + onUpdateSoundBuffer: state.vm.updateSoundBuffer.bind(state.vm) }; }; diff --git a/test/__mocks__/audio-buffer-player.js b/test/__mocks__/audio-buffer-player.js new file mode 100644 index 000000000..c36092be3 --- /dev/null +++ b/test/__mocks__/audio-buffer-player.js @@ -0,0 +1,12 @@ +/* eslint-env jest */ +export default class MockAudioBufferPlayer { + constructor (samples, sampleRate) { + this.samples = samples; + this.sampleRate = sampleRate; + this.play = jest.fn((trimStart, trimEnd, onUpdate) => { + this.onUpdate = onUpdate; + }); + this.stop = jest.fn(); + MockAudioBufferPlayer.instance = this; + } +} diff --git a/test/unit/components/__snapshots__/sound-editor.test.jsx.snap b/test/unit/components/__snapshots__/sound-editor.test.jsx.snap new file mode 100644 index 000000000..b32ad42e3 --- /dev/null +++ b/test/unit/components/__snapshots__/sound-editor.test.jsx.snap @@ -0,0 +1,311 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Sound Editor Component matches snapshot 1`] = ` +
+
+
+ +
+
+ +
+
+ +
+
+
+
+ + + + + +
+
+
+
+
+ +
+
+ +
+
+
+
+
+
+
+
+ +
+
+ +
+
+
+
+
+
+
+`; diff --git a/test/unit/components/sound-editor.test.jsx b/test/unit/components/sound-editor.test.jsx new file mode 100644 index 000000000..f22609cdb --- /dev/null +++ b/test/unit/components/sound-editor.test.jsx @@ -0,0 +1,63 @@ +/* eslint-env jest */ +import React from 'react'; // eslint-disable-line no-unused-vars +import {mount} from 'enzyme'; +import SoundEditor from '../../../src/components/sound-editor/sound-editor'; // eslint-disable-line no-unused-vars +import renderer from 'react-test-renderer'; + +describe('Sound Editor Component', () => { + let props; + beforeEach(() => { + props = { + chunkLevels: [1, 2, 3], + name: 'sound name', + playhead: 0.5, + trimStart: 0.2, + trimEnd: 0.8, + onActivateTrim: jest.fn(), + onChangeName: jest.fn(), + onPlay: jest.fn(), + onSetTrimEnd: jest.fn(), + onSetTrimStart: jest.fn(), + onStop: jest.fn() + }; + }); + + test('matches snapshot', () => { + const component = renderer.create( + + ); + expect(component.toJSON()).toMatchSnapshot(); + }); + + test('trim button appears when trims are null', () => { + const wrapper = mount(); + wrapper.find('button[title="Trim"]').simulate('click'); + expect(props.onActivateTrim).toHaveBeenCalled(); + }); + + test('save button appears when trims are not null', () => { + const wrapper = mount(); + wrapper.find('button[title="Save"]').simulate('click'); + expect(props.onActivateTrim).toHaveBeenCalled(); + }); + + test('play button appears when playhead is null', () => { + const wrapper = mount(); + wrapper.find('button[title="Play"]').simulate('click'); + expect(props.onPlay).toHaveBeenCalled(); + }); + + test('stop button appears when playhead is not null', () => { + const wrapper = mount(); + wrapper.find('button[title="Stop"]').simulate('click'); + expect(props.onStop).toHaveBeenCalled(); + }); + + test('submitting name calls the callback', () => { + const wrapper = mount(); + wrapper.find('input') + .simulate('change', {target: {value: 'hello'}}) + .simulate('blur'); + expect(props.onChangeName).toHaveBeenCalled(); + }); +}); diff --git a/test/unit/containers/sound-editor.test.jsx b/test/unit/containers/sound-editor.test.jsx new file mode 100644 index 000000000..a0838689f --- /dev/null +++ b/test/unit/containers/sound-editor.test.jsx @@ -0,0 +1,93 @@ +/* eslint-env jest */ +import React from 'react'; // eslint-disable-line no-unused-vars +import {mount} from 'enzyme'; +import configureStore from 'redux-mock-store'; +import mockAudioBufferPlayer from '../../__mocks__/audio-buffer-player.js'; + +import SoundEditor from '../../../src/containers/sound-editor'; // eslint-disable-line no-unused-vars +// eslint-disable-next-line no-unused-vars +import SoundEditorComponent from '../../../src/components/sound-editor/sound-editor'; + +jest.mock('../../../src/lib/audio/audio-buffer-player', () => mockAudioBufferPlayer); + +describe('Sound Editor Container', () => { + const mockStore = configureStore(); + let store; + let soundIndex; + let soundBuffer; + let samples = new Float32Array([0, 0, 0]); // eslint-disable-line no-undef + let vm; + + beforeEach(() => { + soundIndex = 0; + soundBuffer = { + sampleRate: 0, + getChannelData: jest.fn(() => samples) + }; + vm = { + getSoundBuffer: jest.fn(() => soundBuffer), + renameSound: jest.fn(), + updateSoundBuffer: jest.fn(), + editingTarget: { + sprite: { + sounds: [{name: 'first name', id: 'first id'}] + } + } + }; + store = mockStore({vm}); + }); + + test('should pass the correct data to the component from the store', () => { + const wrapper = mount(); + const componentProps = wrapper.find(SoundEditorComponent).props(); + // Data retreived and processed by the `connect` with the store + expect(componentProps.name).toEqual('first name'); + expect(componentProps.chunkLevels).toEqual([0]); + expect(mockAudioBufferPlayer.instance.samples).toEqual(samples); + // Initial data + expect(componentProps.playhead).toEqual(null); + expect(componentProps.trimStart).toEqual(null); + expect(componentProps.trimEnd).toEqual(null); + + }); + + test('it plays when clicked and stops when clicked again', () => { + const wrapper = mount(); + const 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([]); + + component.props().onPlay(); + expect(mockAudioBufferPlayer.instance.play).toHaveBeenCalled(); + + // Mock the audio buffer player calling onUpdate + mockAudioBufferPlayer.instance.onUpdate(0.5); + expect(component.props().playhead).toEqual(0.5); + + component.props().onStop(); + expect(mockAudioBufferPlayer.instance.stop).toHaveBeenCalled(); + expect(component.props().playhead).toEqual(null); + }); + + test('it sets the component props for trimming and submits to the vm', () => { + const wrapper = mount(); + const component = wrapper.find(SoundEditorComponent); + + component.props().onActivateTrim(); + expect(component.props().trimStart).not.toEqual(null); + expect(component.props().trimEnd).not.toEqual(null); + + component.props().onActivateTrim(); + expect(vm.updateSoundBuffer).toHaveBeenCalled(); + expect(component.props().trimStart).toEqual(null); + expect(component.props().trimEnd).toEqual(null); + }); + + test('it submits name changes to the vm', () => { + const wrapper = mount(); + const component = wrapper.find(SoundEditorComponent); + component.props().onChangeName('hello'); + expect(vm.renameSound).toHaveBeenCalledWith(soundIndex, 'hello'); + }); +}); From b6f5a6e33c09bad79271bedfb0c0304641d7b5ee Mon Sep 17 00:00:00 2001 From: Paul Kaplan Date: Wed, 2 Aug 2017 15:40:02 -0400 Subject: [PATCH 2/2] Internationalize and update testing to handle react-intl --- src/components/sound-editor/sound-editor.jsx | 51 ++++++++++++++++--- test/helpers/intl-helpers.js | 45 ++++++++++++++++ .../__snapshots__/sound-editor.test.jsx.snap | 4 +- test/unit/components/sound-editor.test.jsx | 17 +++---- test/unit/containers/sound-editor.test.jsx | 10 ++-- 5 files changed, 105 insertions(+), 22 deletions(-) create mode 100644 test/helpers/intl-helpers.js diff --git a/src/components/sound-editor/sound-editor.jsx b/src/components/sound-editor/sound-editor.jsx index 2168ee651..7ac6811ab 100644 --- a/src/components/sound-editor/sound-editor.jsx +++ b/src/components/sound-editor/sound-editor.jsx @@ -1,6 +1,8 @@ import PropTypes from 'prop-types'; import React from 'react'; import classNames from 'classnames'; +import {defineMessages, FormattedMessage, injectIntl, intlShape} from 'react-intl'; + import Waveform from '../waveform/waveform.jsx'; import Label from '../forms/label.jsx'; import Input from '../forms/input.jsx'; @@ -15,6 +17,34 @@ import trimIcon from './icon--trim.svg'; const BufferedInput = BufferedInputHOC(Input); +const messages = defineMessages({ + sound: { + id: 'soundEditor.sound', + description: 'Lable for the name of the sound', + defaultMessage: 'Sound' + }, + play: { + id: 'soundEditor.play', + description: 'Title of the button to start playing the sound', + defaultMessage: 'Play' + }, + stop: { + id: 'soundEditor.stop', + description: 'Title of the button to stop the sound', + defaultMessage: 'Stop' + }, + trim: { + id: 'soundEditor.trim', + description: 'Title of the button to start trimminging the sound', + defaultMessage: 'Trim' + }, + save: { + id: 'soundEditor.save', + description: 'Title of the button to save trimmed sound', + defaultMessage: 'Save' + } +}); + const SoundEditor = props => (
@@ -22,7 +52,7 @@ const SoundEditor = props => ( {props.playhead ? (
-
@@ -81,6 +119,7 @@ const SoundEditor = props => ( SoundEditor.propTypes = { chunkLevels: PropTypes.arrayOf(PropTypes.number).isRequired, + intl: intlShape, name: PropTypes.string.isRequired, onActivateTrim: PropTypes.func, onChangeName: PropTypes.func.isRequired, @@ -93,4 +132,4 @@ SoundEditor.propTypes = { trimStart: PropTypes.number }; -export default SoundEditor; +export default injectIntl(SoundEditor); diff --git a/test/helpers/intl-helpers.js b/test/helpers/intl-helpers.js new file mode 100644 index 000000000..d658aeae0 --- /dev/null +++ b/test/helpers/intl-helpers.js @@ -0,0 +1,45 @@ +/* + * Helpers for using enzyme and react-test-renderer with react-intl + * Directly from https://github.com/yahoo/react-intl/wiki/Testing-with-React-Intl + */ +import React from 'react'; +import renderer from 'react-test-renderer'; +import {IntlProvider, intlShape} from 'react-intl'; +import {mount, shallow} from 'enzyme'; + +const intlProvider = new IntlProvider({locale: 'en'}, {}); +const {intl} = intlProvider.getChildContext(); + +const nodeWithIntlProp = node => { + return React.cloneElement(node, {intl}); +}; + +const shallowWithIntl = (node, {context} = {}) => { + return shallow( + nodeWithIntlProp(node), + { + context: Object.assign({}, context, {intl}) + } + ); +}; + +const mountWithIntl = (node, {context, childContextTypes} = {}) => { + return mount( + nodeWithIntlProp(node), + { + context: Object.assign({}, context, {intl}), + childContextTypes: Object.assign({}, {intl: intlShape}, childContextTypes) + } + ); +}; + +// react-test-renderer component for use with snapshot testing +const componentWithIntl = (children, props = {locale: 'en'}) => { + return renderer.create({children}); +}; + +export { + componentWithIntl, + shallowWithIntl, + mountWithIntl +}; diff --git a/test/unit/components/__snapshots__/sound-editor.test.jsx.snap b/test/unit/components/__snapshots__/sound-editor.test.jsx.snap index b32ad42e3..c757bc5d5 100644 --- a/test/unit/components/__snapshots__/sound-editor.test.jsx.snap +++ b/test/unit/components/__snapshots__/sound-editor.test.jsx.snap @@ -54,7 +54,9 @@ exports[`Sound Editor Component matches snapshot 1`] = ` - Save + + Save +
diff --git a/test/unit/components/sound-editor.test.jsx b/test/unit/components/sound-editor.test.jsx index f22609cdb..9c98edda9 100644 --- a/test/unit/components/sound-editor.test.jsx +++ b/test/unit/components/sound-editor.test.jsx @@ -1,8 +1,7 @@ /* eslint-env jest */ import React from 'react'; // eslint-disable-line no-unused-vars -import {mount} from 'enzyme'; +import {mountWithIntl, componentWithIntl} from '../../helpers/intl-helpers'; import SoundEditor from '../../../src/components/sound-editor/sound-editor'; // eslint-disable-line no-unused-vars -import renderer from 'react-test-renderer'; describe('Sound Editor Component', () => { let props; @@ -23,38 +22,36 @@ describe('Sound Editor Component', () => { }); test('matches snapshot', () => { - const component = renderer.create( - - ); + const component = componentWithIntl(); expect(component.toJSON()).toMatchSnapshot(); }); test('trim button appears when trims are null', () => { - const wrapper = mount(); + const wrapper = mountWithIntl(); wrapper.find('button[title="Trim"]').simulate('click'); expect(props.onActivateTrim).toHaveBeenCalled(); }); test('save button appears when trims are not null', () => { - const wrapper = mount(); + const wrapper = mountWithIntl(); wrapper.find('button[title="Save"]').simulate('click'); expect(props.onActivateTrim).toHaveBeenCalled(); }); test('play button appears when playhead is null', () => { - const wrapper = mount(); + const wrapper = mountWithIntl(); wrapper.find('button[title="Play"]').simulate('click'); expect(props.onPlay).toHaveBeenCalled(); }); test('stop button appears when playhead is not null', () => { - const wrapper = mount(); + const wrapper = mountWithIntl(); wrapper.find('button[title="Stop"]').simulate('click'); expect(props.onStop).toHaveBeenCalled(); }); test('submitting name calls the callback', () => { - const wrapper = mount(); + const wrapper = mountWithIntl(); wrapper.find('input') .simulate('change', {target: {value: 'hello'}}) .simulate('blur'); diff --git a/test/unit/containers/sound-editor.test.jsx b/test/unit/containers/sound-editor.test.jsx index a0838689f..39f1e19b0 100644 --- a/test/unit/containers/sound-editor.test.jsx +++ b/test/unit/containers/sound-editor.test.jsx @@ -1,6 +1,6 @@ /* eslint-env jest */ import React from 'react'; // eslint-disable-line no-unused-vars -import {mount} from 'enzyme'; +import {mountWithIntl} from '../../helpers/intl-helpers'; import configureStore from 'redux-mock-store'; import mockAudioBufferPlayer from '../../__mocks__/audio-buffer-player.js'; @@ -38,7 +38,7 @@ describe('Sound Editor Container', () => { }); test('should pass the correct data to the component from the store', () => { - const wrapper = mount(); + const wrapper = mountWithIntl(); const componentProps = wrapper.find(SoundEditorComponent).props(); // Data retreived and processed by the `connect` with the store expect(componentProps.name).toEqual('first name'); @@ -52,7 +52,7 @@ describe('Sound Editor Container', () => { }); test('it plays when clicked and stops when clicked again', () => { - const wrapper = mount(); + const wrapper = mountWithIntl(); const component = wrapper.find(SoundEditorComponent); // Ensure rendering doesn't start playing any sounds expect(mockAudioBufferPlayer.instance.play.mock.calls).toEqual([]); @@ -71,7 +71,7 @@ describe('Sound Editor Container', () => { }); test('it sets the component props for trimming and submits to the vm', () => { - const wrapper = mount(); + const wrapper = mountWithIntl(); const component = wrapper.find(SoundEditorComponent); component.props().onActivateTrim(); @@ -85,7 +85,7 @@ describe('Sound Editor Container', () => { }); test('it submits name changes to the vm', () => { - const wrapper = mount(); + const wrapper = mountWithIntl(); const component = wrapper.find(SoundEditorComponent); component.props().onChangeName('hello'); expect(vm.renameSound).toHaveBeenCalledWith(soundIndex, 'hello');