test(reader): retain native failure evidence before geometry queries

Preserve source alignment failures when UIA glyph queries throw E_UNEXPECTED. Capture opt-in native color propagation and generated collapsed-section indices to distinguish the remaining source and outline defects; keep all acceptance assertions intact.

Co-Authored-By: GPT-6 <noreply@openai.com>
Signed-off-by: James Maes <jmaes@dmdbrands.com>
This commit is contained in:
James MaesandGPT-6 committed 2026-10-11 15:29:10 -05:00
1 parent dbda6d48da
commit 04c1da8289
6 files changed
+70 -6

No files matched your search

+19
View File
@@ -2,6 +2,25 @@
Updated: 2026-10-11
## Native diagnostic correction - 2026-10-11
Current dbda6d4 CI38171433458 focused gate is terminal17/20,3failures,
zero skips. Initial Light source palette still becomes#1F1F1F rather than
#75628B after an actual UIA Toggle; the queued theme repaint is not proven.
Nested outline expansion still exposes the collapsed child's native peer.
Physical source-focus alignment still fails, but its failure-report geometry
call throws E_UNEXPECTED and masks the timeout before saving the focus logs.
Preserve the original assertions and bounds. Read native logs/tree before
optional glyph geometry and catch only the observed diagnostic Win32Exception.
Add temporary opt-in [DEBUG-source-colors] before/after actual painting and the
native queue, plus [DEBUG-outline-collapse] generated hidden-section indices
following actual jump/toggle commands. These probes log no document text or
paths and must be removed after diagnosis before release. Native/published
jobs114564687334/114564687101 remain live; do not cancel or restart them just
because job logs are not yet available. Full installed/default/Explorer and
stable/dev lifecycle acceptance remains pending. Owner preview55472 is untouched.
## Installed association acceptance boundary - 2026-10-11
The installed harness now supplies a saved/restored test-only installation
+1
View File
@@ -145,6 +145,7 @@ checks below do not substitute for current native/distributed acceptance.
- [ ] Pass hosted CI on the actual current implementation; retain native/published/installed TRXs, screenshots and real PDFs.
- [x] Implement gclo-style separate stable/dev package IDs and installed-channel title/data identity;586 core tests/100% measured lines pass.
- [ ] Verify current side-by-side stable/dev install/activation/registration/update behavior and exact package IDs.
- [ ] Diagnose dbda6d4 focused17/20 failures with retained native color/focus/hidden-section evidence; preserve exact assertions and remove temporary debug probes before release.
- [ ] Adopt the reviewed/published owned-file signing builder; verify actual Azure resource/profile/publisher and repository-bound OIDC/profile-signer permission.
- [ ] Obtain genuine current-head maintainer review acknowledgement, complete required checks and merge.
- [ ] Publish signed stable1.0/dev releases with verification of exact distributed artifacts, timestamp/publisher/checksums and installed update acceptance.
+17 -3
View File
@@ -155,13 +155,14 @@ internal sealed partial class DocumentBrowser
/// <summary>Reveals a heading's hidden ancestors before moving the actual reading viewport to it.</summary>
public Task JumpToHeadingAsync(int index)
public async Task JumpToHeadingAsync(int index)
{
if(index < 0 || index >= _headings.Count)
{
return Task.CompletedTask;
return;
}
return ExecuteDocumentScriptAsync(FormattableString.Invariant($"(()=>{{const h=document.getElementById('mv-heading-{index}'); if(h){{ for(let p=h.parentElement;p;p=p.parentElement) p.hidden=false; h.scrollIntoView({{block:'start'}}); }}}})()"));
await ExecuteDocumentScriptAsync(FormattableString.Invariant($"(()=>{{const h=document.getElementById('mv-heading-{index}'); if(h){{ for(let p=h.parentElement;p;p=p.parentElement) p.hidden=false; h.scrollIntoView({{block:'start'}}); }}}})()"));
await TraceCollapsedSectionsAsync("jump", index);
}
@@ -175,6 +176,7 @@ internal sealed partial class DocumentBrowser
}
Uri document = _policy.DocumentUri;
string? result = await ExecuteDocumentScriptAsync(FormattableString.Invariant($"(()=>{{const e=document.querySelector('[data-mv-body=\"{index}\"]'); if(e) return e.hidden=!e.hidden;}})()"));
await TraceCollapsedSectionsAsync("toggle", index);
if(document == _policy.DocumentUri && _findCollapsed is { } collapsed && result is "true" or "false")
{
_findCollapsed = string.Equals(result, "true", StringComparison.Ordinal) ? collapsed.Append(index).Distinct().ToArray() : collapsed.Where(value => value != index).ToArray();
@@ -195,6 +197,18 @@ internal sealed partial class DocumentBrowser
}
/// <summary>Temporary fixture-only evidence contains generated section indices, never authored text or resource paths.</summary>
private async Task TraceCollapsedSectionsAsync(string operation, int index)
{
if(string.Equals(Environment.GetEnvironmentVariable("MARKDOWNVIEWR_INPUT_TRACE"), "1", StringComparison.Ordinal))
{
string? collapsed = await ExecuteDocumentScriptAsync("Array.from(document.querySelectorAll('[data-mv-body]')).filter(e=>e.hidden).map(e=>Number(e.dataset.mvBody))");
App.Log.Info(FormattableString.Invariant($"[DEBUG-outline-collapse] {operation}; index={index}; collapsed={collapsed}; navigation={_navigationId}."));
}
}
/// <summary>Fixed host operations run only on the ready intercepted document; content script execution remains disabled.</summary>
private async Task<string?> ExecuteDocumentScriptAsync(string script)
{
@@ -92,6 +92,7 @@ public sealed partial class SourceTextView
{
return;
}
TraceSourceAppearance("paint start");
int generation = ++_paintGeneration;
int snapshot = _generation;
var palette = new SourcePalette(_theme, ActualTheme == ElementTheme.Dark);
@@ -120,6 +121,27 @@ public sealed partial class SourceTextView
PaintBatch(tokens, first, palette, foreground, highContrast);
await Task.Yield();
}
TraceSourceAppearance("paint complete");
if(string.Equals(Environment.GetEnvironmentVariable("MARKDOWNVIEWR_INPUT_TRACE"), "1", StringComparison.Ordinal))
{
DispatcherQueue.TryEnqueue(Microsoft.UI.Dispatching.DispatcherQueuePriority.Low, () => TraceSourceAppearance("after native queue"));
}
}
/// <summary>Temporary fixture-only evidence distinguishes parser completion from native foreground replacement without text.</summary>
private void TraceSourceAppearance(string operation)
{
if(_disposed || !string.Equals(Environment.GetEnvironmentVariable("MARKDOWNVIEWR_INPUT_TRACE"), "1", StringComparison.Ordinal))
{
return;
}
SourceToken? heading = _tokens.FirstOrDefault(token => token.Kind == SourceTokenKind.Heading);
global::Windows.UI.Color? color = heading is null ? null : Document.GetRange(heading.Start, heading.Start + heading.Length).CharacterFormat.ForegroundColor;
global::Windows.UI.Color? foreground = (Foreground as SolidColorBrush)?.Color;
global::Windows.UI.Color? content = (GetTemplateChild("ContentElement") as Microsoft.UI.Xaml.Controls.ScrollViewer)?.Foreground is SolidColorBrush brush ? brush.Color : null;
App.Log.Info(FormattableString.Invariant($"[DEBUG-source-colors] {operation}; snapshot={_generation}; paint={_paintGeneration}; tokens={_tokens.Count}; theme={ActualTheme}; focus={FocusState}; heading={color}; foreground={foreground}; content={content}; highContrast={_accessibility.HighContrast}."));
}
@@ -117,7 +117,7 @@ public partial class AppTests
catch(TimeoutException exception)
{
string actual = NativeSourceColorHex(SourceRange(source, literal), session);
throw new TimeoutException(exception.Message + "; Expected=" + expected + "; Actual=" + actual + "; Last native invocation=" + session.LastInvocation + "; Native tree: " + session.DescribeDocumentStatus(), exception);
throw new TimeoutException(exception.Message + "; Expected=" + expected + "; Actual=" + actual + "; Last native invocation=" + session.LastInvocation + "; App logs: " + session.ReadLogs() + "; Native tree: " + session.DescribeDocumentStatus(), exception);
}
}
@@ -625,10 +625,17 @@ public partial class AppTests
}
catch(TimeoutException)
{
FlaUI.Core.ITextRange range = source.Patterns.Text.Pattern.DocumentRange.FindText(text, backward: false, ignoreCase: false);
_output.WriteLine("Source alignment: viewport=" + source.BoundingRectangle + "; glyph rectangles=" + string.Join("; ", range.GetBoundingRectangles().Select(rectangle => rectangle.ToString())));
_output.WriteLine(session.ReadLogs());
_output.WriteLine(session.DescribeDocumentStatus());
try
{
FlaUI.Core.ITextRange range = source.Patterns.Text.Pattern.DocumentRange.FindText(text, backward: false, ignoreCase: false);
_output.WriteLine("Source alignment: viewport=" + source.BoundingRectangle + "; glyph rectangles=" + string.Join("; ", range.GetBoundingRectangles().Select(rectangle => rectangle.ToString())));
}
catch(System.ComponentModel.Win32Exception exception)
{
_output.WriteLine("Native source geometry was unavailable: " + exception.Message);
}
throw;
}
}
@@ -1162,6 +1169,7 @@ public partial class AppTests
AppSession.WaitUntilGone(() => session.FindInApp(cf => cf.ByName("Visible peer body")), "the collapsed parent");
session.ClickElement("ToggleSection");
session.WaitFor(() => session.FindInApp(cf => cf.ByName("Visible peer body")), "the expanded parent");
_output.WriteLine(session.ReadLogs());
Assert.Null(session.FindInApp(cf => cf.ByName("Hidden child body")));
session.InvokeMenuItem("View", "DocumentThemesMenu");
session.ClickElement("DocumentTheme:GitHub Light");