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; } }