Files
LlamaCasty/ytLive.Tests/StorePackagingTests.cs
T
gramps 20cfadca0c TASK 48 slice 3: the self-updater is deleted - the Store updates the app
The creator's ruling (2026-09-27) is Store MSIX + Store IAP, so Microsoft delivers
the updates and the in-app updater is gone rather than parked. This is a
COMPLIANCE action, not cleanup: the Velopack bootstrap downloaded and executed a
payload, which Store policy 10.2.2 does not permit.

Three edit sites, as planned: the PackageReference in ytLive.csproj, 'using
Velopack;' in App.xaml.cs, and the bootstrap block. The self-hosted DigitalOcean
update-URL droplet dies with it.

Guard: ytLive.Tests/StorePackagingTests.cs - the ONE test asserts the app project
references no updater package (Velopack/Squirrel/NetSparkle/AutoUpdater/WinSparkle)
and that no app source file uses the updater API. The check matches CODE (a using
directive, a type usage), not a bare word, so a file's prose may still name what it
deliberately does not do.

Smoke-tested after the removal: MainWindow loaded, 0 exceptions in startup.log.
Full suite 437/437, 0 warnings.
2026-10-22 06:57:34 -07:00

67 lines
3.1 KiB
C#

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;
/// <summary>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.
///
/// <para>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.</para></summary>
public class StorePackagingTests
{
/// <summary>Known self-update packages. If one of these comes back, the Store route has
/// been quietly reversed.</summary>
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.");
}
}
/// <summary>Every C# file of the app project (not the test project, not build output).</summary>
private static IEnumerable<string> 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}"));
}
}