From fdce127d931e1bbce13901a5199a01804ed14f85 Mon Sep 17 00:00:00 2001 From: "Jonas Kellerer (TNG)" Date: Tue, 30 Jul 2024 11:04:09 +0200 Subject: [PATCH] feat(components): add select all/none button to dropdown selector #361 --- .../components/checkbox-selector.stories.tsx | 104 ++++++++++++++++-- .../preact/components/checkbox-selector.tsx | 19 ++++ 2 files changed, 112 insertions(+), 11 deletions(-) diff --git a/components/src/preact/components/checkbox-selector.stories.tsx b/components/src/preact/components/checkbox-selector.stories.tsx index 61c50655..45cf675c 100644 --- a/components/src/preact/components/checkbox-selector.stories.tsx +++ b/components/src/preact/components/checkbox-selector.stories.tsx @@ -1,5 +1,7 @@ import { type Meta, type StoryObj } from '@storybook/preact'; import { expect, fn, waitFor, within } from '@storybook/test'; +import { type FunctionComponent } from 'preact'; +import { useState } from 'preact/hooks'; import { type CheckboxItem, CheckboxSelector, type CheckboxSelectorProps } from './checkbox-selector'; @@ -14,12 +16,33 @@ const meta: Meta = { export default meta; +const WrapperWithState: FunctionComponent = ({ + items: initialItems, + label, + setItems: setItemsMock, +}) => { + const [items, setItems] = useState(initialItems); + + return ( +
+ { + setItemsMock(items); + setItems(items); + }} + /> +
+ ); +}; + export const CheckboxSelectorStory: StoryObj = { render: (args) => { let wrapperStateItems = args.items; return ( - { @@ -37,20 +60,79 @@ export const CheckboxSelectorStory: StoryObj = { label: 'Some label', setItems: fn(), }, - play: async ({ canvasElement, args }) => { + play: async ({ canvasElement, args, step }) => { const canvas = within(canvasElement); - const open = () => canvas.getByText('Some label', { exact: false }); + const open = () => canvas.getByText('Some label'); + const selectAll = () => canvas.getByText('Select all'); + const selectNone = () => canvas.getByText('Select none'); + const firstItem = () => canvas.getByLabelText('item1'); open().click(); - const item1 = canvas.getByLabelText('item1', { exact: false }); - item1.click(); + await step('Select one item', async () => { + firstItem().click(); - await waitFor(() => - expect(args.setItems).toHaveBeenCalledWith([ - { checked: true, label: 'item1' }, - { checked: false, label: 'item2' }, - ]), - ); + await waitFor(() => + expect(args.setItems).toHaveBeenCalledWith([ + { checked: true, label: 'item1' }, + { checked: false, label: 'item2' }, + ]), + ); + }); + + await step('Select all items with one item already selected', async () => { + selectAll().click(); + + await waitFor(() => + expect(args.setItems).toHaveBeenCalledWith([ + { checked: true, label: 'item1' }, + { checked: true, label: 'item2' }, + ]), + ); + }); + + await step('Deselect one item', async () => { + firstItem().click(); + + await waitFor(() => + expect(args.setItems).toHaveBeenCalledWith([ + { checked: false, label: 'item1' }, + { checked: true, label: 'item2' }, + ]), + ); + }); + + await step('Select none with one item already selected', async () => { + selectNone().click(); + + await waitFor(() => + expect(args.setItems).toHaveBeenCalledWith([ + { checked: false, label: 'item1' }, + { checked: false, label: 'item2' }, + ]), + ); + }); + + await step('Select all items with none selected', async () => { + selectAll().click(); + + await waitFor(() => + expect(args.setItems).toHaveBeenCalledWith([ + { checked: true, label: 'item1' }, + { checked: true, label: 'item2' }, + ]), + ); + }); + + await step('Select none with all items selected', async () => { + selectNone().click(); + + await waitFor(() => + expect(args.setItems).toHaveBeenCalledWith([ + { checked: false, label: 'item1' }, + { checked: false, label: 'item2' }, + ]), + ); + }); }, }; diff --git a/components/src/preact/components/checkbox-selector.tsx b/components/src/preact/components/checkbox-selector.tsx index 07218053..e0da4a74 100644 --- a/components/src/preact/components/checkbox-selector.tsx +++ b/components/src/preact/components/checkbox-selector.tsx @@ -18,6 +18,25 @@ export const CheckboxSelector = ({ }: CheckboxSelectorProps) => { return ( + + +
    {items.map((item, index) => (