fix(vt): list column fix round 5/11 — every column throw names its column

BuildListColumn's per-attribute binder calls used the generic "column
items"/"column values"/"column onchange"/"column onclick" context
strings from the initial slice — indistinguishable when a list has
several columns of the same type. Route every column-attribute binder
call (text items/colors/onclick, check values/onchange, icon
values/onclick) through the ColumnContext helper item 2 introduced, so
every throw message reads column[N] type="..." attr. ValidateIconKind
gains an optional context parameter (default "iconkind" for the
existing non-column call sites — <icon>, <button icon>, <list icons>,
none of which changed message-wise beyond wording) so the column
iconkind check can identify its own column too.

Updated all twelve column-throw tests in MarkupListColumnsTests to
assert Assert.Contains on the distinguishing phrase: the ten
attribute-specific ones now check column[0] type="..." attr; the
unknown-<column type> and combined-with-legacy-attribute tests keep
(and, for the type one, add to) their existing distinguishing
assertions. Confirmed each attribute-specific assertion is meaningful
by first running the malformed-colors case against the pre-fix
"column colors must be..." message (mismatch), then landing the
production change alongside the rest.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
Erik 2026-09-06 21:03:43 +02:00
parent b58668c6cd
commit 5d760331f6
2 changed files with 38 additions and 19 deletions

View file

@ -135,6 +135,7 @@ public sealed class MarkupListColumnsTests
var ex = Assert.Throws<FormatException>(
() => MarkupDocument.Build(xml, binding, Sprite));
Assert.Contains("bogus", ex.Message);
Assert.Contains("column[0]", ex.Message);
}
[Fact]
@ -147,7 +148,8 @@ public sealed class MarkupListColumnsTests
" <column type=\"text\" width=\"80\"/>" +
"</list></panel>";
Assert.Throws<FormatException>(() => MarkupDocument.Build(xml, binding, Sprite));
var ex = Assert.Throws<FormatException>(() => MarkupDocument.Build(xml, binding, Sprite));
Assert.Contains("column[0] type=\"text\" items", ex.Message);
}
[Fact]
@ -160,7 +162,8 @@ public sealed class MarkupListColumnsTests
" <column type=\"check\" width=\"20\" onchange=\"{ToggleFester}\"/>" +
"</list></panel>";
Assert.Throws<FormatException>(() => MarkupDocument.Build(xml, binding, Sprite));
var ex = Assert.Throws<FormatException>(() => MarkupDocument.Build(xml, binding, Sprite));
Assert.Contains("column[0] type=\"check\" values", ex.Message);
}
[Fact]
@ -173,7 +176,8 @@ public sealed class MarkupListColumnsTests
" <column type=\"check\" width=\"20\" values=\"{Fester}\"/>" +
"</list></panel>";
Assert.Throws<FormatException>(() => MarkupDocument.Build(xml, binding, Sprite));
var ex = Assert.Throws<FormatException>(() => MarkupDocument.Build(xml, binding, Sprite));
Assert.Contains("column[0] type=\"check\" onchange", ex.Message);
}
[Fact]
@ -186,7 +190,8 @@ public sealed class MarkupListColumnsTests
" <column type=\"icon\" width=\"20\" onclick=\"{ClickIcon}\"/>" +
"</list></panel>";
Assert.Throws<FormatException>(() => MarkupDocument.Build(xml, binding, Sprite));
var ex = Assert.Throws<FormatException>(() => MarkupDocument.Build(xml, binding, Sprite));
Assert.Contains("column[0] type=\"icon\" values", ex.Message);
}
[Fact]
@ -199,7 +204,8 @@ public sealed class MarkupListColumnsTests
" <column type=\"icon\" width=\"20\" values=\"{Icons}\"/>" +
"</list></panel>";
Assert.Throws<FormatException>(() => MarkupDocument.Build(xml, binding, Sprite));
var ex = Assert.Throws<FormatException>(() => MarkupDocument.Build(xml, binding, Sprite));
Assert.Contains("column[0] type=\"icon\" onclick", ex.Message);
}
[Fact]
@ -212,7 +218,8 @@ public sealed class MarkupListColumnsTests
" <column type=\"icon\" width=\"20\" iconkind=\"spel\" values=\"{Icons}\" onclick=\"{ClickIcon}\"/>" +
"</list></panel>";
Assert.Throws<FormatException>(() => MarkupDocument.Build(xml, binding, Sprite));
var ex = Assert.Throws<FormatException>(() => MarkupDocument.Build(xml, binding, Sprite));
Assert.Contains("column[0] type=\"icon\" iconkind", ex.Message);
}
[Fact]
@ -243,7 +250,8 @@ public sealed class MarkupListColumnsTests
" <column type=\"text\" width=\"80\" items=\"{Names}\"/>" +
"</list></panel>";
Assert.Throws<FormatException>(() => MarkupDocument.Build(xml, binding, Sprite));
var ex = Assert.Throws<FormatException>(() => MarkupDocument.Build(xml, binding, Sprite));
Assert.Contains("items/icons/colors", ex.Message);
}
[Fact]
@ -256,7 +264,8 @@ public sealed class MarkupListColumnsTests
" <column type=\"text\" width=\"80\" items=\"{Names}\"/>" +
"</list></panel>";
Assert.Throws<FormatException>(() => MarkupDocument.Build(xml, binding, Sprite));
var ex = Assert.Throws<FormatException>(() => MarkupDocument.Build(xml, binding, Sprite));
Assert.Contains("items/icons/colors", ex.Message);
}
[Fact]
@ -269,7 +278,8 @@ public sealed class MarkupListColumnsTests
" <column type=\"text\" width=\"80\" items=\"{Names}\"/>" +
"</list></panel>";
Assert.Throws<FormatException>(() => MarkupDocument.Build(xml, binding, Sprite));
var ex = Assert.Throws<FormatException>(() => MarkupDocument.Build(xml, binding, Sprite));
Assert.Contains("items/icons/colors", ex.Message);
}
[Fact]
@ -321,7 +331,8 @@ public sealed class MarkupListColumnsTests
" <column type=\"text\" width=\"80\" items=\"{Names}\" colors=\"notabinding\"/>" +
"</list></panel>";
Assert.Throws<FormatException>(() => MarkupDocument.Build(xml, binding, Sprite));
var ex = Assert.Throws<FormatException>(() => MarkupDocument.Build(xml, binding, Sprite));
Assert.Contains("column[0] type=\"text\" colors", ex.Message);
}
// ── Fix round: text column optional onclick (fix item 1) ────────────────