From 46c0b10e0e7d42b5a2a53d25e885ef2e4492baa7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Chy=C5=82a?= Date: Mon, 11 Mar 2024 13:17:13 +0100 Subject: [PATCH] Fix: Dashboard crashing when entering variants (#4715) * Fix undefined channel listing array * Add changeset --- .changeset/strange-ladybugs-judge.md | 5 +++ .../AvailabilityCard.tsx | 16 ++++---- .../useFilteredChannelListing.test.ts | 40 +++++++++++++++++++ .../useFilteredChannelListing.ts | 23 +++++++++++ 4 files changed, 76 insertions(+), 8 deletions(-) create mode 100644 .changeset/strange-ladybugs-judge.md create mode 100644 src/products/components/ProductVariantChannels/ChannelsAvailabilityCard/useFilteredChannelListing.test.ts create mode 100644 src/products/components/ProductVariantChannels/ChannelsAvailabilityCard/useFilteredChannelListing.ts diff --git a/.changeset/strange-ladybugs-judge.md b/.changeset/strange-ladybugs-judge.md new file mode 100644 index 00000000000..e5651b430a7 --- /dev/null +++ b/.changeset/strange-ladybugs-judge.md @@ -0,0 +1,5 @@ +--- +"saleor-dashboard": patch +--- + +Add check if channel listing array is undefined before call filter on it to prevent Dashboard crash diff --git a/src/products/components/ProductVariantChannels/ChannelsAvailabilityCard/AvailabilityCard.tsx b/src/products/components/ProductVariantChannels/ChannelsAvailabilityCard/AvailabilityCard.tsx index 834b65eaba2..f6c7eaf34a0 100644 --- a/src/products/components/ProductVariantChannels/ChannelsAvailabilityCard/AvailabilityCard.tsx +++ b/src/products/components/ProductVariantChannels/ChannelsAvailabilityCard/AvailabilityCard.tsx @@ -8,6 +8,7 @@ import React from "react"; import { ProductChannelListing } from "./../types"; import { ChannelsListItem } from "./ChannelsListItem"; +import { useFilteredChannelListing } from "./useFilteredChannelListing"; import CardContainer from "./VariantDetailsChannelsAvailabilityCardContainer"; interface AvailabilityCardProps { @@ -15,7 +16,7 @@ interface AvailabilityCardProps { ChannelPriceAndPreorderData, IChannelPriceAndPreorderArgs >; - productChannelListings: ProductChannelListing; + productChannelListings: ProductChannelListing | undefined; } export const AvailabilityCard: React.FC = ({ @@ -23,16 +24,15 @@ export const AvailabilityCard: React.FC = ({ productChannelListings, children, }) => { + const filteredListings = useFilteredChannelListing({ + allAvailableListings, + channelListing: productChannelListings, + }); + if (allAvailableListings.length === 0) { - return {}; + return {null}; } - const listingIds = allAvailableListings.map(lst => lst.id); - const filteredListings: ProductChannelListing = - productChannelListings?.filter((channel: ProductChannelListing[0]) => - listingIds.includes(channel.channel.id), - ); - return ( {filteredListings.map((listing: ProductChannelListing[0]) => ( diff --git a/src/products/components/ProductVariantChannels/ChannelsAvailabilityCard/useFilteredChannelListing.test.ts b/src/products/components/ProductVariantChannels/ChannelsAvailabilityCard/useFilteredChannelListing.test.ts new file mode 100644 index 00000000000..1eede0ded6b --- /dev/null +++ b/src/products/components/ProductVariantChannels/ChannelsAvailabilityCard/useFilteredChannelListing.test.ts @@ -0,0 +1,40 @@ +import { useFilteredChannelListing } from "./useFilteredChannelListing"; + +describe("useFilteredChannelListing", () => { + it("should return empty array if channelListing is null or undefined", () => { + // Arrange + const allAvailableListings = [{ id: "1" }, { id: "2" }]; + const channelListing = null; + + // Act + const result = useFilteredChannelListing({ + allAvailableListings, + channelListing, + }); + + // Assert + expect(result).toEqual([]); + }); + + it("should return array with filtered channel listings", () => { + // Arrange + const allAvailableListings = [{ id: "1" }, { id: "2" }, { id: "3" }]; + const channelListing = [ + { channel: { id: "1" } }, + { channel: { id: "3" } }, + { channel: { id: "4" } }, + ]; + + // Act + const result = useFilteredChannelListing({ + allAvailableListings, + channelListing, + }); + + // Assert + expect(result).toEqual([ + { channel: { id: "1" } }, + { channel: { id: "3" } }, + ]); + }); +}); diff --git a/src/products/components/ProductVariantChannels/ChannelsAvailabilityCard/useFilteredChannelListing.ts b/src/products/components/ProductVariantChannels/ChannelsAvailabilityCard/useFilteredChannelListing.ts new file mode 100644 index 00000000000..931eff25bf6 --- /dev/null +++ b/src/products/components/ProductVariantChannels/ChannelsAvailabilityCard/useFilteredChannelListing.ts @@ -0,0 +1,23 @@ +interface ChannelListing { + channel: { + id: string; + }; +} + +export const useFilteredChannelListing = ({ + channelListing, + allAvailableListings, +}: { + allAvailableListings: Array<{ id: string }>; + channelListing: ChannelListing[] | null | undefined; +}) => { + if (!channelListing) { + return []; + } + + const listingIds = allAvailableListings.map(lst => lst.id); + + return channelListing.filter(channel => + listingIds.includes(channel.channel.id), + ); +};