user://atlas_cache/ is one directory for every worktree gate run, live capture driver, and real play session, and T-1183's Tier-2/3 lookup short-circuits BEFORE test_mode's silent-no-op IPC — so a warm shared cache delivers real canvases into tests written against 'nothing ever arrives'. Caught live: a concurrent GJ380c Global capture flipped the two before-any-canvas viewer tests in another worktree's push gate. Adds disk_cache_root_override on StepCanvasViewer (threads into StepCanvasRequest's existing test-injection-only seam; production leaves it empty) and routes every direct viewer construction in the viewer + legend suites through a _make_viewer() helper pinning an isolated root. First slice of T-1193's viewer test seam; screen-built viewers still share the default root (noted on T-1193). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
106 lines
4.2 KiB
GDScript
106 lines
4.2 KiB
GDScript
## T-1182 tests: StepCanvasLegend — smoke coverage (PR #203 review, Hoshe
|
|
## note). Not the retired atlas_window_legend.gd's own richer suite (that
|
|
## file never had a dedicated test — its coverage lived entirely inside
|
|
## AtlasWindowViewer's own suites, now retired); this pins the panel's basic
|
|
## lifecycle/content contract directly.
|
|
class_name TestStepCanvasLegend
|
|
extends GdUnitTestSuite
|
|
|
|
const LegendScript := preload("res://ui/implant/apps/atlas/step_canvas/step_canvas_legend.gd")
|
|
const StepCanvasTransport := preload("res://ui/implant/apps/atlas/step_canvas/step_canvas_transport.gd")
|
|
|
|
## Same Tier-2/3 isolation as test_step_canvas_viewer.gd's _make_viewer()
|
|
## (T-1193 first slice): the default disk-cache root is machine-shared, and a
|
|
## warm cache delivers canvases into tests entered on real body ids.
|
|
const TEST_DISK_CACHE_ROOT := "user://test_step_canvas_legend_cache/"
|
|
|
|
|
|
func _make_viewer() -> StepCanvasViewer:
|
|
var v: StepCanvasViewer = auto_free(StepCanvasViewer.new())
|
|
v.disk_cache_root_override = TEST_DISK_CACHE_ROOT
|
|
return v
|
|
|
|
|
|
func test_legend_starts_hidden_before_refresh() -> void:
|
|
var v: StepCanvasViewer = _make_viewer()
|
|
add_child(v)
|
|
var legend = LegendScript.new(v)
|
|
auto_free(legend)
|
|
assert_bool(legend.visible).is_false()
|
|
|
|
|
|
func test_refresh_makes_the_legend_visible_and_populates_content() -> void:
|
|
var v: StepCanvasViewer = _make_viewer()
|
|
add_child(v)
|
|
v.enter({"body_id": "GJ380c", "body_radius_km": 6238.4}, {})
|
|
var legend = LegendScript.new(v)
|
|
add_child(legend)
|
|
legend.refresh()
|
|
assert_bool(legend.visible).is_true()
|
|
assert_int(legend.get_implant_children().size()).override_failure_message(
|
|
"refresh() must populate at least the always-on morphology/glaciation sections"
|
|
).is_greater(0)
|
|
|
|
|
|
## refresh() is a no-op (does not crash) when the legend has no viewer —
|
|
## defensive guard against a construction-order mistake.
|
|
func test_refresh_without_a_viewer_does_not_crash() -> void:
|
|
var legend = LegendScript.new(null)
|
|
auto_free(legend)
|
|
legend.refresh()
|
|
assert_bool(legend.visible).is_false()
|
|
|
|
|
|
## Toggling a gen_* overlay on changes the legend's content (the active
|
|
## toggle section appears) without crashing — the same "no active toggle by
|
|
## default, one section per active toggle" contract the retired
|
|
## atlas_window_legend.gd's own refresh() doc described.
|
|
func test_refresh_reflects_the_active_overlay_toggle() -> void:
|
|
var v: StepCanvasViewer = _make_viewer()
|
|
add_child(v)
|
|
v.enter({"body_id": "GJ380c", "body_radius_km": 6238.4}, {})
|
|
var legend = LegendScript.new(v)
|
|
add_child(legend)
|
|
legend.refresh()
|
|
var rows_before: int = legend.get_implant_children().size()
|
|
|
|
v.set_overlay_visible("gen_dw_temp", true)
|
|
legend.refresh()
|
|
var rows_after: int = legend.get_implant_children().size()
|
|
|
|
assert_int(rows_after).override_failure_message(
|
|
"activating a toggle overlay must add its own legend section"
|
|
).is_greater(rows_before)
|
|
|
|
|
|
func test_reposition_sets_a_fixed_panel_margin_position() -> void:
|
|
var v: StepCanvasViewer = _make_viewer()
|
|
add_child(v)
|
|
var legend = LegendScript.new(v)
|
|
auto_free(legend)
|
|
legend.reposition()
|
|
assert_that(legend.position).is_equal(Vector2(LegendScript.PANEL_MARGIN, 60.0))
|
|
|
|
|
|
## T-1192 review fix: RESERVED_COLUMN_PX is now a direct read of
|
|
## StepCanvasTransport.LEGEND_COLUMN_PX (not an independently-typed
|
|
## literal), so a const-vs-const cross-pin test would be structurally
|
|
## unable to fail — it is the SAME value by construction. What's still
|
|
## worth proving directly is the geometric guarantee that constant is FOR:
|
|
## the legend's own ACTUAL laid-out right edge (`reposition()`'s position.x
|
|
## + the panel's real minimum width) must land at or before the reserved
|
|
## column, with room to spare — never right up against it, and certainly
|
|
## never past it into where the canvas is centered from.
|
|
func test_legend_actual_right_edge_stays_inside_the_reserved_column() -> void:
|
|
var v: StepCanvasViewer = _make_viewer()
|
|
add_child(v)
|
|
var legend = LegendScript.new(v)
|
|
auto_free(legend)
|
|
legend.reposition()
|
|
|
|
var actual_right_edge: float = legend.position.x + legend.custom_minimum_size.x
|
|
assert_float(actual_right_edge).override_failure_message(
|
|
"the legend's real laid-out right edge must stay inside the column"
|
|
+ " StepCanvasViewer reserves for it, with margin to spare"
|
|
).is_less(StepCanvasTransport.LEGEND_COLUMN_PX)
|