diff --git a/jetpack b/jetpack index 3ec4ba6abc..45bd3eb8e0 160000 --- a/jetpack +++ b/jetpack @@ -1 +1 @@ -Subproject commit 3ec4ba6abcdf76fb8c9b4750a4581e62efc5254a +Subproject commit 45bd3eb8e002552570a292551373478206b721c5 diff --git a/src/allowed-blocks-setup.js b/src/allowed-blocks-setup.js new file mode 100644 index 0000000000..06457bed92 --- /dev/null +++ b/src/allowed-blocks-setup.js @@ -0,0 +1,120 @@ +/** + * WordPress dependencies + */ +import { dispatch } from '@wordpress/data'; +import { getBlockTypes } from '@wordpress/blocks'; +/** + * Internal dependencies + */ +import { JETPACK_DATA_PATH } from '../jetpack/projects/plugins/jetpack/extensions/shared/get-jetpack-data'; +import { registerBlock as registerJetpackLayoutGridBlock } from '../block-experiments/blocks/layout-grid/src'; +import { + registerContactInfoBlock as registerJetpackContactInfoBlock, + registerStoryBlock as registerJetpackStoryBlock, +} from '../jetpack/projects/plugins/jetpack/extensions/editor.native'; + +// Please also consider updating ./block-support/supported-blocks.json +const availableJetpackBlocks = { + 'contact-info': { available: true }, + 'layout-grid': { available: true }, + story: { available: true }, +}; + +const mapToJetpackData = ( { + isJetpackActive = false, + userData: tracksUserData = null, + siteFragment = null, + blogId: wpcomBlogId = 1, +} ) => { + return { + siteFragment, + tracksUserData, + wpcomBlogId, + jetpack: { is_active: isJetpackActive }, + available_blocks: availableJetpackBlocks, + }; +}; + +const registerJetpackBlocksIfCapable = ( props = {} ) => { + const { + capabilities: { + layoutGridBlock = false, + mediaFilesCollectionBlock = false, + contactInfoBlock = false, + } = {}, + } = props; + + if ( layoutGridBlock ) { + registerJetpackLayoutGridBlock(); + } + + if ( mediaFilesCollectionBlock ) { + registerJetpackStoryBlock(); + } + + if ( contactInfoBlock ) { + registerJetpackContactInfoBlock(); + } +}; + +export const setupJetpackBlocks = ( props = {} ) => { + const { jetpackState = { blogId: 1, isJetpackActive: true } } = props; + const { isJetpackActive = false } = jetpackState; + + if ( isJetpackActive ) { + global.window[ JETPACK_DATA_PATH ] = mapToJetpackData( jetpackState ); + registerJetpackBlocksIfCapable( props ); + } +}; + +export const setupAllowedBlocks = ( props = {} ) => { + const registeredBlocks = getBlockTypes().map( ( { name } ) => name ); + const { showBlocks = registeredBlocks, hideBlocks = [] } = props; + const wereShowBlocksProvided = showBlocks !== registeredBlocks; + const uniqueRegisteredHideBlocks = hideBlocks.filter( ( name, index ) => { + return ( + // Is Unique? + hideBlocks.indexOf( name ) === index && + // Is Unambiguous? + ( ! wereShowBlocksProvided || ! showBlocks.includes( name ) ) && + // Is Registered? + registeredBlocks.includes( name ) + ); + } ); + const uniqueRegisteredShowBlocks = ! wereShowBlocksProvided + ? showBlocks + : showBlocks.filter( ( name, index ) => { + return ( + // Is Unique? + showBlocks.indexOf( name ) === index && + // Is Unambiguous? + ! hideBlocks.includes( name ) && + // Is Registered? + registeredBlocks.includes( name ) + ); + } ); + const wereShowBlocksFilteredDownToAnEmptySet = + wereShowBlocksProvided && + showBlocks.length > 0 && + uniqueRegisteredShowBlocks.length === 0; + const invertRegisteredShowBlocks = wereShowBlocksFilteredDownToAnEmptySet + ? [] + : registeredBlocks.filter( ( name ) => { + return ! uniqueRegisteredShowBlocks.includes( name ); + } ); + const hiddenBlockTypes = [ + ...uniqueRegisteredHideBlocks, + ...invertRegisteredShowBlocks, + ]; + + if ( hiddenBlockTypes.length > 0 ) { + dispatch( 'core/edit-post' ).hideBlockTypes( [ + ...new Set( hiddenBlockTypes ), + ] ); + } +}; + +export const setupBlocks = ( props = {} ) => { + setupJetpackBlocks( props ); + setupAllowedBlocks( props ); +}; diff --git a/src/block-experiments-setup.js b/src/block-experiments-setup.js deleted file mode 100644 index 037826718c..0000000000 --- a/src/block-experiments-setup.js +++ /dev/null @@ -1,8 +0,0 @@ -// This file is to set up the jetpack/layout-grid block that currently lives in block-experiments/blocks/layout-grid -import { registerBlock } from '../block-experiments/blocks/layout-grid/src'; - -export default function setupBlockExperiments( capabilities ) { - if ( capabilities.layoutGridBlock ) { - registerBlock(); - } -} diff --git a/src/index.js b/src/index.js index f1bbf1af93..91532a4b19 100644 --- a/src/index.js +++ b/src/index.js @@ -11,8 +11,7 @@ import { * Internal dependencies */ import correctTextFontWeight from './text-font-weight-correct'; -import setupJetpackEditor from './jetpack-editor-setup'; -import setupBlockExperiments from './block-experiments-setup'; +import { setupBlocks } from './allowed-blocks-setup'; import initialHtml from './initial-html'; addAction( 'native.pre-render', 'gutenberg-mobile', () => { @@ -21,11 +20,7 @@ addAction( 'native.pre-render', 'gutenberg-mobile', () => { } ); addAction( 'native.render', 'gutenberg-mobile', ( props ) => { - setupJetpackEditor( - props.jetpackState || { blogId: 1, isJetpackActive: true } - ); - const capabilities = props.capabilities ?? {}; - setupBlockExperiments( capabilities ); + setupBlocks( props ); } ); addFilter( 'native.block_editor_props', 'gutenberg-mobile', ( editorProps ) => { diff --git a/src/jetpack-editor-setup.js b/src/jetpack-editor-setup.js deleted file mode 100644 index f6405ddbd6..0000000000 --- a/src/jetpack-editor-setup.js +++ /dev/null @@ -1,75 +0,0 @@ -/** - * Internal dependencies - */ -import { JETPACK_DATA_PATH } from '../jetpack/projects/plugins/jetpack/extensions/shared/get-jetpack-data'; -/** - * WordPress dependencies - */ -import { dispatch, select } from '@wordpress/data'; - -// When adding new blocks to this list please also consider updating ./block-support/supported-blocks.json -const supportedJetpackBlocks = { - 'contact-info': { - available: true, - }, - story: { - available: true, - }, -}; - -const setJetpackData = ( { - isJetpackActive = false, - userData = null, - siteFragment = null, - blogId, -} ) => { - const availableBlocks = supportedJetpackBlocks; - const jetpackEditorInitialState = { - available_blocks: availableBlocks, - jetpack: { - is_active: isJetpackActive, - }, - siteFragment, - tracksUserData: userData, - wpcomBlogId: blogId, - }; - global.window[ JETPACK_DATA_PATH ] = jetpackEditorInitialState; - return jetpackEditorInitialState; -}; - -export default ( jetpackState ) => { - if ( ! jetpackState.isJetpackActive ) { - return; - } - - const jetpackData = setJetpackData( jetpackState ); - - const toggleBlock = ( capability, blockName ) => { - if ( capability !== true ) { - dispatch( 'core/edit-post' ).hideBlockTypes( [ blockName ] ); - } else { - dispatch( 'core/edit-post' ).showBlockTypes( [ blockName ] ); - } - }; - - // Note on the use of setTimeout() here: - // We observed the settings may not be ready exactly when the native.render hooks get run but rather - // right after that execution cycle (because state hasn't changed yet). Hence, we're only checking for - // the actual settings to be loaded by using setTimeout without a delay parameter. This ensures the - // settings are loaded onto the store and we can use the core/block-editor selector by the time we do - // the actual check. - - // eslint-disable-next-line @wordpress/react-no-unsafe-timeout - setTimeout( () => { - const capabilities = select( 'core/block-editor' ).getSettings( - 'capabilities' - ); - - toggleBlock( capabilities.mediaFilesCollectionBlock, 'jetpack/story' ); - toggleBlock( capabilities.contactInfoBlock, 'jetpack/contact-info' ); - } ); - - require( '../jetpack/projects/plugins/jetpack/extensions/editor' ); - - return jetpackData; -}; diff --git a/src/test/index.js b/src/test/index.js index f0bd82863e..895a5d21c3 100644 --- a/src/test/index.js +++ b/src/test/index.js @@ -1,28 +1,481 @@ -describe( 'Test Jetpack blocks', () => { - it( 'should setup the editor for jetpack without failing', () => { - const mockRegisterBlockCollection = jest.fn(); - jest.mock( '@wordpress/blocks', () => { - return { - getCategories: () => [ { slug: 'media' } ], - setCategories: jest.fn(), - registerBlockCollection: mockRegisterBlockCollection, - withBlockContentContext: jest.fn(), +import { + getBlockTypes, + registerBlockType, + unregisterBlockType, +} from '@wordpress/blocks'; +import { select } from '@wordpress/data'; +import { defaultHooks } from '@wordpress/hooks'; +import { JETPACK_DATA_PATH } from '../../jetpack/projects/plugins/jetpack/extensions/shared/get-jetpack-data'; + +/** + * These are integration tests written with the intention of asserting the initialization of the Gutenberg Mobile + * editor. As they are integration tests, modules that were being mocked globally are now unmocked to use their + * real implementations. + * + * The intention of these integration tests is to ensure that: + * 0. Jetpack initialization is handled correctly by registering the Jetpack Block Collection, initializing Jetpack Data, + * and registering all Jetpack Block Types that you may be capable of using. + * 1. Allowed block types are displayed correctly in the block selector if a subset of blocks is provided to be shown + * or hidden. + * + * The tests are staged such that `require( '../index' )` mimics the entry point of the initialization of the Gutenberg + * Mobile editor, and `defaultHooks.doAction( 'native.render', props )` is the `native.render` hook that would normally be + * listened for when the editor is initializing. So all the tests ensure that when certain `props` are passed in from the + * `native.render` hook that the underlying Redux Store state is reduced expectedly. This is deliberately done to keep + * the tests as black-box as possible such that the implementation details of the application code may be changed more + * freely without a tight coupling on the code that tests it. + */ +describe( 'Gutenberg Mobile Initialization', () => { + beforeAll( () => { + jest.unmock( '@wordpress/api-fetch' ); + jest.unmock( '@wordpress/blocks' ); + } ); + + describe( 'Jetpack Blocks', () => { + it( `should register Jetpack block collection.`, () => { + // Arrange + const expectedCollectionTitle = 'Jetpack'; + const props = { jetpackState: { isJetpackActive: false } }; + require( '../index' ); + // Act + defaultHooks.doAction( 'native.render', props ); + // Assert + const { getCollections } = select( 'core/blocks' ); + const { + jetpack: { title: actualCollectionTitle = '' } = {}, + } = getCollections(); + expect( actualCollectionTitle ).toEqual( expectedCollectionTitle ); + } ); + + it( `should NOT register JETPACK_DATA_PATH when Jetpack is INACTIVE.`, () => { + // Arrange + const expectedJetpackData = undefined; + const props = { jetpackState: { isJetpackActive: false } }; + require( '../index' ); + // Act + defaultHooks.doAction( 'native.render', props ); + // Assert + const actualJetpackData = global.window[ JETPACK_DATA_PATH ]; + expect( actualJetpackData ).toEqual( expectedJetpackData ); + } ); + + it( `should register JETPACK_DATA_PATH with DEFAULT values when Jetpack is ACTIVE + AND Jetpack state is UNPROVIDED.`, () => { + // Arrange + const expectedJetpackData = { + available_blocks: { + 'contact-info': { available: true }, + 'layout-grid': { available: true }, + story: { available: true }, + }, + jetpack: { is_active: true }, + siteFragment: null, + tracksUserData: null, + wpcomBlogId: 1, + }; + const props = { jetpackState: { isJetpackActive: true } }; + require( '../index' ); + // Act + defaultHooks.doAction( 'native.render', props ); + // Assert + const actualJetpackData = global.window[ JETPACK_DATA_PATH ]; + expect( actualJetpackData ).toEqual( expectedJetpackData ); + } ); + + it( `should register JETPACK_DATA_PATH with CUSTOM values when Jetpack is ACTIVE + AND Jetpack state is PROVIDED.`, () => { + // Arrange + const expectedJetpackData = { + available_blocks: { + 'contact-info': { available: true }, + 'layout-grid': { available: true }, + story: { available: true }, + }, + jetpack: { is_active: true }, + siteFragment: '#fragment', + tracksUserData: {}, + wpcomBlogId: 1337, + }; + const props = { + jetpackState: { + isJetpackActive: true, + siteFragment: '#fragment', + userData: {}, + blogId: 1337, + }, + }; + require( '../index' ); + // Act + defaultHooks.doAction( 'native.render', props ); + // Assert + const actualJetpackData = global.window[ JETPACK_DATA_PATH ]; + expect( actualJetpackData ).toEqual( expectedJetpackData ); + } ); + + it( `should NOT register "jetpack/*" block types when Jetpack is INACTIVE + AND you are INCAPABLE.`, () => { + // Arrange + const expectedBlockTypes = []; + const props = { + jetpackState: { isJetpackActive: false }, + capabilities: { + layoutGridBlock: false, + mediaFilesCollectionBlock: false, + contactInfoBlock: false, + }, + }; + require( '../index' ); + // Act + defaultHooks.doAction( 'native.render', props ); + // Assert + const actualBlockTypes = getBlockTypes(); + expect( actualBlockTypes ).toEqual( expectedBlockTypes ); + } ); + + it( `should NOT register "jetpack/*" block types when Jetpack is INACTIVE + even if you are CAPABLE.`, () => { + // Arrange + const expectedBlockTypes = []; + const props = { + jetpackState: { isJetpackActive: false }, + capabilities: { + layoutGridBlock: true, + mediaFilesCollectionBlock: true, + contactInfoBlock: true, + }, + }; + require( '../index' ); + // Act + defaultHooks.doAction( 'native.render', props ); + // Assert + const actualBlockTypes = getBlockTypes(); + expect( actualBlockTypes ).toEqual( expectedBlockTypes ); + } ); + + it( `should NOT register "jetpack/*" block types when Jetpack is ACTIVE + AND you are INCAPABLE.`, () => { + // Arrange + const expectedBlockTypes = []; + const props = { + jetpackState: { isJetpackActive: true }, + capabilities: { + layoutGridBlock: false, + mediaFilesCollectionBlock: false, + contactInfoBlock: false, + }, + }; + require( '../index' ); + // Act + defaultHooks.doAction( 'native.render', props ); + // Assert + const actualBlockTypes = getBlockTypes(); + expect( actualBlockTypes ).toEqual( expectedBlockTypes ); + } ); + + it( `should register the "jetpack/*" block types when Jetpack is ACTIVE + AND you are CAPABLE.`, () => { + // Arrange + const expectedBlockTypes = [ + 'jetpack/address', + 'jetpack/contact-info', + 'jetpack/email', + 'jetpack/layout-grid', + 'jetpack/layout-grid-column', + 'jetpack/phone', + 'jetpack/story', + ].sort(); + const props = { + jetpackState: { isJetpackActive: true }, + capabilities: { + layoutGridBlock: true, + mediaFilesCollectionBlock: true, + contactInfoBlock: true, + }, }; + require( '../index' ); + // Act + defaultHooks.doAction( 'native.render', props ); + // Assert + const actualBlockTypes = getBlockTypes() + .map( ( { name } ) => name ) + .sort(); + expect( actualBlockTypes ).toEqual( expectedBlockTypes ); + } ); + + afterAll( () => { + [ + 'jetpack/address', + 'jetpack/contact-info', + 'jetpack/email', + 'jetpack/layout-grid', + 'jetpack/layout-grid-column', + 'jetpack/phone', + 'jetpack/story', + ].forEach( ( name ) => { + unregisterBlockType( name ); + } ); + } ); + } ); + + describe( 'Allowed Blocks', () => { + beforeAll( () => { + [ 'core/audio', 'jetpack/story' ].forEach( ( name ) => + registerBlockType( name, { title: name } ) + ); + } ); + + describe( 'Allow ALL REGISTERED Blocks', () => { + it( `should show ALL REGISTERED block types when NONE are provided.`, () => { + // Arrange + const expectedHiddenBlockTypes = []; + const props = {}; + require( '../index' ); + // Act + defaultHooks.doAction( 'native.render', props ); + // Assert + const { getPreference } = select( 'core/edit-post' ); + const actualHiddenBlockTypes = getPreference( + 'hiddenBlockTypes' + ); + expect( actualHiddenBlockTypes ).toEqual( + expectedHiddenBlockTypes + ); + } ); + + it( `should NOT hide ALL OTHER block types when the provided block type to be shown is UNREGISTERED.`, () => { + // Arrange + const expectedHiddenBlockTypes = []; + const props = { showBlocks: [ 'jetpack/unregistered' ] }; + require( '../index' ); + // Act + defaultHooks.doAction( 'native.render', props ); + // Assert + const { getPreference } = select( 'core/edit-post' ); + const actualHiddenBlockTypes = getPreference( + 'hiddenBlockTypes' + ); + expect( actualHiddenBlockTypes ).toEqual( + expectedHiddenBlockTypes + ); + } ); + + it( `should show ALL REGISTERED block types when ALL REGISTERED block types are provided to be shown.`, () => { + // Arrange + const expectedHiddenBlockTypes = []; + const props = { + showBlocks: [ 'core/audio', 'jetpack/story' ], + }; + require( '../index' ); + // Act + defaultHooks.doAction( 'native.render', props ); + // Assert + const { getPreference } = select( 'core/edit-post' ); + const actualHiddenBlockTypes = getPreference( + 'hiddenBlockTypes' + ); + expect( actualHiddenBlockTypes ).toEqual( + expectedHiddenBlockTypes + ); + } ); + + it( `should NOT hide the provided block type when it is UNREGISTERED.`, () => { + // Arrange + const expectedHiddenBlockTypes = []; + const props = { hideBlocks: [ 'jetpack/unregistered' ] }; + require( '../index' ); + // Act + defaultHooks.doAction( 'native.render', props ); + // Assert + const { getPreference } = select( 'core/edit-post' ); + const actualHiddenBlockTypes = getPreference( + 'hiddenBlockTypes' + ); + expect( actualHiddenBlockTypes ).toEqual( + expectedHiddenBlockTypes + ); + } ); + + it( `should NOT hide ANY provided block types that are ambiguously asked to be shown.`, () => { + // Arrange + const expectedHiddenBlockTypes = []; + const props = { + hideBlocks: [ 'core/audio', 'jetpack/story' ], + showBlocks: [ 'jetpack/story', 'core/audio' ], + }; + require( '../index' ); + // Act + defaultHooks.doAction( 'native.render', props ); + // Assert + const { getPreference } = select( 'core/edit-post' ); + const actualHiddenBlockTypes = getPreference( + 'hiddenBlockTypes' + ); + expect( actualHiddenBlockTypes ).toEqual( + expectedHiddenBlockTypes + ); + } ); + + it( `should NOT hide ANY provided UNREGISTERED block type that is ambiguously asked to be shown.`, () => { + // Arrange + const expectedHiddenBlockTypes = []; + const props = { + hideBlocks: [ 'jetpack/unregistered' ], + showBlocks: [ 'jetpack/unregistered' ], + }; + require( '../index' ); + // Act + defaultHooks.doAction( 'native.render', props ); + // Assert + const { getPreference } = select( 'core/edit-post' ); + const actualHiddenBlockTypes = getPreference( + 'hiddenBlockTypes' + ); + expect( actualHiddenBlockTypes ).toEqual( + expectedHiddenBlockTypes + ); + } ); + } ); + + describe( 'Allow SOME REGISTERED Blocks', () => { + it( `should hide ALL OTHER block types when the provided block type to be shown is REGISTERED.`, () => { + // Arrange + const expectedHiddenBlockTypes = [ 'jetpack/story' ]; + const props = { showBlocks: [ 'core/audio' ] }; + require( '../index' ); + // Act + defaultHooks.doAction( 'native.render', props ); + // Assert + const { getPreference } = select( 'core/edit-post' ); + const actualHiddenBlockTypes = getPreference( + 'hiddenBlockTypes' + ); + expect( actualHiddenBlockTypes ).toEqual( + expectedHiddenBlockTypes + ); + } ); + + it( `should hide ALL OTHER block types when the provided block types to be shown are REGISTERED AND UNREGISTERED.`, () => { + // Arrange + const expectedHiddenBlockTypes = [ 'jetpack/story' ]; + const props = { + showBlocks: [ 'core/audio', 'jetpack/unregistered' ], + }; + require( '../index' ); + // Act + defaultHooks.doAction( 'native.render', props ); + // Assert + const { getPreference } = select( 'core/edit-post' ); + const actualHiddenBlockTypes = getPreference( + 'hiddenBlockTypes' + ); + expect( actualHiddenBlockTypes ).toEqual( + expectedHiddenBlockTypes + ); + } ); + + it( `should hide ANY REGISTERED block types when ANY REGISTERED block types are provided to be hidden.`, () => { + // Arrange + const expectedHiddenBlockTypes = [ 'jetpack/story' ]; + const props = { hideBlocks: [ 'jetpack/story' ] }; + require( '../index' ); + // Act + defaultHooks.doAction( 'native.render', props ); + // Assert + const { getPreference } = select( 'core/edit-post' ); + const actualHiddenBlockTypes = getPreference( + 'hiddenBlockTypes' + ); + expect( actualHiddenBlockTypes ).toEqual( + expectedHiddenBlockTypes + ); + } ); + + it( `should hide ANY REGISTERED block types when the provided block types to be hidden are REGISTERED AND UNREGISTERED.`, () => { + // Arrange + const expectedHiddenBlockTypes = [ 'jetpack/story' ]; + const props = { + hideBlocks: [ 'jetpack/story', 'jetpack/unregistered' ], + }; + require( '../index' ); + // Act + defaultHooks.doAction( 'native.render', props ); + // Assert + const { getPreference } = select( 'core/edit-post' ); + const actualHiddenBlockTypes = getPreference( + 'hiddenBlockTypes' + ); + expect( actualHiddenBlockTypes ).toEqual( + expectedHiddenBlockTypes + ); + } ); + + it( `should hide ANY provided REGISTERED block types that are also UNAMBIGUOUSLY asked to be NOT shown.`, () => { + // Arrange + const expectedHiddenBlockTypes = [ 'jetpack/story' ]; + const props = { + hideBlocks: [ 'jetpack/story' ], + showBlocks: [ 'core/audio' ], + }; + require( '../index' ); + // Act + defaultHooks.doAction( 'native.render', props ); + // Assert + const { getPreference } = select( 'core/edit-post' ); + const actualHiddenBlockTypes = getPreference( + 'hiddenBlockTypes' + ); + expect( actualHiddenBlockTypes ).toEqual( + expectedHiddenBlockTypes + ); + } ); + } ); + + describe( 'Allow NO REGISTERED Blocks', () => { + it( `should hide ALL REGISTERED block types when ALL REGISTERED block types are provided to be hidden.`, () => { + // Arrange + const expectedHiddenBlockTypes = [ + 'core/audio', + 'jetpack/story', + ].sort(); + const props = { hideBlocks: [ 'core/audio', 'jetpack/story' ] }; + require( '../index' ); + // Act + defaultHooks.doAction( 'native.render', props ); + // Assert + const { getPreference } = select( 'core/edit-post' ); + const actualHiddenBlockTypes = getPreference( + 'hiddenBlockTypes' + ).sort(); + expect( actualHiddenBlockTypes ).toEqual( + expectedHiddenBlockTypes + ); + } ); + + it( `should hide ALL REGISTERED block types when NO block types are provided to be shown.`, () => { + // Arrange + const expectedHiddenBlockTypes = [ + 'core/audio', + 'jetpack/story', + ].sort(); + const props = { showBlocks: [] }; + require( '../index' ); + // Act + defaultHooks.doAction( 'native.render', props ); + // Assert + const { getPreference } = select( 'core/edit-post' ); + const actualHiddenBlockTypes = getPreference( + 'hiddenBlockTypes' + ).sort(); + expect( actualHiddenBlockTypes ).toEqual( + expectedHiddenBlockTypes + ); + } ); + } ); + + afterAll( () => { + [ 'core/audio', 'jetpack/story' ].forEach( ( name ) => { + unregisterBlockType( name ); + } ); } ); - jest.mock( - '../../jetpack/projects/plugins/jetpack/extensions/blocks/contact-info/editor.js', - () => jest.fn() - ); - jest.mock( - '../../jetpack/projects/plugins/jetpack/extensions/blocks/story/editor.js', - () => jest.fn() - ); - - const setupJetpackEditor = require( '../jetpack-editor-setup' ).default; - setupJetpackEditor( { blogId: 1, isJetpackActive: true } ); - - expect( mockRegisterBlockCollection.mock.calls[ 0 ][ 0 ] ).toBe( - 'jetpack' - ); } ); } );