using System.Linq; using TrajectoryPlanningVisualization; namespace TrajectoryPlanningVisualizationVerificationHost; internal static class WebAssetChecks { public static void Run() { BuildsDeterministicSmokeSnapshots(); string html = EmbeddedWebAssets.ReadText("index.html"); string css = EmbeddedWebAssets.ReadText("app.css"); string js = EmbeddedWebAssets.ReadText("app.js"); Verification.True(html.Contains("路径总览"), "overview Chinese title"); Verification.True(html.Contains("LS / ST"), "LS/ST tab"); Verification.True(html.Contains("曲率与运动学"), "kinematics tab"); Verification.True(html.Contains("周期历史"), "history tab"); Verification.True(html.Contains("生效配置"), "configuration panel"); Verification.True(css.Contains("--current-trajectory: #1769aa"), "scientific current color"); Verification.True(css.Contains("stroke-width: 1.1"), "thin scientific line"); Verification.True(css.Contains("main > section[hidden] { display: none !important; }"), "hidden sections cannot be overridden by grid rules"); Verification.True(css.Contains(".axis-tick-y"), "SVG y ticks have a semantic class"); Verification.True(css.Contains(".axis-label-y"), "SVG y labels have a semantic class"); Verification.True(css.Contains(".world-empty-state"), "empty overview has a semantic state"); Verification.True(css.Contains(".world-coarse"), "coarse path semantic class"); Verification.True(css.Contains(".world-local-g2"), "Local G2 semantic class"); Verification.True(css.Contains(".world-segment-active"), "active direction semantic class"); Verification.True(css.Contains(".world-current"), "current trajectory semantic class"); Verification.True(css.Contains(".world-coordinate-grid"), "overview exposes a metric grid semantic class"); Verification.True(css.Contains(".world-axis-zero"), "overview exposes a zero-axis semantic class"); Verification.True(css.Contains(".world-axis-tick"), "overview exposes coordinate tick semantics"); Verification.True(css.Contains(".world-axis-label"), "overview exposes coordinate axis-label semantics"); Verification.True(js.Contains("function niceWorldStep("), "overview selects readable metric tick steps"); Verification.True(js.Contains("function worldMetrics("), "overview derives stable world-to-screen metrics"); Verification.True(js.Contains("function renderWorldCoordinates("), "overview renders its own metric coordinate system"); Verification.True(js.Contains("X (m)") && js.Contains("Y (m)"), "overview labels both metric axes"); Verification.True(css.Contains("--world-smoothed-path"), "overview defines a dedicated smoothed-path color"); Verification.True(css.Contains("--world-em-trajectory"), "overview defines a dedicated EM-path color"); Verification.True(css.Contains(".world-marker-shape"), "overview marker shapes use a shared screen-space class"); Verification.True(css.Contains(".marker-smooth-start"), "overview styles the smoothed-path start marker"); Verification.True(js.Contains("function markerTransform("), "overview anchors fixed-size markers in world coordinates"); Verification.True(js.Contains("function appendWorldMarker("), "overview centralizes fixed-size marker rendering"); Verification.True(!js.Contains("const corners = [[.38, .18]"), "vehicle marker no longer uses a large world-size rectangle"); Verification.True(!css.Contains(".marker-vehicle .vehicle-outline { fill: none; stroke: #20252b; stroke-width: .7; }"), "vehicle outline no longer uses a world-scale heavy stroke"); Verification.True(!css.Contains(".marker-vehicle .vehicle-heading { stroke: #20252b; stroke-width: .8; }"), "vehicle marker no longer uses world-scale heavy strokes"); Verification.True(css.Contains(".marker-vehicle"), "vehicle marker semantic class"); Verification.True(css.Contains(".marker-plan-start"), "plan start marker semantic class"); Verification.True(css.Contains(".marker-gear-switch"), "gear-switch marker semantic class"); Verification.True(css.Contains(".marker-final-goal"), "final goal marker semantic class"); Verification.True(js.Contains("末点后无时间区间"), "jerk terminal explanation"); Verification.True(js.Contains("__TRAJECTORY_VISUALIZATION_TEST__"), "test hook flag is explicit"); Verification.True(js.Contains("Object.freeze"), "test hooks are frozen"); Verification.True(js.Contains("未收到 Local G2 路径"), "empty overview names the missing source"); Verification.True(html.Contains("occupancy-grid"), "single occupancy canvas exists"); Verification.True(html.Contains("world-overlay"), "SVG trajectory overlay exists"); Verification.True(html.Contains("id=\"world-legend\""), "overview contains a screen-space legend host"); Verification.True(html.Contains("aria-label=\"路径图例\""), "overview legend has a Chinese accessible name"); Verification.True(css.Contains(".world-legend"), "overview legend has a screen-space visual container"); Verification.True(css.Contains(".world-legend-swatch"), "overview legend exposes semantic line and marker samples"); Verification.True(js.Contains("function renderWorldLegend("), "overview builds legend entries from current snapshot data"); Verification.True(js.Contains("legendChinese"), "overview reuses exported Chinese polyline legends"); Verification.True(js.Contains("atob"), "compact occupancy bitset is decoded in browser"); Verification.True(!html.Contains("http://") && !html.Contains("https://"), "page has no CDN URL"); } private static void BuildsDeterministicSmokeSnapshots() { PlanningVisualizationStaticSnapshot staticSnapshot = SampleSnapshotFactory.CreateStaticSnapshot(); PlanningVisualizationDynamicSnapshot dynamicSnapshot = SampleSnapshotFactory.CreateDynamicSnapshot(1L); Verification.True(staticSnapshot.StaticPolylines.Any(line => line.Kind == "coarse"), "smoke snapshot exposes the coarse comparison path"); Verification.True(staticSnapshot.StaticPolylines.Any(line => line.Kind == "local-g2"), "smoke snapshot exposes the smoothed comparison path"); Verification.True(staticSnapshot.StaticMarkers.Any(marker => marker.Kind == "smooth-start"), "smoke snapshot exposes the smoothed-path start marker"); Verification.Equal(2, staticSnapshot.DirectionSegments.Count, "smoke snapshot has two direction segments"); Verification.True(staticSnapshot.StaticMarkers.Any(marker => marker.Kind == "gear-switch"), "smoke snapshot has a gear marker"); Verification.True(staticSnapshot.ConfigurationGroups.Count > 0, "smoke snapshot has effective configuration"); foreach (string chartId in new[] { "ls", "st", "curvature-s", "curvature-t", "velocity-t", "acceleration-t", "jerk-t", "yaw-rate-t" }) { Verification.True(dynamicSnapshot.Charts.Any(chart => chart.Id == chartId), "smoke snapshot includes chart " + chartId); } } }