using System.Text.RegularExpressions;
using Avalonia;
using Avalonia.Headless.XUnit;
using Avalonia.Styling;
namespace AvParser.UI.HeadlessTests;
///
/// Every resource key the XAML asks for must actually resolve.
///
///
/// A DynamicResource naming a key that does not exist fails silently: the property simply
/// keeps its default, so a background never paints and a brush is transparent. That shipped twice —
/// most recently as a viewer overlay you could see straight through, caught only by looking at a
/// screenshot. Both themes are checked, because a key can exist in one dictionary and not the other.
///
public partial class ResourceKeyTests
{
[GeneratedRegex(@"\{(?:Dynamic|Static)Resource\s+([A-Za-z0-9_.]+)\s*\}", RegexOptions.Compiled)]
private static partial Regex ResourceMarkup();
/// Keys defined inside a view's own Resources block rather than in a theme.
private static readonly HashSet Local = new(StringComparer.Ordinal) { "LocalizedOptionTemplate" };
private static DirectoryInfo RepositoryRoot()
{
var directory = new DirectoryInfo(AppContext.BaseDirectory);
while (directory is not null && !File.Exists(Path.Combine(directory.FullName, "AvParser.slnx")))
{
directory = directory.Parent;
}
return directory ?? throw new InvalidOperationException("Could not find the repository root.");
}
[AvaloniaTheory]
[InlineData("Light")]
[InlineData("Dark")]
public void Every_resource_key_used_in_xaml_resolves(string theme)
{
var application = Application.Current.ShouldNotBeNull();
application.RequestedThemeVariant = theme == "Light" ? ThemeVariant.Light : ThemeVariant.Dark;
var views = Path.Combine(RepositoryRoot().FullName, "src", "AvParser.UI");
var files = Directory.GetFiles(views, "*.axaml", SearchOption.AllDirectories);
files.ShouldNotBeEmpty();
var missing = new SortedSet(StringComparer.Ordinal);
foreach (var file in files)
{
foreach (Match match in ResourceMarkup().Matches(File.ReadAllText(file)))
{
var key = match.Groups[1].Value;
if (Local.Contains(key))
{
continue;
}
if (!application.TryGetResource(key, application.ActualThemeVariant, out _))
{
missing.Add($"{key} ({Path.GetFileName(file)})");
}
}
}
missing.ShouldBeEmpty();
}
}