using System.Net;
using System.Text;
using Xunit;
using ytLive.Models;
using ytLive.Services;
namespace ytLive.Tests;
///
/// The one integration test for ship step 7 (private-only go live): the
/// broadcast-insert request must carry privacyStatus "private" — the dialog is
/// locked to Private and the service must never send anything else.
///
public class YouTubeStreamServiceTests
{
private sealed class RecordingHandler : HttpMessageHandler
{
public string? LastBody;
public string ResponseBody = """{"id":"BC123","snippet":{"title":"t"}}""";
protected override Task SendAsync(
HttpRequestMessage request, CancellationToken cancellationToken)
{
LastBody = request.Content?.ReadAsStringAsync().GetAwaiter().GetResult();
return Task.FromResult(new HttpResponseMessage(HttpStatusCode.OK)
{
Content = new StringContent(ResponseBody, Encoding.UTF8, "application/json"),
});
}
}
private static YouTubeAuthService CreateAuth() => new("test-id", "test-secret");
[Fact]
public async Task CreateBroadcast_Always_Sends_Private_PrivacyStatus()
{
var handler = new RecordingHandler();
var auth = CreateAuth();
auth.SetSession(new YouTubeChannel
{
AccessToken = "acc-123",
TokenExpiry = DateTime.UtcNow.AddHours(1),
});
var service = new YouTubeStreamService(auth, new HttpClient(handler));
var id = await service.CreateBroadcast("Test Stream", "A description", DateTime.UtcNow);
Assert.Equal("BC123", id);
Assert.NotNull(handler.LastBody);
Assert.Contains("\"privacyStatus\":\"private\"", handler.LastBody);
}
[Fact]
public async Task CreateBroadcast_Without_Session_Returns_Null()
{
var handler = new RecordingHandler();
var auth = CreateAuth(); // no session
var service = new YouTubeStreamService(auth, new HttpClient(handler));
var id = await service.CreateBroadcast("Test Stream", "A description", DateTime.UtcNow);
Assert.Null(id);
Assert.Null(handler.LastBody); // never reached the API
}
}