UNPKG

@allurereport/web-classic

Version:

The static files for Allure Classic Report

140 lines (124 loc) 4.79 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 { TreeFiltersState, TreeSortBy } from "@/stores/tree"; import type { AwesomeRecursiveTree, AwesomeTree, AwesomeTreeGroup, AwesomeTreeLeaf } from "../../types"; export const isIncluded = (leaf: TreeLeaf<AwesomeTreeLeaf>, filterOptions: TreeFiltersState) => { const queryMatched = !filterOptions?.query || leaf.name.toLowerCase().includes(filterOptions.query.toLowerCase()); const statusMatched = !filterOptions?.status || filterOptions?.status === "total" || leaf.status === filterOptions.status; const flakyMatched = !filterOptions?.filter?.flaky || leaf.flaky; const retryMatched = !filterOptions?.filter?.retry || leaf.retry; // TODO: at this moment we don't have a new field implementation even in the generator // const newMatched = !filterOptions?.filter?.new || leaf.new; return [queryMatched, statusMatched, flakyMatched, retryMatched].every(Boolean); }; const leafComparatorByTreeSortBy = (sortBy: TreeSortBy): Comparator<TreeLeaf<AwesomeTreeLeaf>> => { const typedCompareBy = compareBy<TreeLeaf<AwesomeTreeLeaf>>; switch (sortBy) { case "order": return typedCompareBy("groupOrder", ordinal()); case "duration": return typedCompareBy("duration", ordinal()); case "alphabet": return typedCompareBy("name", alphabetically()); case "status": return typedCompareBy("status", byStatus()); } }; const groupComparatorByTreeSortBy = (sortBy: TreeSortBy): Comparator<DefaultTreeGroup> => { const typedCompareBy = compareBy<DefaultTreeGroup>; switch (sortBy) { case "alphabet": return typedCompareBy("name", alphabetically()); case "order": case "duration": case "status": return typedCompareBy("statistic", byStatistic()); } }; export const leafComparator = (filterOptions: TreeFiltersState): Comparator<TreeLeaf<AwesomeTreeLeaf>> => { const cmp = leafComparatorByTreeSortBy(filterOptions.sortBy); const directional = filterOptions.direction === "asc" ? cmp : reverse(cmp); // apply fallback sorting by name return andThen([directional, compareBy("name", alphabetically())]); }; export const groupComparator = (filterOptions: TreeFiltersState): Comparator<DefaultTreeGroup> => { const cmp = groupComparatorByTreeSortBy(filterOptions.sortBy); const directional = filterOptions.direction === "asc" ? cmp : reverse(cmp); // apply fallback sorting by name return andThen([directional, compareBy("name", alphabetically())]); }; export const filterLeaves = ( leaves: string[] = [], leavesById: AwesomeTree["leavesById"], filterOptions: TreeFiltersState, ) => { const filteredLeaves = [...leaves] .map((leafId) => leavesById[leafId]) .filter((leaf: TreeLeaf<AwesomeTreeLeaf>) => isIncluded(leaf, filterOptions)); const comparator = leafComparator(filterOptions); return filteredLeaves.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"]; filterOptions?: TreeFiltersState; }): AwesomeRecursiveTree => { const { group, groupsById, leavesById, filterOptions } = payload; const groupLeaves: string[] = group.leaves ?? []; const leaves = filterLeaves(groupLeaves, leavesById, filterOptions); const trees = group.groups ?.map((groupId) => createRecursiveTree({ group: groupsById[groupId], groupsById, leavesById, filterOptions, }), ) ?.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(filterOptions)), }; }; 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)); };