From 4021b6167b0cc746913f32f333b1783f402ecdf0 Mon Sep 17 00:00:00 2001 From: Pyifan Date: Fri, 3 Jan 2025 18:10:11 +0800 Subject: [PATCH] first getReport of interactive mode to load full report --- testplan/runnable/interactive/http.py | 11 ++++--- .../testing/src/Report/InteractiveReport.js | 29 ++++++++++++------- 2 files changed, 25 insertions(+), 15 deletions(-) diff --git a/testplan/runnable/interactive/http.py b/testplan/runnable/interactive/http.py index 0cacec057..9f19c86f1 100644 --- a/testplan/runnable/interactive/http.py +++ b/testplan/runnable/interactive/http.py @@ -127,8 +127,9 @@ class Report(flask_restx.Resource): def get(self): """Get the state of the root interactive report.""" + full = flask.request.args.get("full", "false").lower() == "true" with ihandler.report_mutex: - return _serialize_report_entry(ihandler.report) + return _serialize_report_entry(ihandler.report, full=full) def put(self): """Update the state of the root interactive report.""" @@ -752,8 +753,7 @@ def _validate_json_body(json_body: Dict) -> None: if json_body is None: raise werkzeug.exceptions.BadRequest("JSON body is required for PUT") - -def _serialize_report_entry(report_entry): +def _serialize_report_entry(report_entry, full=False): """ Serialize a report entry representing a testcase or a test group. For a test group shallow serialization is used instead. @@ -761,7 +761,10 @@ def _serialize_report_entry(report_entry): if isinstance(report_entry, TestCaseReport): return report_entry.serialize() elif isinstance(report_entry, (TestGroupReport, TestReport)): - return report_entry.shallow_serialize() + if full: + return report_entry.serialize() + else: + return report_entry.shallow_serialize() else: raise TypeError(f"Unexpected report entry type: {type(report_entry)}") diff --git a/testplan/web_ui/testing/src/Report/InteractiveReport.js b/testplan/web_ui/testing/src/Report/InteractiveReport.js index 2d282b6a3..efd6e92af 100644 --- a/testplan/web_ui/testing/src/Report/InteractiveReport.js +++ b/testplan/web_ui/testing/src/Report/InteractiveReport.js @@ -42,7 +42,10 @@ import { encodeURIComponent2, parseToJson } from "../Common/utils"; import { POLL_MS, CATEGORIES } from "../Common/defaults"; import { AssertionContext, defaultAssertionStatus } from "../Common/context"; import { ErrorBoundary } from "../Common/ErrorBoundary"; -import { displayTimeInfoPreference, timeInfoUTCPreference } from "../UserSettings/UserSettings"; +import { + displayTimeInfoPreference, + timeInfoUTCPreference, +} from "../UserSettings/UserSettings"; const api_prefix = "/api/v1/interactive"; const pendingEnvRequestAtom = atom(""); @@ -87,6 +90,7 @@ class InteractiveReportComponent extends BaseReport { running: false, aborting: false, assertionStatus: defaultAssertionStatus, + firstGet: true, // state variable to track the first getReport }; } @@ -119,7 +123,7 @@ class InteractiveReportComponent extends BaseReport { * * If running in dev mode we just display a fake report. */ - getReport() { + getReport(firstGet = true) { if (this.state.aborting) { this.setError({ message: "Server is aborting ..." }); return; @@ -127,8 +131,11 @@ class InteractiveReportComponent extends BaseReport { if (this.props.match.params.uid === "_dev") { setTimeout(() => this.setReport(FakeInteractiveReport), 1500); } else { + const url = firstGet + ? "/api/v1/interactive/report?full=true" + : "/api/v1/interactive/report"; axios - .get("/api/v1/interactive/report", { transformResponse: parseToJson }) + .get(url, { transformResponse: parseToJson }) .then((response) => { if ( response.data.runtime_status === "ready" || @@ -142,10 +149,9 @@ class InteractiveReportComponent extends BaseReport { this.setState({ running: false }); } } - if ( - !this.state.report || - this.state.report.hash !== response.data.hash - ) { + if (firstGet) { + this.setReport(response.data); + } else if (this.state.report.hash !== response.data.hash) { this.getTests().then((tests) => { const rawReport = { ...response.data, entries: tests }; this.setReport(rawReport); @@ -155,7 +161,10 @@ class InteractiveReportComponent extends BaseReport { .catch(this.setError) .finally(() => { // We poll for updates to the report every second. - setTimeout(this.getReport, this.props.poll_intervall || POLL_MS); + setTimeout( + () => this.getReport(false), + this.props.poll_intervall || POLL_MS + ); }); } } @@ -491,9 +500,7 @@ class InteractiveReportComponent extends BaseReport { }; if (!isReportLeaf(reportEntry) && !_.isEmpty(entries)) { - pruneEntry.entries = entries.map((entry) => - this.pruneReportEntry(entry) - ); + pruneEntry.entries = entries.map((entry) => this.pruneReportEntry(entry)); } return pruneEntry;