Skip to content

Commit

Permalink
Drop Zone: Omit unallowed block types
Browse files Browse the repository at this point in the history
  • Loading branch information
aduth committed Jan 31, 2018
1 parent 732a296 commit 40bb47b
Show file tree
Hide file tree
Showing 2 changed files with 187 additions and 3 deletions.
11 changes: 8 additions & 3 deletions editor/components/block-drop-zone/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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;
}
Expand All @@ -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;
}
Expand Down Expand Up @@ -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 );
179 changes: 179 additions & 0 deletions editor/components/block-drop-zone/test/index.js
Original file line number Diff line number Diff line change
@@ -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( <BlockDropZone isLocked /> );

expect( wrapper.type() ).toBe( null );
} );

it( 'should do nothing if no matched transform for dropped files', ( done ) => {
const insertBlocks = jest.fn();
const wrapper = shallow(
<BlockDropZone insertBlocks={ insertBlocks } />
);

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(
<BlockDropZone
index={ 0 }
insertBlocks={ insertBlocks } />
);

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(
<BlockDropZone
index={ 0 }
insertBlocks={ insertBlocks } />
);

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(
<BlockDropZone
index={ 0 }
allowedBlockTypes={ [ 'core/bar' ] }
insertBlocks={ insertBlocks } />
);

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(
<BlockDropZone
index={ 0 }
allowedBlockTypes={ [ 'core/foo' ] }
insertBlocks={ insertBlocks } />
);

wrapper.prop( 'onFilesDrop' )( [
{
isFooMatch: true,
type: 'application/x-fake',
},
], { y: 'top' } );

process.nextTick( () => {
expect( insertBlocks ).toHaveBeenCalled();
done();
} );
} );
} );

0 comments on commit 40bb47b

Please sign in to comment.