Skip to content

Commit

Permalink
Preventing crash when assigning product to shipping rate (#5188)
Browse files Browse the repository at this point in the history
* Fix reading id of undefined products

* Add changeset
  • Loading branch information
poulch authored Oct 9, 2024
1 parent 45b8168 commit 8bf935a
Show file tree
Hide file tree
Showing 5 changed files with 80 additions and 13 deletions.
5 changes: 5 additions & 0 deletions .changeset/loud-weeks-tap.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"saleor-dashboard": patch
---

Assigning product to shipping method weight rate no more cause error
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
// @ts-strict-ignore
import { FetchResult } from "@apollo/client";
import { Channel, isAvailableInChannel } from "@dashboard/channels/utils";
import BackButton from "@dashboard/components/BackButton";
Expand All @@ -8,17 +7,20 @@ import { DashboardModal } from "@dashboard/components/Modal";
import ResponsiveTable from "@dashboard/components/ResponsiveTable";
import TableCellAvatar from "@dashboard/components/TableCellAvatar";
import TableRowLink from "@dashboard/components/TableRowLink";
import { SearchProductsQuery, ShippingPriceExcludeProductMutation } from "@dashboard/graphql";
import { ShippingPriceExcludeProductMutation } from "@dashboard/graphql";
import useSearchQuery from "@dashboard/hooks/useSearchQuery";
import { renderCollection } from "@dashboard/misc";
import { FetchMoreProps, RelayToFlat } from "@dashboard/types";
import { isProductSelected } from "@dashboard/shipping/components/ShippingMethodProductsAddDialog/utils";
import { FetchMoreProps } from "@dashboard/types";
import { CircularProgress, TableBody, TableCell, TextField } from "@material-ui/core";
import { makeStyles } from "@saleor/macaw-ui";
import { Box, Skeleton, Text } from "@saleor/macaw-ui-next";
import React from "react";
import InfiniteScroll from "react-infinite-scroll-component";
import { FormattedMessage, useIntl } from "react-intl";

import { Product, Products } from "./types";

const useStyles = makeStyles(
() => ({
avatar: {
Expand All @@ -41,18 +43,18 @@ const useStyles = makeStyles(
export interface ShippingMethodProductsAddDialogProps extends FetchMoreProps {
confirmButtonState: ConfirmButtonTransitionState;
open: boolean;
products: RelayToFlat<SearchProductsQuery["search"]>;
products: Products;
onClose: () => void;
onFetch: (query: string) => void;
onSubmit: (ids: string[]) => Promise<FetchResult<ShippingPriceExcludeProductMutation>>;
availableChannels: Channel[];
}

const handleProductAssign = (
product: RelayToFlat<SearchProductsQuery["search"]>[0],
product: Product,
isSelected: boolean,
selectedProducts: RelayToFlat<SearchProductsQuery["search"]>,
setSelectedProducts: (data: RelayToFlat<SearchProductsQuery["search"]>) => void,
selectedProducts: Products,
setSelectedProducts: (data: Products) => void,
) => {
if (isSelected) {
setSelectedProducts(
Expand Down Expand Up @@ -80,9 +82,7 @@ const ShippingMethodProductsAddDialog: React.FC<ShippingMethodProductsAddDialogP
const classes = useStyles();
const intl = useIntl();
const [query, onQueryChange, resetQuery] = useSearchQuery(onFetch);
const [selectedProducts, setSelectedProducts] = React.useState<
RelayToFlat<SearchProductsQuery["search"]>
>([]);
const [selectedProducts, setSelectedProducts] = React.useState<Products>([]);
const handleSubmit = () => {
onSubmit(selectedProducts.map(product => product.id)).then(() => {
setSelectedProducts([]);
Expand Down Expand Up @@ -153,9 +153,7 @@ const ShippingMethodProductsAddDialog: React.FC<ShippingMethodProductsAddDialogP
{renderCollection(
products,
(product, productIndex) => {
const isSelected = selectedProducts.some(
selectedProduct => selectedProduct.id === product.id,
);
const isSelected = isProductSelected(selectedProducts, product?.id);

const isProductAvailable = isAvailableInChannel({
availableChannels,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { SearchProductsQuery } from "@dashboard/graphql";
import { RelayToFlat } from "@dashboard/types";

export type Products = NonNullable<RelayToFlat<SearchProductsQuery["search"]>>;
export type Product = Products[0];
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { Products } from "./types";
import { isProductSelected } from "./utils";

describe("isProductSelected", () => {
it("should return false if product id is not provided", () => {
// Arrange
const selectedProducts = [{ id: "1" }, { id: "2" }] as Products;
const productId = undefined;

// Act
const result = isProductSelected(selectedProducts, productId);

// Assert
expect(result).toEqual(false);
});

it("should return false if product id is not in selected products", () => {
// Arrange
const selectedProducts = [{ id: "1" }, { id: "2" }] as Products;
const productId = "3";

// Act
const result = isProductSelected(selectedProducts, productId);

// Assert
expect(result).toEqual(false);
});

it("should return false if no selected product", () => {
// Arrange
const selectedProducts = [] as Products;
const productId = "1";

// Act
const result = isProductSelected(selectedProducts, productId);

// Assert
expect(result).toEqual(false);
});

it("should return true if product id is in selected products", () => {
// Arrange
const selectedProducts = [{ id: "1" }, { id: "2" }] as Products;
const productId = "2";

// Act
const result = isProductSelected(selectedProducts, productId);

// Assert
expect(result).toEqual(true);
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { Products } from "./types";

export const isProductSelected = (selectedProducts: Products, productId?: string) => {
if (!productId) return false;

return selectedProducts.some(selectedProduct => selectedProduct.id === productId);
};

0 comments on commit 8bf935a

Please sign in to comment.