Files
LlamaCasty/ytLive.Tests/EntitlementTests.cs
T
gramps 15734a5477 feat(zoom): Ctrl closes the box, and a Follow pill that re-anchors the capture
Two creator directives, 2026-11-01.

**Ctrl-down dismisses an open zoom box.** Window-level PreviewKeyDown, so the same hand that
opened it can put it away. It cannot cancel itself at creation: Ctrl is already held before
the right-click that makes the box, so the keydown fires while nothing is open.

**Follow mode, default Anchor.** A PillToggle in App Settings ("Follow the box"), persisted
as Zoom.FollowBox. Off — the default — keeps the 2026-10-08 model: the capture stays on the
clicked point and dragging only moves the box over it. On, UpdateZoomMove re-anchors the
capture to the box centre (half the box's size, clamped per axis), so the magnifier shows
whatever it hovers. Flipping to Follow while the box is open snaps it immediately.

Three tests: anchor drags leave CaptureX alone, follow moves it to the expected quarter-offset
centre, and the setting round-trips through LayoutStore (tested against the store, not via two
view models — two live VMs fight over the temp DB, which is a fixture problem, not a bug).

Both new test classes share a collection tag: MainViewModel.LayoutPathOverride is static, and
xUnit runs classes in parallel, so without it the two view models collided (one failure in a
combined run, clean when run apart).

Release build 0 warnings; 14 tests pass across zoom, entitlement and preview history. Debug
build is blocked by the running app (PID 47388) — close it and the exe updates.
2026-11-01 08:51:28 -08:00

71 lines
2.3 KiB
C#

using System;
using System.IO;
using Xunit;
using ytLive.Services.Entitlement;
using ytLive.ViewModels;
namespace ytLive.Tests;
/// <summary>
/// The entitlement seam (2026-11-01): one question — "may this session emit Pro output?" — with a
/// Steam DLC rail, a Polar rail to come, and a fail-closed default.
///
/// <para>The rule that must never break: **no configured rail means the free profile**. A missing
/// DLC id, a missing Steam client or a thrown native load all resolve to false; none of them may
/// crash the app or quietly grant Pro.</para>
/// </summary>
// Shares the static MainViewModel.LayoutPathOverride with the sibling class; without a
// shared collection xUnit runs them in parallel and the two view models fight over one temp DB.
[Collection("MainViewModelLayoutPath")]
public class EntitlementTests
{
[Fact]
public void No_configured_dlc_id_reads_as_no_entitlement()
{
// The state before the Steamworks app exists: pure false, no native call attempted.
Assert.False(SteamEntitlement.NotConfigured().IsPro);
}
[Fact]
public void A_steam_entitlement_without_a_client_is_the_free_tier_not_a_crash()
{
// No steam_appid.txt in the test host and no client running: Init fails, we report false.
var entitlement = new SteamEntitlement(1234567u);
Assert.False(entitlement.IsPro);
}
[Fact]
public void The_fake_reports_what_a_test_sets()
{
var fake = new FakeEntitlement(true);
Assert.True(fake.IsPro);
fake.IsPro = false;
Assert.False(fake.IsPro);
}
[Fact]
public void The_view_model_takes_its_answer_from_the_rail()
{
var tempDb = Path.Combine(Path.GetTempPath(), $"llamacasty-entitlement-{Guid.NewGuid():N}.db");
MainViewModel.LayoutPathOverride = tempDb;
try
{
var vm = new MainViewModel();
// Default rail is NotConfigured → free output.
Assert.False(vm.HasProOutput);
vm.EntitlementOverride = new FakeEntitlement(true);
Assert.True(vm.HasProOutput);
vm.EntitlementOverride = new FakeEntitlement(false);
Assert.False(vm.HasProOutput);
}
finally
{
MainViewModel.LayoutPathOverride = null;
try { File.Delete(tempDb); } catch (IOException) { }
}
}
}