feat: implement SSE architecture for real-time temperature updates with componentized dashboard charts and validation tests
This commit is contained in:
@@ -87,6 +87,16 @@ export function runTests() {
|
||||
assert(bffEventsRoute.includes("searchParams"), "Next.js SSE proxy must forward query parameters to FastAPI");
|
||||
|
||||
const chart = readFrontendFile("components", "dashboard", "scan-terminal", "LiveTemperatureThresholdChart.tsx");
|
||||
const chartCanvasPath = path.join(process.cwd(), "components", "dashboard", "scan-terminal", "TemperatureChartCanvas.tsx");
|
||||
const chartStatsPath = path.join(process.cwd(), "components", "dashboard", "scan-terminal", "TemperatureStatsBars.tsx");
|
||||
const chartRunwayPath = path.join(process.cwd(), "components", "dashboard", "scan-terminal", "TemperatureRunwayDetails.tsx");
|
||||
const chartTooltipPath = path.join(process.cwd(), "components", "dashboard", "scan-terminal", "TemperatureTooltipContent.tsx");
|
||||
assert(fs.existsSync(chartCanvasPath), "temperature chart Recharts canvas must live in TemperatureChartCanvas.tsx");
|
||||
assert(fs.existsSync(chartStatsPath), "temperature chart stat bars must live in TemperatureStatsBars.tsx");
|
||||
assert(fs.existsSync(chartRunwayPath), "temperature chart runway detail panel must live in TemperatureRunwayDetails.tsx");
|
||||
assert(fs.existsSync(chartTooltipPath), "temperature chart tooltip must live in TemperatureTooltipContent.tsx");
|
||||
const chartCanvas = fs.readFileSync(chartCanvasPath, "utf8");
|
||||
const chartTooltip = fs.readFileSync(chartTooltipPath, "utf8");
|
||||
const chartLogicPath = path.join(process.cwd(), "components", "dashboard", "scan-terminal", "temperature-chart-logic.ts");
|
||||
assert(fs.existsSync(chartLogicPath), "temperature chart pure data logic must live in temperature-chart-logic.ts");
|
||||
const chartLogic = fs.readFileSync(chartLogicPath, "utf8");
|
||||
@@ -99,11 +109,16 @@ export function runTests() {
|
||||
assert(chart.includes("useSseResyncVersion"), "temperature chart must resync full detail when SSE replay is incomplete");
|
||||
assert(chartLogic.includes("runway_points"), "temperature chart must merge v1 runway_points into runway history");
|
||||
assert(chart.includes("2 * 60_000"), "temperature chart must wait two minutes without patches before full-fetch fallback");
|
||||
assert(chart.includes("TemperatureTooltipContent"), "temperature chart must use a custom tooltip content component");
|
||||
assert(chart.includes("filterNull={false}"), "temperature chart tooltip must keep null-slot payload so hover works between sparse points");
|
||||
assert(chart.includes("nearestSeriesValue"), "temperature chart tooltip must fall back to nearest non-null value for connected sparse lines");
|
||||
assert(chart.includes("TemperatureChartCanvas"), "temperature chart shell must compose the extracted chart canvas");
|
||||
assert(chart.includes("TemperatureStatsBars"), "temperature chart shell must compose the extracted stat bars");
|
||||
assert(chart.includes("TemperatureRunwayDetails"), "temperature chart shell must compose the extracted runway panel");
|
||||
assert(!chart.includes("from \"recharts\""), "LiveTemperatureThresholdChart.tsx must not import Recharts directly");
|
||||
assert(!chart.includes("function TemperatureTooltipContent"), "LiveTemperatureThresholdChart.tsx must not define tooltip content inline");
|
||||
assert(chartCanvas.includes("TemperatureTooltipContent"), "temperature chart canvas must use a custom tooltip content component");
|
||||
assert(chartCanvas.includes("filterNull={false}"), "temperature chart tooltip must keep null-slot payload so hover works between sparse points");
|
||||
assert(chartTooltip.includes("nearestSeriesValue"), "temperature chart tooltip must fall back to nearest non-null value for connected sparse lines");
|
||||
assert(chart.includes("isHourlyLoading"), "temperature chart must keep a per-panel hourly loading state");
|
||||
assert(chart.includes("加载图表") && chart.includes("absolute inset-2"), "temperature chart must render an in-chart loading overlay");
|
||||
assert(chartCanvas.includes("加载图表") && chartCanvas.includes("absolute inset-2"), "temperature chart must render an in-chart loading overlay");
|
||||
assert(chart.includes("hasLoadedHourlyDetailRef"), "temperature chart must distinguish first load from background refreshes");
|
||||
const fallbackRefreshBlock = chart.match(/const refreshFullDetail = \(\) => \{[\s\S]*?\n \};/)?.[0] || "";
|
||||
assert(
|
||||
@@ -122,9 +137,15 @@ export function runTests() {
|
||||
chart.includes("targetResolution !== nextTargetResolution"),
|
||||
"temperature chart must guard target-resolution state updates to prevent render/update loops",
|
||||
);
|
||||
assert(!chartCanvas.includes("ResponsiveContainer"), "temperature chart canvas must not mount Recharts through ResponsiveContainer at 0x0");
|
||||
assert(chartCanvas.includes("ResizeObserver"), "temperature chart canvas must measure its host with ResizeObserver");
|
||||
assert(
|
||||
chart.includes("initialDimension") && chart.includes("minHeight={"),
|
||||
"temperature chart ResponsiveContainer must have stable initial/min dimensions to avoid zero-size resize loops",
|
||||
chartCanvas.includes("chartSize.width > 0") && chartCanvas.includes("chartSize.height > 0"),
|
||||
"temperature chart canvas must render Recharts only after positive host dimensions are measured",
|
||||
);
|
||||
assert(
|
||||
chartCanvas.includes("width={chartWidth}") && chartCanvas.includes("height={chartHeight}"),
|
||||
"temperature chart canvas must pass explicit positive width/height to Recharts",
|
||||
);
|
||||
assert(!chart.includes("3D"), "temperature chart UI must not expose a 3D/future-forecast mode");
|
||||
assert(!chart.includes("build3DayChartData"), "temperature chart component must not render future prediction curves");
|
||||
|
||||
Reference in New Issue
Block a user