Skip to content

Commit

Permalink
Block Bindings: Accept client ID as parameter for `useBlockBindingsUt…
Browse files Browse the repository at this point in the history
…ils` (#65818)

* Pass `clientId` to `useBlockBindingsUtils`

* Add unit tests for `useBlockBindingsUtils`

* Use `resetBlocks` instead of `insertBlocks` in unit test

Co-authored-by: SantosGuillamot <[email protected]>
Co-authored-by: gziolo <[email protected]>
  • Loading branch information
3 people authored and kevin940726 committed Oct 11, 2024
1 parent 6235b5d commit e8444ce
Show file tree
Hide file tree
Showing 3 changed files with 187 additions and 6 deletions.
4 changes: 4 additions & 0 deletions packages/block-editor/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -877,6 +877,10 @@ updateBlockBindings( { url: undefined } );
removeAllBlockBindings();
```

_Parameters_

- _clientId_ `?string`: Optional block client ID. If not set, it will use the current block client ID from the context.

_Returns_

- `?WPBlockBindingsUtils`: Object containing the block bindings utils.
Expand Down
15 changes: 9 additions & 6 deletions packages/block-editor/src/utils/block-bindings.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ function isObjectEmpty( object ) {
* - `updateBlockBindings`: Updates the value of the bindings connected to block attributes. It can be used to remove a specific binding by setting the value to `undefined`.
* - `removeAllBlockBindings`: Removes the bindings property of the `metadata` attribute.
*
* @param {?string} clientId Optional block client ID. If not set, it will use the current block client ID from the context.
*
* @return {?WPBlockBindingsUtils} Object containing the block bindings utils.
*
* @example
Expand Down Expand Up @@ -60,8 +62,9 @@ function isObjectEmpty( object ) {
* removeAllBlockBindings();
* ```
*/
export function useBlockBindingsUtils() {
const { clientId } = useBlockEditContext();
export function useBlockBindingsUtils( clientId ) {
const { clientId: contextClientId } = useBlockEditContext();
const blockClientId = clientId || contextClientId;
const { updateBlockAttributes } = useDispatch( blockEditorStore );
const { getBlockAttributes } = useRegistry().select( blockEditorStore );

Expand Down Expand Up @@ -96,7 +99,7 @@ export function useBlockBindingsUtils() {
*/
const updateBlockBindings = ( bindings ) => {
const { metadata: { bindings: currentBindings, ...metadata } = {} } =
getBlockAttributes( clientId );
getBlockAttributes( blockClientId );
const newBindings = { ...currentBindings };

Object.entries( bindings ).forEach( ( [ attribute, binding ] ) => {
Expand All @@ -116,7 +119,7 @@ export function useBlockBindingsUtils() {
delete newMetadata.bindings;
}

updateBlockAttributes( clientId, {
updateBlockAttributes( blockClientId, {
metadata: isObjectEmpty( newMetadata ) ? undefined : newMetadata,
} );
};
Expand All @@ -134,8 +137,8 @@ export function useBlockBindingsUtils() {
*/
const removeAllBlockBindings = () => {
const { metadata: { bindings, ...metadata } = {} } =
getBlockAttributes( clientId );
updateBlockAttributes( clientId, {
getBlockAttributes( blockClientId );
updateBlockAttributes( blockClientId, {
metadata: isObjectEmpty( metadata ) ? undefined : metadata,
} );
};
Expand Down
174 changes: 174 additions & 0 deletions packages/block-editor/src/utils/test/use-block-bindings-utils.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
/**
* External dependencies
*/
import { renderHook } from '@testing-library/react';

/**
* WordPress dependencies
*/
import { store as blockEditorStore } from '@wordpress/block-editor';
import { dispatch, select } from '@wordpress/data';
import {
createBlock,
getBlockTypes,
unregisterBlockType,
} from '@wordpress/blocks';
import { registerCoreBlocks } from '@wordpress/block-library';

/**
* Internal dependencies
*/
import { useBlockBindingsUtils } from '../';

describe( 'useBlockBindingsUtils', () => {
beforeAll( () => {
// Register all core blocks
registerCoreBlocks();
} );

let clientId;
beforeEach( async () => {
const block = createBlock( 'core/paragraph', {
metadata: {
name: 'Block name',
bindings: {
prop1: {
source: 'core/post-meta',
args: {
key: 'initial_key',
},
},
prop2: {
source: 'core/post-meta',
args: {
key: 'initial_key',
},
},
},
},
} );
await dispatch( blockEditorStore ).resetBlocks( [ block ] );
clientId = block.clientId;
} );

afterAll( () => {
// Remove blocks after all tests.
dispatch( blockEditorStore ).resetBlocks( [] );

// Clean up registered blocks
getBlockTypes().forEach( ( block ) => {
unregisterBlockType( block.name );
} );
} );

it( 'should be possible to update just one connection', async () => {
renderHook( () => {
const { updateBlockBindings } = useBlockBindingsUtils( clientId );
updateBlockBindings( {
prop1: {
source: 'core/post-meta',
args: {
key: 'new_key',
},
},
} );
} );
const { metadata } =
await select( blockEditorStore ).getBlockAttributes( clientId );
expect( metadata ).toMatchObject( {
// Other metadata properties shouldn't change.
name: 'Block name',
bindings: {
prop1: {
source: 'core/post-meta',
args: {
key: 'new_key',
},
},
prop2: {
source: 'core/post-meta',
args: {
key: 'initial_key',
},
},
},
} );
} );

it( 'should be possible to update multiple connections at once', async () => {
renderHook( () => {
const { updateBlockBindings } = useBlockBindingsUtils( clientId );
updateBlockBindings( {
prop1: {
source: 'core/post-meta',
args: {
key: 'new_key',
},
},
prop2: {
source: 'core/post-meta',
args: {
key: 'new_key',
},
},
} );
} );
const { metadata } =
await select( blockEditorStore ).getBlockAttributes( clientId );
expect( metadata ).toMatchObject( {
// Other metadata properties shouldn't change.
name: 'Block name',
bindings: {
prop1: {
source: 'core/post-meta',
args: {
key: 'new_key',
},
},
prop2: {
source: 'core/post-meta',
args: {
key: 'new_key',
},
},
},
} );
} );

it( 'should be possible to remove connections', async () => {
renderHook( () => {
const { updateBlockBindings } = useBlockBindingsUtils( clientId );
updateBlockBindings( {
prop2: undefined,
} );
} );
const { metadata } =
await select( blockEditorStore ).getBlockAttributes( clientId );
expect( metadata ).toMatchObject( {
// Other metadata properties shouldn't change.
name: 'Block name',
bindings: {
prop1: {
source: 'core/post-meta',
args: {
key: 'initial_key',
},
},
},
} );
} );

it( 'should be possible to remove all connections', async () => {
renderHook( () => {
const { removeAllBlockBindings } =
useBlockBindingsUtils( clientId );
removeAllBlockBindings();
} );
const { metadata } =
await select( blockEditorStore ).getBlockAttributes( clientId );
expect( metadata ).toMatchObject( {
// Other metadata properties shouldn't change.
name: 'Block name',
} );
} );
} );

0 comments on commit e8444ce

Please sign in to comment.