diff --git a/docs/data/data-core-editor.md b/docs/data/data-core-editor.md index becc9a84181138..7645b8da7cc512 100644 --- a/docs/data/data-core-editor.md +++ b/docs/data/data-core-editor.md @@ -1393,6 +1393,7 @@ the specified post object and editor settings. *Parameters* * post: Post object. + * edits: Initial edited attributes object. ### resetPost @@ -1429,7 +1430,6 @@ Returns an action object used to setup the editor state when first opening an ed * post: Post object. * blocks: Array of blocks. - * edits: Initial edited attributes object. ### resetBlocks @@ -1576,6 +1576,15 @@ Returns an action object resetting the template validity. Returns an action object synchronize the template with the list of blocks +### editPost + +Returns an action object used in signalling that attributes of the post have +been edited. + +*Parameters* + + * edits: Post attributes to edit. + ### savePost Returns an action object to save the post. diff --git a/lib/client-assets.php b/lib/client-assets.php index c34e03edc7d5f1..42829081cca2ea 100644 --- a/lib/client-assets.php +++ b/lib/client-assets.php @@ -1463,26 +1463,16 @@ function gutenberg_editor_scripts_and_styles( $hook ) { $demo_content = ob_get_clean(); $initial_edits = array( - 'title' => array( - 'raw' => __( 'Welcome to the Gutenberg Editor', 'gutenberg' ), - ), - 'content' => array( - 'raw' => $demo_content, - ), + 'title' => __( 'Welcome to the Gutenberg Editor', 'gutenberg' ), + 'content' => $demo_content, ); } elseif ( $is_new_post ) { // Override "(Auto Draft)" new post default title with empty string, // or filtered value. $initial_edits = array( - 'title' => array( - 'raw' => $post->post_title, - ), - 'content' => array( - 'raw' => $post->post_content, - ), - 'excerpt' => array( - 'raw' => $post->post_excerpt, - ), + 'title' => $post->post_title, + 'content' => $post->post_content, + 'excerpt' => $post->post_excerpt, ); } else { $initial_edits = null; diff --git a/packages/edit-post/src/editor.js b/packages/edit-post/src/editor.js index 35680ab884baf8..31a51bffcaa95d 100644 --- a/packages/edit-post/src/editor.js +++ b/packages/edit-post/src/editor.js @@ -14,7 +14,7 @@ function Editor( { hasFixedToolbar, focusMode, post, - overridePost, + initialEdits, onError, ...props } ) { @@ -32,7 +32,8 @@ function Editor( { diff --git a/packages/edit-post/src/index.js b/packages/edit-post/src/index.js index 70c8cf4d38fece..0832cbd141f697 100644 --- a/packages/edit-post/src/index.js +++ b/packages/edit-post/src/index.js @@ -22,18 +22,27 @@ import Editor from './editor'; * an unhandled error occurs, replacing previously mounted editor element using * an initial state from prior to the crash. * - * @param {Object} postType Post type of the post to edit. - * @param {Object} postId ID of the post to edit. - * @param {Element} target DOM node in which editor is rendered. - * @param {?Object} settings Editor settings object. - * @param {Object} overridePost Post properties to override. + * @param {Object} postType Post type of the post to edit. + * @param {Object} postId ID of the post to edit. + * @param {Element} target DOM node in which editor is rendered. + * @param {?Object} settings Editor settings object. + * @param {Object} initialEdits Programmatic edits to apply initially, to be + * considered as non-user-initiated (bypass for + * unsaved changes prompt). */ -export function reinitializeEditor( postType, postId, target, settings, overridePost ) { +export function reinitializeEditor( postType, postId, target, settings, initialEdits ) { unmountComponentAtNode( target ); - const reboot = reinitializeEditor.bind( null, postType, postId, target, settings, overridePost ); + const reboot = reinitializeEditor.bind( null, postType, postId, target, settings, initialEdits ); render( - , + , target ); } @@ -44,15 +53,17 @@ export function reinitializeEditor( postType, postId, target, settings, override * The return value of this function is not necessary if we change where we * call initializeEditor(). This is due to metaBox timing. * - * @param {string} id Unique identifier for editor instance. - * @param {Object} postType Post type of the post to edit. - * @param {Object} postId ID of the post to edit. - * @param {?Object} settings Editor settings object. - * @param {Object} overridePost Post properties to override. + * @param {string} id Unique identifier for editor instance. + * @param {Object} postType Post type of the post to edit. + * @param {Object} postId ID of the post to edit. + * @param {?Object} settings Editor settings object. + * @param {Object} initialEdits Programmatic edits to apply initially, to be + * considered as non-user-initiated (bypass for + * unsaved changes prompt). */ -export function initializeEditor( id, postType, postId, settings, overridePost ) { +export function initializeEditor( id, postType, postId, settings, initialEdits ) { const target = document.getElementById( id ); - const reboot = reinitializeEditor.bind( null, postType, postId, target, settings, overridePost ); + const reboot = reinitializeEditor.bind( null, postType, postId, target, settings, initialEdits ); registerCoreBlocks(); @@ -64,7 +75,13 @@ export function initializeEditor( id, postType, postId, settings, overridePost ) ] ); render( - , + , target ); } diff --git a/packages/editor/src/components/provider/index.js b/packages/editor/src/components/provider/index.js index 49cfc550d39c49..ebe4edf43e653a 100644 --- a/packages/editor/src/components/provider/index.js +++ b/packages/editor/src/components/provider/index.js @@ -28,7 +28,7 @@ class EditorProvider extends Component { props.updateEditorSettings( props.settings ); props.updatePostLock( props.settings.postLock ); - props.setupEditor( props.post ); + props.setupEditor( props.post, props.initialEdits ); if ( props.settings.autosave ) { props.createWarningNotice( diff --git a/packages/editor/src/store/actions.js b/packages/editor/src/store/actions.js index d0946c4f0e3d0b..265430e2852e0f 100644 --- a/packages/editor/src/store/actions.js +++ b/packages/editor/src/store/actions.js @@ -17,14 +17,16 @@ import { dispatch } from '@wordpress/data'; * Returns an action object used in signalling that editor has initialized with * the specified post object and editor settings. * - * @param {Object} post Post object. + * @param {Object} post Post object. + * @param {Object} edits Initial edited attributes object. * * @return {Object} Action object. */ -export function setupEditor( post ) { +export function setupEditor( post, edits ) { return { type: 'SETUP_EDITOR', post, + edits, }; } @@ -76,18 +78,16 @@ export function updatePost( edits ) { /** * Returns an action object used to setup the editor state when first opening an editor. * - * @param {Object} post Post object. - * @param {Array} blocks Array of blocks. - * @param {Object} edits Initial edited attributes object. + * @param {Object} post Post object. + * @param {Array} blocks Array of blocks. * * @return {Object} Action object. */ -export function setupEditorState( post, blocks, edits ) { +export function setupEditorState( post, blocks ) { return { type: 'SETUP_EDITOR_STATE', post, blocks, - edits, }; } @@ -381,6 +381,14 @@ export function synchronizeTemplate() { }; } +/** + * Returns an action object used in signalling that attributes of the post have + * been edited. + * + * @param {Object} edits Post attributes to edit. + * + * @return {Object} Action object. + */ export function editPost( edits ) { return { type: 'EDIT_POST', diff --git a/packages/editor/src/store/defaults.js b/packages/editor/src/store/defaults.js index 3145afdcb60b67..bdce6ea7427c44 100644 --- a/packages/editor/src/store/defaults.js +++ b/packages/editor/src/store/defaults.js @@ -119,3 +119,10 @@ export const EDITOR_SETTINGS_DEFAULTS = { // List of allowed mime types and file extensions. allowedMimeTypes: null, }; + +/** + * Default initial edits state. + * + * @type {Object} + */ +export const INITIAL_EDITS_DEFAULTS = {}; diff --git a/packages/editor/src/store/effects.js b/packages/editor/src/store/effects.js index 3f3aef99e5ad6d..5dd688e5d5fc71 100644 --- a/packages/editor/src/store/effects.js +++ b/packages/editor/src/store/effects.js @@ -1,7 +1,7 @@ /** * External dependencies */ -import { compact, last } from 'lodash'; +import { compact, last, has } from 'lodash'; /** * WordPress dependencies @@ -200,11 +200,20 @@ export default { ) ); }, SETUP_EDITOR( action, store ) { - const { post } = action; + const { post, edits } = action; const state = store.getState(); - // Parse content as blocks - let blocks = parse( post.content.raw ); + // In order to ensure maximum of a single parse during setup, edits are + // included as part of editor setup action. Assume edited content as + // canonical if provided, falling back to post. + let content; + if ( has( edits, [ 'content' ] ) ) { + content = edits.content; + } else { + content = post.content.raw; + } + + let blocks = parse( content ); // Apply a template for new posts only, if exists. const isNewPost = post.status === 'auto-draft'; @@ -213,13 +222,7 @@ export default { blocks = synchronizeBlocksWithTemplate( blocks, template ); } - // Include auto draft title in edits while not flagging post as dirty - const edits = {}; - if ( isNewPost ) { - edits.title = post.title.raw; - } - - const setupAction = setupEditorState( post, blocks, edits ); + const setupAction = setupEditorState( post, blocks ); return compact( [ setupAction, diff --git a/packages/editor/src/store/reducer.js b/packages/editor/src/store/reducer.js index db5e59ca930b87..83e252d204c4d5 100644 --- a/packages/editor/src/store/reducer.js +++ b/packages/editor/src/store/reducer.js @@ -28,7 +28,11 @@ import { combineReducers } from '@wordpress/data'; */ import withHistory from '../utils/with-history'; import withChangeDetection from '../utils/with-change-detection'; -import { PREFERENCES_DEFAULTS, EDITOR_SETTINGS_DEFAULTS } from './defaults'; +import { + PREFERENCES_DEFAULTS, + EDITOR_SETTINGS_DEFAULTS, + INITIAL_EDITS_DEFAULTS, +} from './defaults'; import { insertAt, moveTo } from './array'; /** @@ -97,6 +101,23 @@ function getFlattenedBlocks( blocks ) { return flattenedBlocks; } +/** + * Returns an object against which it is safe to perform mutating operations, + * given the original object and its current working copy. + * + * @param {Object} original Original object. + * @param {Object} working Working object. + * + * @return {Object} Mutation-safe object. + */ +function getMutateSafeObject( original, working ) { + if ( original === working ) { + return { ...original }; + } + + return working; +} + /** * Returns true if the two object arguments have the same keys, or false * otherwise. @@ -219,16 +240,10 @@ export const editor = flow( [ edits( state = {}, action ) { switch ( action.type ) { case 'EDIT_POST': - case 'SETUP_EDITOR_STATE': return reduce( action.edits, ( result, value, key ) => { // Only assign into result if not already same value if ( value !== state[ key ] ) { - // Avoid mutating original state by creating shallow - // clone. Should only occur once per reduce. - if ( result === state ) { - result = { ...state }; - } - + result = getMutateSafeObject( state, result ); result[ key ] = value; } @@ -253,10 +268,7 @@ export const editor = flow( [ return result; } - if ( state === result ) { - result = { ...state }; - } - + result = getMutateSafeObject( state, result ); delete result[ key ]; return result; }, state ); @@ -296,11 +308,7 @@ export const editor = flow( [ // Consider as updates only changed values const nextAttributes = reduce( action.attributes, ( result, value, key ) => { if ( value !== result[ key ] ) { - // Avoid mutating original block by creating shallow clone - if ( result === state[ action.clientId ].attributes ) { - result = { ...result }; - } - + result = getMutateSafeObject( state[ action.clientId ].attributes, result ); result[ key ] = value; } @@ -514,6 +522,52 @@ export const editor = flow( [ } ), } ); +/** + * Reducer returning the initial edits state. With matching shape to that of + * `editor.edits`, the initial edits are those applied programmatically, are + * not considered in prmopting the user for unsaved changes, and are included + * in (and reset by) the next save payload. + * + * @param {Object} state Current state. + * @param {Object} action Action object. + * + * @return {Object} Next state. + */ +export function initialEdits( state = INITIAL_EDITS_DEFAULTS, action ) { + switch ( action.type ) { + case 'SETUP_EDITOR': + if ( ! action.edits ) { + break; + } + + return action.edits; + + case 'RESET_BLOCKS': + case 'SETUP_EDITOR_STATE': + if ( 'content' in state ) { + return omit( state, 'content' ); + } + + return state; + + case 'UPDATE_POST': + return reduce( action.edits, ( result, value, key ) => { + if ( ! result.hasOwnProperty( key ) ) { + return result; + } + + result = getMutateSafeObject( state, result ); + delete result[ key ]; + return result; + }, state ); + + case 'RESET_POST': + return INITIAL_EDITS_DEFAULTS; + } + + return state; +} + /** * Reducer returning the last-known state of the current post, in the format * returned by the WP REST API. @@ -923,10 +977,7 @@ export const reusableBlocks = combineReducers( { const value = { clientId, title }; if ( ! isEqual( nextState[ id ], value ) ) { - if ( nextState === state ) { - nextState = { ...nextState }; - } - + nextState = getMutateSafeObject( state, nextState ); nextState[ id ] = value; } @@ -1095,6 +1146,7 @@ export function autosave( state = null, action ) { export default optimist( combineReducers( { editor, + initialEdits, currentPost, isTyping, isCaretWithinFormattedText, diff --git a/packages/editor/src/store/selectors.js b/packages/editor/src/store/selectors.js index b6613d0421574a..fbb560176ec62e 100644 --- a/packages/editor/src/store/selectors.js +++ b/packages/editor/src/store/selectors.js @@ -220,9 +220,18 @@ export function getCurrentPostLastRevisionId( state ) { * * @return {Object} Object of key value pairs comprising unsaved edits. */ -export function getPostEdits( state ) { - return state.editor.present.edits; -} +export const getPostEdits = createSelector( + ( state ) => { + return { + ...state.initialEdits, + ...state.editor.present.edits, + }; + }, + ( state ) => [ + state.editor.present.edits, + state.initialEdits, + ] +); /** * Returns an attribute value of the saved post. @@ -591,6 +600,7 @@ export const getBlock = createSelector( state.editor.present.blocks.byClientId[ clientId ], getBlockDependantsCacheBust( state, clientId ), state.editor.present.edits.meta, + state.initialEdits.meta, state.currentPost.meta, ] ); @@ -698,6 +708,7 @@ export const getBlocksByClientId = createSelector( ), ( state ) => [ state.editor.present.edits.meta, + state.initialEdits.meta, state.currentPost.meta, state.editor.present.blocks, ] @@ -1016,6 +1027,7 @@ export const getMultiSelectedBlocks = createSelector( state.blockSelection.end, state.editor.present.blocks.byClientId, state.editor.present.edits.meta, + state.initialEdits.meta, state.currentPost.meta, ] ); @@ -1533,6 +1545,7 @@ export const getEditedPostContent = createSelector( }, ( state ) => [ state.editor.present.edits.content, + state.initialEdits.content, state.editor.present.blocks, ], ); diff --git a/packages/editor/src/store/test/reducer.js b/packages/editor/src/store/test/reducer.js index 1864e95a6ce174..7b5a7c8d1b5f2c 100644 --- a/packages/editor/src/store/test/reducer.js +++ b/packages/editor/src/store/test/reducer.js @@ -1038,22 +1038,6 @@ describe( 'state', () => { } ); } ); - it( 'should save initial post state', () => { - const state = editor( undefined, { - type: 'SETUP_EDITOR_STATE', - edits: { - status: 'draft', - title: 'post title', - }, - blocks: [], - } ); - - expect( state.present.edits ).toEqual( { - status: 'draft', - title: 'post title', - } ); - } ); - it( 'should omit content when resetting', () => { // Use case: When editing in Text mode, we defer to content on // the property, but we reset blocks by parse when switching diff --git a/packages/editor/src/store/test/selectors.js b/packages/editor/src/store/test/selectors.js index ea2ebd04664680..64303d84aaa3c8 100644 --- a/packages/editor/src/store/test/selectors.js +++ b/packages/editor/src/store/test/selectors.js @@ -231,6 +231,7 @@ describe( 'selectors', () => { }, }, }, + initialEdits: {}, }; expect( isEditedPostNew( state ) ).toBe( true ); @@ -248,6 +249,7 @@ describe( 'selectors', () => { }, }, }, + initialEdits: {}, }; expect( isEditedPostNew( state ) ).toBe( false ); @@ -517,6 +519,7 @@ describe( 'selectors', () => { edits: {}, }, }, + initialEdits: {}, }; expect( getEditedPostAttribute( state, 'slug' ) ).toBe( 'post slug' ); @@ -532,6 +535,7 @@ describe( 'selectors', () => { }, }, }, + initialEdits: {}, }; expect( getEditedPostAttribute( state, 'slug' ) ).toBe( 'new slug' ); @@ -547,6 +551,7 @@ describe( 'selectors', () => { edits: { status: 'private' }, }, }, + initialEdits: {}, }; expect( getEditedPostAttribute( state, 'title' ) ).toBe( 'sassel' ); @@ -562,6 +567,7 @@ describe( 'selectors', () => { edits: { title: 'youcha' }, }, }, + initialEdits: {}, }; expect( getEditedPostAttribute( state, 'title' ) ).toBe( 'youcha' ); @@ -575,6 +581,7 @@ describe( 'selectors', () => { edits: {}, }, }, + initialEdits: {}, }; expect( getEditedPostAttribute( state, 'valueOf' ) ).toBeUndefined(); @@ -689,6 +696,7 @@ describe( 'selectors', () => { edits: { title: 'terga' }, }, }, + initialEdits: {}, }; expect( getPostEdits( state ) ).toEqual( { title: 'terga' } ); @@ -706,6 +714,7 @@ describe( 'selectors', () => { edits: {}, }, }, + initialEdits: {}, }; expect( getEditedPostVisibility( state ) ).toBe( 'public' ); @@ -721,6 +730,7 @@ describe( 'selectors', () => { edits: {}, }, }, + initialEdits: {}, }; expect( getEditedPostVisibility( state ) ).toBe( 'private' ); @@ -737,6 +747,7 @@ describe( 'selectors', () => { edits: {}, }, }, + initialEdits: {}, }; expect( getEditedPostVisibility( state ) ).toBe( 'password' ); @@ -756,6 +767,7 @@ describe( 'selectors', () => { }, }, }, + initialEdits: {}, }; expect( getEditedPostVisibility( state ) ).toBe( 'private' ); @@ -1060,6 +1072,7 @@ describe( 'selectors', () => { edits: {}, }, }, + initialEdits: {}, currentPost: {}, saving: {}, }; @@ -1078,6 +1091,7 @@ describe( 'selectors', () => { edits: {}, }, }, + initialEdits: {}, currentPost: { title: 'sassel', }, @@ -1100,6 +1114,7 @@ describe( 'selectors', () => { edits: {}, }, }, + initialEdits: {}, currentPost: { title: 'sassel', }, @@ -1120,6 +1135,7 @@ describe( 'selectors', () => { edits: {}, }, }, + initialEdits: {}, currentPost: { excerpt: 'sassel', }, @@ -1150,6 +1166,7 @@ describe( 'selectors', () => { edits: {}, }, }, + initialEdits: {}, currentPost: {}, saving: {}, }; @@ -1170,6 +1187,7 @@ describe( 'selectors', () => { edits: {}, }, }, + initialEdits: {}, currentPost: { title: 'sassel', }, @@ -1195,6 +1213,7 @@ describe( 'selectors', () => { edits: {}, }, }, + initialEdits: {}, currentPost: { title: 'sassel', }, @@ -1215,6 +1234,7 @@ describe( 'selectors', () => { edits: {}, }, }, + initialEdits: {}, currentPost: { title: 'foo', excerpt: 'foo', @@ -1265,6 +1285,7 @@ describe( 'selectors', () => { edits: {}, }, }, + initialEdits: {}, currentPost: { title: 'foo', content: 'foo', @@ -1337,6 +1358,7 @@ describe( 'selectors', () => { edits: {}, }, }, + initialEdits: {}, currentPost: {}, }; @@ -1364,6 +1386,7 @@ describe( 'selectors', () => { edits: {}, }, }, + initialEdits: {}, currentPost: {}, }; @@ -1381,6 +1404,7 @@ describe( 'selectors', () => { edits: {}, }, }, + initialEdits: {}, currentPost: { content: '', }, @@ -1402,6 +1426,7 @@ describe( 'selectors', () => { }, }, }, + initialEdits: {}, currentPost: {}, }; @@ -1417,6 +1442,7 @@ describe( 'selectors', () => { edits: { date: moment().add( 7, 'days' ).format( '' ) }, }, }, + initialEdits: {}, }; expect( isEditedPostBeingScheduled( state ) ).toBe( true ); @@ -1429,6 +1455,7 @@ describe( 'selectors', () => { edits: { date: '2016-05-30T17:21:39' }, }, }, + initialEdits: {}, }; expect( isEditedPostBeingScheduled( state ) ).toBe( false ); @@ -1436,16 +1463,6 @@ describe( 'selectors', () => { } ); describe( 'isEditedPostDateFloating', () => { - let editor; - - beforeEach( () => { - editor = { - present: { - edits: {}, - }, - }; - } ); - it( 'should return true for draft posts where the date matches the modified date', () => { const state = { currentPost: { @@ -1453,7 +1470,12 @@ describe( 'selectors', () => { modified: '2018-09-27T01:23:45.678Z', status: 'draft', }, - editor, + editor: { + present: { + edits: {}, + }, + }, + initialEdits: {}, }; expect( isEditedPostDateFloating( state ) ).toBe( true ); @@ -1466,7 +1488,12 @@ describe( 'selectors', () => { modified: '2018-09-27T01:23:45.678Z', status: 'auto-draft', }, - editor, + editor: { + present: { + edits: {}, + }, + }, + initialEdits: {}, }; expect( isEditedPostDateFloating( state ) ).toBe( true ); @@ -1479,7 +1506,12 @@ describe( 'selectors', () => { modified: '1970-01-01T00:00:00.000Z', status: 'draft', }, - editor, + editor: { + present: { + edits: {}, + }, + }, + initialEdits: {}, }; expect( isEditedPostDateFloating( state ) ).toBe( false ); @@ -1492,7 +1524,12 @@ describe( 'selectors', () => { modified: '1970-01-01T00:00:00.000Z', status: 'auto-draft', }, - editor, + editor: { + present: { + edits: {}, + }, + }, + initialEdits: {}, }; expect( isEditedPostDateFloating( state ) ).toBe( false ); @@ -1505,7 +1542,12 @@ describe( 'selectors', () => { modified: '2018-09-27T01:23:45.678Z', status: 'publish', }, - editor, + editor: { + present: { + edits: {}, + }, + }, + initialEdits: {}, }; expect( isEditedPostDateFloating( state ) ).toBe( false ); @@ -1535,6 +1577,7 @@ describe( 'selectors', () => { edits: {}, }, }, + initialEdits: {}, }; const nextState = { @@ -1553,6 +1596,7 @@ describe( 'selectors', () => { edits: {}, }, }, + initialEdits: {}, }; expect( @@ -1577,6 +1621,7 @@ describe( 'selectors', () => { edits: {}, }, }, + initialEdits: {}, }; const nextState = { @@ -1597,6 +1642,7 @@ describe( 'selectors', () => { edits: {}, }, }, + initialEdits: {}, }; expect( @@ -1627,6 +1673,7 @@ describe( 'selectors', () => { edits: {}, }, }, + initialEdits: {}, }; const nextState = { @@ -1647,6 +1694,7 @@ describe( 'selectors', () => { edits: {}, }, }, + initialEdits: {}, }; expect( @@ -1676,6 +1724,7 @@ describe( 'selectors', () => { edits: {}, }, }, + initialEdits: {}, }; const nextState = { @@ -1696,6 +1745,7 @@ describe( 'selectors', () => { edits: {}, }, }, + initialEdits: {}, }; expect( @@ -1729,6 +1779,7 @@ describe( 'selectors', () => { edits: {}, }, }, + initialEdits: {}, }; const nextState = { @@ -1751,6 +1802,7 @@ describe( 'selectors', () => { edits: {}, }, }, + initialEdits: {}, }; expect( @@ -1772,6 +1824,7 @@ describe( 'selectors', () => { edits: {}, }, }, + initialEdits: {}, }; const name = getBlockName( state, 'afd1cb17-2c08-4e7a-91be-007ba7ddc3a1' ); @@ -1800,6 +1853,7 @@ describe( 'selectors', () => { edits: {}, }, }, + initialEdits: {}, }; const name = getBlockName( state, 'afd1cb17-2c08-4e7a-91be-007ba7ddc3a1' ); @@ -1826,6 +1880,7 @@ describe( 'selectors', () => { edits: {}, }, }, + initialEdits: {}, }; expect( getBlock( state, 123 ) ).toEqual( { @@ -1848,6 +1903,7 @@ describe( 'selectors', () => { edits: {}, }, }, + initialEdits: {}, }; expect( getBlock( state, 123 ) ).toBe( null ); @@ -1872,6 +1928,7 @@ describe( 'selectors', () => { edits: {}, }, }, + initialEdits: {}, }; expect( getBlock( state, 123 ) ).toEqual( { @@ -1921,6 +1978,7 @@ describe( 'selectors', () => { edits: {}, }, }, + initialEdits: {}, }; expect( getBlock( state, 123 ) ).toEqual( { @@ -1954,6 +2012,7 @@ describe( 'selectors', () => { edits: {}, }, }, + initialEdits: {}, }; expect( getBlocks( state ) ).toEqual( [ @@ -2008,6 +2067,7 @@ describe( 'selectors', () => { edits: {}, }, }, + initialEdits: {}, }; expect( getClientIdsOfDescendants( state, [ 'uuid-10' ] ) ).toEqual( [ 'uuid-12', @@ -2067,6 +2127,7 @@ describe( 'selectors', () => { edits: {}, }, }, + initialEdits: {}, }; expect( getClientIdsWithDescendants( state ) ).toEqual( [ 'uuid-6', @@ -2262,6 +2323,7 @@ describe( 'selectors', () => { edits: {}, }, }, + initialEdits: {}, blockSelection: { start: null, end: null }, }; @@ -2287,6 +2349,7 @@ describe( 'selectors', () => { edits: {}, }, }, + initialEdits: {}, blockSelection: { start: 23, end: 123 }, }; @@ -2312,6 +2375,7 @@ describe( 'selectors', () => { edits: {}, }, }, + initialEdits: {}, blockSelection: { start: 23, end: 23 }, }; @@ -2474,6 +2538,7 @@ describe( 'selectors', () => { edits: {}, }, }, + initialEdits: {}, blockSelection: { start: null, end: null }, currentPost: {}, }; @@ -3073,6 +3138,7 @@ describe( 'selectors', () => { edits: {}, }, }, + initialEdits: {}, insertionPoint: { rootClientId: undefined, index: 0, @@ -3107,6 +3173,7 @@ describe( 'selectors', () => { edits: {}, }, }, + initialEdits: {}, insertionPoint: null, }; @@ -3140,6 +3207,7 @@ describe( 'selectors', () => { edits: {}, }, }, + initialEdits: {}, insertionPoint: null, }; @@ -3173,6 +3241,7 @@ describe( 'selectors', () => { edits: {}, }, }, + initialEdits: {}, insertionPoint: null, }; @@ -3206,6 +3275,7 @@ describe( 'selectors', () => { edits: {}, }, }, + initialEdits: {}, insertionPoint: null, }; @@ -3315,6 +3385,7 @@ describe( 'selectors', () => { edits: {}, }, }, + initialEdits: {}, currentPost: {}, }; @@ -3337,6 +3408,7 @@ describe( 'selectors', () => { edits: {}, }, }, + initialEdits: {}, currentPost: {}, }; @@ -3358,6 +3430,7 @@ describe( 'selectors', () => { edits: {}, }, }, + initialEdits: {}, currentPost: {}, }; @@ -3379,6 +3452,7 @@ describe( 'selectors', () => { edits: {}, }, }, + initialEdits: {}, currentPost: {}, }; @@ -3400,6 +3474,7 @@ describe( 'selectors', () => { edits: {}, }, }, + initialEdits: {}, currentPost: {}, }; @@ -3422,6 +3497,7 @@ describe( 'selectors', () => { edits: {}, }, }, + initialEdits: {}, currentPost: {}, }; @@ -3488,6 +3564,7 @@ describe( 'selectors', () => { }, }, }, + initialEdits: {}, currentPost: {}, }; @@ -3513,6 +3590,7 @@ describe( 'selectors', () => { edits: {}, }, }, + initialEdits: {}, currentPost: {}, }; @@ -3539,6 +3617,7 @@ describe( 'selectors', () => { edits: {}, }, }, + initialEdits: {}, currentPost: {}, }; @@ -3569,6 +3648,7 @@ describe( 'selectors', () => { edits: {}, }, }, + initialEdits: {}, currentPost: {}, }; @@ -3593,6 +3673,7 @@ describe( 'selectors', () => { edits: {}, }, }, + initialEdits: {}, currentPost: {}, }; @@ -3623,6 +3704,7 @@ describe( 'selectors', () => { edits: {}, }, }, + initialEdits: {}, currentPost: {}, }; @@ -3826,6 +3908,7 @@ describe( 'selectors', () => { edits: {}, }, }, + initialEdits: {}, reusableBlocks: { data: { 1: { clientId: 'block1', title: 'Reusable Block 1' }, @@ -3886,6 +3969,7 @@ describe( 'selectors', () => { edits: {}, }, }, + initialEdits: {}, reusableBlocks: { data: { 1: { clientId: 'block1', title: 'Reusable Block 1' }, @@ -3925,6 +4009,7 @@ describe( 'selectors', () => { edits: {}, }, }, + initialEdits: {}, reusableBlocks: { data: { 1: { clientId: 'block1', title: 'Reusable Block 1' }, @@ -3986,6 +4071,7 @@ describe( 'selectors', () => { edits: {}, }, }, + initialEdits: {}, reusableBlocks: { data: {}, }, @@ -4012,6 +4098,7 @@ describe( 'selectors', () => { edits: {}, }, }, + initialEdits: {}, reusableBlocks: { data: {}, }, @@ -4038,6 +4125,7 @@ describe( 'selectors', () => { edits: {}, }, }, + initialEdits: {}, reusableBlocks: { data: {}, }, @@ -4071,6 +4159,7 @@ describe( 'selectors', () => { edits: {}, }, }, + initialEdits: {}, reusableBlocks: { data: {}, }, @@ -4302,9 +4391,6 @@ describe( 'selectors', () => { saving: { requesting: false, }, - editor: { - edits: {}, - }, currentPost: { status: 'publish', }, @@ -4319,9 +4405,6 @@ describe( 'selectors', () => { saving: { requesting: true, }, - editor: { - edits: {}, - }, currentPost: { status: 'draft', }, @@ -4336,9 +4419,6 @@ describe( 'selectors', () => { saving: { requesting: true, }, - editor: { - edits: {}, - }, currentPost: { status: 'publish', }, @@ -4355,9 +4435,6 @@ describe( 'selectors', () => { saving: { requesting: false, }, - editor: { - edits: {}, - }, currentPost: { status: 'publish', }, @@ -4372,9 +4449,6 @@ describe( 'selectors', () => { saving: { requesting: true, }, - editor: { - edits: {}, - }, currentPost: { status: 'publish', }, @@ -4391,11 +4465,6 @@ describe( 'selectors', () => { saving: { requesting: false, }, - editor: { - edits: { - status: 'publish', - }, - }, currentPost: { status: 'draft', }, @@ -4410,9 +4479,6 @@ describe( 'selectors', () => { saving: { requesting: true, }, - editor: { - edits: {}, - }, currentPost: { status: 'publish', }, @@ -4509,6 +4575,7 @@ describe( 'selectors', () => { edits: {}, }, }, + initialEdits: {}, }; expect( isPermalinkEditable( state ) ).toBe( false ); @@ -4522,6 +4589,7 @@ describe( 'selectors', () => { edits: {}, }, }, + initialEdits: {}, }; expect( isPermalinkEditable( state ) ).toBe( false ); @@ -4535,6 +4603,7 @@ describe( 'selectors', () => { edits: {}, }, }, + initialEdits: {}, }; expect( isPermalinkEditable( state ) ).toBe( true ); @@ -4548,6 +4617,7 @@ describe( 'selectors', () => { edits: {}, }, }, + initialEdits: {}, }; expect( isPermalinkEditable( state ) ).toBe( true ); @@ -4564,6 +4634,7 @@ describe( 'selectors', () => { edits: {}, }, }, + initialEdits: {}, }; expect( getPermalink( state ) ).toBe( url ); @@ -4580,6 +4651,7 @@ describe( 'selectors', () => { edits: {}, }, }, + initialEdits: {}, }; expect( getPermalink( state ) ).toBe( 'http://foo.test/bar/baz/' ); @@ -4603,6 +4675,7 @@ describe( 'selectors', () => { edits: {}, }, }, + initialEdits: {}, }; expect( getPermalinkParts( state ) ).toEqual( parts ); @@ -4623,6 +4696,7 @@ describe( 'selectors', () => { edits: {}, }, }, + initialEdits: {}, }; expect( getPermalinkParts( state ) ).toEqual( parts );