UNPKG

@allurereport/web-awesome

Version:

The static files for Allure Awesome Report

172 lines (146 loc) 4.98 kB
import type { Comparator, DefaultTreeGroup, Statistic, TestStatus, TreeLeaf } from "@allurereport/core-api"; import { alphabetically, andThen, byStatistic, byStatus, compareBy, emptyStatistic, incrementStatistic, mergeStatistic, ordinal, reverse, } from "@allurereport/core-api"; import type { SortBy } from "@/stores/treeSort"; import type { AwesomeRecursiveTree, AwesomeTree, AwesomeTreeGroup, AwesomeTreeLeaf } from "../../types"; const leafComparatorByTreeSortBy = (sortBy: SortBy = "status,asc"): Comparator<TreeLeaf<AwesomeTreeLeaf>> => { const typedCompareBy = compareBy<TreeLeaf<AwesomeTreeLeaf>>; switch (sortBy) { case "order,asc": case "order,desc": return typedCompareBy("groupOrder", ordinal()); case "duration,asc": case "duration,desc": return typedCompareBy("duration", ordinal()); case "name,asc": case "name,desc": return typedCompareBy("name", alphabetically()); case "status,asc": case "status,desc": return typedCompareBy("status", byStatus()); default: // eslint-disable-next-line no-console console.warn(`unsupported comparator ${sortBy as string}`); return () => 0; } }; const groupComparatorByTreeSortBy = (sortBy: SortBy = "status,asc"): Comparator<DefaultTreeGroup> => { const typedCompareBy = compareBy<DefaultTreeGroup>; switch (sortBy) { case "name,desc": case "name,asc": return typedCompareBy("name", alphabetically()); case "order,desc": case "order,asc": case "duration,desc": case "duration,asc": case "status,desc": case "status,asc": return typedCompareBy("statistic", byStatistic()); default: // eslint-disable-next-line no-console console.warn(`unsupported comparator ${sortBy as string}`); return () => 0; } }; const withDirection = <T extends { name: string }>(cmp: Comparator<T>, sortBy: SortBy): Comparator<T> => { const sortParams = sortBy.split(","); const isStatusSort = sortParams.includes("status"); const isDescending = sortParams.includes("desc"); const nameComparator = compareBy<T>("name", alphabetically()); return andThen([ isDescending && !isStatusSort ? reverse(cmp) : cmp, isDescending && isStatusSort ? reverse(nameComparator) : nameComparator, ]); }; export const leafComparator = (sortBy: SortBy = "status,asc"): Comparator<TreeLeaf<AwesomeTreeLeaf>> => { const cmp = leafComparatorByTreeSortBy(sortBy); return withDirection(cmp, sortBy); }; export const groupComparator = (sortBy: SortBy = "status,asc"): Comparator<DefaultTreeGroup> => { const cmp = groupComparatorByTreeSortBy(sortBy); return withDirection(cmp, sortBy); }; export const filterLeaves = ( leafIds: string[] = [], leavesById: AwesomeTree["leavesById"], filterPredicate: (item: AwesomeTreeLeaf) => boolean, sortBy: SortBy = "status,asc", ) => { let leaves = [...leafIds].map((leafId) => leavesById[leafId]); if (filterPredicate) { leaves = leaves.filter(filterPredicate); } const comparator = leafComparator(sortBy); return leaves.sort(comparator); }; /** * Fills the given tree from generator and returns recursive tree which includes leaves data instead of their IDs * Filters leaves when `filterOptions` property is provided * @param payload */ export const createRecursiveTree = (payload: { group: AwesomeTreeGroup; groupsById: AwesomeTree["groupsById"]; leavesById: AwesomeTree["leavesById"]; filterPredicate: (item: AwesomeTreeLeaf) => boolean; sortBy: SortBy; }): AwesomeRecursiveTree => { const { group, groupsById, leavesById, filterPredicate, sortBy } = payload; const groupLeaves: string[] = group.leaves ?? []; const leaves = filterLeaves(groupLeaves, leavesById, filterPredicate, sortBy); const trees = group.groups ?.flatMap((groupId) => { const nestedGroup = groupsById[groupId]; if (!nestedGroup) { return []; } return [ createRecursiveTree({ group: nestedGroup, groupsById, leavesById, filterPredicate, sortBy, }), ]; }) ?.filter((rt) => !isRecursiveTreeEmpty(rt)) ?? []; const statistic: Statistic = emptyStatistic(); trees.forEach((rt: AwesomeRecursiveTree) => { if (rt.statistic) { const additional: Statistic = rt.statistic; mergeStatistic(statistic, additional); } }); leaves.forEach((leaf) => { const status: TestStatus = leaf.status; incrementStatistic(statistic, status); }); return { ...group, statistic, leaves, trees: trees.sort(groupComparator(sortBy)), }; }; export const isRecursiveTreeEmpty = (tree: AwesomeRecursiveTree): boolean => { if (!tree.trees?.length && !tree.leaves?.length) { return true; } if (tree.leaves?.length) { return false; } return tree.trees?.every((subTree) => isRecursiveTreeEmpty(subTree)); };