72 lines
3.3 KiB
C#
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"));
|
|
}
|
|
}
|