Skip to content

ColorPicker: Add tests for ColorPicker Alpha slider #69203

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

Merged
merged 11 commits into from
Apr 25, 2025

Conversation

im3dabasia
Copy link
Contributor

@im3dabasia im3dabasia commented Feb 14, 2025

What?

Closes #49344
Related comment: #49214 (comment)

Related PRs: #49214, #49698

This PR improves the unit tests for the ColorPicker component by adding test coverage for the Alpha slider and its corresponding input field when enableAlpha. Previously, tests covered most input fields (hex, HSL, RGB, and hue slider), but the Alpha slider had no dedicated tests.

Why?

The maintainers have emphasized that these tests are important for the editor. While previous tests validated various input interactions, they did not:

  • Ensure that the Alpha slider updates correctly when the input field is changed.
  • Cover enableAlpha={true}, leaving a gap in test coverage.

How?

  • Added tests to check that the Alpha slider updates when the user types in the Alpha input field and when adjusting the slider.
  • Verified that the correct RGBA/HSLA values are passed to onChange when changing transparency via both the input field and the slider.
  • Used user-event for more accurate simulation of real user interactions.

Testing Instructions

  1. Run the test by the following command:
npm run test:unit packages/components/src/color-picker/test/index.tsx
  1. Check that the new test cases for the Alpha slider and input field pass.
  2. Confirm that the test verifies the expected value in onChange when modifying alpha.
  3. Review the test implementation to ensure coverage of both slider and input interactions.

Screenshot

image

@im3dabasia im3dabasia marked this pull request as ready for review February 14, 2025 16:17
Copy link

github-actions bot commented Feb 14, 2025

The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the props-bot label.

If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message.

Co-authored-by: im3dabasia <im3dabasia1@git.wordpress.org>
Co-authored-by: ciampo <mciampini@git.wordpress.org>
Co-authored-by: Mamaduka <mamaduka@git.wordpress.org>

To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook.

@t-hamano t-hamano added [Type] Code Quality Issues or PRs that relate to code quality [Package] Components /packages/components labels Feb 20, 2025
@im3dabasia
Copy link
Contributor Author

Hi @ciampo,

Since you had proposed adding alpha tests to the ColorPicker component, I've implemented those changes. Could you please review my PR when you have a moment?

CC: @t-hamano

Comment on lines 394 to 398
const alphaSliders = screen.getAllByRole( 'slider', {
name: 'Alpha',
} );

const alphaSlider = alphaSliders.at( -1 )!;
Copy link
Contributor

@ciampo ciampo Apr 4, 2025

Choose a reason for hiding this comment

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

Why don't we use getByRole instead of getAllByRole ? If we did that, there wouldn't be a need for the at( -1 ) call

I see that there are two "alpha" sliders, which is unfortunate, although only the second one (the one that we need for the test) seems to be an actual input[type="range"]

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The reason I could not use getByRole is because as you correctly identified there are 2 Alpha sliders for HSL and RGB color formats. That is why I used this work around getAllByRole followed by at( -1 ).

This is similar to this case here, where HSL has 2 Hue sliders rendered

const hueSliders = screen.getAllByRole( 'slider', {
name: 'Hue',
} );
expect( hueSliders ).toHaveLength( 2 );
// Reason for the `!` post-fix expression operator: if the check above
// doesn't fail, we're guaranteed that `hueSlider` is not undefined.
const hueSlider = hueSliders.at( -1 )!;

Copy link
Contributor

Choose a reason for hiding this comment

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

Sounds like we could open an issue to work on an improvement here — grouping the HSLA and RGBA inputs in a fieldset (or similar) for better labelling and discoverability.

Screenshot 2025-04-04 at 14 16 36

Would you be able to open an issue about it? Thank you!

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@ciampo, could you please share a bit more about what issue we should open? Just need some clarification. Thanks!

Copy link
Contributor Author

@im3dabasia im3dabasia May 2, 2025

Choose a reason for hiding this comment

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

Hi for this issue I researched and can say that there are 2 ways we can work on this

Currently in trunk the code is returning a fragment like shown in the snippet down below.

Code in trunk with fragments being returned as parent

<>
<InputWithSlider
min={ 0 }
max={ 359 }
label="Hue"
abbreviation="H"
value={ colorValue.h }
onChange={ ( nextH: number ) => {
updateHSLAValue( { h: nextH } );
} }
/>
<InputWithSlider
min={ 0 }
max={ 100 }
label="Saturation"
abbreviation="S"
value={ colorValue.s }
onChange={ ( nextS: number ) => {
updateHSLAValue( { s: nextS } );
} }
/>
<InputWithSlider
min={ 0 }
max={ 100 }
label="Lightness"
abbreviation="L"
value={ colorValue.l }
onChange={ ( nextL: number ) => {
updateHSLAValue( { l: nextL } );
} }
/>
{ enableAlpha && (
<InputWithSlider
min={ 0 }
max={ 100 }
label="Alpha"
abbreviation="A"
value={ Math.trunc( 100 * colorValue.a ) }
onChange={ ( nextA: number ) => {
updateHSLAValue( { a: nextA / 100 } );
} }
/>
) }
</>

  1. We can remove the fragments and add a div like this instead of the fragments. This pattern is visible in places like the duotone-picker/color-list-picker , link-control.
<div group="role" aria-label="HSL Inputs"> 
    <InputWithSlider/>
    <InputWithSlider/>
    <InputWithSlider/>
</div>
  1. Another approach is use a VStack. VStack has spacing prop which we can use to handle the spacing between the InputWithSlider. A spacing of 2 would match the current column gaps of 8px which is (4px *2). Whereas in the custom div approach we would have to manage the gap by adding additional CSS class and the properties.
<VStack spacing="2"> 
    <InputWithSlider/>
    <InputWithSlider/>
    <InputWithSlider/>
</VStack>

I would like to hear your thoughts on which approach would be better.

cc: @ciampo , @t-hamano , @Mamaduka

Copy link
Contributor

Choose a reason for hiding this comment

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

We probably need to decide first what the issues are and what the ideal structure would be in terms of accessibility.

The current problem of the ColorPicker component is that when the color type is "HSL", the slider for changing the overall color and the slider for changing only the "H" value are both labeled "HSL", so screen reader users won't know if they're editing the overall color or just the H value. And as far as I know, the current testing library doesn't offer an option to distinguish between the two using getByRole. Is this correct?

color-picker

In other words, the DOM tree is structured as follows:

  • slider "Color"
  • slider "Hue”: This control is for the overall color
  • slider "Alpha"
  • combobox "Color format"
  • button: "Copy"
  • spinbutton "Hue"
  • slider "Hue": This control is for the "H" value
  • spinbutton "Saturation"
  • slider "Saturation"
  • spinbutton "Lightness"
  • slider "Lightness"

I'm not sure if this is acceptable from an accessibility perspective, but how about differentiating the labels? For example, by changing the latter "Hue" label to "Hue (HSL H value)".

If this isn't ideal, maybe we could group the H, S, L inputs as you say.

cc @joedolson @afercia @alexstine

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks @t-hamano , While others chip in their suggestions, what you said is possible we can do that as well in that scenario we need to change 2 labels ie.

  1. "Hue" label to "Hue (HSL H value)". This would give us a new label for both RGB/HSL for the top input slider.
  2. Secondly when alpha (opacity) is enabled we have 2 opacity sliders which once again cause a conflict so for this as well we need to change the label.

Since this issue is anyway closed i'm thinking to open a PR for the same and continue the discussions there?

Screenshots of Alpha label Screenshot 2025-05-07 at 12 10 42 PM Screenshot 2025-05-07 at 12 09 43 PM

@im3dabasia im3dabasia requested a review from ciampo April 9, 2025 11:13
@im3dabasia
Copy link
Contributor Author

Hi @ciampo , When you have a moment please review this PR. I have incorporated the changes that you had requested for.

Looking forward!

Copy link
Contributor

@ciampo ciampo left a comment

Choose a reason for hiding this comment

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

LGTM 🚀

Good to merge once a CHANGELOG entry is added

@im3dabasia im3dabasia force-pushed the fix/add-alpha-tests-color-picker branch from 066a490 to 9258a6b Compare April 16, 2025 06:01
@im3dabasia
Copy link
Contributor Author

LGTM 🚀

Good to merge once a CHANGELOG entry is added

Thanks for the many iterations @ciampo .

I have added an entry in the CHANGELOG.md in this 9258a6b.

When you a moment, please have a look at it. Lmk if any further changes need to made before 🚢

@im3dabasia im3dabasia requested a review from ciampo April 16, 2025 08:19
@ciampo ciampo enabled auto-merge (squash) April 16, 2025 09:00
@ciampo
Copy link
Contributor

ciampo commented Apr 16, 2025

It's looking good! The PR will merge as soon as CI checks are completed

@im3dabasia
Copy link
Contributor Author

They unit tests appear to be failing. I'll rebase the PR. After this #69912 , The failing tests should pass.

auto-merge was automatically disabled April 16, 2025 10:09

Head branch was pushed to by a user without write access

@im3dabasia im3dabasia force-pushed the fix/add-alpha-tests-color-picker branch from 9258a6b to 353a0e7 Compare April 16, 2025 10:09
@im3dabasia
Copy link
Contributor Author

@ciampo , Thanks for 36f90e1.

I guess we can now ship it 🚢 . All CI tests are passing 🚀

@Mamaduka
Copy link
Member

Can we merge this? @im3dabasia, @ciampo

@im3dabasia
Copy link
Contributor Author

Can we merge this? @im3dabasia, @ciampo

Yes @Mamaduka , We can. Actually @ciampo had enabled auto-merge before but due to some CI checks failing we rebased this PR.

Now since all CI checks are passing we can merge this PR to trunk . No issues

@Mamaduka Mamaduka merged commit 973e916 into WordPress:trunk Apr 25, 2025
60 checks passed
@github-actions github-actions bot added this to the Gutenberg 20.8 milestone Apr 25, 2025
chriszarate pushed a commit to chriszarate/gutenberg that referenced this pull request Jul 1, 2025
Co-authored-by: im3dabasia <im3dabasia1@git.wordpress.org>
Co-authored-by: ciampo <mciampini@git.wordpress.org>
Co-authored-by: Mamaduka <mamaduka@git.wordpress.org>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Package] Components /packages/components [Type] Code Quality Issues or PRs that relate to code quality
Projects
None yet
Development

Successfully merging this pull request may close these issues.

ColorPicker: improve unit tests
4 participants