Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add component level tests to withDuotoneControls HOC #48353

Closed
wants to merge 8 commits into from
2 changes: 1 addition & 1 deletion packages/block-editor/src/hooks/duotone.js
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ function addDuotoneAttributes( settings ) {
*
* @return {Function} Wrapped component.
*/
const withDuotoneControls = createHigherOrderComponent(
export const withDuotoneControls = createHigherOrderComponent(
( BlockEdit ) => ( props ) => {
const hasDuotoneSupport = hasBlockSupport(
props.name,
Expand Down
242 changes: 242 additions & 0 deletions packages/block-editor/src/hooks/test/duotone.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,253 @@
/**
* External dependencies
*/
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';

/**
* WordPress dependencies
*/
import { registerBlockType, unregisterBlockType } from '@wordpress/blocks';
import { SlotFillProvider } from '@wordpress/components';

/**
* Internal dependencies
*/
import BlockEditorProvider from '../../components/provider';
import BlockControls from '../../components/block-controls';
// eslint-disable-next-line no-unused-vars
import BlockEdit from '../../components/block-edit';
getdave marked this conversation as resolved.
Show resolved Hide resolved
import {
withDuotoneControls,
getColorsFromDuotonePreset,
getDuotonePresetFromColors,
} from '../duotone';

describe( 'withDuotoneControls', () => {
const blockName = 'core/test-block';

const blockSettings = {
save: () => {},
category: 'media',
title: 'Block Title',
edit: ( { children } ) => <>{ children }</>,
supports: {
color: {
__experimentalDuotone: 'img',
},
},
};

const blockProps = {
name: blockName,
attributes: {},
isSelected: true,
};

const blockEditorSettings = {
__experimentalFeatures: {
color: {
palette: {
default: [
{
name: 'Pale pink',
slug: 'pale-pink',
color: '#f78da7',
},
{
name: 'Vivid green cyan',
slug: 'vivid-green-cyan',
color: '#00d084',
},
],
},
defaultDuotone: true,
duotone: {
default: [
{
name: 'Black and white',
slug: 'black-and-white',
colors: [ '#000000', '#FFFFFF' ],
},
{
name: 'Pale pink and green',
slug: 'palepink-green',
colors: [ '#f78da7', '#00d084' ],
},
],
},
},
},
};

const duotonePresets =
blockEditorSettings.__experimentalFeatures.color.duotone.default;

const WithDuotoneControls = withDuotoneControls( ( { wrapperProps } ) => (
<div { ...wrapperProps } />
) );

beforeEach( () => {
registerBlockType( blockName, blockSettings );
} );

afterEach( () => {
unregisterBlockType( blockName );
} );

it( 'should not show Duotone panel in toolbar for blocks that do not support Duotone', () => {
// A Block with no duotone support.
registerBlockType( 'test/no-duotone-support-block', {
...blockSettings,
name: 'Block with no duotone support',
supports: {}, // no duotone support.
} );

const blockNoDuotoneProps = {
...blockProps,
name: 'test/no-duotone-support-block',
};

render(
<BlockEditorProvider settings={ blockEditorSettings } value={ [] }>
<SlotFillProvider>
<BlockEdit { ...blockNoDuotoneProps }>
<WithDuotoneControls />
</BlockEdit>
<BlockControls.Slot group="block" />
</SlotFillProvider>
</BlockEditorProvider>
);

const duotoneToggleButton = screen.queryByRole( 'button', {
name: 'Apply duotone filter',
} );
expect( duotoneToggleButton ).not.toBeInTheDocument();
} );

it( 'should show Duotone panel with presets in toolbar for blocks that support Duotone', async () => {
const user = userEvent.setup();
render(
<BlockEditorProvider settings={ blockEditorSettings } value={ [] }>
<SlotFillProvider>
<BlockEdit { ...blockProps }>
<WithDuotoneControls />
</BlockEdit>
<BlockControls.Slot group="block" />
</SlotFillProvider>
</BlockEditorProvider>
);

const duotoneToggleButton = screen.getByRole( 'button', {
name: 'Apply duotone filter',
} );

await user.click( duotoneToggleButton );

const duotonePopover = screen.queryByRole( 'group', {
name: 'Duotone',
} );
expect( duotonePopover ).toBeInTheDocument();

const unsetOption = screen.queryByRole( 'button', {
name: 'Unset',
} );
expect( unsetOption ).toBeInTheDocument();

duotonePresets?.forEach( ( preset ) => {
// check in document
const presetOption = screen.queryByRole( 'button', {
name: `Duotone: ${ preset.name }`,
} );
expect( presetOption ).toBeInTheDocument();
} );
} );

it( 'should select the duotone preset in the panel when the block attribute contains a duotone preset', async () => {
const user = userEvent.setup();
const duotonePreset = duotonePresets[ 0 ];
const blockWithDuotoneProps = {
...blockProps,
attributes: {
style: {
color: {
duotone: duotonePreset.slug,
},
},
},
};

render(
<BlockEditorProvider settings={ blockEditorSettings } value={ [] }>
<SlotFillProvider>
<BlockEdit { ...blockWithDuotoneProps }>
<WithDuotoneControls />
</BlockEdit>
<BlockControls.Slot group="block" />
</SlotFillProvider>
</BlockEditorProvider>
);

const duotoneToggleButton = screen.getByRole( 'button', {
name: 'Apply duotone filter',
} );

await user.click( duotoneToggleButton );

const presetOption = screen.queryByRole( 'button', {
name: `Duotone: ${ duotonePreset.name }`,
pressed: true, // the selected preset should be pressed.
} );
expect( presetOption ).toBeInTheDocument();
} );

it( 'should not show a selected Duotone preset in the panel when the block attribute contains a custom duotone', async () => {
const user = userEvent.setup();
const blockWithDuotoneProps = {
...blockProps,
attributes: {
style: {
color: {
duotone: [ 'rgb(0, 0, 0)', 'rgb(255, 255, 255)' ],
},
},
},
};

render(
<BlockEditorProvider settings={ blockEditorSettings } value={ [] }>
<SlotFillProvider>
<BlockEdit { ...blockWithDuotoneProps }>
<WithDuotoneControls />
</BlockEdit>
<BlockControls.Slot group="block" />
</SlotFillProvider>
</BlockEditorProvider>
);

const duotoneToggleButton = screen.getByRole( 'button', {
name: 'Apply duotone filter',
} );

await user.click( duotoneToggleButton );

const unsetOption = screen.queryByRole( 'button', {
name: 'Unset',
pressed: false, // the unset option should not be pressed.
} );
expect( unsetOption ).toBeInTheDocument();
Comment on lines +234 to +238
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should tests for things like this belong in the components package under duotone-picker instead?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeh to be fair they could be. It's straying into e2e test territory.


duotonePresets?.forEach( ( preset ) => {
// check in document
const presetOption = screen.queryByRole( 'button', {
name: `Duotone: ${ preset.name }`,
pressed: false, // no preset should be pressed.
} );
expect( presetOption ).toBeInTheDocument();
} );
} );
} );

describe( 'Duotone utilities', () => {
const duotonePalette = [
{
Expand Down
1 change: 1 addition & 0 deletions packages/components/src/duotone-picker/duotone-picker.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ function DuotonePicker( {
key="unset"
value="unset"
isSelected={ isUnset }
aria-label={ __( 'Unset' ) }
tooltipText={ __( 'Unset' ) }
className="components-duotone-picker__color-indicator"
onClick={ () => {
Expand Down