@allurereport/plugin-classic 3.0.0-beta.7 → 3.0.0-beta.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/plugin.js CHANGED
@@ -3,67 +3,73 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
3
3
  if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
4
4
  return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
5
5
  };
6
- var _Allure2Plugin_generate;
7
- import { convertTestResult } from "./converters.js";
8
- import { generateAttachmentsData, generateCategoriesData, generateDefaultWidgetData, generateEmptyTrendData, generateEnvironmentJson, generateExecutorJson, generatePackagesData, generateStaticFiles, generateSummaryJson, generateTestResults, generateTimelineData, generateTree, generateTrendData, } from "./generators.js";
6
+ var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
7
+ if (kind === "m") throw new TypeError("Private method is not writable");
8
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
9
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
10
+ return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
11
+ };
12
+ var _AllureAwesomePlugin_writer, _AllureAwesomePlugin_generate;
13
+ import { preciseTreeLabels } from "@allurereport/plugin-api";
14
+ import { generateAttachmentsFiles, generateEnvironmentJson, generateHistoryDataPoints, generatePieChart, generateStaticFiles, generateStatistic, generateTestResults, generateTree, generateTreeByCategories, } from "./generators.js";
9
15
  import { InMemoryReportDataWriter, ReportFileDataWriter } from "./writer.js";
10
- export class Allure2Plugin {
16
+ export class AllureAwesomePlugin {
11
17
  constructor(options = {}) {
12
18
  this.options = options;
13
- _Allure2Plugin_generate.set(this, async (context, store) => {
14
- const { reportName = "Allure Report", singleFile = false, reportLanguage = "en" } = this.options ?? {};
15
- const writer = singleFile ? new InMemoryReportDataWriter() : new ReportFileDataWriter(context.reportFiles);
16
- const attachmentLinks = await store.allAttachments();
17
- const attachmentMap = await generateAttachmentsData(writer, attachmentLinks, (id) => store.attachmentContentById(id));
18
- const categories = (await store.metadataByKey("allure2_categories")) ?? [];
19
- const environmentItems = (await store.metadataByKey("allure_environment")) ?? [];
20
- const tests = await store.allTestResults({ includeHidden: true });
21
- const allTr = [];
22
- for (const value of tests) {
23
- const fixtures = await store.fixturesByTrId(value.id);
24
- const retries = await store.retriesByTrId(value.id);
25
- const history = await store.historyByTrId(value.id);
26
- const allure2TestResult = convertTestResult({
27
- attachmentMap,
28
- fixtures,
29
- categories,
30
- retries,
31
- history,
32
- }, value);
33
- allTr.push(allure2TestResult);
19
+ _AllureAwesomePlugin_writer.set(this, void 0);
20
+ _AllureAwesomePlugin_generate.set(this, async (context, store) => {
21
+ const { singleFile, groupBy = [] } = this.options ?? {};
22
+ const environmentItems = await store.metadataByKey("allure_environment");
23
+ const statistic = await store.testsStatistic();
24
+ const attachments = await store.allAttachments();
25
+ await generateStatistic(__classPrivateFieldGet(this, _AllureAwesomePlugin_writer, "f"), statistic);
26
+ await generatePieChart(__classPrivateFieldGet(this, _AllureAwesomePlugin_writer, "f"), statistic);
27
+ const convertedTrs = await generateTestResults(__classPrivateFieldGet(this, _AllureAwesomePlugin_writer, "f"), store);
28
+ const treeLabels = preciseTreeLabels(!groupBy.length ? ["parentSuite", "suite", "subSuite"] : groupBy, convertedTrs, ({ labels }) => labels.map(({ name }) => name));
29
+ const behaviorLabels = preciseTreeLabels(!groupBy.length ? ["epic", "feature", "story"] : groupBy, convertedTrs, ({ labels }) => labels.map(({ name }) => name));
30
+ const packagesLabels = preciseTreeLabels(!groupBy.length ? ["package"] : groupBy, convertedTrs, ({ labels }) => labels.map(({ name }) => name));
31
+ await generateTreeByCategories(__classPrivateFieldGet(this, _AllureAwesomePlugin_writer, "f"), "categories", convertedTrs);
32
+ await generateTree(__classPrivateFieldGet(this, _AllureAwesomePlugin_writer, "f"), "tree", treeLabels, convertedTrs);
33
+ await generateTree(__classPrivateFieldGet(this, _AllureAwesomePlugin_writer, "f"), "behaviors", behaviorLabels, convertedTrs);
34
+ await generateTree(__classPrivateFieldGet(this, _AllureAwesomePlugin_writer, "f"), "packages", packagesLabels, convertedTrs);
35
+ await generateHistoryDataPoints(__classPrivateFieldGet(this, _AllureAwesomePlugin_writer, "f"), store);
36
+ if (environmentItems?.length) {
37
+ await generateEnvironmentJson(__classPrivateFieldGet(this, _AllureAwesomePlugin_writer, "f"), environmentItems);
38
+ }
39
+ if (attachments?.length) {
40
+ await generateAttachmentsFiles(__classPrivateFieldGet(this, _AllureAwesomePlugin_writer, "f"), attachments, (id) => store.attachmentContentById(id));
34
41
  }
35
- await generateTestResults(writer, allTr);
36
- const displayedTr = allTr.filter((atr) => !atr.hidden);
37
- await generateTree(writer, "suites", ["parentSuite", "suite", "subSuite"], displayedTr);
38
- await generateTree(writer, "behaviors", ["epic", "feature", "story"], displayedTr);
39
- await generatePackagesData(writer, displayedTr);
40
- await generateCategoriesData(writer, displayedTr);
41
- await generateTimelineData(writer, allTr);
42
- await generateSummaryJson(writer, reportName, displayedTr);
43
- await generateEnvironmentJson(writer, environmentItems);
44
- const executor = await store.metadataByKey("allure2_executor");
45
- const historyDataPoints = await store.allHistoryDataPoints();
46
- await generateExecutorJson(writer, executor);
47
- await generateDefaultWidgetData(writer, displayedTr, "duration.json", "status-chart.json", "severity.json");
48
- await generateTrendData(writer, reportName, displayedTr, historyDataPoints);
49
- await generateEmptyTrendData(writer, "duration-trend.json", "categories-trend.json", "retry-trend.json");
50
- const reportDataFiles = singleFile ? writer.reportFiles() : [];
42
+ const reportDataFiles = singleFile ? __classPrivateFieldGet(this, _AllureAwesomePlugin_writer, "f").reportFiles() : [];
51
43
  await generateStaticFiles({
44
+ ...this.options,
52
45
  allureVersion: context.allureVersion,
53
- reportName,
54
- reportLanguage,
55
- singleFile,
56
46
  reportFiles: context.reportFiles,
57
47
  reportDataFiles,
58
48
  reportUuid: context.reportUuid,
49
+ reportName: context.reportName,
59
50
  });
60
51
  });
52
+ this.start = async (context) => {
53
+ const { singleFile } = this.options;
54
+ if (singleFile) {
55
+ __classPrivateFieldSet(this, _AllureAwesomePlugin_writer, new InMemoryReportDataWriter(), "f");
56
+ return;
57
+ }
58
+ __classPrivateFieldSet(this, _AllureAwesomePlugin_writer, new ReportFileDataWriter(context.reportFiles), "f");
59
+ await Promise.resolve();
60
+ };
61
61
  this.update = async (context, store) => {
62
- await __classPrivateFieldGet(this, _Allure2Plugin_generate, "f").call(this, context, store);
62
+ if (!__classPrivateFieldGet(this, _AllureAwesomePlugin_writer, "f")) {
63
+ throw new Error("call start first");
64
+ }
65
+ await __classPrivateFieldGet(this, _AllureAwesomePlugin_generate, "f").call(this, context, store);
63
66
  };
64
67
  this.done = async (context, store) => {
65
- await this.update(context, store);
68
+ if (!__classPrivateFieldGet(this, _AllureAwesomePlugin_writer, "f")) {
69
+ throw new Error("call start first");
70
+ }
71
+ await __classPrivateFieldGet(this, _AllureAwesomePlugin_generate, "f").call(this, context, store);
66
72
  };
67
73
  }
68
74
  }
69
- _Allure2Plugin_generate = new WeakMap();
75
+ _AllureAwesomePlugin_writer = new WeakMap(), _AllureAwesomePlugin_generate = new WeakMap();
package/dist/writer.d.ts CHANGED
@@ -1,36 +1,36 @@
1
1
  import type { ReportFiles, ResultFile } from "@allurereport/plugin-api";
2
- import type { Allure2TestResult } from "./model.js";
2
+ import type { AllureAwesomeTestResult } from "@allurereport/web-awesome";
3
3
  export interface ReportFile {
4
4
  name: string;
5
5
  value: string;
6
6
  }
7
- export interface Allure2DataWriter {
7
+ export interface AllureAwesomeDataWriter {
8
8
  writeData(fileName: string, data: any): Promise<void>;
9
9
  writeWidget(fileName: string, data: any): Promise<void>;
10
- writeTestCase(test: Allure2TestResult): Promise<void>;
10
+ writeTestCase(test: AllureAwesomeTestResult): Promise<void>;
11
11
  writeAttachment(source: string, file: ResultFile): Promise<void>;
12
12
  }
13
- export declare class FileSystemReportDataWriter implements Allure2DataWriter {
13
+ export declare class FileSystemReportDataWriter implements AllureAwesomeDataWriter {
14
14
  private readonly output;
15
15
  constructor(output: string);
16
16
  writeData(fileName: string, data: any): Promise<void>;
17
17
  writeWidget(fileName: string, data: any): Promise<void>;
18
- writeTestCase(test: Allure2TestResult): Promise<void>;
18
+ writeTestCase(test: AllureAwesomeTestResult): Promise<void>;
19
19
  writeAttachment(source: string, file: ResultFile): Promise<void>;
20
20
  }
21
- export declare class InMemoryReportDataWriter implements Allure2DataWriter {
21
+ export declare class InMemoryReportDataWriter implements AllureAwesomeDataWriter {
22
22
  #private;
23
23
  writeData(fileName: string, data: any): Promise<void>;
24
24
  writeWidget(fileName: string, data: any): Promise<void>;
25
- writeTestCase(test: Allure2TestResult): Promise<void>;
25
+ writeTestCase(test: AllureAwesomeTestResult): Promise<void>;
26
26
  writeAttachment(fileName: string, file: ResultFile): Promise<void>;
27
27
  reportFiles(): ReportFile[];
28
28
  }
29
- export declare class ReportFileDataWriter implements Allure2DataWriter {
29
+ export declare class ReportFileDataWriter implements AllureAwesomeDataWriter {
30
30
  readonly reportFiles: ReportFiles;
31
31
  constructor(reportFiles: ReportFiles);
32
32
  writeData(fileName: string, data: any): Promise<void>;
33
33
  writeWidget(fileName: string, data: any): Promise<void>;
34
34
  writeAttachment(source: string, file: ResultFile): Promise<void>;
35
- writeTestCase(test: Allure2TestResult): Promise<void>;
35
+ writeTestCase(test: AllureAwesomeTestResult): Promise<void>;
36
36
  }
package/dist/writer.js CHANGED
@@ -21,9 +21,9 @@ export class FileSystemReportDataWriter {
21
21
  await writeFile(resolve(distFolder, fileName), JSON.stringify(data), { encoding: "utf-8" });
22
22
  }
23
23
  async writeTestCase(test) {
24
- const distFolder = resolve(this.output, "data", "test-cases");
24
+ const distFolder = resolve(this.output, "data", "test-results");
25
25
  await mkdir(distFolder, { recursive: true });
26
- await writeFile(resolve(distFolder, `${test.uid}.json`), JSON.stringify(test), { encoding: "utf-8" });
26
+ await writeFile(resolve(distFolder, `${test.id}.json`), JSON.stringify(test), { encoding: "utf-8" });
27
27
  }
28
28
  async writeAttachment(source, file) {
29
29
  const distFolder = resolve(this.output, "data", "attachments");
@@ -44,7 +44,7 @@ export class InMemoryReportDataWriter {
44
44
  __classPrivateFieldGet(this, _InMemoryReportDataWriter_data, "f")[dist] = Buffer.from(JSON.stringify(data), "utf-8");
45
45
  }
46
46
  async writeTestCase(test) {
47
- const dist = join("data", "test-cases", `${test.uid}.json`);
47
+ const dist = join("data", "test-results", `${test.id}.json`);
48
48
  __classPrivateFieldGet(this, _InMemoryReportDataWriter_data, "f")[dist] = Buffer.from(JSON.stringify(test), "utf-8");
49
49
  }
50
50
  async writeAttachment(fileName, file) {
@@ -55,10 +55,7 @@ export class InMemoryReportDataWriter {
55
55
  }
56
56
  }
57
57
  reportFiles() {
58
- return Object.keys(__classPrivateFieldGet(this, _InMemoryReportDataWriter_data, "f")).map((key) => ({
59
- name: key,
60
- value: __classPrivateFieldGet(this, _InMemoryReportDataWriter_data, "f")[key].toString("base64"),
61
- }));
58
+ return Object.keys(__classPrivateFieldGet(this, _InMemoryReportDataWriter_data, "f")).map((key) => ({ name: key, value: __classPrivateFieldGet(this, _InMemoryReportDataWriter_data, "f")[key].toString("base64") }));
62
59
  }
63
60
  }
64
61
  _InMemoryReportDataWriter_data = new WeakMap();
@@ -80,6 +77,6 @@ export class ReportFileDataWriter {
80
77
  await this.reportFiles.addFile(join("data", "attachments", source), contentBuffer);
81
78
  }
82
79
  async writeTestCase(test) {
83
- await this.reportFiles.addFile(join("data", "test-cases", `${test.uid}.json`), Buffer.from(JSON.stringify(test), "utf8"));
80
+ await this.reportFiles.addFile(join("data", "test-results", `${test.id}.json`), Buffer.from(JSON.stringify(test), "utf8"));
84
81
  }
85
82
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@allurereport/plugin-classic",
3
- "version": "3.0.0-beta.7",
3
+ "version": "3.0.0-beta.9",
4
4
  "description": "The classic version of Allure HTML report",
5
5
  "keywords": [
6
6
  "allure",
@@ -30,20 +30,23 @@
30
30
  "test": "rimraf ./out && vitest run"
31
31
  },
32
32
  "dependencies": {
33
- "@allurereport/core-api": "3.0.0-beta.7",
34
- "@allurereport/plugin-api": "3.0.0-beta.7",
35
- "@allurereport/web-classic": "3.0.0-beta.7",
36
- "@allurereport/web-commons": "3.0.0-beta.7",
33
+ "@allurereport/core-api": "3.0.0-beta.9",
34
+ "@allurereport/plugin-api": "3.0.0-beta.9",
35
+ "@allurereport/web-awesome": "3.0.0-beta.9",
36
+ "@allurereport/web-classic": "3.0.0-beta.9",
37
+ "@allurereport/web-commons": "3.0.0-beta.9",
38
+ "d3-shape": "^3.2.0",
37
39
  "handlebars": "^4.7.8"
38
40
  },
39
41
  "devDependencies": {
40
42
  "@stylistic/eslint-plugin": "^2.6.1",
43
+ "@types/d3-shape": "^3.1.6",
41
44
  "@types/eslint": "^8.56.11",
42
45
  "@types/node": "^20.17.9",
43
46
  "@typescript-eslint/eslint-plugin": "^8.0.0",
44
47
  "@typescript-eslint/parser": "^8.0.0",
45
48
  "@vitest/runner": "^2.1.8",
46
- "allure-vitest": "^3.0.7",
49
+ "allure-vitest": "^3.0.9",
47
50
  "eslint": "^8.57.0",
48
51
  "eslint-config-prettier": "^9.1.0",
49
52
  "eslint-plugin-import": "^2.29.1",
package/dist/tree.d.ts DELETED
@@ -1,44 +0,0 @@
1
- import type { Statistic } from "@allurereport/core-api";
2
- import type { Allure2Status, Allure2TestResult, Allure2Time } from "./model.js";
3
- export interface TreeNode {
4
- name: string;
5
- }
6
- export interface TreeGroup extends TreeNode {
7
- uid: string;
8
- name: string;
9
- children: TreeNode[];
10
- }
11
- export interface TreeLeaf extends TreeNode {
12
- uid: string;
13
- parentUid: string;
14
- status: Allure2Status;
15
- time: Allure2Time;
16
- flaky: boolean;
17
- newFailed: boolean;
18
- newBroken: boolean;
19
- newPassed: boolean;
20
- retriesCount: number;
21
- retriesStatusChange: boolean;
22
- tags: string[];
23
- parameters: string[];
24
- }
25
- export interface TreeLayer {
26
- groups: string[];
27
- }
28
- export interface WidgetItem {
29
- uid: string;
30
- name: string;
31
- statistic: Statistic;
32
- }
33
- export interface WidgetData {
34
- items: WidgetItem[];
35
- total: number;
36
- }
37
- declare const createLeaf: (endNode: TreeGroup, test: Allure2TestResult) => TreeLeaf;
38
- export type LeafFactory = typeof createLeaf;
39
- export type Classifier = (test: Allure2TestResult) => TreeLayer[] | undefined;
40
- export declare const byLabels: (labelNames: string[]) => Classifier;
41
- export declare const createTree: (tests: Allure2TestResult[], classifier: Classifier, leafFactory?: LeafFactory) => TreeGroup;
42
- export declare const collapseTree: (treeGroup: TreeGroup, separator?: string) => TreeGroup;
43
- export declare const createWidget: (root: TreeGroup) => WidgetData;
44
- export {};
package/dist/tree.js DELETED
@@ -1,113 +0,0 @@
1
- import { byStatistic } from "@allurereport/core-api";
2
- import { compareBy } from "@allurereport/core-api";
3
- import { createHash } from "node:crypto";
4
- import { calculateStatisticByLeafs } from "./utils.js";
5
- const rootNodeUid = "__ROOT__";
6
- const createLeaf = (endNode, test) => {
7
- const leaf = {
8
- parentUid: endNode.uid,
9
- uid: test.uid,
10
- name: test.name,
11
- status: test.status,
12
- time: { ...test.time },
13
- flaky: test.flaky,
14
- newFailed: test.newFailed,
15
- newBroken: test.newBroken,
16
- newPassed: test.newPassed,
17
- retriesCount: test.retriesCount,
18
- retriesStatusChange: test.retriesStatusChange,
19
- parameters: test.parameters.filter((p) => p.value).map((p) => p.value),
20
- tags: test.extra.tags ?? [],
21
- };
22
- return leaf;
23
- };
24
- export const byLabels = (labelNames) => {
25
- return (test) => groupByLabels(test, labelNames);
26
- };
27
- export const createTree = (tests, classifier, leafFactory = createLeaf) => {
28
- const groups = new Map();
29
- const root = { uid: rootNodeUid, name: rootNodeUid, children: [] };
30
- groups.set(root.uid, root);
31
- for (const test of tests) {
32
- const treeLayers = classifier(test);
33
- if (!treeLayers) {
34
- continue;
35
- }
36
- getEndNodes(test, root, treeLayers, 0, groups).forEach((endNode) => {
37
- const leaf = leafFactory(endNode, test);
38
- endNode.children.push(leaf);
39
- });
40
- }
41
- return root;
42
- };
43
- const getEndNodes = (item, node, classifiers, index, groups) => {
44
- if (index >= classifiers.length) {
45
- return [node];
46
- }
47
- const layer = classifiers[index];
48
- return layer.groups.flatMap((name) => {
49
- const uid = groupUid(node.uid, name);
50
- if (!groups.has(uid)) {
51
- const value = { uid, name, children: [] };
52
- groups.set(uid, value);
53
- node.children.push(value);
54
- }
55
- const treeGroup = groups.get(uid);
56
- return getEndNodes(item, treeGroup, classifiers, index + 1, groups);
57
- });
58
- };
59
- const groupByLabels = (test, labelNames) => {
60
- const result = [];
61
- for (const name of labelNames) {
62
- const groups = test.labels
63
- .filter((label) => label.name === name)
64
- .filter((label) => !!label.value)
65
- .map((label) => label.value);
66
- if (groups.length !== 0) {
67
- result.push({ groups: Array.from(new Set(groups)) });
68
- }
69
- }
70
- return result;
71
- };
72
- const groupUid = (parentUid, groupName) => {
73
- return md5(parentUid ? `${parentUid}.${groupName}` : groupName);
74
- };
75
- const md5 = (data) => createHash("md5").update(data).digest("hex");
76
- export const collapseTree = (treeGroup, separator = ".") => {
77
- const newChildren = treeGroup.children.map((c) => {
78
- if (!("children" in c)) {
79
- return c;
80
- }
81
- let res = c;
82
- while (res.children.length === 1 && "children" in res.children[0]) {
83
- const child = res.children[0];
84
- res = {
85
- uid: groupUid(res.uid, child.uid),
86
- name: res.name + separator + child.name,
87
- children: child.children,
88
- };
89
- }
90
- return res;
91
- });
92
- treeGroup.children = newChildren;
93
- return treeGroup;
94
- };
95
- export const createWidget = (root) => {
96
- const items = root.children
97
- .map((c) => {
98
- if (!("children" in c)) {
99
- return undefined;
100
- }
101
- const res = c;
102
- const statistic = calculateStatisticByLeafs(res);
103
- return { uid: res.uid, name: res.name, statistic };
104
- })
105
- .filter((value) => value)
106
- .map((value) => value)
107
- .sort(compareBy("statistic", byStatistic()))
108
- .slice(0, 10);
109
- return {
110
- items,
111
- total: root.children.length,
112
- };
113
- };
package/dist/utils.d.ts DELETED
@@ -1,8 +0,0 @@
1
- import type { Statistic } from "@allurereport/core-api";
2
- import type { Allure2Status, Allure2TestResult, GroupTime } from "./model.js";
3
- import type { TreeGroup } from "./tree.js";
4
- export declare const updateStatistic: (statistic: Statistic, test: {
5
- status: Allure2Status;
6
- }) => undefined;
7
- export declare const updateTime: (time: GroupTime, test: Allure2TestResult) => undefined;
8
- export declare const calculateStatisticByLeafs: (treeGroup: TreeGroup) => Statistic;
package/dist/utils.js DELETED
@@ -1,43 +0,0 @@
1
- import { statisticKeys } from "./model.js";
2
- export const updateStatistic = (statistic, test) => {
3
- statistic[test.status] = (statistic[test.status] ?? 0) + 1;
4
- statistic.total = (statistic.total ?? 0) + 1;
5
- };
6
- export const updateTime = (time, test) => {
7
- const { start, stop, duration } = test.time;
8
- if (duration === undefined) {
9
- return;
10
- }
11
- time.maxDuration = Math.max(time.maxDuration ?? 0, duration);
12
- time.minDuration = Math.min(time.minDuration ?? Number.MAX_VALUE, duration);
13
- time.sumDuration = (time.sumDuration ?? 0) + duration;
14
- if (start !== undefined) {
15
- time.start = Math.min(time.start ?? Number.MAX_VALUE, start);
16
- }
17
- if (stop !== undefined) {
18
- time.stop = Math.max(time.stop ?? Number.MIN_VALUE, stop);
19
- }
20
- if (time.start !== undefined && time.stop !== undefined) {
21
- time.duration = Math.max(0, time.stop - time.start);
22
- }
23
- };
24
- export const calculateStatisticByLeafs = (treeGroup) => {
25
- const current = { total: 0 };
26
- treeGroup.children.forEach((child) => {
27
- if ("children" in child) {
28
- const childGroup = child;
29
- const statistic = calculateStatisticByLeafs(childGroup);
30
- statisticKeys.forEach((key) => {
31
- const statisticElement = statistic[key];
32
- if (statisticElement !== undefined) {
33
- current[key] = (current[key] ?? 0) + statisticElement;
34
- }
35
- });
36
- }
37
- else {
38
- const childLeaf = child;
39
- updateStatistic(current, childLeaf);
40
- }
41
- });
42
- return current;
43
- };