using System; using System.Windows; using Microsoft.Data.Sqlite; using System.Windows.Controls; using System.Windows.Media; using System.Windows.Threading; using Xunit; using ytLive.Controls; using ytLive.Models; using ytLive.Services.Entitlement; using ytLive.ViewModels; namespace ytLive.Tests; /// /// The About overlay is the in-app creator hub: it opens from the real window, /// and its licensing sub-panel surfaces the full THIRD-PARTY-NOTICES.txt /// in-app (scrolling text, never the OS viewer / Notepad). Drives the real VM /// through the real window — same real-App + temp-DB pattern as the round-clip /// and source-naming tests. /// [Collection("RealApp")] public sealed class AboutHubTests { private readonly RealAppHost _app; public AboutHubTests(RealAppHost app) { _app = app; } [Fact] public void About_Opens_InApp_Licensing_Loads_Shipped_Notices() { _app.Run(Run); } private void Run() { var tempDb = System.IO.Path.Combine(System.IO.Path.GetTempPath(), $"ytLlive-about-{Guid.NewGuid():N}.db"); MainViewModel.LayoutPathOverride = tempDb; var window = new MainWindow(); var vm = (MainViewModel)window.DataContext; try { // About hub opens (the wordmark / gear menu entry point). vm.OpenAboutCommand.Execute(null); Assert.True(vm.IsAboutOpen); Assert.False(vm.IsLicensesOpen); // The hub links resolve to real destinations. Assert.Equal("https://youtube.com/@llamachileshop", MainViewModel.ChannelUrl); Assert.Equal("https://mastodon.llamachile.tube/@gramps", MainViewModel.MastodonUrl); Assert.Equal("https://buymeacoffee.com/llamachiley", MainViewModel.CoffeeUrl); Assert.Equal("https://llamacasty.com", MainViewModel.PremiumUrl); // The licensing panel loads the full shipped notices text in-app. vm.OpenLicensesCommand.Execute(null); Assert.True(vm.IsLicensesOpen); Assert.False(string.IsNullOrWhiteSpace(vm.LicensesText)); Assert.Contains("Third-Party Notices", vm.LicensesText, StringComparison.OrdinalIgnoreCase); Assert.Contains("LGPL", vm.LicensesText, StringComparison.OrdinalIgnoreCase); // Back returns to the hub view (code-behind click handler path is // equivalent; here we assert the VM contract the handler uses). vm.IsLicensesOpen = false; Assert.True(vm.IsAboutOpen); } finally { window.Close(); MainViewModel.LayoutPathOverride = null; SqliteConnection.ClearAllPools(); try { System.IO.File.Delete(tempDb); } catch { /* best-effort cleanup */ } } } /// /// The About box is a conversion surface (creator, 2026-11-05): a large logo, the 1-2-3 tagline, /// the offer, one primary CTA with the price on it — and a paying customer sees none of the price. /// [Fact] public void About_ShowsTheOfferToFreeUsers_AndNothingToSellToOwners() { _app.Run(() => { var tempDb = Path.Combine(Path.GetTempPath(), $"llamacasty-about-{Guid.NewGuid():N}.db"); MainViewModel.LayoutPathOverride = tempDb; MainWindow? window = null; try { window = new MainWindow(); var vm = (MainViewModel)window.DataContext; vm.EntitlementOverride = new FakeEntitlement(false, "Steam licensing is not configured in this build."); window.Show(); vm.OpenAboutCommand.Execute(null); window.UpdateLayout(); var badge = FindVisualChildByName