diff --git a/.changeset/slow-mangos-beg.md b/.changeset/slow-mangos-beg.md new file mode 100644 index 00000000000..6f64d2be29c --- /dev/null +++ b/.changeset/slow-mangos-beg.md @@ -0,0 +1,5 @@ +--- +"saleor-dashboard": patch +--- + +You can now provide 0 variant price value during product creation diff --git a/src/products/components/ProductVariantPrice/ProductVariantPrice.test.tsx b/src/products/components/ProductVariantPrice/ProductVariantPrice.test.tsx new file mode 100644 index 00000000000..4c51e89e548 --- /dev/null +++ b/src/products/components/ProductVariantPrice/ProductVariantPrice.test.tsx @@ -0,0 +1,87 @@ +import { ChannelData } from "@dashboard/channels/utils"; +import { ThemeWrapper } from "@test/themeWrapper"; +import { fireEvent, render, screen } from "@testing-library/react"; +import React from "react"; + +import { ProductVariantPrice } from "./ProductVariantPrice"; + +const wrapper = ({ children }: { children: React.ReactNode }) => ( + {children} +); + +jest.mock("react-intl", () => ({ + useIntl: jest.fn(() => ({ + formatMessage: jest.fn(x => x.defaultMessage), + })), + defineMessages: jest.fn(x => x), + FormattedMessage: ({ defaultMessage }: { defaultMessage: string }) => <>{defaultMessage}, +})); + +describe("ProductVariantPrice", () => { + it("should render not assign info text when variant is not assigned to any channel", () => { + // Arrange + render(, { wrapper }); + + // Assert + expect( + screen.getByText( + "Assign this variant to a channel in the product channel manager to define prices", + ), + ).toBeInTheDocument(); + }); + + it("should allow to display 0 value", async () => { + // Arrange + const listing = [ + { + id: "1", + currency: "USD", + price: 0, + preorderThreshold: 0, + }, + ] as unknown as ChannelData[]; + + render(, { + wrapper, + }); + + // Assert + expect(screen.getByTestId("price-field")).toHaveValue(0); + }); + + it("should allow to set price value", () => { + // Arrange + const onChange = jest.fn(); + const listing = [ + { + id: "1", + currency: "USD", + price: "", + preorderThreshold: 0, + }, + ] as unknown as ChannelData[]; + + render( + , + { + wrapper, + }, + ); + + const input = screen.getByTestId("price-field"); + + // Act + fireEvent.change(input, { target: { value: 0 } }); + + // Assert + expect(onChange).toHaveBeenCalledWith("1", { + price: 0, + preorderThreshold: 0, + costPrice: undefined, + }); + }); +}); diff --git a/src/products/components/ProductVariantPrice/ProductVariantPrice.tsx b/src/products/components/ProductVariantPrice/ProductVariantPrice.tsx index 9ae465d92db..495fb7ba7ab 100644 --- a/src/products/components/ProductVariantPrice/ProductVariantPrice.tsx +++ b/src/products/components/ProductVariantPrice/ProductVariantPrice.tsx @@ -148,7 +148,7 @@ export const ProductVariantPrice: React.FC = props => priceApiError ? getProductErrorMessage(priceApiError, intl) : "" } name={fieldName} - value={listing.price || ""} + value={listing.price ?? ""} currencySymbol={listing.currency} onChange={e => onChange(listing.id, { @@ -159,6 +159,7 @@ export const ProductVariantPrice: React.FC = props => } disabled={loading} required + data-test-id="price-field" /> ) : ( @@ -172,7 +173,7 @@ export const ProductVariantPrice: React.FC = props => })} error={!!costPriceError} name={`${listing.id}-channel-costPrice`} - value={listing.costPrice || ""} + value={listing.costPrice ?? ""} currencySymbol={listing.currency} onChange={e => onChange(listing.id, { @@ -183,6 +184,7 @@ export const ProductVariantPrice: React.FC = props => } disabled={loading} hint={costPriceError ? getProductErrorMessage(costPriceError, intl) : ""} + data-test-id="cost-price-field" /> ) : (