package templates import ( "strings" "testing" "vetting/internal/model" ) // TestDetailSummary_RootAttrs asserts the root
carries the // stable id and sse-swap target. Successive SSE swaps replace the // outer element, so without these attributes the second swap would // have nothing to target. func TestDetailSummary_RootAttrs(t *testing.T) { d := HostDetailData{ Tile: TileData{ Host: model.Host{ID: 7, Name: "alpha", MAC: "aa:bb:cc:dd:ee:ff"}, }, } html := RenderDetailSummaryString(d) for _, want := range []string{ `id="detail-summary-7"`, `sse-swap="detail-summary-7"`, `hx-swap="outerHTML"`, } { if !strings.Contains(html, want) { t.Errorf("DetailSummary missing %q in:\n%s", want, html) } } } func TestDetailActions_RootAttrs(t *testing.T) { d := HostDetailData{ Tile: TileData{ Host: model.Host{ID: 7, Name: "alpha", MAC: "aa:bb:cc:dd:ee:ff"}, }, } html := RenderDetailActionsString(d) for _, want := range []string{ `id="detail-actions-7"`, `sse-swap="detail-actions-7"`, `hx-swap="outerHTML"`, } { if !strings.Contains(html, want) { t.Errorf("DetailActions missing %q in:\n%s", want, html) } } } // TestDetailSpecDiffs_EmptyWrapper: when a run exists but has no diffs, // the
wrapper still renders so a later SSE push has a target. // Without this, the very first SpecValidate diff write would have no // DOM element to swap into. func TestDetailSpecDiffs_EmptyWrapper(t *testing.T) { d := HostDetailData{ Tile: TileData{ Host: model.Host{ID: 7}, Latest: &model.Run{ID: 42}, }, } html := RenderDetailSpecDiffsString(d) for _, want := range []string{ `id="detail-specdiffs-42"`, `sse-swap="detail-specdiffs-42"`, } { if !strings.Contains(html, want) { t.Errorf("DetailSpecDiffs missing %q in empty state:\n%s", want, html) } } if strings.Contains(html, ":\n%s", html) } } // TestDetailHold_EmptyWrapper: same rationale as specdiffs — the // section wrapper is always present when a run exists so the first // hold event has a target. func TestDetailHold_EmptyWrapper(t *testing.T) { d := HostDetailData{ Tile: TileData{ Host: model.Host{ID: 7}, Latest: &model.Run{ID: 42, State: model.StateInventoryCheck}, }, } html := RenderDetailHoldString(d) for _, want := range []string{ `id="detail-hold-42"`, `sse-swap="detail-hold-42"`, } { if !strings.Contains(html, want) { t.Errorf("DetailHold missing %q in empty state:\n%s", want, html) } } if strings.Contains(html, "SSH available") { t.Errorf("DetailHold non-holding state must not render SSH block:\n%s", html) } } // TestDetailHold_HoldingRendersSSH: once the run enters FailedHolding // with an IP, the wrapper renders the ssh invocation. func TestDetailHold_HoldingRendersSSH(t *testing.T) { d := HostDetailData{ Tile: TileData{ Host: model.Host{ID: 7}, HoldKeyPath: "/tmp/hold.key", Latest: &model.Run{ ID: 42, State: model.StateFailedHolding, HoldIP: "10.0.0.7", }, }, } html := RenderDetailHoldString(d) if !strings.Contains(html, "ssh -i /tmp/hold.key root@10.0.0.7") { t.Errorf("DetailHold missing ssh invocation:\n%s", html) } }