45 lines
1.7 KiB
C#
45 lines
1.7 KiB
C#
namespace WxAgent.Core;
|
|
|
|
public sealed class UiTraversalGuard(int maxNodes = 10_000, int maxDepth = 40)
|
|
{
|
|
private readonly HashSet<string> _visited = new(StringComparer.Ordinal);
|
|
public int NodeCount { get; private set; }
|
|
public bool Truncated { get; private set; }
|
|
public bool CycleDetected { get; private set; }
|
|
|
|
public bool TryVisit(string runtimeId, int depth)
|
|
{
|
|
if (NodeCount >= maxNodes || depth > maxDepth)
|
|
{
|
|
Truncated = true;
|
|
return false;
|
|
}
|
|
if (runtimeId.Length > 0 && !_visited.Add(runtimeId))
|
|
{
|
|
CycleDetected = true;
|
|
return false;
|
|
}
|
|
NodeCount++;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
public sealed record UiSnapshotComparison(IReadOnlyList<string> AddedAutomationIds,
|
|
IReadOnlyList<string> RemovedAutomationIds, IReadOnlyList<string> MissingRequiredControls)
|
|
{
|
|
public static UiSnapshotComparison Compare(UiNodeSnapshot baseline, UiNodeSnapshot current)
|
|
{
|
|
static IEnumerable<string> ReadIds(UiNodeSnapshot root) =>
|
|
new[] { root.AutomationId }.Concat(root.Children.SelectMany(ReadIds));
|
|
static HashSet<string> Ids(UiNodeSnapshot root) => ReadIds(root)
|
|
.Where(id => id.Length > 0 && !id.StartsWith("[id:", StringComparison.Ordinal))
|
|
.ToHashSet(StringComparer.Ordinal);
|
|
var before = Ids(baseline);
|
|
var after = Ids(current);
|
|
return new UiSnapshotComparison(
|
|
after.Except(before).Order(StringComparer.Ordinal).ToArray(),
|
|
before.Except(after).Order(StringComparer.Ordinal).ToArray(),
|
|
WechatLocators.RequiredAutomationIds.Where(id => !after.Contains(id)).ToArray());
|
|
}
|
|
}
|