diff --git a/editor/components/block-drop-zone/index.js b/editor/components/block-drop-zone/index.js
index 29f76029940b1..ff9bef73dfb68 100644
--- a/editor/components/block-drop-zone/index.js
+++ b/editor/components/block-drop-zone/index.js
@@ -2,7 +2,7 @@
* External Dependencies
*/
import { connect } from 'react-redux';
-import { reduce, get, find } from 'lodash';
+import { reduce, includes, get, find } from 'lodash';
/**
* WordPress dependencies
@@ -16,7 +16,7 @@ import { compose } from '@wordpress/element';
*/
import { insertBlocks, updateBlockAttributes } from '../../store/actions';
-function BlockDropZone( { index, isLocked, ...props } ) {
+export function BlockDropZone( { index, isLocked, allowedBlockTypes, ...props } ) {
if ( isLocked ) {
return null;
}
@@ -29,6 +29,10 @@ function BlockDropZone( { index, isLocked, ...props } ) {
const onDropFiles = ( files, position ) => {
const transformation = reduce( getBlockTypes(), ( ret, blockType ) => {
+ if ( Array.isArray( allowedBlockTypes ) && ! includes( allowedBlockTypes, blockType.name ) ) {
+ return ret;
+ }
+
if ( ret ) {
return ret;
}
@@ -67,10 +71,11 @@ export default compose(
{ insertBlocks, updateBlockAttributes }
),
withContext( 'editor' )( ( settings ) => {
- const { templateLock } = settings;
+ const { templateLock, blockTypes } = settings;
return {
isLocked: !! templateLock,
+ allowedBlockTypes: blockTypes,
};
} )
)( BlockDropZone );
diff --git a/editor/components/block-drop-zone/test/index.js b/editor/components/block-drop-zone/test/index.js
new file mode 100644
index 0000000000000..ec83e0a4db7fb
--- /dev/null
+++ b/editor/components/block-drop-zone/test/index.js
@@ -0,0 +1,179 @@
+/**
+ * External dependencies
+ */
+import { shallow } from 'enzyme';
+import { noop } from 'lodash';
+
+/**
+ * WordPress dependencies
+ */
+import {
+ registerBlockType,
+ getBlockTypes,
+ unregisterBlockType,
+ createBlock,
+} from '@wordpress/blocks';
+
+/**
+ * Internal dependencies
+ */
+import { BlockDropZone } from '../';
+
+describe( 'BlockDropZone', () => {
+ beforeAll( () => {
+ registerBlockType( 'core/foo', {
+ save: noop,
+
+ category: 'common',
+
+ title: 'block title',
+
+ attributes: {
+ fileType: {
+ type: 'string',
+ },
+ },
+
+ transforms: {
+ from: [
+ {
+ type: 'files',
+ isMatch: ( files ) => files.some( ( file ) => file.isFooMatch ),
+ transform( files ) {
+ return Promise.resolve( files.map( ( file ) => (
+ createBlock( 'core/foo', { fileType: file.type } )
+ ) ) );
+ },
+ },
+ ],
+ },
+ } );
+ } );
+
+ afterAll( () => {
+ getBlockTypes().forEach( block => {
+ unregisterBlockType( block.name );
+ } );
+ } );
+
+ it( 'should render nothing if template locking in effect', () => {
+ const wrapper = shallow( );
+
+ expect( wrapper.type() ).toBe( null );
+ } );
+
+ it( 'should do nothing if no matched transform for dropped files', ( done ) => {
+ const insertBlocks = jest.fn();
+ const wrapper = shallow(
+
+ );
+
+ wrapper.prop( 'onFilesDrop' )( [
+ {
+ isBarMatch: true,
+ type: 'application/x-fake',
+ },
+ ] );
+
+ process.nextTick( () => {
+ expect( insertBlocks ).not.toHaveBeenCalled();
+ done();
+ } );
+ } );
+
+ it( 'should call insert callback with transformed files', ( done ) => {
+ const insertBlocks = jest.fn();
+ const wrapper = shallow(
+
+ );
+
+ wrapper.prop( 'onFilesDrop' )( [
+ {
+ isFooMatch: true,
+ type: 'application/x-fake',
+ },
+ ], { y: 'bottom' } );
+
+ process.nextTick( () => {
+ expect( insertBlocks ).toHaveBeenCalled();
+ const [ blocks, index ] = insertBlocks.mock.calls[ 0 ];
+ expect( blocks ).toHaveLength( 1 );
+ expect( blocks[ 0 ] ).toMatchObject( {
+ name: 'core/foo',
+ attributes: {
+ fileType: 'application/x-fake',
+ },
+ } );
+ expect( index ).toBe( 1 );
+ done();
+ } );
+ } );
+
+ it( 'should call insert callback with transformed files (top)', ( done ) => {
+ const insertBlocks = jest.fn();
+ const wrapper = shallow(
+
+ );
+
+ wrapper.prop( 'onFilesDrop' )( [
+ {
+ isFooMatch: true,
+ type: 'application/x-fake',
+ },
+ ], { y: 'top' } );
+
+ process.nextTick( () => {
+ const [ , index ] = insertBlocks.mock.calls[ 0 ];
+ expect( index ).toBe( 0 );
+ done();
+ } );
+ } );
+
+ it( 'should respect allowed block types (not allowed)', ( done ) => {
+ const insertBlocks = jest.fn();
+ const wrapper = shallow(
+
+ );
+
+ wrapper.prop( 'onFilesDrop' )( [
+ {
+ isFooMatch: true,
+ type: 'application/x-fake',
+ },
+ ], { y: 'top' } );
+
+ process.nextTick( () => {
+ expect( insertBlocks ).not.toHaveBeenCalled();
+ done();
+ } );
+ } );
+
+ it( 'should respect allowed block types (allowed)', ( done ) => {
+ const insertBlocks = jest.fn();
+ const wrapper = shallow(
+
+ );
+
+ wrapper.prop( 'onFilesDrop' )( [
+ {
+ isFooMatch: true,
+ type: 'application/x-fake',
+ },
+ ], { y: 'top' } );
+
+ process.nextTick( () => {
+ expect( insertBlocks ).toHaveBeenCalled();
+ done();
+ } );
+ } );
+} );