From 9eff87c32ada88b3d3a3512cbe2e2d322890575e Mon Sep 17 00:00:00 2001 From: Riad Benguella Date: Wed, 27 Dec 2017 12:13:32 +0100 Subject: [PATCH] MetaBoxes: Remove dirty-checking metaboxes state --- docs/meta-box.md | 8 +- .../meta-boxes/meta-boxes-area/index.js | 33 +--- editor/components/post-saved-state/index.js | 6 +- editor/store/actions.js | 21 +- editor/store/effects.js | 5 +- editor/store/reducer.js | 23 +-- editor/store/selectors.js | 39 ++-- editor/store/test/actions.js | 14 +- editor/store/test/effects.js | 8 +- editor/store/test/reducer.js | 43 +--- editor/store/test/selectors.js | 183 ++++++------------ 11 files changed, 104 insertions(+), 279 deletions(-) diff --git a/docs/meta-box.md b/docs/meta-box.md index 51de1464389720..fb10f2995cb7b2 100644 --- a/docs/meta-box.md +++ b/docs/meta-box.md @@ -57,11 +57,9 @@ When rendering the Gutenberg Page, the metaboxes are rendered to a hidden div `# #### MetaBoxArea Component -When the component renders it will store a ref to the metaboxes container, retrieve the metaboxes HTML from the prefetch location and watches input and changes. +When the component renders it will store a ref to the metaboxes container, retrieve the metaboxes HTML from the prefetch location. -The change detection will store the current form's `FormData`, then whenever a change is detected the current form data will be checked vs, the original form data. This serves as a way to see if the meta box state is dirty. When the meta box state has been detected to have changed, a Redux action `META_BOX_STATE_CHANGED` is dispatched, updating the store setting the isDirty flag to `true`. If the state ever returns back to the original form data, `META_BOX_STATE_CHANGED` is dispatched again to set the isDirty flag to `false`. A selector `isMetaBoxStateDirty()` is used to help check whether the post can be updated. It checks each meta box for whether it is dirty, and if there is at least one dirty meta box, it will return true. This dirty detection does not impact creating new posts, as the content will have to change before meta boxes can trigger the overall dirty state. - -When the post is updated, only meta boxes areas that are active and dirty, will be submitted. This removes any unnecessary requests being made. No extra revisions, are created either by the meta box submissions. A Redux action will trigger on `REQUEST_POST_UPDATE` for any dirty meta box. See `editor/effects.js`. The `REQUEST_META_BOX_UPDATES` action will set that meta boxes' state to `isUpdating`, the `isUpdating` prop will be sent into the `MetaBoxArea` and cause a form submission. +When the post is updated, only meta boxes areas that are active will be submitted. This removes any unnecessary requests being made. No extra revisions, are created either by the meta box submissions. A Redux action will trigger on `REQUEST_POST_UPDATE` for any active meta box. See `editor/effects.js`. The `REQUEST_META_BOX_UPDATES` action will set that meta boxes' state to `isUpdating`, the `isUpdating` prop will be sent into the `MetaBoxArea` and cause a form submission. If the metabox area is saving, we display an updating overlay, to prevent users from changing the form values while the meta box is submitting. @@ -75,7 +73,7 @@ So an example url would look like: This url is automatically passed into React via a `_wpMetaBoxUrl` global variable. -Thus page page mimics the `post.php` post form, so when it is submitted it will normally fire all of the necessary hooks and actions, and have the proper global state to correctly fire any PHP meta box mumbo jumbo without needing to modify any existing code. On successful submission, React will signal a `handleMetaBoxReload` to set up the new form state for dirty checking, remove the updating overlay, and set the store to no longer be updating the meta box area. +Thus page page mimics the `post.php` post form, so when it is submitted it will normally fire all of the necessary hooks and actions, and have the proper global state to correctly fire any PHP meta box mumbo jumbo without needing to modify any existing code. On successful submission, React will signal a `handleMetaBoxReload` to remove the updating overlay, and set the store to no longer be updating the meta box area. ### Common Compatibility Issues diff --git a/editor/components/meta-boxes/meta-boxes-area/index.js b/editor/components/meta-boxes/meta-boxes-area/index.js index a4d71ac27adbd1..862d1c7d6cd15b 100644 --- a/editor/components/meta-boxes/meta-boxes-area/index.js +++ b/editor/components/meta-boxes/meta-boxes-area/index.js @@ -1,7 +1,6 @@ /** * External dependencies */ -import { isEqual } from 'lodash'; import classnames from 'classnames'; import { connect } from 'react-redux'; import jQuery from 'jquery'; @@ -17,7 +16,7 @@ import { Spinner } from '@wordpress/components'; * Internal dependencies */ import './style.scss'; -import { handleMetaBoxReload, metaBoxStateChanged, metaBoxLoaded } from '../../../store/actions'; +import { handleMetaBoxReload, metaBoxLoaded } from '../../../store/actions'; import { getMetaBox, isSavingPost } from '../../../store/selectors'; class MetaBoxesArea extends Component { @@ -29,7 +28,6 @@ class MetaBoxesArea extends Component { }; this.originalFormData = ''; this.bindNode = this.bindNode.bind( this ); - this.checkState = this.checkState.bind( this ); } bindNode( node ) { @@ -43,17 +41,9 @@ class MetaBoxesArea extends Component { componentWillUnmount() { this.mounted = false; - this.unbindFormEvents(); document.querySelector( '#metaboxes' ).appendChild( this.form ); } - unbindFormEvents() { - if ( this.form ) { - this.form.removeEventListener( 'change', this.checkState ); - this.form.removeEventListener( 'input', this.checkState ); - } - } - componentWillReceiveProps( nextProps ) { if ( nextProps.isUpdating && ! this.props.isUpdating ) { this.setState( { loading: true } ); @@ -84,8 +74,6 @@ class MetaBoxesArea extends Component { this.node.appendChild( this.form ); this.form.onSubmit = ( event ) => event.preventDefault(); this.originalFormData = this.getFormData(); - this.form.addEventListener( 'change', this.checkState ); - this.form.addEventListener( 'input', this.checkState ); this.props.metaBoxLoaded( location ); } @@ -93,21 +81,6 @@ class MetaBoxesArea extends Component { return jQuery( this.form ).serialize(); } - checkState() { - const { loading } = this.state; - const { isDirty, changedMetaBoxState, location } = this.props; - - const newIsDirty = ! isEqual( this.originalFormData, this.getFormData() ); - - /** - * If we are not updating, then if dirty and equal to original, then set not dirty. - * If we are not updating, then if not dirty and not equal to original, set as dirty. - */ - if ( ! loading && isDirty !== newIsDirty ) { - changedMetaBoxState( location, newIsDirty ); - } - } - render() { const { location } = this.props; const { loading } = this.state; @@ -132,10 +105,9 @@ class MetaBoxesArea extends Component { function mapStateToProps( state, ownProps ) { const metaBox = getMetaBox( state, ownProps.location ); - const { isDirty, isUpdating } = metaBox; + const { isUpdating } = metaBox; return { - isDirty, isUpdating, isPostSaving: isSavingPost( state ) ? true : false, }; @@ -145,7 +117,6 @@ function mapDispatchToProps( dispatch ) { return { // Used to set the reference to the MetaBox in redux, fired when the component mounts. metaBoxReloaded: ( location ) => dispatch( handleMetaBoxReload( location ) ), - changedMetaBoxState: ( location, hasChanged ) => dispatch( metaBoxStateChanged( location, hasChanged ) ), metaBoxLoaded: ( location ) => dispatch( metaBoxLoaded( location ) ), }; } diff --git a/editor/components/post-saved-state/index.js b/editor/components/post-saved-state/index.js index a24b0f29a95a91..a7015033a01ec3 100644 --- a/editor/components/post-saved-state/index.js +++ b/editor/components/post-saved-state/index.js @@ -23,9 +23,10 @@ import { isEditedPostSaveable, getCurrentPost, getEditedPostAttribute, + hasMetaBoxes, } from '../../store/selectors'; -export function PostSavedState( { isNew, isPublished, isDirty, isSaving, isSaveable, status, onStatusChange, onSave } ) { +export function PostSavedState( { hasActiveMetaboxes, isNew, isPublished, isDirty, isSaving, isSaveable, status, onStatusChange, onSave } ) { const className = 'editor-post-saved-state'; if ( isSaving ) { @@ -40,7 +41,7 @@ export function PostSavedState( { isNew, isPublished, isDirty, isSaving, isSavea return null; } - if ( ! isNew && ! isDirty ) { + if ( ! isNew && ! isDirty && ! hasActiveMetaboxes ) { return ( @@ -74,6 +75,7 @@ export default connect( isSaving: isSavingPost( state ), isSaveable: isEditedPostSaveable( state ), status: getEditedPostAttribute( state, 'status' ), + hasActiveMetaboxes: hasMetaBoxes( state ), } ), { onStatusChange: ( status ) => editPost( { status } ), diff --git a/editor/store/actions.js b/editor/store/actions.js index ebfc8ff6452cd1..b5d37b06d7350a 100644 --- a/editor/store/actions.js +++ b/editor/store/actions.js @@ -479,30 +479,11 @@ export function metaBoxLoaded( location ) { /** * Returns an action object used to request meta box update. * - * @param {Array} locations Locations of meta boxes: ['normal', 'side', 'advanced' ]. - * * @return {Object} Action object */ -export function requestMetaBoxUpdates( locations ) { +export function requestMetaBoxUpdates() { return { type: 'REQUEST_META_BOX_UPDATES', - locations, - }; -} - -/** - * Returns an action object used to set meta box state changed. - * - * @param {String} location Location of meta box: 'normal', 'side' or 'advanced'. - * @param {Boolean} hasChanged Whether the meta box has changed. - * - * @return {Object} Action object - */ -export function metaBoxStateChanged( location, hasChanged ) { - return { - type: 'META_BOX_STATE_CHANGED', - location, - hasChanged, }; } diff --git a/editor/store/effects.js b/editor/store/effects.js index 96046d03034f3f..a582042c7458e8 100644 --- a/editor/store/effects.js +++ b/editor/store/effects.js @@ -41,7 +41,6 @@ import { import { getCurrentPost, getCurrentPostType, - getDirtyMetaBoxes, getEditedPostContent, getPostEdits, isCurrentPostPublished, @@ -105,7 +104,7 @@ export default { }, REQUEST_POST_UPDATE_SUCCESS( action, store ) { const { previousPost, post } = action; - const { dispatch, getState } = store; + const { dispatch } = store; const publishStatus = [ 'publish', 'private', 'future' ]; const isPublished = includes( publishStatus, previousPost.status ); @@ -145,7 +144,7 @@ export default { } // Update dirty meta boxes. - dispatch( requestMetaBoxUpdates( getDirtyMetaBoxes( getState() ) ) ); + dispatch( requestMetaBoxUpdates() ); if ( get( window.history.state, 'id' ) !== post.id ) { window.history.replaceState( diff --git a/editor/store/reducer.js b/editor/store/reducer.js index 1f439b9e12a69c..3ae3081eadce95 100644 --- a/editor/store/reducer.js +++ b/editor/store/reducer.js @@ -653,7 +653,6 @@ const locations = [ const defaultMetaBoxState = locations.reduce( ( result, key ) => { result[ key ] = { isActive: false, - isDirty: false, isUpdating: false, }; @@ -678,7 +677,6 @@ export function metaBoxes( state = defaultMetaBoxState, action ) { ...state[ action.location ], isLoaded: true, isUpdating: false, - isDirty: false, }, }; case 'HANDLE_META_BOX_RELOAD': @@ -687,26 +685,15 @@ export function metaBoxes( state = defaultMetaBoxState, action ) { [ action.location ]: { ...state[ action.location ], isUpdating: false, - isDirty: false, }, }; case 'REQUEST_META_BOX_UPDATES': - return action.locations.reduce( ( newState, location ) => { - newState[ location ] = { - ...state[ location ], - isUpdating: true, - isDirty: false, + return mapValues( state, ( metaBox ) => { + return { + ...metaBox, + isUpdating: metaBox.isActive, }; - return newState; - }, { ...state } ); - case 'META_BOX_STATE_CHANGED': - return { - ...state, - [ action.location ]: { - ...state[ action.location ], - isDirty: action.hasChanged, - }, - }; + } ); default: return state; } diff --git a/editor/store/selectors.js b/editor/store/selectors.js index 356dbf123858f7..5abb6ba3bcfcd4 100644 --- a/editor/store/selectors.js +++ b/editor/store/selectors.js @@ -12,6 +12,7 @@ import { without, compact, find, + some, } from 'lodash'; import createSelector from 'rememo'; @@ -65,32 +66,34 @@ export function getMetaBox( state, location ) { } /** - * Returns a list of dirty meta box locations. + * Returns true if the post is using Meta Boxes * * @param {Object} state Global application state - * @return {Array} Array of locations for dirty meta boxes. + * @return {Boolean} Whether there are metaboxes or not. */ -export const getDirtyMetaBoxes = createSelector( +export const hasMetaBoxes = createSelector( ( state ) => { - return reduce( getMetaBoxes( state ), ( result, metaBox, location ) => { - return metaBox.isDirty && metaBox.isActive ? - [ ...result, location ] : - result; - }, [] ); + return some( getMetaBoxes( state ), ( metaBox ) => { + return metaBox.isActive; + } ); }, ( state ) => state.metaBoxes, ); /** - * Returns the dirty state of legacy meta boxes. + * Returns true if the the Meta Boxes are being saved * - * Checks whether the entire meta box state is dirty. So if a sidebar is dirty, - * but a normal area is not dirty, this will overall return dirty. - * - * @param {Object} state Global application state - * @return {Boolean} Whether state is dirty. True if dirty, false if not. + * @param {Object} state Global application state + * @return {Boolean} Whether the metaboxes are being saved. */ -export const isMetaBoxStateDirty = ( state ) => getDirtyMetaBoxes( state ).length > 0; +export const isSavingMetaBoxes = createSelector( + ( state ) => { + return some( getMetaBoxes( state ), ( metaBox ) => { + return metaBox.isUpdating; + } ); + }, + ( state ) => state.metaBoxes, +); /** * Returns the current active panel for the sidebar. @@ -206,7 +209,7 @@ export function isEditedPostNew( state ) { * @return {Boolean} Whether unsaved values exist */ export function isEditedPostDirty( state ) { - return state.editor.isDirty || isMetaBoxStateDirty( state ); + return state.editor.isDirty; } /** @@ -351,7 +354,7 @@ export function isCurrentPostPublished( state ) { */ export function isEditedPostPublishable( state ) { const post = getCurrentPost( state ); - return isEditedPostDirty( state ) || [ 'publish', 'private', 'future' ].indexOf( post.status ) === -1; + return isEditedPostDirty( state ) || hasMetaBoxes( state ) || [ 'publish', 'private', 'future' ].indexOf( post.status ) === -1; } /** @@ -938,7 +941,7 @@ export function isBlockInsertionPointVisible( state ) { * @return {Boolean} Whether post is being saved */ export function isSavingPost( state ) { - return state.saving.requesting; + return state.saving.requesting || isSavingMetaBoxes( state ); } /** diff --git a/editor/store/test/actions.js b/editor/store/test/actions.js index 5f3d00a47add12..cfff0c9e885f13 100644 --- a/editor/store/test/actions.js +++ b/editor/store/test/actions.js @@ -8,7 +8,6 @@ import { stopTyping, requestMetaBoxUpdates, handleMetaBoxReload, - metaBoxStateChanged, initializeMetaBoxState, fetchReusableBlocks, updateReusableBlock, @@ -555,9 +554,8 @@ describe( 'actions', () => { describe( 'requestMetaBoxUpdates', () => { it( 'should return the REQUEST_META_BOX_UPDATES action', () => { - expect( requestMetaBoxUpdates( [ 'normal' ] ) ).toEqual( { + expect( requestMetaBoxUpdates() ).toEqual( { type: 'REQUEST_META_BOX_UPDATES', - locations: [ 'normal' ], } ); } ); } ); @@ -571,16 +569,6 @@ describe( 'actions', () => { } ); } ); - describe( 'metaBoxStateChanged', () => { - it( 'should return the META_BOX_STATE_CHANGED action with a hasChanged flag', () => { - expect( metaBoxStateChanged( 'normal', true ) ).toEqual( { - type: 'META_BOX_STATE_CHANGED', - location: 'normal', - hasChanged: true, - } ); - } ); - } ); - describe( 'initializeMetaBoxState', () => { it( 'should return the META_BOX_STATE_CHANGED action with a hasChanged flag', () => { const metaBoxes = { diff --git a/editor/store/test/effects.js b/editor/store/test/effects.js index a2fed5952e5615..2acf97d4eb0dea 100644 --- a/editor/store/test/effects.js +++ b/editor/store/test/effects.js @@ -282,7 +282,7 @@ describe( 'effects', () => { describe( '.REQUEST_POST_UPDATE_SUCCESS', () => { const handler = effects.REQUEST_POST_UPDATE_SUCCESS; - let getDirtyMetaBoxesSpy, replaceStateSpy; + let replaceStateSpy; const defaultPost = { id: 1, @@ -303,18 +303,14 @@ describe( 'effects', () => { } ); beforeAll( () => { - getDirtyMetaBoxesSpy = jest.spyOn( selectors, 'getDirtyMetaBoxes' ); replaceStateSpy = jest.spyOn( window.history, 'replaceState' ); } ); beforeEach( () => { - getDirtyMetaBoxesSpy.mockReset(); - getDirtyMetaBoxesSpy.mockReturnValue( [ 'normal', 'side' ] ); replaceStateSpy.mockReset(); } ); afterAll( () => { - getDirtyMetaBoxesSpy.mockRestore(); replaceStateSpy.mockRestore(); } ); @@ -327,7 +323,7 @@ describe( 'effects', () => { handler( { post: post, previousPost: post }, store ); expect( dispatch ).toHaveBeenCalledTimes( 1 ); - expect( dispatch ).toHaveBeenCalledWith( requestMetaBoxUpdates( [ 'normal', 'side' ] ) ); + expect( dispatch ).toHaveBeenCalledWith( requestMetaBoxUpdates() ); } ); it( 'should dispatch notices when publishing or scheduling a post', () => { diff --git a/editor/store/test/reducer.js b/editor/store/test/reducer.js index 737f1a1782c1f1..8bd9eec38aa111 100644 --- a/editor/store/test/reducer.js +++ b/editor/store/test/reducer.js @@ -1251,23 +1251,21 @@ describe( 'state', () => { const expected = { normal: { isActive: false, - isDirty: false, isUpdating: false, }, side: { isActive: false, - isDirty: false, isUpdating: false, }, advanced: { isActive: false, - isDirty: false, isUpdating: false, }, }; expect( actual ).toEqual( expected ); } ); + it( 'should set the sidebar to active', () => { const theMetaBoxes = { normal: false, @@ -1284,19 +1282,16 @@ describe( 'state', () => { const expected = { normal: { isActive: false, - isDirty: false, isUpdating: false, isLoaded: false, }, side: { isActive: true, - isDirty: false, isUpdating: false, isLoaded: false, }, advanced: { isActive: false, - isDirty: false, isUpdating: false, isLoaded: false, }, @@ -1304,53 +1299,33 @@ describe( 'state', () => { expect( actual ).toEqual( expected ); } ); + it( 'should switch updating to off', () => { const action = { type: 'HANDLE_META_BOX_RELOAD', location: 'normal', }; - const theMetaBoxes = metaBoxes( { normal: { isUpdating: true, isActive: false, isDirty: true } }, action ); + const theMetaBoxes = metaBoxes( { normal: { isUpdating: true, isActive: false } }, action ); const actual = theMetaBoxes.normal; const expected = { isActive: false, isUpdating: false, - isDirty: false, }; expect( actual ).toEqual( expected ); } ); + it( 'should switch updating to on', () => { const action = { type: 'REQUEST_META_BOX_UPDATES', - locations: [ 'normal' ], }; - const theMetaBoxes = metaBoxes( undefined, action ); - const actual = theMetaBoxes.normal; - const expected = { - isActive: false, - isUpdating: true, - isDirty: false, - }; - - expect( actual ).toEqual( expected ); - } ); - it( 'should return with the isDirty flag as true', () => { - const action = { - type: 'META_BOX_STATE_CHANGED', - location: 'normal', - hasChanged: true, - }; - const theMetaBoxes = metaBoxes( undefined, action ); - const actual = theMetaBoxes.normal; - const expected = { - isActive: false, - isDirty: true, - isUpdating: false, - }; - - expect( actual ).toEqual( expected ); + const theMetaBoxes = metaBoxes( { normal: { isActive: true }, side: { isActive: false } }, action ); + expect( theMetaBoxes ).toEqual( { + normal: { isActive: true, isUpdating: true }, + side: { isActive: false, isUpdating: false }, + } ); } ); } ); diff --git a/editor/store/test/selectors.js b/editor/store/test/selectors.js index 527c836c19421d..bd7d9602ded8a7 100644 --- a/editor/store/test/selectors.js +++ b/editor/store/test/selectors.js @@ -73,9 +73,9 @@ import { getMostFrequentlyUsedBlocks, getRecentlyUsedBlocks, getMetaBoxes, - getDirtyMetaBoxes, + hasMetaBoxes, + isSavingMetaBoxes, getMetaBox, - isMetaBoxStateDirty, getReusableBlock, isSavingReusableBlock, isSelectionEnabled, @@ -99,7 +99,6 @@ describe( 'selectors', () => { } ); beforeEach( () => { - getDirtyMetaBoxes.clear(); getBlock.clear(); getBlocks.clear(); getEditedPostContent.clear(); @@ -129,174 +128,124 @@ describe( 'selectors', () => { } ); } ); - describe( 'getDirtyMetaBoxes', () => { - it( 'should return array of just the side location', () => { + describe( 'hasMetaBoxes', () => { + it( 'should return true if there are active meta boxes', () => { const state = { metaBoxes: { normal: { isActive: false, - isDirty: false, - isUpdating: false, }, side: { isActive: true, - isDirty: true, - isUpdating: false, }, }, }; - expect( getDirtyMetaBoxes( state ) ).toEqual( [ 'side' ] ); + expect( hasMetaBoxes( state ) ).toBe( true ); } ); - } ); - describe( 'getMetaBoxes', () => { - it( 'should return the state of all meta boxes', () => { + it( 'should return false if there are no active meta boxes', () => { const state = { metaBoxes: { normal: { - isDirty: false, - isUpdating: false, + isActive: false, }, side: { - isDirty: false, - isUpdating: false, + isActive: false, }, }, }; - expect( getMetaBoxes( state ) ).toEqual( { - normal: { - isDirty: false, - isUpdating: false, - }, - side: { - isDirty: false, - isUpdating: false, - }, - } ); + expect( hasMetaBoxes( state ) ).toBe( false ); } ); } ); - describe( 'getMetaBox', () => { - it( 'should return the state of selected meta box', () => { + describe( 'isSavingMetaBoxes', () => { + it( 'should return true if some meta boxes are saving', () => { const state = { metaBoxes: { normal: { isActive: false, - isDirty: false, isUpdating: false, }, side: { isActive: true, - isDirty: false, - isUpdating: false, + isUpdating: true, }, }, }; - expect( getMetaBox( state, 'side' ) ).toEqual( { - isActive: true, - isDirty: false, - isUpdating: false, - } ); + expect( isSavingMetaBoxes( state ) ).toBe( true ); } ); - } ); - describe( 'isMetaBoxStateDirty', () => { - it( 'should return false', () => { + it( 'should return false if no meta boxes are saving', () => { const state = { metaBoxes: { normal: { isActive: false, - isDirty: false, isUpdating: false, }, side: { - isActive: false, - isDirty: false, + isActive: true, isUpdating: false, }, }, }; - expect( isMetaBoxStateDirty( state ) ).toEqual( false ); + expect( isSavingMetaBoxes( state ) ).toBe( false ); } ); + } ); - it( 'should return false when a dirty meta box is not active.', () => { + describe( 'getMetaBoxes', () => { + it( 'should return the state of all meta boxes', () => { const state = { metaBoxes: { normal: { - isActive: false, - isDirty: true, + isDirty: false, isUpdating: false, }, side: { - isActive: false, isDirty: false, isUpdating: false, }, }, }; - expect( isMetaBoxStateDirty( state ) ).toEqual( false ); - } ); - - it( 'should return false when both meta boxes are dirty but inactive.', () => { - const state = { - metaBoxes: { - normal: { - isActive: false, - isDirty: true, - isUpdating: false, - }, - side: { - isActive: false, - isDirty: true, - isUpdating: false, - }, + expect( getMetaBoxes( state ) ).toEqual( { + normal: { + isDirty: false, + isUpdating: false, }, - }; - - expect( isMetaBoxStateDirty( state ) ).toEqual( false ); + side: { + isDirty: false, + isUpdating: false, + }, + } ); } ); + } ); - it( 'should return false when a dirty meta box is active.', () => { + describe( 'getMetaBox', () => { + it( 'should return the state of selected meta box', () => { const state = { metaBoxes: { normal: { - isActive: true, - isDirty: true, - isUpdating: false, - }, - side: { isActive: false, isDirty: false, isUpdating: false, }, - }, - }; - - expect( isMetaBoxStateDirty( state ) ).toEqual( true ); - } ); - - it( 'should return false when both meta boxes are dirty and active.', () => { - const state = { - metaBoxes: { - normal: { - isActive: true, - isDirty: true, - isUpdating: false, - }, side: { isActive: true, - isDirty: true, + isDirty: false, isUpdating: false, }, }, }; - expect( isMetaBoxStateDirty( state ) ).toEqual( true ); + expect( getMetaBox( state, 'side' ) ).toEqual( { + isActive: true, + isDirty: false, + isUpdating: false, + } ); } ); } ); @@ -593,38 +542,11 @@ describe( 'selectors', () => { } ); describe( 'isEditedPostDirty', () => { - const metaBoxes = { - normal: { - isActive: false, - isDirty: false, - isUpdating: false, - }, - side: { - isActive: false, - isDirty: false, - isUpdating: false, - }, - }; - // Those dirty dang meta boxes. - const dirtyMetaBoxes = { - normal: { - isActive: true, - isDirty: true, - isUpdating: false, - }, - side: { - isActive: false, - isDirty: false, - isUpdating: false, - }, - }; - it( 'should return true when post saved state dirty', () => { const state = { editor: { isDirty: true, }, - metaBoxes, }; expect( isEditedPostDirty( state ) ).toBe( true ); @@ -635,22 +557,10 @@ describe( 'selectors', () => { editor: { isDirty: false, }, - metaBoxes, }; expect( isEditedPostDirty( state ) ).toBe( false ); } ); - - it( 'should return true when post saved state not dirty, but meta box state has changed.', () => { - const state = { - editor: { - isDirty: false, - }, - metaBoxes: dirtyMetaBoxes, - }; - - expect( isEditedPostDirty( state ) ).toBe( true ); - } ); } ); describe( 'isCleanNewPost', () => { @@ -2077,7 +1987,7 @@ describe( 'selectors', () => { expect( isSavingPost( state ) ).toBe( true ); } ); - it( 'should return false if the post is currently being saved', () => { + it( 'should return false if the post is not currently being saved', () => { const state = { saving: { requesting: false, @@ -2086,6 +1996,21 @@ describe( 'selectors', () => { expect( isSavingPost( state ) ).toBe( false ); } ); + + it( 'should return true if the post is notcurrently being saved but meta boxes are saving', () => { + const state = { + saving: { + requesting: false, + }, + metaBoxes: { + normal: { + isUpdating: true, + }, + }, + }; + + expect( isSavingPost( state ) ).toBe( true ); + } ); } ); describe( 'didPostSaveRequestSucceed', () => {