using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text.RegularExpressions; using System.Xml.Linq; using Xunit; namespace ytLive.Tests; /// TASK 48, slice 3 — the creator's ruling (2026-09-27): the app ships as a /// **Microsoft Store MSIX** and the **Store updates it**. The self-update subsystem that /// existed for the abandoned self-hosted route (a Velopack bootstrap plus the DigitalOcean /// update-URL droplet) is therefore deleted, not parked: a second updater inside a /// Store-installed package fights the Store's own updater. /// /// This test is the guard: the app project references no updater package and no app /// source file uses the updater API — so the deleted subsystem cannot creep back in, and /// the "the Store updates it" decision stays the only update path. public class StorePackagingTests { /// Known self-update packages. If one of these comes back, the Store route has /// been quietly reversed. private static readonly string[] UpdaterPackages = { "Velopack", "Squirrel", "NetSparkle", "AutoUpdater", "WinSparkle" }; [Fact] public void The_app_ships_no_self_update_subsystem() { // 1. The app project references no updater package. var project = XDocument.Load(SourceAssert.RepoPath("ytLive.csproj")); var packages = project.Descendants() .Where(e => e.Name.LocalName == "PackageReference") .Select(e => (string?)e.Attribute("Include")) .Where(name => name != null) .ToHashSet(StringComparer.OrdinalIgnoreCase); foreach (var updater in UpdaterPackages) Assert.DoesNotContain(updater, packages); // 2. No app source file uses the updater API. Matched as CODE (a using directive, // a type usage), not as a bare word — a file's prose is allowed to name what it // deliberately does not do. var root = Path.GetDirectoryName(SourceAssert.RepoPath("ytLive.csproj"))!; foreach (var file in AppSourceFiles(root)) { var text = File.ReadAllText(file); Assert.False( Regex.IsMatch(text, @"^\s*using\s+Velopack\s*;", RegexOptions.Multiline), $"{Path.GetFileName(file)} still imports the Velopack updater — the Store updates this app."); Assert.False( Regex.IsMatch(text, @"\bVelopackApp\b"), $"{Path.GetFileName(file)} still calls the Velopack updater — the Store updates this app."); } } /// Every C# file of the app project (not the test project, not build output). private static IEnumerable AppSourceFiles(string root) { return Directory.EnumerateFiles(root, "*.cs", SearchOption.AllDirectories) .Where(path => !path.Contains($"{Path.DirectorySeparatorChar}ytLive.Tests{Path.DirectorySeparatorChar}")) .Where(path => !path.Contains($"{Path.DirectorySeparatorChar}obj{Path.DirectorySeparatorChar}")) .Where(path => !path.Contains($"{Path.DirectorySeparatorChar}bin{Path.DirectorySeparatorChar}")); } }