-
Notifications
You must be signed in to change notification settings - Fork 4.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Editor: PostTextEditor: Fix case where empty state value defers to pr…
…op (#9513) * Editor: PostTextEditor: Fix case where empty state value defers to prop * PostTextEditor: Always derive state from props except when dirty
- Loading branch information
1 parent
cd2ff2e
commit 71c4d8f
Showing
3 changed files
with
181 additions
and
39 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
147 changes: 147 additions & 0 deletions
147
packages/editor/src/components/post-text-editor/test/index.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,147 @@ | ||
/** | ||
* External dependencies | ||
*/ | ||
import { create } from 'react-test-renderer'; | ||
import Textarea from 'react-autosize-textarea'; | ||
|
||
/** | ||
* Internal dependencies | ||
*/ | ||
import { PostTextEditor } from '../'; | ||
|
||
// "Downgrade" ReactAutosizeTextarea to a regular textarea. Assumes aligned | ||
// props interface. | ||
jest.mock( 'react-autosize-textarea', () => ( props ) => <textarea { ...props } /> ); | ||
|
||
describe( 'PostTextEditor', () => { | ||
it( 'should render via the prop value', () => { | ||
const wrapper = create( <PostTextEditor value="Hello World" /> ); | ||
|
||
const textarea = wrapper.root.findByType( Textarea ); | ||
expect( textarea.props.value ).toBe( 'Hello World' ); | ||
} ); | ||
|
||
it( 'should render via the state value when edits made', () => { | ||
const onChange = jest.fn(); | ||
const wrapper = create( | ||
<PostTextEditor | ||
value="Hello World" | ||
onChange={ onChange } | ||
/> | ||
); | ||
|
||
const textarea = wrapper.root.findByType( Textarea ); | ||
textarea.props.onChange( { target: { value: 'Hello Chicken' } } ); | ||
|
||
expect( textarea.props.value ).toBe( 'Hello Chicken' ); | ||
expect( onChange ).toHaveBeenCalledWith( 'Hello Chicken' ); | ||
} ); | ||
|
||
it( 'should render via the state value when edits made, even if prop value changes', () => { | ||
const onChange = jest.fn(); | ||
const wrapper = create( | ||
<PostTextEditor | ||
value="Hello World" | ||
onChange={ onChange } | ||
/> | ||
); | ||
|
||
const textarea = wrapper.root.findByType( Textarea ); | ||
textarea.props.onChange( { target: { value: 'Hello Chicken' } } ); | ||
|
||
wrapper.update( | ||
<PostTextEditor | ||
value="Goodbye World" | ||
onChange={ onChange } | ||
/> | ||
); | ||
|
||
expect( textarea.props.value ).toBe( 'Hello Chicken' ); | ||
expect( onChange ).toHaveBeenCalledWith( 'Hello Chicken' ); | ||
} ); | ||
|
||
it( 'should render via the state value when edits made, even if prop value changes and state value empty', () => { | ||
const onChange = jest.fn(); | ||
const wrapper = create( | ||
<PostTextEditor | ||
value="Hello World" | ||
onChange={ onChange } | ||
/> | ||
); | ||
|
||
const textarea = wrapper.root.findByType( Textarea ); | ||
textarea.props.onChange( { target: { value: '' } } ); | ||
|
||
wrapper.update( | ||
<PostTextEditor | ||
value="Goodbye World" | ||
onChange={ onChange } | ||
/> | ||
); | ||
|
||
expect( textarea.props.value ).toBe( '' ); | ||
expect( onChange ).toHaveBeenCalledWith( '' ); | ||
} ); | ||
|
||
it( 'calls onPersist after changes made and user stops editing', () => { | ||
const onPersist = jest.fn(); | ||
const wrapper = create( | ||
<PostTextEditor | ||
value="Hello World" | ||
onChange={ () => {} } | ||
onPersist={ onPersist } | ||
/> | ||
); | ||
|
||
const textarea = wrapper.root.findByType( Textarea ); | ||
textarea.props.onChange( { target: { value: '' } } ); | ||
textarea.props.onBlur(); | ||
|
||
expect( onPersist ).toHaveBeenCalledWith( '' ); | ||
} ); | ||
|
||
it( 'does not call onPersist after user stops editing without changes', () => { | ||
const onPersist = jest.fn(); | ||
const wrapper = create( | ||
<PostTextEditor | ||
value="Hello World" | ||
onChange={ () => {} } | ||
onPersist={ onPersist } | ||
/> | ||
); | ||
|
||
const textarea = wrapper.root.findByType( Textarea ); | ||
textarea.props.onBlur(); | ||
|
||
expect( onPersist ).not.toHaveBeenCalled(); | ||
} ); | ||
|
||
it( 'resets to prop value after user stops editing', () => { | ||
// This isn't the most realistic case, since typically we'd assume the | ||
// parent renderer to pass the value as it had received onPersist. The | ||
// test here is more an edge case to stress that it's intentionally | ||
// differentiating between state and prop values. | ||
const wrapper = create( | ||
<PostTextEditor | ||
value="Hello World" | ||
onChange={ () => {} } | ||
onPersist={ () => {} } | ||
/> | ||
); | ||
|
||
const textarea = wrapper.root.findByType( Textarea ); | ||
textarea.props.onChange( { target: { value: '' } } ); | ||
|
||
wrapper.update( | ||
<PostTextEditor | ||
value="Goodbye World" | ||
onChange={ () => {} } | ||
onPersist={ () => {} } | ||
/> | ||
); | ||
|
||
textarea.props.onBlur(); | ||
|
||
expect( textarea.props.value ).toBe( 'Goodbye World' ); | ||
} ); | ||
} ); |