test(app): slice 7 fix round B item 15 — build every mosstank*.xml against a real MossTankPanel
Every existing MossTank markup pin (MossTankMarkupContractTests) validates
mosstank*.xml against MossTankPanel through reflection alone — "does a
public property with this name and this CLR type exist" — never through
MarkupDocument.Build itself, the code that actually mounts a plugin panel
at runtime. Build has its own validation a reflection-only check can't
see (attribute-format exceptions, delegate-shape mismatches, numeric-
attribute parsing, column-type dispatch). Before this test, a markup bug
of that shape would throw inside RetailUiRuntime.MountPlugins's own
try/catch and the panel would simply not appear — no test failure, no
visible error short of a live client screenshot.
New MossTankMarkupBuildOverRealFilesTests (AcDream.App.Tests) builds every
real mosstank*.xml file against a REAL MossTankPanel with a stub
IPluginHost (same shape as MossTankMarkupContractTests.StubHost) and a
fake sprite resolver. Required: a real compile-time ProjectReference from
AcDream.App.Tests to AcDream.Plugins.MossTank (test-only exception to the
plugin/host boundary — AcDream.App itself never links this assembly, see
its own ReferenceOutputAssembly=false copy target) plus
InternalsVisibleTo("AcDream.App.Tests") on the plugin project (MossTankPanel
is internal). The test project also globs mosstank*.xml from the plugin's
source directory into its own output, same pattern item 13 established.
This test caught a REAL bug on its first run: mosstank-advanced.xml's new
lFilterList (item 9's category checklist) had no selected="..." attribute.
MarkupDocument.BindRequiredIntReader throws "list selected must be an int
binding" when a <list>'s selected attribute is missing at all — a pure
checklist with no real "selected row" concept still needs one to satisfy
the markup grammar. Fixed by adding SelectedAdvancedOptionCategoryIndex
(always -1; item 10 already removed row-selection-band rendering for
every column grid, so this drives no visible highlight) and wiring
selected="{SelectedAdvancedOptionCategoryIndex}" onto that list.
tests/AcDream.Plugins.MossTank.Tests: 675/675 (unchanged — this item's
scope is entirely App-side plus one real bug fix invisible to MossTank's
own reflection-only pins).
tests/AcDream.App.Tests --filter Markup|Plugin|UiMenu|Slider: 283/3 skipped/286 (was 278/3/281, +5: the new Theory's 5 file cases).
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
parent
b0fee80e6f
commit
7ca9785665
6 changed files with 140 additions and 0 deletions
|
|
@ -11,6 +11,14 @@
|
|||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<InternalsVisibleTo Include="AcDream.Plugins.MossTank.Tests" />
|
||||
<!-- Fix round B item 15: AcDream.App.Tests constructs a real
|
||||
MossTankPanel directly (MossTankMarkupBuildOverRealFilesTests) so
|
||||
MarkupDocument.Build validates every mosstank*.xml's actual
|
||||
attribute/binding grammar, not just reflection-visible property
|
||||
names/types. A test-only exception to the plugin/host compile-time
|
||||
boundary (AcDream.App itself never links this assembly — see
|
||||
AcDream.App.csproj's ReferenceOutputAssembly=false copy target). -->
|
||||
<InternalsVisibleTo Include="AcDream.App.Tests" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\AcDream.Plugin.Abstractions\AcDream.Plugin.Abstractions.csproj">
|
||||
|
|
|
|||
|
|
@ -471,6 +471,14 @@ internal sealed partial class MossTankPanel
|
|||
public IReadOnlyList<string> AdvancedOptionCategoryNames { get; } =
|
||||
VtankOptionCatalog.CategoryBits.Select(bit => $"0x{bit:X}").ToArray();
|
||||
public IReadOnlyList<bool> AdvancedOptionCategoryEnabled => _advancedOptionCategoryEnabled;
|
||||
// Fix round B item 15's own build-over-real-files test caught this:
|
||||
// <list> markup REQUIRES a "selected" int binding (MarkupDocument.
|
||||
// BindRequiredIntReader throws "must be an int binding" when the
|
||||
// attribute is missing) even for a pure checklist with no real
|
||||
// selection concept — item 10 already removed the row-selection band
|
||||
// rendering for every column grid, so this value drives no visible
|
||||
// highlight; it exists purely to satisfy the markup grammar.
|
||||
public int SelectedAdvancedOptionCategoryIndex => -1;
|
||||
public Action<int> ToggleAdvancedOptionCategoryAt => index =>
|
||||
{
|
||||
if ((uint)index >= (uint)_advancedOptionCategoryEnabled.Length)
|
||||
|
|
|
|||
|
|
@ -81,7 +81,12 @@
|
|||
<column type="text" width="187" items="{AdvancedOptionNames}" onclick="{SelectAdvancedOption}" />
|
||||
<column type="text" width="69" items="{AdvancedOptionValueColumn}" onclick="{SelectAdvancedOption}" />
|
||||
</list>
|
||||
<!-- Fix round B item 15's own build-over-real-files test caught a real
|
||||
bug here: <list> markup requires a "selected" int binding even for a
|
||||
pure checklist with no real selection concept — see
|
||||
SelectedAdvancedOptionCategoryIndex's own doc comment. -->
|
||||
<list x="268" y="4" w="120" h="180" rowheight="18"
|
||||
selected="{SelectedAdvancedOptionCategoryIndex}"
|
||||
tooltip="Uncheck a category to hide its settings from the list on the left.">
|
||||
<column type="check" width="20" values="{AdvancedOptionCategoryEnabled}" onchange="{ToggleAdvancedOptionCategoryAt}" />
|
||||
<column type="text" width="*" items="{AdvancedOptionCategoryNames}" onclick="{ToggleAdvancedOptionCategoryAt}" />
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue