From c39a17b5ee6dcdcb4fe37fa4afb21cffc9e4567a Mon Sep 17 00:00:00 2001 From: Mohamed Khelif Date: Fri, 8 Sep 2023 13:19:24 -0400 Subject: [PATCH] Refactor to make testing easier --- .../FileTableTab/GroupedFilesTable/index.tsx | 15 +- .../task/taskTabs/FileTableTab/index.tsx | 14 +- src/pages/task/taskTabs/FileTableTab/types.ts | 6 + .../task/taskTabs/FileTableTab/utils.test.ts | 151 ++++++++++++++++++ src/pages/task/taskTabs/FileTableTab/utils.ts | 23 +++ 5 files changed, 190 insertions(+), 19 deletions(-) create mode 100644 src/pages/task/taskTabs/FileTableTab/types.ts create mode 100644 src/pages/task/taskTabs/FileTableTab/utils.test.ts create mode 100644 src/pages/task/taskTabs/FileTableTab/utils.ts diff --git a/src/pages/task/taskTabs/FileTableTab/GroupedFilesTable/index.tsx b/src/pages/task/taskTabs/FileTableTab/GroupedFilesTable/index.tsx index c84c21a52c..ae858bcc9b 100644 --- a/src/pages/task/taskTabs/FileTableTab/GroupedFilesTable/index.tsx +++ b/src/pages/task/taskTabs/FileTableTab/GroupedFilesTable/index.tsx @@ -15,11 +15,12 @@ import { } from "@leafygreen-ui/table/new"; import { Subtitle } from "@leafygreen-ui/typography"; import { StyledLink } from "components/styles"; -import { File } from "gql/generated/types"; +import { Unpacked } from "types/utils"; +import { GroupedFiles } from "../types"; -type GroupedFilesTableFile = Omit; +type GroupedFilesFile = Unpacked; interface GroupedFilesTableProps { - files: GroupedFilesTableFile[]; + files: GroupedFilesFile[]; taskName?: string; } const GroupedFilesTable: React.FC = ({ @@ -28,7 +29,7 @@ const GroupedFilesTable: React.FC = ({ }) => { const tableContainerRef = useRef(null); - const columns = useMemo>>( + const columns = useMemo>>( () => [ { accessorKey: "name", @@ -44,7 +45,7 @@ const GroupedFilesTable: React.FC = ({ ], [] ); - const table = useLeafyGreenTable({ + const table = useLeafyGreenTable({ containerRef: tableContainerRef, data: files, columns, @@ -59,7 +60,7 @@ const GroupedFilesTable: React.FC = ({ {table .getHeaderGroups() - .map((headerGroup: HeaderGroup) => ( + .map((headerGroup: HeaderGroup) => ( {headerGroup.headers.map((header) => ( @@ -73,7 +74,7 @@ const GroupedFilesTable: React.FC = ({ ))} - {rows.map((row: LeafyGreenTableRow) => ( + {rows.map((row: LeafyGreenTableRow) => ( {row.getVisibleCells().map((cell) => ( diff --git a/src/pages/task/taskTabs/FileTableTab/index.tsx b/src/pages/task/taskTabs/FileTableTab/index.tsx index b108868975..6f7d2e5e1e 100644 --- a/src/pages/task/taskTabs/FileTableTab/index.tsx +++ b/src/pages/task/taskTabs/FileTableTab/index.tsx @@ -8,6 +8,7 @@ import { useToastContext } from "context/toast"; import { TaskFilesQuery, TaskFilesQueryVariables } from "gql/generated/types"; import { GET_TASK_FILES } from "gql/queries"; import GroupedFilesTable from "./GroupedFilesTable"; +import { filterGroupedFiles } from "./utils"; interface FilesTableTabProps { taskId: string; @@ -31,18 +32,7 @@ const FilesTableTab: React.FC = ({ execution, taskId }) => { const { taskFiles } = data?.task ?? {}; const { groupedFiles = [] } = taskFiles ?? {}; - const filteredGroupedFiles = groupedFiles.reduce((acc, groupedFile) => { - const filteredFiles = groupedFile?.files?.filter((file) => - file?.name?.toLowerCase().includes(search.toLowerCase()) - ); - if (filteredFiles?.length) { - acc.push({ - ...groupedFile, - files: filteredFiles, - }); - } - return acc; - }, [] as (typeof taskFiles)["groupedFiles"]); + const filteredGroupedFiles = filterGroupedFiles(groupedFiles, search); // We only want to show the file group name if there are multiple file groups. const hasMultipleFileGroups = groupedFiles.length > 1; diff --git a/src/pages/task/taskTabs/FileTableTab/types.ts b/src/pages/task/taskTabs/FileTableTab/types.ts new file mode 100644 index 0000000000..becb7bf7bb --- /dev/null +++ b/src/pages/task/taskTabs/FileTableTab/types.ts @@ -0,0 +1,6 @@ +import { TaskFilesQuery } from "gql/generated/types"; +import { Unpacked } from "types/utils"; + +export type GroupedFiles = Unpacked< + TaskFilesQuery["task"]["taskFiles"]["groupedFiles"] +>; diff --git a/src/pages/task/taskTabs/FileTableTab/utils.test.ts b/src/pages/task/taskTabs/FileTableTab/utils.test.ts new file mode 100644 index 0000000000..b2bdacaa04 --- /dev/null +++ b/src/pages/task/taskTabs/FileTableTab/utils.test.ts @@ -0,0 +1,151 @@ +import { filterGroupedFiles } from "./utils"; + +describe("filterGroupedFiles", () => { + it("should return an empty array if groupedFiles is empty", () => { + const groupedFiles = []; + const search = ""; + const result = filterGroupedFiles(groupedFiles, search); + expect(result).toStrictEqual([]); + }); + it("should return the original array if search is empty", () => { + const groupedFiles = [ + { + taskName: "some_task_name", + files: [ + { + name: "some_file_name", + link: "some_url", + }, + ], + }, + ]; + const search = ""; + const result = filterGroupedFiles(groupedFiles, search); + expect(result).toStrictEqual(groupedFiles); + }); + it("should filter the array if search is not empty", () => { + const groupedFiles = [ + { + taskName: "some_task_name", + files: [ + { + name: "some_file_name", + link: "some_url", + }, + { + name: "some_other_file_name", + link: "some_url", + }, + ], + }, + ]; + const search = "some_file_name"; + const result = filterGroupedFiles(groupedFiles, search); + expect(result).toStrictEqual([ + { + taskName: "some_task_name", + files: [ + { + name: "some_file_name", + link: "some_url", + }, + ], + }, + ]); + }); + it("should filter across multiple groups", () => { + const groupedFiles = [ + { + taskName: "some_task_name", + files: [ + { + name: "some_file_name", + link: "some_url", + }, + { + name: "some_other_file_name", + link: "some_url", + }, + ], + }, + { + taskName: "some_other_task_name", + files: [ + { + name: "some_file_name", + link: "some_url", + }, + { + name: "some_other_file_name", + link: "some_url", + }, + ], + }, + ]; + const search = "some_file_name"; + const result = filterGroupedFiles(groupedFiles, search); + expect(result).toStrictEqual([ + { + taskName: "some_task_name", + files: [ + { + name: "some_file_name", + link: "some_url", + }, + ], + }, + { + taskName: "some_other_task_name", + files: [ + { + name: "some_file_name", + link: "some_url", + }, + ], + }, + ]); + }); + it("should not return groups that have no matching files", () => { + const groupedFiles = [ + { + taskName: "some_task_name", + files: [ + { + name: "some_matching_file_name", + link: "some_url", + }, + { + name: "some_other_file_name", + link: "some_url", + }, + ], + }, + { + taskName: "some_other_task_name", + files: [ + { + name: "some_file_name", + link: "some_url", + }, + { + name: "some_other_file_name", + link: "some_url", + }, + ], + }, + ]; + const search = "some_matching_file_name"; + const result = filterGroupedFiles(groupedFiles, search); + expect(result).toStrictEqual([ + { + taskName: "some_task_name", + files: [ + { + name: "some_matching_file_name", + link: "some_url", + }, + ], + }, + ]); + }); +}); diff --git a/src/pages/task/taskTabs/FileTableTab/utils.ts b/src/pages/task/taskTabs/FileTableTab/utils.ts new file mode 100644 index 0000000000..a51d618f97 --- /dev/null +++ b/src/pages/task/taskTabs/FileTableTab/utils.ts @@ -0,0 +1,23 @@ +import type { GroupedFiles } from "./types"; + +/** + * `filterGroupedFiles` filters the groupedFiles array from the TaskFilesQuery + * @param groupedFiles - the groupedFiles array from the TaskFilesQuery + * @param search - the search string + * @returns - a new array of groupedFiles that contain the search string + */ +const filterGroupedFiles = (groupedFiles: GroupedFiles[], search: string) => + groupedFiles.reduce((acc, groupedFile) => { + const filteredFiles = groupedFile?.files?.filter((file) => + file?.name?.toLowerCase().includes(search.toLowerCase()) + ); + if (filteredFiles?.length) { + acc.push({ + ...groupedFile, + files: filteredFiles, + }); + } + return acc; + }, [] as GroupedFiles[]); + +export { filterGroupedFiles };