using Amphora;
using System;
using System.Collections.Generic;
using UnitTestSharp;
namespace Glass.UnitTests
{
public class FileDialogModelTests : TestFixture
{
///
/// Counts and collects what a model announces.
///
public class Listener
{
public int Changes;
public int Cancellations;
public readonly List Accepted = new List();
public Listener(FileDialogModel model)
{
model.OnChanged += () => ++Changes;
model.OnCancelled += () => ++Cancellations;
model.OnAccepted += path => Accepted.Add(path);
}
}
///
/// An InMemoryFileSystem that can be told to fail, or to have no roots.
///
public class FaultyFileSystem : IFileSystem
{
private readonly InMemoryFileSystem inner;
public bool ListFails;
public bool CreateDirectoryFails;
public bool NoRoots;
public FaultyFileSystem(InMemoryFileSystem inner)
{
this.inner = inner;
}
public IReadOnlyList Roots => NoRoots ? Array.Empty() : inner.Roots;
public string GetParent(string path) => inner.GetParent(path);
public string Combine(string directory, string name) => inner.Combine(directory, name);
public string GetName(string path) => inner.GetName(path);
public Status ValidateFileName(string name) => inner.ValidateFileName(name);
public FileKind GetKind(string path) => inner.GetKind(path);
public StatusOr> List(string directory)
{
if (ListFails)
{
return AccessDenied.Fail();
}
return inner.List(directory);
}
public Status CreateDirectory(string path)
{
if (CreateDirectoryFails)
{
return DiskFull.Fail();
}
return inner.CreateDirectory(path);
}
}
public static readonly MessageFailureKind AccessDenied =
new MessageFailureKind("Glass.UnitTests.AccessDenied", "Access denied.");
public static readonly MessageFailureKind DiskFull =
new MessageFailureKind("Glass.UnitTests.DiskFull", "Disk full.");
private static readonly FileFilter TextFiles = new FileFilter("Text files", new[] { ".txt" });
private static readonly FileFilter MarkdownFiles = new FileFilter("Markdown files", new[] { ".md" });
///
/// A root holding a.txt, b.md and a directory called dir.
///
private static InMemoryFileSystem Mixed()
{
var returnMe = new InMemoryFileSystem();
returnMe.AddFile("/a.txt");
returnMe.AddFile("/b.md");
returnMe.AddDirectory("/dir");
return returnMe;
}
private static FileDialogModel OpenModel(string startDirectory = null)
{
return FileDialogModel.Create(
InMemoryFileSystemTests.Sample(), FileDialogMode.Open, startDirectory: startDirectory).Value;
}
private static FileDialogModel SaveModel(
IReadOnlyList filters = null, string startDirectory = null)
{
return FileDialogModel.Create(
InMemoryFileSystemTests.Sample(), FileDialogMode.Save, filters, startDirectory).Value;
}
public class CreateTests : TestFixture
{
public void Defaults_StartInTheFirstRootWithNothingSelected()
{
FileDialogModel model = OpenModel();
CheckEqual("/", model.Directory);
CheckEqual(3, model.Entries.Count);
CheckNull(model.SelectedIndex);
CheckEqual("", model.FileName);
CheckFalse(model.AwaitingOverwriteConfirmation);
}
public void Always_KeepsTheMode()
{
CheckEqual(FileDialogMode.Save, SaveModel().Mode);
}
public void StartDirectory_IsListed()
{
FileDialogModel model = OpenModel("/docs");
CheckEqual("/docs", model.Directory);
CheckEqual(2, model.Entries.Count);
}
public void MissingStartDirectory_ReturnsWhy()
{
StatusOr created = FileDialogModel.Create(
InMemoryFileSystemTests.Sample(), FileDialogMode.Open, startDirectory: "/nowhere");
CheckEqual(FileSystemFailures.NotFound.Fail("/nowhere"), created.Status);
}
public void StartDirectoryThatIsAFile_ReturnsWhy()
{
StatusOr created = FileDialogModel.Create(
InMemoryFileSystemTests.Sample(), FileDialogMode.Open, startDirectory: "/top.txt");
CheckEqual(FileSystemFailures.NotADirectory.Fail("/top.txt"), created.Status);
}
public void RootThatCantBeRead_ReturnsWhy()
{
var fileSystem = new FaultyFileSystem(InMemoryFileSystemTests.Sample()) { ListFails = true };
CheckEqual(AccessDenied.Fail(), FileDialogModel.Create(fileSystem, FileDialogMode.Open).Status);
}
public void FileSystemWithNoRoots_IsFineGivenAStartDirectory()
{
var fileSystem = new FaultyFileSystem(InMemoryFileSystemTests.Sample()) { NoRoots = true };
StatusOr created =
FileDialogModel.Create(fileSystem, FileDialogMode.Open, startDirectory: "/docs");
CheckEqual("/docs", created.Value.Directory);
}
public void NoFilters_MeansAllFiles()
{
FileDialogModel model = OpenModel();
CheckEqual(1, model.Filters.Count);
CheckEqual(FileFilter.AllFiles, model.Filters[0]);
CheckEqual(0, model.SelectedFilterIndex);
}
public void EmptyFilters_MeansAllFiles()
{
FileDialogModel model = SaveModel(new List());
CheckEqual(FileFilter.AllFiles, model.Filters[0]);
}
public void GivenFilters_StartOnTheFirst()
{
FileDialogModel model =
FileDialogModel.Create(Mixed(), FileDialogMode.Open, new[] { MarkdownFiles, TextFiles }).Value;
CheckEqual(0, model.SelectedFilterIndex);
CheckEqual(2, model.Entries.Count);
CheckEqual("b.md", model.Entries[1].Name);
}
public void NullFileSystem_Throws()
{
CheckThrow(typeof(ArgumentNullException));
FileDialogModel.Create(null, FileDialogMode.Open);
}
public void FileSystemWithNoRoots_Throws()
{
var fileSystem = new FaultyFileSystem(InMemoryFileSystemTests.Sample()) { NoRoots = true };
CheckThrow(typeof(ArgumentException));
FileDialogModel.Create(fileSystem, FileDialogMode.Open);
}
}
public class EntriesTests : TestFixture
{
public void Directories_ComeBeforeFiles()
{
var fileSystem = new InMemoryFileSystem();
fileSystem.AddFile("/a.txt");
fileSystem.AddDirectory("/z");
FileDialogModel model = FileDialogModel.Create(fileSystem, FileDialogMode.Open).Value;
CheckEqual("z", model.Entries[0].Name);
CheckEqual("a.txt", model.Entries[1].Name);
}
public void Names_AreOrderedIgnoringCase()
{
var fileSystem = new InMemoryFileSystem();
fileSystem.AddFile("/b.txt");
fileSystem.AddFile("/A.txt");
fileSystem.AddFile("/c.txt");
FileDialogModel model = FileDialogModel.Create(fileSystem, FileDialogMode.Open).Value;
CheckEqual("A.txt", model.Entries[0].Name);
CheckEqual("b.txt", model.Entries[1].Name);
CheckEqual("c.txt", model.Entries[2].Name);
}
public void NamesDifferingOnlyInCase_AreOrderedOrdinally()
{
var fileSystem = new InMemoryFileSystem();
fileSystem.AddFile("/a.txt");
fileSystem.AddFile("/A.txt");
FileDialogModel model = FileDialogModel.Create(fileSystem, FileDialogMode.Open).Value;
CheckEqual("A.txt", model.Entries[0].Name);
CheckEqual("a.txt", model.Entries[1].Name);
}
public void Filter_HidesOtherFilesButNotDirectories()
{
FileDialogModel model = FileDialogModel.Create(Mixed(), FileDialogMode.Open, new[] { TextFiles }).Value;
CheckEqual(2, model.Entries.Count);
CheckEqual("dir", model.Entries[0].Name);
CheckEqual("a.txt", model.Entries[1].Name);
}
}
public class NavigateToTests : TestFixture
{
public void Always_ShowsTheDirectory()
{
FileDialogModel model = OpenModel();
model.NavigateTo("/docs/notes");
CheckEqual("/docs/notes", model.Directory);
CheckEqual(1, model.Entries.Count);
CheckEqual("todo.txt", model.Entries[0].Name);
}
public void Always_NotifiesOnce()
{
FileDialogModel model = OpenModel();
var listener = new Listener(model);
model.NavigateTo("/docs");
CheckEqual(1, listener.Changes);
}
public void Always_ClearsTheSelection()
{
FileDialogModel model = OpenModel();
model.Select(0);
model.NavigateTo("/docs");
CheckNull(model.SelectedIndex);
}
public void InOpenMode_ClearsTheFileName()
{
FileDialogModel model = OpenModel();
model.Select(2);
model.NavigateTo("/docs");
CheckEqual("", model.FileName);
}
public void InSaveMode_KeepsTheFileName()
{
FileDialogModel model = SaveModel();
model.SetFileName("mine.txt");
model.NavigateTo("/docs");
CheckEqual("mine.txt", model.FileName);
}
public void ADirectoryThatCantBeRead_LeavesThingsAsTheyWereAndReturnsWhy()
{
FileDialogModel model = OpenModel();
var listener = new Listener(model);
Status navigated = model.NavigateTo("/top.txt");
CheckEqual(FileSystemFailures.NotADirectory.Fail("/top.txt"), navigated);
CheckEqual("/", model.Directory);
CheckEqual(3, model.Entries.Count);
CheckEqual(1, listener.Changes);
}
public void Success_ReturnsOk()
{
CheckEqual(Status.Ok, OpenModel().NavigateTo("/docs"));
}
public void Always_DropsAWaitingOverwriteQuestion()
{
FileDialogModel model = SaveModel();
model.SetFileName("top.txt");
model.Accept();
model.NavigateTo("/docs");
CheckFalse(model.AwaitingOverwriteConfirmation);
}
public void MalformedPath_Throws()
{
FileDialogModel model = OpenModel();
CheckThrow(typeof(ArgumentException));
model.NavigateTo("docs");
}
}
public class UpTests : TestFixture
{
public void InADirectory_ShowsItsParentAndReturnsOk()
{
FileDialogModel model = OpenModel("/docs/notes");
CheckEqual(Status.Ok, model.Up());
CheckEqual("/docs", model.Directory);
}
public void AtARoot_DoesNothingAndReturnsOk()
{
FileDialogModel model = OpenModel();
var listener = new Listener(model);
CheckEqual(Status.Ok, model.Up());
CheckEqual("/", model.Directory);
CheckEqual(0, listener.Changes);
}
public void ParentThatCantBeRead_ReturnsWhy()
{
var fileSystem = new FaultyFileSystem(InMemoryFileSystemTests.Sample());
FileDialogModel model =
FileDialogModel.Create(fileSystem, FileDialogMode.Open, startDirectory: "/docs").Value;
fileSystem.ListFails = true;
CheckEqual(AccessDenied.Fail(), model.Up());
CheckEqual("/docs", model.Directory);
}
}
public class SelectTests : TestFixture
{
public void AFile_SelectsItAndFillsInTheFileName()
{
FileDialogModel model = OpenModel();
model.Select(2);
CheckEqual(2, model.SelectedIndex);
CheckEqual("top.txt", model.FileName);
}
public void ADirectory_SelectsItAndLeavesTheFileName()
{
FileDialogModel model = SaveModel();
model.SetFileName("mine.txt");
model.Select(0);
CheckEqual(0, model.SelectedIndex);
CheckEqual("mine.txt", model.FileName);
}
public void Null_ClearsTheSelectionAndLeavesTheFileName()
{
FileDialogModel model = OpenModel();
model.Select(2);
model.Select(null);
CheckNull(model.SelectedIndex);
CheckEqual("top.txt", model.FileName);
}
public void Always_NotifiesOnce()
{
FileDialogModel model = OpenModel();
var listener = new Listener(model);
model.Select(0);
CheckEqual(1, listener.Changes);
}
public void IndexPastTheEnd_Throws()
{
FileDialogModel model = OpenModel();
CheckThrow(typeof(ArgumentOutOfRangeException));
model.Select(3);
}
public void NegativeIndex_Throws()
{
FileDialogModel model = OpenModel();
CheckThrow(typeof(ArgumentOutOfRangeException));
model.Select(-1);
}
}
public class OpenTests : TestFixture
{
public void ADirectory_GoesIntoItAndReturnsOk()
{
FileDialogModel model = OpenModel();
var listener = new Listener(model);
CheckEqual(Status.Ok, model.Open(0));
CheckEqual("/docs", model.Directory);
CheckEqual(1, listener.Changes);
CheckEqual(0, listener.Accepted.Count);
}
public void ADirectoryThatCantBeRead_ReturnsWhy()
{
var fileSystem = new FaultyFileSystem(InMemoryFileSystemTests.Sample());
FileDialogModel model = FileDialogModel.Create(fileSystem, FileDialogMode.Open).Value;
fileSystem.ListFails = true;
CheckEqual(AccessDenied.Fail(), model.Open(0));
CheckEqual("/", model.Directory);
}
public void AFileWhenOpening_AcceptsItAndReturnsOk()
{
FileDialogModel model = OpenModel();
var listener = new Listener(model);
CheckEqual(Status.Ok, model.Open(2));
CheckEqual(new List { "/top.txt" }, listener.Accepted);
CheckEqual("top.txt", model.FileName);
CheckEqual(2, model.SelectedIndex);
CheckEqual(1, listener.Changes);
}
public void AFileWhenSaving_AsksBeforeReplacingItAndReturnsOk()
{
FileDialogModel model = SaveModel();
var listener = new Listener(model);
CheckEqual(Status.Ok, model.Open(2));
CheckEqual(0, listener.Accepted.Count);
CheckTrue(model.AwaitingOverwriteConfirmation);
}
public void IndexPastTheEnd_Throws()
{
FileDialogModel model = OpenModel();
CheckThrow(typeof(ArgumentOutOfRangeException));
model.Open(3);
}
public void NegativeIndex_Throws()
{
FileDialogModel model = OpenModel();
CheckThrow(typeof(ArgumentOutOfRangeException));
model.Open(-1);
}
}
public class SetFileNameTests : TestFixture
{
public void Always_ChangesTheNameAndClearsTheSelection()
{
FileDialogModel model = OpenModel();
model.Select(2);
model.SetFileName("other.txt");
CheckEqual("other.txt", model.FileName);
CheckNull(model.SelectedIndex);
}
public void Always_NotifiesOnce()
{
FileDialogModel model = SaveModel();
var listener = new Listener(model);
model.SetFileName("mine.txt");
CheckEqual(1, listener.Changes);
}
public void Null_Throws()
{
FileDialogModel model = SaveModel();
CheckThrow(typeof(ArgumentNullException));
model.SetFileName(null);
}
}
public class SelectFilterTests : TestFixture
{
[IgnoreTest]
private static FileDialogModel NewModel()
{
return FileDialogModel.Create(Mixed(), FileDialogMode.Open,
new[] { FileFilter.AllFiles, TextFiles, MarkdownFiles }).Value;
}
public void Always_NarrowsTheEntries()
{
FileDialogModel model = NewModel();
model.SelectFilter(2);
CheckEqual(2, model.SelectedFilterIndex);
CheckEqual(2, model.Entries.Count);
CheckEqual("b.md", model.Entries[1].Name);
}
public void ASelectedFileThatStillShows_StaysSelected()
{
FileDialogModel model = NewModel();
model.Select(1);
model.SelectFilter(1);
CheckEqual(1, model.SelectedIndex);
CheckEqual("a.txt", model.Entries[1].Name);
}
public void ASelectedFileThatIsHidden_IsDeselected()
{
FileDialogModel model = NewModel();
model.Select(1);
model.SelectFilter(2);
CheckNull(model.SelectedIndex);
}
public void ASelectedDirectory_StaysSelected()
{
FileDialogModel model = NewModel();
model.Select(0);
model.SelectFilter(1);
CheckEqual(0, model.SelectedIndex);
}
public void NothingSelected_StaysThatWay()
{
FileDialogModel model = NewModel();
model.SelectFilter(1);
CheckNull(model.SelectedIndex);
}
public void Always_NotifiesOnce()
{
FileDialogModel model = NewModel();
var listener = new Listener(model);
model.SelectFilter(1);
CheckEqual(1, listener.Changes);
}
public void IndexPastTheEnd_Throws()
{
FileDialogModel model = NewModel();
CheckThrow(typeof(ArgumentOutOfRangeException));
model.SelectFilter(3);
}
public void NegativeIndex_Throws()
{
FileDialogModel model = NewModel();
CheckThrow(typeof(ArgumentOutOfRangeException));
model.SelectFilter(-1);
}
}
public class NewFolderTests : TestFixture
{
public void Always_MakesAFolderSelectsItAndReturnsOk()
{
FileDialogModel model = OpenModel();
CheckEqual(Status.Ok, model.NewFolder());
CheckNotNull(model.SelectedIndex);
CheckEqual("New folder", model.Entries[model.SelectedIndex.Value].Name);
CheckTrue(model.Entries[model.SelectedIndex.Value].IsDirectory);
}
public void NameTaken_UsesTheNextNumber()
{
FileDialogModel model = OpenModel();
model.NewFolder();
model.NewFolder();
CheckEqual("New folder (2)", model.Entries[model.SelectedIndex.Value].Name);
}
public void SeveralNamesTaken_UsesTheFirstFreeNumber()
{
var fileSystem = new InMemoryFileSystem();
fileSystem.AddDirectory("/New folder");
fileSystem.AddDirectory("/New folder (2)");
FileDialogModel model = FileDialogModel.Create(fileSystem, FileDialogMode.Open).Value;
model.NewFolder();
CheckEqual("New folder (3)", model.Entries[model.SelectedIndex.Value].Name);
}
public void Always_NotifiesOnce()
{
FileDialogModel model = OpenModel();
var listener = new Listener(model);
model.NewFolder();
CheckEqual(1, listener.Changes);
}
public void WhenTheDirectoryCantBeReadBack_ReturnsWhy()
{
var fileSystem = new FaultyFileSystem(InMemoryFileSystemTests.Sample());
FileDialogModel model = FileDialogModel.Create(fileSystem, FileDialogMode.Open).Value;
fileSystem.ListFails = true;
CheckEqual(AccessDenied.Fail(), model.NewFolder());
}
public void WhenTheFileSystemRefuses_ReturnsWhyAndLeavesTheEntries()
{
var fileSystem = new FaultyFileSystem(InMemoryFileSystemTests.Sample()) { CreateDirectoryFails = true };
FileDialogModel model = FileDialogModel.Create(fileSystem, FileDialogMode.Open).Value;
var listener = new Listener(model);
CheckEqual(DiskFull.Fail(), model.NewFolder());
CheckEqual(3, model.Entries.Count);
CheckEqual(1, listener.Changes);
}
}
public class AcceptTests : TestFixture
{
public void Open_WithNoFileName_SaysToPickAFile()
{
FileDialogModel model = OpenModel();
var listener = new Listener(model);
CheckEqual(FileDialogFailures.NothingPicked.Fail(FileDialogMode.Open), model.Accept());
CheckEqual(0, listener.Accepted.Count);
}
public void Open_ExistingFile_RaisesAcceptedWithItsPath()
{
FileDialogModel model = OpenModel();
var listener = new Listener(model);
model.SetFileName("top.txt");
CheckEqual(Status.Ok, model.Accept());
CheckEqual(new List { "/top.txt" }, listener.Accepted);
}
public void Open_FileInAnotherDirectory_RaisesAcceptedWithItsPath()
{
FileDialogModel model = OpenModel("/docs");
var listener = new Listener(model);
model.SetFileName("readme.txt");
model.Accept();
CheckEqual(new List { "/docs/readme.txt" }, listener.Accepted);
}
public void Open_MissingFile_SaysItDoesntExist()
{
FileDialogModel model = OpenModel();
var listener = new Listener(model);
model.SetFileName("missing.txt");
CheckEqual(FileSystemFailures.NotFound.Fail("/missing.txt"), model.Accept());
CheckEqual(0, listener.Accepted.Count);
}
public void Open_NameOfADirectory_SaysItIsADirectory()
{
FileDialogModel model = OpenModel();
model.SetFileName("docs");
CheckEqual(FileSystemFailures.IsADirectory.Fail("/docs"), model.Accept());
}
public void Open_InvalidName_GivesTheFileSystemsReason()
{
FileDialogModel model = OpenModel();
model.SetFileName("a/b");
CheckEqual(new InMemoryFileSystem().ValidateFileName("a/b"), model.Accept());
}
public void Save_NewName_RaisesAcceptedWithItsPath()
{
FileDialogModel model = SaveModel();
var listener = new Listener(model);
model.SetFileName("mine.txt");
model.Accept();
CheckEqual(new List { "/mine.txt" }, listener.Accepted);
CheckFalse(model.AwaitingOverwriteConfirmation);
}
public void Save_WithNoFileName_SaysToPickAName()
{
FileDialogModel model = SaveModel();
CheckEqual(FileDialogFailures.NothingPicked.Fail(FileDialogMode.Save), model.Accept());
}
public void Save_InvalidName_GivesTheFileSystemsReason()
{
FileDialogModel model = SaveModel();
model.SetFileName("a/b");
CheckEqual(new InMemoryFileSystem().ValidateFileName("a/b"), model.Accept());
}
public void Save_NameOfADirectory_SaysItIsADirectory()
{
FileDialogModel model = SaveModel();
model.SetFileName("docs");
CheckEqual(FileSystemFailures.IsADirectory.Fail("/docs"), model.Accept());
}
public void Save_ExistingFile_AsksBeforeReplacingIt()
{
FileDialogModel model = SaveModel();
var listener = new Listener(model);
model.SetFileName("top.txt");
CheckEqual(Status.Ok, model.Accept());
CheckTrue(model.AwaitingOverwriteConfirmation);
CheckEqual(0, listener.Accepted.Count);
}
public void Save_NameWithoutAnExtension_GetsTheSelectedFiltersFirstExtension()
{
FileDialogModel model = SaveModel(new[] { TextFiles });
var listener = new Listener(model);
model.SetFileName("notes");
model.Accept();
CheckEqual("notes.txt", model.FileName);
CheckEqual(new List { "/notes.txt" }, listener.Accepted);
}
public void Save_NameWithoutAnExtension_AsksAboutTheFileItBecomes()
{
FileDialogModel model = SaveModel(new[] { TextFiles });
model.SetFileName("top");
model.Accept();
CheckEqual("top.txt", model.FileName);
CheckTrue(model.AwaitingOverwriteConfirmation);
}
public void Save_NameWithAnExtension_KeepsIt()
{
FileDialogModel model = SaveModel(new[] { TextFiles });
model.SetFileName("notes.md");
model.Accept();
CheckEqual("notes.md", model.FileName);
}
public void Save_NameEndingInADot_KeepsIt()
{
FileDialogModel model = SaveModel(new[] { TextFiles });
model.SetFileName("notes.");
model.Accept();
CheckEqual("notes.", model.FileName);
}
public void Save_NameStartingWithADotAndNoOther_GetsTheExtension()
{
FileDialogModel model = SaveModel(new[] { TextFiles });
model.SetFileName(".hidden");
model.Accept();
CheckEqual(".hidden.txt", model.FileName);
}
public void Save_FilterWithNoExtensions_KeepsTheNameAsItIs()
{
FileDialogModel model = SaveModel();
model.SetFileName("notes");
model.Accept();
CheckEqual("notes", model.FileName);
}
public void Save_DefaultFilter_KeepsTheNameAsItIs()
{
FileDialogModel model = SaveModel(new[] { default(FileFilter) });
model.SetFileName("notes");
model.Accept();
CheckEqual("notes", model.FileName);
}
public void Always_NotifiesOnce()
{
FileDialogModel model = OpenModel();
var listener = new Listener(model);
model.Accept();
CheckEqual(1, listener.Changes);
}
}
public class ConfirmOverwriteTests : TestFixture
{
[IgnoreTest]
private static FileDialogModel AwaitingModel()
{
FileDialogModel model = SaveModel(new[] { TextFiles });
model.SetFileName("top");
model.Accept();
return model;
}
public void Always_RaisesAcceptedWithThePath()
{
FileDialogModel model = AwaitingModel();
var listener = new Listener(model);
model.ConfirmOverwrite();
CheckEqual(new List { "/top.txt" }, listener.Accepted);
}
public void Always_StopsAwaitingAndNotifiesOnce()
{
FileDialogModel model = AwaitingModel();
var listener = new Listener(model);
model.ConfirmOverwrite();
CheckFalse(model.AwaitingOverwriteConfirmation);
CheckEqual(1, listener.Changes);
}
public void NothingWaiting_Throws()
{
FileDialogModel model = SaveModel();
CheckThrow(typeof(InvalidOperationException));
model.ConfirmOverwrite();
}
}
public class CancelOverwriteTests : TestFixture
{
[IgnoreTest]
private static FileDialogModel AwaitingModel()
{
FileDialogModel model = SaveModel();
model.SetFileName("top.txt");
model.Accept();
return model;
}
public void Waiting_StopsAwaitingWithoutAcceptingAndNotifiesOnce()
{
FileDialogModel model = AwaitingModel();
var listener = new Listener(model);
model.CancelOverwrite();
CheckFalse(model.AwaitingOverwriteConfirmation);
CheckEqual(0, listener.Accepted.Count);
CheckEqual(1, listener.Changes);
}
public void NothingWaiting_DoesNothing()
{
FileDialogModel model = SaveModel();
var listener = new Listener(model);
model.CancelOverwrite();
CheckEqual(0, listener.Changes);
}
}
public class CancelTests : TestFixture
{
public void Always_RaisesCancelled()
{
FileDialogModel model = OpenModel();
var listener = new Listener(model);
model.Cancel();
CheckEqual(1, listener.Cancellations);
CheckEqual(0, listener.Accepted.Count);
}
public void Always_NotifiesOnceAndDropsAWaitingOverwriteQuestion()
{
FileDialogModel model = SaveModel();
model.SetFileName("top.txt");
model.Accept();
var listener = new Listener(model);
model.Cancel();
CheckFalse(model.AwaitingOverwriteConfirmation);
CheckEqual(1, listener.Changes);
}
}
}
}