Files
LlamaCasty/ytLive.Tests/PrivateBroadcastCloseOutTests.cs
T

72 lines
3.3 KiB
C#

using System.Net;
using System.Text;
using System.Xml.Linq;
using Xunit;
using ytLive.Models;
using ytLive.Services;
using ytLive.ViewModels;
namespace ytLive.Tests;
/// <summary>Creator ruling 2026-10-09: a PRIVATE broadcast ends like a recording — Enter keeps
/// it on YouTube, Escape deletes it.</summary>
public class PrivateBroadcastCloseOutTests
{
private sealed class Handler : HttpMessageHandler
{
public string Privacy = "private";
public readonly List<string> Requests = new();
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken ct)
{
Requests.Add($"{request.Method.Method} {request.RequestUri!.PathAndQuery}");
if (request.Method == HttpMethod.Delete)
return Task.FromResult(new HttpResponseMessage(HttpStatusCode.NoContent));
var body = "{\"items\":[{\"id\":\"BC1\",\"status\":{\"privacyStatus\":\"" + Privacy + "\",\"lifeCycleStatus\":\"complete\"}}]}";
return Task.FromResult(new HttpResponseMessage(HttpStatusCode.OK)
{
Content = new StringContent(body, Encoding.UTF8, "application/json"),
});
}
}
private static YouTubeStreamService Service(Handler handler)
{
var auth = new YouTubeAuthService("test-id", "test-secret");
auth.SetSession(new YouTubeChannel { AccessToken = "acc", TokenExpiry = DateTime.UtcNow.AddHours(1) });
return new YouTubeStreamService(auth, new HttpClient(handler));
}
[Fact]
public async Task Private_Broadcast_Escape_Deletes_Enter_Keeps_Public_Is_Never_Asked()
{
// Escape / Delete → the video is deleted from YouTube.
var h = new Handler();
var (outcome, error) = await MainViewModel.ClosePrivateBroadcastAsync(Service(h), "BC1", askKeep: () => false);
Assert.Equal(MainViewModel.PrivateBroadcastOutcome.Deleted, outcome);
Assert.Null(error);
Assert.Contains(h.Requests, r => r.StartsWith("DELETE /youtube/v3/videos?id=BC1"));
// Enter / Keep → nothing is deleted.
h = new Handler();
(outcome, _) = await MainViewModel.ClosePrivateBroadcastAsync(Service(h), "BC1", askKeep: () => true);
Assert.Equal(MainViewModel.PrivateBroadcastOutcome.Kept, outcome);
Assert.DoesNotContain(h.Requests, r => r.StartsWith("DELETE"));
// Not private (changed mid-stream) → no prompt, nothing deleted.
h = new Handler { Privacy = "public" };
var asked = false;
(outcome, _) = await MainViewModel.ClosePrivateBroadcastAsync(Service(h), "BC1", askKeep: () => asked = true);
Assert.Equal(MainViewModel.PrivateBroadcastOutcome.NotPrivate, outcome);
Assert.False(asked);
Assert.DoesNotContain(h.Requests, r => r.StartsWith("DELETE"));
// The prompt itself: Enter = Keep (IsDefault), Escape = Delete (IsCancel).
XNamespace x = "http://schemas.microsoft.com/winfx/2006/xaml";
var doc = XDocument.Load(SourceAssert.RepoPath("KeepBroadcastDialog.xaml"));
XElement Named(string name) => doc.Descendants().Single(e => (string?)e.Attribute(x + "Name") == name);
Assert.Equal("True", (string?)Named("KeepBroadcastButton").Attribute("IsDefault"));
Assert.Equal("True", (string?)Named("DeleteBroadcastButton").Attribute("IsCancel"));
}
}