From 03fc4c2daebbdb4065c0dc10346b08fccbc296a0 Mon Sep 17 00:00:00 2001 From: dominik-zeglen Date: Mon, 19 Oct 2020 11:33:51 +0200 Subject: [PATCH] Fix multiple value dropdown --- .../MultiAutocompleteSelectField.tsx | 14 ++- src/products/utils/handlers.test.ts | 111 ++++++++++++++++++ src/products/utils/handlers.ts | 33 ++---- 3 files changed, 127 insertions(+), 31 deletions(-) create mode 100644 src/products/utils/handlers.test.ts diff --git a/src/components/MultiAutocompleteSelectField/MultiAutocompleteSelectField.tsx b/src/components/MultiAutocompleteSelectField/MultiAutocompleteSelectField.tsx index cd88b6ec8..e0f20ff1a 100644 --- a/src/components/MultiAutocompleteSelectField/MultiAutocompleteSelectField.tsx +++ b/src/components/MultiAutocompleteSelectField/MultiAutocompleteSelectField.tsx @@ -170,13 +170,15 @@ const MultiAutocompleteSelectFieldComponent: React.FC {isOpen && (!!inputValue || !!choices.length) && ( { - add.onClick(); - closeMenu(); + add={ + add && { + ...add, + onClick: () => { + add.onClick(); + closeMenu(); + } } - }} + } choices={choices.filter( choice => !value.includes(choice.value) )} diff --git a/src/products/utils/handlers.test.ts b/src/products/utils/handlers.test.ts new file mode 100644 index 000000000..ccc1690a9 --- /dev/null +++ b/src/products/utils/handlers.test.ts @@ -0,0 +1,111 @@ +import { FormsetData } from "@saleor/hooks/useFormset"; +import { AttributeInputTypeEnum } from "@saleor/types/globalTypes"; + +import { ProductAttributeInputData } from "../components/ProductAttributes"; +import { createAttributeMultiChangeHandler } from "./handlers"; + +const attributes: FormsetData = [ + { + data: { + inputType: AttributeInputTypeEnum.DROPDOWN, + isRequired: false, + values: [ + { + __typename: "AttributeValue", + id: "attrv-1", + name: "Attribute 1 Value 1", + slug: "attr-1-v-1" + } + ] + }, + id: "attr-1", + label: "Attribute 1", + value: [] + }, + { + data: { + inputType: AttributeInputTypeEnum.MULTISELECT, + isRequired: false, + values: [ + { + __typename: "AttributeValue", + id: "attrv-2", + name: "Attribute 2 Value 1", + slug: "attr-2-v-1" + }, + { + __typename: "AttributeValue", + id: "attrv-3", + name: "Attribute 2 Value 2", + slug: "attr-2-v-2" + }, + { + __typename: "AttributeValue", + id: "attrv-4", + name: "Attribute 2 Value 3", + slug: "attr-2-v-3" + } + ] + }, + id: "attr-2", + label: "Attribute 2", + value: ["attr-2-v-3"] + } +]; + +describe("Multiple select", () => { + it("is able to select value", () => { + const change = jest.fn(); + const trigger = jest.fn(); + const handler = createAttributeMultiChangeHandler( + change, + attributes, + trigger + ); + + handler("attr-2", "attr-2-v-1"); + + expect(change).toHaveBeenCalledTimes(1); + expect(change.mock.calls[0][0]).toBe("attr-2"); + expect(change.mock.calls[0][1]).toHaveLength(2); + expect(change.mock.calls[0][1][0]).toBe("attr-2-v-3"); + expect(change.mock.calls[0][1][1]).toBe("attr-2-v-1"); + expect(trigger).toHaveBeenCalledTimes(1); + }); + + it("is able to deselect value", () => { + const change = jest.fn(); + const trigger = jest.fn(); + const handler = createAttributeMultiChangeHandler( + change, + attributes, + trigger + ); + + handler("attr-2", "attr-2-v-3"); + + expect(change).toHaveBeenCalledTimes(1); + expect(change.mock.calls[0][0]).toBe("attr-2"); + expect(change.mock.calls[0][1]).toHaveLength(0); + expect(trigger).toHaveBeenCalledTimes(1); + }); + + it("is able to add custom value", () => { + const change = jest.fn(); + const trigger = jest.fn(); + const handler = createAttributeMultiChangeHandler( + change, + attributes, + trigger + ); + + handler("attr-2", "A Value"); + + expect(change).toHaveBeenCalledTimes(1); + expect(change.mock.calls[0][0]).toBe("attr-2"); + expect(change.mock.calls[0][1]).toHaveLength(2); + expect(change.mock.calls[0][1][0]).toBe("attr-2-v-3"); + expect(change.mock.calls[0][1][1]).toBe("A Value"); + expect(trigger).toHaveBeenCalledTimes(1); + }); +}); diff --git a/src/products/utils/handlers.ts b/src/products/utils/handlers.ts index 4571ec244..9f854c40a 100644 --- a/src/products/utils/handlers.ts +++ b/src/products/utils/handlers.ts @@ -1,4 +1,3 @@ -import { MultiAutocompleteChoiceType } from "@saleor/components/MultiAutocompleteSelectField"; import { FormChange } from "@saleor/hooks/useForm"; import { FormsetChange, FormsetData } from "@saleor/hooks/useFormset"; import { toggle } from "@saleor/utils/lists"; @@ -18,38 +17,22 @@ export function createAttributeChangeHandler( export function createAttributeMultiChangeHandler( changeAttributeData: FormsetChange, - attributes: FormsetData, + attributes: FormsetData, triggerChange: () => void ): FormsetChange { return (attributeId: string, value: string) => { - const attributeValue = attributes - .find(attribute => attribute.id === attributeId) - .data.values.find(attributeValue => attributeValue.slug === value); - - const valueChoice = { - label: attributeValue ? attributeValue.name : value, - value - }; - - const itemIndex = attributes.findIndex(item => item.id === attributeId); - const attributeValues: MultiAutocompleteChoiceType[] = attributes[ - itemIndex - ].data.values.map(value => ({ - label: value.name, - value: value.id - })); + const attribute = attributes.find( + attribute => attribute.id === attributeId + ); const newAttributeValues = toggle( - valueChoice, - attributeValues, - (a, b) => a.value === b.value + value, + attribute.value, + (a, b) => a === b ); triggerChange(); - changeAttributeData( - attributeId, - newAttributeValues.map(({ value }) => value) - ); + changeAttributeData(attributeId, newAttributeValues); }; }