using System;
using System.IO;
using Xunit;
using ytLive.ViewModels;
namespace ytLive.Tests;
///
/// The post-recording save dialog (CREATOR RULING 2026-09-26).
/// Reported symptom: clicking Cancel in the save prompt still saved the
/// recording under the default name — Cancel behaved like "accept the default". The
/// creator's intent is explicit: Enter accepts the default file name and saves;
/// Cancel cancels the save and discards the footage.
/// The bug was in the caller, not the modal — FinalizeRecordingAsync ran
/// File.Move unconditionally, so ShowDialog() == false fell straight
/// through into the save. These tests drive the extracted commit-or-discard decision
/// against real files in a temp folder, which is what would have caught it.
///
public sealed class RecordingSaveDialogTests : IDisposable
{
private readonly string _dir = Path.Combine(
Path.GetTempPath(), "ytLive-recsave-" + Guid.NewGuid().ToString("N")[..8]);
private const string AutoStem = "ty-20260926-1405-0130";
private const string StartStem = "ty-20260926-1405-0000";
private const string Bytes = "fake-mp4-payload";
public RecordingSaveDialogTests() => Directory.CreateDirectory(_dir);
public void Dispose()
{
try { Directory.Delete(_dir, recursive: true); } catch { /* best-effort */ }
}
/// The reported bug: Cancel must leave NOTHING in the videos folder — not
/// the temp start-name file, and not a renamed copy of it either.
[Fact]
public void Cancel_DiscardsTheFootage_AndLeavesNothingOnDisk()
{
var start = WriteStartFile();
var result = CompleteRecordingSave(start, _dir, AutoStem, chosenStem: null, creatorSaved: false);
Assert.Equal(MainViewModel.RecordingSaveOutcome.Discarded, result.Outcome);
Assert.False(File.Exists(start), "Cancel must delete the temp recording, not move it");
Assert.Empty(Directory.GetFiles(_dir));
}
/// Enter on the pre-filled default is a Save — the file lands under the
/// auto name with its bytes intact (the creator's other half of the ruling).
[Fact]
public void EnterOnTheDefault_KeepsTheAutoName_AndSavesTheFootage()
{
var start = WriteStartFile();
var result = CompleteRecordingSave(start, _dir, AutoStem, AutoStem, creatorSaved: true);
Assert.Equal(MainViewModel.RecordingSaveOutcome.Saved, result.Outcome);
var expected = Path.Combine(_dir, AutoStem + ".mp4");
Assert.Equal(expected, result.FinalPath);
Assert.False(File.Exists(start), "Save renames the temp file — it must not be left behind");
Assert.Equal(Bytes, File.ReadAllText(expected));
Assert.Single(Directory.GetFiles(_dir));
}
/// A cleared name box on an explicit Save still means "keep the auto
/// name" (the dialog promises this) — Cancel is the only way to discard.
[Fact]
public void SaveWithABlankName_StillFallsBackToTheAutoName()
{
var start = WriteStartFile();
var result = CompleteRecordingSave(start, _dir, AutoStem, " ", creatorSaved: true);
Assert.Equal(MainViewModel.RecordingSaveOutcome.Saved, result.Outcome);
Assert.True(File.Exists(Path.Combine(_dir, AutoStem + ".mp4")));
}
/// An explicit Save with a chosen name honours that name.
[Fact]
public void SaveWithAChosenName_UsesThatName()
{
var start = WriteStartFile();
var result = CompleteRecordingSave(start, _dir, AutoStem, "my-stream", creatorSaved: true);
Assert.Equal("my-stream.mp4", Path.GetFileName(result.FinalPath!));
}
/// Never clobber an earlier recording: a second save with the same name
/// gets uniquified rather than overwriting the first.
[Fact]
public void SaveWithACollidingName_UniquifiesInsteadOfOverwriting()
{
var first = WriteStartFile();
Assert.Equal(
MainViewModel.RecordingSaveOutcome.Saved,
CompleteRecordingSave(first, _dir, AutoStem, AutoStem, true).Outcome);
var second = WriteStartFile();
var result = CompleteRecordingSave(second, _dir, AutoStem, AutoStem, true);
Assert.Equal(AutoStem + "-2.mp4", Path.GetFileName(result.FinalPath!));
Assert.Equal(2, Directory.GetFiles(_dir).Length);
}
private static MainViewModel.RecordingSaveResult CompleteRecordingSave(
string startPath, string dir, string autoStem, string? chosenStem, bool creatorSaved)
=> MainViewModel.CompleteRecordingSave(startPath, dir, autoStem, chosenStem, creatorSaved);
private string WriteStartFile()
{
var start = Path.Combine(_dir, StartStem + ".mp4");
File.WriteAllText(start, Bytes);
return start;
}
}