From 03af3479b773b01470ee73cecc67bac21f38ce35 Mon Sep 17 00:00:00 2001 From: Patryk Andrzejewski Date: Thu, 12 Sep 2024 10:27:41 +0200 Subject: [PATCH] Return empty cell for removed row (#5157) * Return empty cell for removed row * Return empty cell for removed row --- .changeset/pretty-keys-sneeze.md | 5 + .../OrderListDatagrid/datagrid.test.ts | 156 +++++++++++++++++- .../components/OrderListDatagrid/datagrid.ts | 5 +- 3 files changed, 161 insertions(+), 5 deletions(-) create mode 100644 .changeset/pretty-keys-sneeze.md diff --git a/.changeset/pretty-keys-sneeze.md b/.changeset/pretty-keys-sneeze.md new file mode 100644 index 00000000000..810b54edf78 --- /dev/null +++ b/.changeset/pretty-keys-sneeze.md @@ -0,0 +1,5 @@ +--- +"saleor-dashboard": patch +--- + +Grid no longer crashes when removing row. diff --git a/src/orders/components/OrderListDatagrid/datagrid.test.ts b/src/orders/components/OrderListDatagrid/datagrid.test.ts index e0f6425b430..67819fb57d3 100644 --- a/src/orders/components/OrderListDatagrid/datagrid.test.ts +++ b/src/orders/components/OrderListDatagrid/datagrid.test.ts @@ -1,7 +1,22 @@ -import { OrderListQuery } from "@dashboard/graphql"; +import { GetCellContentOpts } from "@dashboard/components/Datagrid/Datagrid"; +import { AvailableColumn } from "@dashboard/components/Datagrid/types"; +import { OrderListQuery, OrderStatus, PaymentChargeStatusEnum } from "@dashboard/graphql"; import { RelayToFlat } from "@dashboard/types"; +import { TextCell } from "@glideapps/glide-data-grid"; +import { renderHook } from "@testing-library/react-hooks"; -import { getCustomerCellContent } from "./datagrid"; +import { getCustomerCellContent, useGetCellContent } from "./datagrid"; + +jest.mock("react-intl", () => ({ + useIntl: jest.fn(() => ({ + formatMessage: jest.fn(x => x), + })), + defineMessages: jest.fn(x => x), +})); + +jest.mock("@saleor/macaw-ui-next", () => ({ + useTheme: () => ({ theme: "defaultLight" }), +})); describe("getCustomerCellContent", () => { it("should return billing address first name and last name when exists", () => { @@ -45,3 +60,140 @@ describe("getCustomerCellContent", () => { expect(result.displayData).toEqual("-"); }); }); + +describe("useGetCellContent", () => { + // Arrange + const mockColumns: AvailableColumn[] = [ + { id: "number", title: "Number", width: 100 }, + { id: "date", title: "Date", width: 100 }, + { id: "customer", title: "Customer", width: 100 }, + { id: "payment", title: "Payment", width: 100 }, + { id: "status", title: "Status", width: 100 }, + { id: "total", title: "Total", width: 100 }, + ]; + + const mockOrders = [ + { + __typename: "Order", + id: "order-1", + number: "1", + created: "2023-01-01T00:00:00Z", + userEmail: "john@example.com", + paymentStatus: "PAID" as PaymentChargeStatusEnum, + status: "FULFILLED" as OrderStatus, + billingAddress: null, + total: { gross: { amount: 100, currency: "USD" } }, + }, + ] as RelayToFlat>; + + it("should return correct cell content for each column", () => { + // Arrange + const { result } = renderHook(() => + useGetCellContent({ columns: mockColumns, orders: mockOrders }), + ); + const getCellContent = result.current; + const contentOpts = { added: [], removed: [] } as unknown as GetCellContentOpts; + + // Act & Assert + expect(getCellContent([0, 0], contentOpts)).toEqual({ + allowOverlay: false, + cursor: "pointer", + data: "1", + displayData: "1", + kind: "text", + readonly: true, + style: "normal", + }); + expect(getCellContent([1, 0], contentOpts)).toEqual({ + allowOverlay: true, + copyData: "2023-01-01T00:00:00Z", + cursor: "pointer", + data: { + kind: "date-cell", + value: "2023-01-01T00:00:00Z", + }, + kind: "custom", + readonly: false, + }); + expect(getCellContent([2, 0], contentOpts)).toEqual({ + allowOverlay: false, + cursor: "pointer", + data: "john@example.com", + displayData: "john@example.com", + kind: "text", + readonly: true, + style: "normal", + }); + expect(getCellContent([3, 0], contentOpts)).toEqual({ + allowOverlay: true, + copyData: "PAID", + cursor: "pointer", + data: { + color: { + base: "#ffdeea", + border: "#eec4cf", + text: "#6a4751", + }, + kind: "auto-tags-cell", + value: "PAID", + }, + kind: "custom", + readonly: false, + }); + expect(getCellContent([4, 0], contentOpts)).toEqual({ + allowOverlay: true, + copyData: { + defaultMessage: "Fulfilled", + description: "order status", + id: "pkjXPD", + }, + cursor: "pointer", + data: { + color: { + base: "#d7f5d7", + border: "#bddabd", + text: "#415a41", + }, + kind: "auto-tags-cell", + value: { + defaultMessage: "Fulfilled", + description: "order status", + id: "pkjXPD", + }, + }, + kind: "custom", + readonly: false, + }); + expect(getCellContent([5, 0], contentOpts)).toEqual({ + allowOverlay: true, + copyData: "100", + cursor: "pointer", + data: { currency: "USD", kind: "money-cell", value: 100 }, + kind: "custom", + readonly: false, + }); + }); + + it("should return empty cell for invalid column", () => { + // Arrange + const { result } = renderHook(() => + useGetCellContent({ columns: mockColumns, orders: mockOrders }), + ); + const getCellContent = result.current; + const contentOpts = { added: [], removed: [] } as unknown as GetCellContentOpts; + + // Act & Assert + expect((getCellContent([10, 0], contentOpts) as TextCell).data).toBe(""); + }); + + it("should return empty cell for removed row", () => { + const { result } = renderHook(() => + useGetCellContent({ columns: mockColumns, orders: mockOrders }), + ); + const getCellContent = result.current; + const contentOpts = { added: [1], removed: [] } as unknown as GetCellContentOpts; + + // Act & Assert + expect((getCellContent([0, 1], contentOpts) as TextCell).data).toBe(""); + }); +}); diff --git a/src/orders/components/OrderListDatagrid/datagrid.ts b/src/orders/components/OrderListDatagrid/datagrid.ts index 7febe58d8ff..64b01c335c3 100644 --- a/src/orders/components/OrderListDatagrid/datagrid.ts +++ b/src/orders/components/OrderListDatagrid/datagrid.ts @@ -76,13 +76,12 @@ export const useGetCellContent = ({ columns, orders }: GetCellContentProps) => { return ([column, row]: Item, { added, removed }: GetCellContentOpts): GridCell => { const columnId = columns[column]?.id; + const rowData = added.includes(row) ? undefined : orders[getDatagridRowDataIndex(row, removed)]; - if (!columnId) { + if (!columnId || !rowData) { return readonlyTextCell(""); } - const rowData = added.includes(row) ? undefined : orders[getDatagridRowDataIndex(row, removed)]; - switch (columnId) { case "number": return readonlyTextCell(rowData.number);