summaryrefslogtreecommitdiff
path: root/src/Notepad/Presentation/Model/Menu/File
diff options
context:
space:
mode:
authormo <mo.khan@gmail.com>2018-11-04 15:22:16 -0700
committermo <mo.khan@gmail.com>2018-11-04 15:22:16 -0700
commit5ee1f55497a4e30322a56f133f897ecde1612967 (patch)
treebf544e0879234c3623869627d8786776cb19b8e9 /src/Notepad/Presentation/Model/Menu/File
initial commit.HEADmaster
Diffstat (limited to 'src/Notepad/Presentation/Model/Menu/File')
-rw-r--r--src/Notepad/Presentation/Model/Menu/File/Commands/ExitCommandSpecs.cs34
-rw-r--r--src/Notepad/Presentation/Model/Menu/File/Commands/IExitCommand.cs18
-rw-r--r--src/Notepad/Presentation/Model/Menu/File/Commands/ISaveCommand.cs27
-rw-r--r--src/Notepad/Presentation/Model/Menu/File/Commands/SaveCommandSpecs.cs95
-rw-r--r--src/Notepad/Presentation/Model/Menu/File/ExitMenuItem.cs23
-rw-r--r--src/Notepad/Presentation/Model/Menu/File/ExitMenuItemSpecs.cs72
-rw-r--r--src/Notepad/Presentation/Model/Menu/File/FileMenu.cs26
-rw-r--r--src/Notepad/Presentation/Model/Menu/File/FileMenuSpecs.cs105
-rw-r--r--src/Notepad/Presentation/Model/Menu/File/NewMenuItem.cs17
-rw-r--r--src/Notepad/Presentation/Model/Menu/File/NewMenuItemSpecs.cs46
-rw-r--r--src/Notepad/Presentation/Model/Menu/File/SaveAsMenuItem.cs24
-rw-r--r--src/Notepad/Presentation/Model/Menu/File/SaveAsMenuItemSpecs.cs102
-rw-r--r--src/Notepad/Presentation/Model/Menu/File/SaveMenuItem.cs23
-rw-r--r--src/Notepad/Presentation/Model/Menu/File/SaveMenuItemSpecs.cs99
14 files changed, 711 insertions, 0 deletions
diff --git a/src/Notepad/Presentation/Model/Menu/File/Commands/ExitCommandSpecs.cs b/src/Notepad/Presentation/Model/Menu/File/Commands/ExitCommandSpecs.cs
new file mode 100644
index 0000000..00855b6
--- /dev/null
+++ b/src/Notepad/Presentation/Model/Menu/File/Commands/ExitCommandSpecs.cs
@@ -0,0 +1,34 @@
+using MbUnit.Framework;
+using Notepad.Infrastructure.System;
+using Rhino.Mocks;
+
+namespace Notepad.Presentation.Model.Menu.File.Commands {
+ public class ExitCommandSpecs {}
+
+ [TestFixture]
+ public class when_executing_the_exit_command_specs_ {
+ private MockRepository mockery;
+ private IApplicationEnvironment application;
+
+ [SetUp]
+ public void SetUp() {
+ mockery = new MockRepository();
+ application = mockery.DynamicMock<IApplicationEnvironment>();
+ }
+
+ [Test]
+ public void should_ask_the_application_environment_to_shut_down() {
+ using (mockery.Record()) {
+ application.ShutDown();
+ }
+
+ using (mockery.Playback()) {
+ CreateSUT().Execute();
+ }
+ }
+
+ private IExitCommand CreateSUT() {
+ return new ExitCommand(application);
+ }
+ }
+} \ No newline at end of file
diff --git a/src/Notepad/Presentation/Model/Menu/File/Commands/IExitCommand.cs b/src/Notepad/Presentation/Model/Menu/File/Commands/IExitCommand.cs
new file mode 100644
index 0000000..a78c32b
--- /dev/null
+++ b/src/Notepad/Presentation/Model/Menu/File/Commands/IExitCommand.cs
@@ -0,0 +1,18 @@
+using Notepad.Infrastructure.Core;
+using Notepad.Infrastructure.System;
+
+namespace Notepad.Presentation.Model.Menu.File.Commands {
+ public interface IExitCommand : ICommand {}
+
+ public class ExitCommand : IExitCommand {
+ private readonly IApplicationEnvironment application;
+
+ public ExitCommand(IApplicationEnvironment application) {
+ this.application = application;
+ }
+
+ public void Execute() {
+ application.ShutDown();
+ }
+ }
+} \ No newline at end of file
diff --git a/src/Notepad/Presentation/Model/Menu/File/Commands/ISaveCommand.cs b/src/Notepad/Presentation/Model/Menu/File/Commands/ISaveCommand.cs
new file mode 100644
index 0000000..ea7c396
--- /dev/null
+++ b/src/Notepad/Presentation/Model/Menu/File/Commands/ISaveCommand.cs
@@ -0,0 +1,27 @@
+using Notepad.Infrastructure.Core;
+using Notepad.Presentation.Core;
+using Notepad.Presentation.Presenters.Menu.File;
+using Notepad.Tasks;
+
+namespace Notepad.Presentation.Model.Menu.File.Commands {
+ public interface ISaveCommand : ICommand {}
+
+ public class SaveCommand : ISaveCommand {
+ private readonly IApplicationController controller;
+ private readonly IDocumentTasks tasks;
+
+ public SaveCommand(IApplicationController controller, IDocumentTasks tasks) {
+ this.controller = controller;
+ this.tasks = tasks;
+ }
+
+ public void Execute() {
+ if (!tasks.HasAPathToSaveToBeenSpecified()) {
+ controller.Run<ISaveAsPresenter>();
+ }
+ else {
+ tasks.SaveTheActiveDocument();
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/src/Notepad/Presentation/Model/Menu/File/Commands/SaveCommandSpecs.cs b/src/Notepad/Presentation/Model/Menu/File/Commands/SaveCommandSpecs.cs
new file mode 100644
index 0000000..7e4d827
--- /dev/null
+++ b/src/Notepad/Presentation/Model/Menu/File/Commands/SaveCommandSpecs.cs
@@ -0,0 +1,95 @@
+using MbUnit.Framework;
+using Notepad.Presentation.Core;
+using Notepad.Presentation.Presenters.Menu.File;
+using Notepad.Tasks;
+using Rhino.Mocks;
+
+namespace Notepad.Presentation.Model.Menu.File.Commands {
+ public class SaveCommandSpecs {}
+
+ [TestFixture]
+ public class when_executing_the_save_command_and_a_file_path_to_save_to_has_not_been_specified_ {
+ private MockRepository mockery;
+ private IApplicationController applicationController;
+ private IDocumentTasks tasks;
+
+ [SetUp]
+ public void SetUp() {
+ mockery = new MockRepository();
+ applicationController = mockery.DynamicMock<IApplicationController>();
+ tasks = mockery.DynamicMock<IDocumentTasks>();
+
+ SetupResult.For(tasks.HasAPathToSaveToBeenSpecified()).Return(false);
+ }
+
+ [Test]
+ public void should_run_the_save_as_presenter() {
+ using (mockery.Record()) {
+ applicationController.Run<ISaveAsPresenter>();
+ }
+
+ using (mockery.Playback()) {
+ CreateSUT().Execute();
+ }
+ }
+
+ [Test]
+ public void should_not_save_the_active_document() {
+ using (mockery.Record()) {
+ tasks.SaveTheActiveDocument();
+ LastCall.Repeat.Never();
+ }
+
+ using (mockery.Playback()) {
+ CreateSUT().Execute();
+ }
+ }
+
+ private ISaveCommand CreateSUT() {
+ return new SaveCommand(applicationController, tasks);
+ }
+ }
+
+ [TestFixture]
+ public class when_executing_the_save_command_and_a_path_to_save_to_has_already_been_specified_ {
+ private MockRepository mockery;
+ private IApplicationController applicationController;
+ private IDocumentTasks tasks;
+
+ [SetUp]
+ public void SetUp() {
+ mockery = new MockRepository();
+ applicationController = mockery.DynamicMock<IApplicationController>();
+ tasks = mockery.DynamicMock<IDocumentTasks>();
+
+ SetupResult.For(tasks.HasAPathToSaveToBeenSpecified()).Return(true);
+ }
+
+ [Test]
+ public void should_not_run_the_save_as_presenter() {
+ using (mockery.Record()) {
+ applicationController.Run<ISaveAsPresenter>();
+ LastCall.Repeat.Never();
+ }
+
+ using (mockery.Playback()) {
+ CreateSUT().Execute();
+ }
+ }
+
+ [Test]
+ public void should_save_the_active_document() {
+ using (mockery.Record()) {
+ tasks.SaveTheActiveDocument();
+ }
+
+ using (mockery.Playback()) {
+ CreateSUT().Execute();
+ }
+ }
+
+ private ISaveCommand CreateSUT() {
+ return new SaveCommand(applicationController, tasks);
+ }
+ }
+} \ No newline at end of file
diff --git a/src/Notepad/Presentation/Model/Menu/File/ExitMenuItem.cs b/src/Notepad/Presentation/Model/Menu/File/ExitMenuItem.cs
new file mode 100644
index 0000000..c926dac
--- /dev/null
+++ b/src/Notepad/Presentation/Model/Menu/File/ExitMenuItem.cs
@@ -0,0 +1,23 @@
+using Notepad.Presentation.Model.Menu.File.Commands;
+
+namespace Notepad.Presentation.Model.Menu.File {
+ public class ExitMenuItem : IMenuItem {
+ private readonly IExitCommand exitCommand;
+
+ public ExitMenuItem(IExitCommand exitCommand) {
+ this.exitCommand = exitCommand;
+ }
+
+ public string Name() {
+ return "E&xit";
+ }
+
+ public void Click() {
+ exitCommand.Execute();
+ }
+
+ public bool BelongsTo(ISubMenu menu) {
+ return menu.Name().Equals(MenuNames.File);
+ }
+ }
+} \ No newline at end of file
diff --git a/src/Notepad/Presentation/Model/Menu/File/ExitMenuItemSpecs.cs b/src/Notepad/Presentation/Model/Menu/File/ExitMenuItemSpecs.cs
new file mode 100644
index 0000000..3220ae5
--- /dev/null
+++ b/src/Notepad/Presentation/Model/Menu/File/ExitMenuItemSpecs.cs
@@ -0,0 +1,72 @@
+using MbUnit.Framework;
+using Notepad.Presentation.Model.Menu.File.Commands;
+using Notepad.Test.Extensions;
+using Rhino.Mocks;
+
+namespace Notepad.Presentation.Model.Menu.File {
+ public class ExitMenuItemSpecs {}
+
+ [TestFixture]
+ public class when_asking_the_exit_menu_item_for_its_name_ {
+ [Test]
+ public void should_return_the_correct_name() {
+ CreateSUT().Name().ShouldBeEqualTo("E&xit");
+ }
+
+ private IMenuItem CreateSUT() {
+ return new ExitMenuItem(null);
+ }
+ }
+
+ [TestFixture]
+ public class when_clicking_on_the_exit_menu_item_ {
+ private MockRepository mockery;
+ private IExitCommand exitCommand;
+
+ [SetUp]
+ public void SetUp() {
+ mockery = new MockRepository();
+ exitCommand = mockery.DynamicMock<IExitCommand>();
+ }
+
+ [Test]
+ public void should_execute_the_exit_command() {
+ using (mockery.Record()) {}
+
+ using (mockery.Playback()) {
+ CreateSUT().Click();
+ }
+ }
+
+ private IMenuItem CreateSUT() {
+ return new ExitMenuItem(exitCommand);
+ }
+ }
+
+ [TestFixture]
+ public class when_asking_the_exit_menu_item_if_it_belongs_to_a_menu_that_it_does {
+ private MockRepository mockery;
+ private ISubMenu fileMenu;
+
+ [SetUp]
+ public void SetUp() {
+ mockery = new MockRepository();
+ fileMenu = mockery.DynamicMock<ISubMenu>();
+
+ SetupResult.For(fileMenu.Name()).Return(MenuNames.File);
+ }
+
+ [Test]
+ public void should_return_true() {
+ using (mockery.Record()) {}
+
+ using (mockery.Playback()) {
+ CreateSUT().BelongsTo(fileMenu).ShouldBeEqualTo(true);
+ }
+ }
+
+ private IMenuItem CreateSUT() {
+ return new ExitMenuItem(null);
+ }
+ }
+} \ No newline at end of file
diff --git a/src/Notepad/Presentation/Model/Menu/File/FileMenu.cs b/src/Notepad/Presentation/Model/Menu/File/FileMenu.cs
new file mode 100644
index 0000000..98b5a47
--- /dev/null
+++ b/src/Notepad/Presentation/Model/Menu/File/FileMenu.cs
@@ -0,0 +1,26 @@
+using System.Collections.Generic;
+using Notepad.Domain.Repositories;
+using Notepad.Infrastructure.Extensions;
+
+namespace Notepad.Presentation.Model.Menu.File {
+ public class FileMenu : ISubMenu {
+ private readonly IRepository<IMenuItem> repository;
+ private readonly IMenuItemComparer menuItemComparer;
+
+ public FileMenu(IRepository<IMenuItem> repository, IMenuItemComparer menuItemComparer) {
+ this.repository = repository;
+ this.menuItemComparer = menuItemComparer;
+ }
+
+ public IEnumerable<IMenuItem> AllMenuItems() {
+ return repository
+ .All()
+ .ThatSatisfy(menuItem => menuItem.BelongsTo(this))
+ .SortedUsing(menuItemComparer);
+ }
+
+ public string Name() {
+ return MenuNames.File;
+ }
+ }
+} \ No newline at end of file
diff --git a/src/Notepad/Presentation/Model/Menu/File/FileMenuSpecs.cs b/src/Notepad/Presentation/Model/Menu/File/FileMenuSpecs.cs
new file mode 100644
index 0000000..8630ad3
--- /dev/null
+++ b/src/Notepad/Presentation/Model/Menu/File/FileMenuSpecs.cs
@@ -0,0 +1,105 @@
+using System.Collections.Generic;
+using MbUnit.Framework;
+using Notepad.Domain.Repositories;
+using Notepad.Infrastructure.Extensions;
+using Notepad.Test.Extensions;
+using Rhino.Mocks;
+
+namespace Notepad.Presentation.Model.Menu.File {
+ public class FileMenuSpecs {}
+
+ [TestFixture]
+ public class when_asking_the_file_menu_for_its_name_ {
+ [Test]
+ public void should_return_the_correct_name() {
+ CreateSUT().Name().ShouldBeEqualTo(MenuNames.File);
+ }
+
+ private ISubMenu CreateSUT() {
+ return new FileMenu(null, null);
+ }
+ }
+
+ [TestFixture]
+ public class when_asking_the_file_menu_for_its_menu_items_ {
+ private MockRepository mockery;
+ private IRepository<IMenuItem> repository;
+ private ISubMenu sut;
+ private IMenuItemComparer menuItemComparer;
+
+ [SetUp]
+ public void SetUp() {
+ mockery = new MockRepository();
+ repository = mockery.DynamicMock<IRepository<IMenuItem>>();
+ menuItemComparer = mockery.DynamicMock<IMenuItemComparer>();
+
+ sut = CreateSUT();
+ }
+
+ [Test]
+ public void should_ask_the_repository_for_all_the_menu_items() {
+ using (mockery.Record()) {
+ Expect
+ .Call(repository.All())
+ .Return(new List<IMenuItem>())
+ .Repeat
+ .AtLeastOnce();
+ }
+
+ using (mockery.Playback()) {
+ sut.AllMenuItems().Walk();
+ }
+ }
+
+ [Test]
+ public void should_return_the_menu_items_that_belong_to_the_file_menu() {
+ var saveMenuItem = mockery.DynamicMock<IMenuItem>();
+ var helpMenuItem = mockery.DynamicMock<IMenuItem>();
+
+ var allMenuItems = new List<IMenuItem> {saveMenuItem, helpMenuItem};
+
+ using (mockery.Record()) {
+ SetupResult.For(repository.All()).Return(allMenuItems);
+ SetupResult.For(saveMenuItem.BelongsTo(sut)).Return(true);
+ SetupResult.For(helpMenuItem.BelongsTo(sut)).Return(false);
+ }
+
+ using (mockery.Playback()) {
+ var returnedItems = sut.AllMenuItems();
+ returnedItems.ShouldContain(saveMenuItem);
+ returnedItems.ShouldNotContain(helpMenuItem);
+ }
+ }
+
+ [Test]
+ public void should_sort_the_items_in_the_file_menu() {
+ var firstItem = mockery.DynamicMock<IMenuItem>();
+ var secondItem = mockery.DynamicMock<IMenuItem>();
+
+ var allMenuItems = new List<IMenuItem> {firstItem, secondItem};
+
+ using (mockery.Record()) {
+ SetupResult.For(repository.All()).Return(allMenuItems);
+ SetupResult.For(firstItem.BelongsTo(null))
+ .IgnoreArguments()
+ .Return(true);
+ SetupResult.For(secondItem.BelongsTo(null))
+ .IgnoreArguments()
+ .Return(true);
+ Expect
+ .Call(menuItemComparer.Compare(firstItem, secondItem))
+ .Return(1)
+ .Repeat
+ .AtLeastOnce();
+ }
+
+ using (mockery.Playback()) {
+ sut.AllMenuItems().Walk();
+ }
+ }
+
+ private ISubMenu CreateSUT() {
+ return new FileMenu(repository, menuItemComparer);
+ }
+ }
+} \ No newline at end of file
diff --git a/src/Notepad/Presentation/Model/Menu/File/NewMenuItem.cs b/src/Notepad/Presentation/Model/Menu/File/NewMenuItem.cs
new file mode 100644
index 0000000..ab527d8
--- /dev/null
+++ b/src/Notepad/Presentation/Model/Menu/File/NewMenuItem.cs
@@ -0,0 +1,17 @@
+using System;
+
+namespace Notepad.Presentation.Model.Menu.File {
+ public class NewMenuItem : IMenuItem {
+ public void Click() {
+ throw new NotImplementedException();
+ }
+
+ public bool BelongsTo(ISubMenu menu) {
+ return menu.Name().Equals(MenuNames.File);
+ }
+
+ public string Name() {
+ return "&New";
+ }
+ }
+} \ No newline at end of file
diff --git a/src/Notepad/Presentation/Model/Menu/File/NewMenuItemSpecs.cs b/src/Notepad/Presentation/Model/Menu/File/NewMenuItemSpecs.cs
new file mode 100644
index 0000000..54a7b20
--- /dev/null
+++ b/src/Notepad/Presentation/Model/Menu/File/NewMenuItemSpecs.cs
@@ -0,0 +1,46 @@
+using MbUnit.Framework;
+using Notepad.Test.Extensions;
+using Rhino.Mocks;
+
+namespace Notepad.Presentation.Model.Menu.File {
+ public class NewMenuItemSpecs {}
+
+ [TestFixture]
+ public class when_asking_the_new_file_menu_if_it_belongs_to_the_file_menu_ {
+ private MockRepository mockery;
+ private ISubMenu fileMenu;
+
+ [SetUp]
+ public void SetUp() {
+ mockery = new MockRepository();
+ fileMenu = mockery.DynamicMock<ISubMenu>();
+
+ SetupResult.For(fileMenu.Name()).Return("&File");
+ }
+
+ [Test]
+ public void should_return_true() {
+ using (mockery.Record()) {}
+
+ using (mockery.Playback()) {
+ CreateSUT().BelongsTo(fileMenu).ShouldBeEqualTo(true);
+ }
+ }
+
+ private IMenuItem CreateSUT() {
+ return new NewMenuItem();
+ }
+ }
+
+ [TestFixture]
+ public class when_asking_the_new_file_menu_item_for_its_name_ {
+ [Test]
+ public void should_return_the_correct_name() {
+ CreateSUT().Name().ShouldBeEqualTo("&New");
+ }
+
+ private IMenuItem CreateSUT() {
+ return new NewMenuItem();
+ }
+ }
+} \ No newline at end of file
diff --git a/src/Notepad/Presentation/Model/Menu/File/SaveAsMenuItem.cs b/src/Notepad/Presentation/Model/Menu/File/SaveAsMenuItem.cs
new file mode 100644
index 0000000..859ad32
--- /dev/null
+++ b/src/Notepad/Presentation/Model/Menu/File/SaveAsMenuItem.cs
@@ -0,0 +1,24 @@
+using Notepad.Presentation.Presenters.Commands;
+using Notepad.Presentation.Presenters.Menu.File;
+
+namespace Notepad.Presentation.Model.Menu.File {
+ public class SaveAsMenuItem : IMenuItem {
+ private readonly IRunPresenterCommand<ISaveAsPresenter> saveAsCommand;
+
+ public SaveAsMenuItem(IRunPresenterCommand<ISaveAsPresenter> saveAsCommand) {
+ this.saveAsCommand = saveAsCommand;
+ }
+
+ public string Name() {
+ return "Save &As...";
+ }
+
+ public void Click() {
+ saveAsCommand.Execute();
+ }
+
+ public bool BelongsTo(ISubMenu menu) {
+ return menu.Name().Equals(MenuNames.File);
+ }
+ }
+} \ No newline at end of file
diff --git a/src/Notepad/Presentation/Model/Menu/File/SaveAsMenuItemSpecs.cs b/src/Notepad/Presentation/Model/Menu/File/SaveAsMenuItemSpecs.cs
new file mode 100644
index 0000000..a7c7fd0
--- /dev/null
+++ b/src/Notepad/Presentation/Model/Menu/File/SaveAsMenuItemSpecs.cs
@@ -0,0 +1,102 @@
+using MbUnit.Framework;
+using Notepad.Presentation.Model.Menu.File.Commands;
+using Notepad.Presentation.Presenters.Commands;
+using Notepad.Presentation.Presenters.Menu.File;
+using Notepad.Test.Extensions;
+using Rhino.Mocks;
+
+namespace Notepad.Presentation.Model.Menu.File {
+ public class SaveAsMenuItemSpecs {}
+
+ [TestFixture]
+ public class when_asking_the_save_as_menu_item_for_its_name_ {
+ [Test]
+ public void should_return_the_correct_name() {
+ CreateSUT().Name().ShouldBeEqualTo("Save &As...");
+ }
+
+ private IMenuItem CreateSUT() {
+ return new SaveAsMenuItem(null);
+ }
+ }
+
+ [TestFixture]
+ public class when_clicking_on_the_save_as_menu_item_ {
+ private MockRepository mockery;
+ private IRunPresenterCommand<ISaveAsPresenter> saveAsCommand;
+
+ [SetUp]
+ public void SetUp() {
+ mockery = new MockRepository();
+ saveAsCommand = mockery.DynamicMock<IRunPresenterCommand<ISaveAsPresenter>>();
+ }
+
+ [Test]
+ public void should_execute_the_save_as_command() {
+ using (mockery.Record()) {}
+
+ using (mockery.Playback()) {
+ CreateSUT().Click();
+ }
+ }
+
+ private IMenuItem CreateSUT() {
+ return new SaveAsMenuItem(saveAsCommand);
+ }
+ }
+
+ [TestFixture]
+ public class when_asking_the_save_as_menu_item_if_it_belongs_to_a_menu_that_it_does {
+ private MockRepository mockery;
+ private ISubMenu fileMenu;
+
+ [SetUp]
+ public void SetUp() {
+ mockery = new MockRepository();
+ fileMenu = mockery.DynamicMock<ISubMenu>();
+
+ SetupResult.For(fileMenu.Name()).Return(MenuNames.File);
+ }
+
+ [Test]
+ public void should_return_true() {
+ using (mockery.Record()) {}
+
+ using (mockery.Playback()) {
+ CreateSUT().BelongsTo(fileMenu).ShouldBeEqualTo(true);
+ }
+ }
+
+ private IMenuItem CreateSUT() {
+ return new SaveAsMenuItem(null);
+ }
+ }
+
+ [TestFixture]
+ public class when_asking_the_save_as_menu_item_if_it_belongs_to_a_menu_item_that_it_does_not {
+ private MockRepository mockery;
+ private ISubMenu unknownMenu;
+
+ [SetUp]
+ public void SetUp() {
+ mockery = new MockRepository();
+ unknownMenu = mockery.DynamicMock<ISubMenu>();
+
+ SetupResult.For(unknownMenu.Name()).Return("blah");
+ }
+
+ [Test]
+ public void should_return_false() {
+ using (mockery.Record()) {}
+
+ using (mockery.Playback()) {
+ CreateSUT().BelongsTo(unknownMenu).ShouldBeEqualTo(false);
+ }
+ }
+
+
+ private IMenuItem CreateSUT() {
+ return new SaveAsMenuItem(null);
+ }
+ }
+} \ No newline at end of file
diff --git a/src/Notepad/Presentation/Model/Menu/File/SaveMenuItem.cs b/src/Notepad/Presentation/Model/Menu/File/SaveMenuItem.cs
new file mode 100644
index 0000000..f99c179
--- /dev/null
+++ b/src/Notepad/Presentation/Model/Menu/File/SaveMenuItem.cs
@@ -0,0 +1,23 @@
+using Notepad.Presentation.Model.Menu.File.Commands;
+
+namespace Notepad.Presentation.Model.Menu.File {
+ public class SaveMenuItem : IMenuItem {
+ private readonly ISaveCommand saveCommand;
+
+ public SaveMenuItem(ISaveCommand saveCommand) {
+ this.saveCommand = saveCommand;
+ }
+
+ public bool BelongsTo(ISubMenu menu) {
+ return menu.Name().Equals(MenuNames.File);
+ }
+
+ public void Click() {
+ saveCommand.Execute();
+ }
+
+ public string Name() {
+ return "&Save";
+ }
+ }
+} \ No newline at end of file
diff --git a/src/Notepad/Presentation/Model/Menu/File/SaveMenuItemSpecs.cs b/src/Notepad/Presentation/Model/Menu/File/SaveMenuItemSpecs.cs
new file mode 100644
index 0000000..071adf8
--- /dev/null
+++ b/src/Notepad/Presentation/Model/Menu/File/SaveMenuItemSpecs.cs
@@ -0,0 +1,99 @@
+using MbUnit.Framework;
+using Notepad.Presentation.Model.Menu.File.Commands;
+using Notepad.Test.Extensions;
+using Rhino.Mocks;
+
+namespace Notepad.Presentation.Model.Menu.File {
+ public class SaveMenuItemSpecs {}
+
+ [TestFixture]
+ public class when_asking_the_save_menu_item_for_its_name_ {
+ [Test]
+ public void should_return_the_correct_name() {
+ CreateSUT().Name().ShouldBeEqualTo("&Save");
+ }
+
+ private IMenuItem CreateSUT() {
+ return new SaveMenuItem(null);
+ }
+ }
+
+ [TestFixture]
+ public class when_clicking_on_the_save_menu_item_ {
+ private MockRepository mockery;
+ private ISaveCommand saveCommand;
+
+ [SetUp]
+ public void SetUp() {
+ mockery = new MockRepository();
+ saveCommand = mockery.DynamicMock<ISaveCommand>();
+ }
+
+ [Test]
+ public void should_execute_the_save_command() {
+ using (mockery.Record()) {}
+
+ using (mockery.Playback()) {
+ CreateSUT().Click();
+ }
+ }
+
+ private IMenuItem CreateSUT() {
+ return new SaveMenuItem(saveCommand);
+ }
+ }
+
+ [TestFixture]
+ public class when_asking_the_save_menu_item_if_it_belongs_to_a_menu_that_it_does {
+ private MockRepository mockery;
+ private ISubMenu fileMenu;
+
+ [SetUp]
+ public void SetUp() {
+ mockery = new MockRepository();
+ fileMenu = mockery.DynamicMock<ISubMenu>();
+
+ SetupResult.For(fileMenu.Name()).Return(MenuNames.File);
+ }
+
+ [Test]
+ public void should_return_true() {
+ using (mockery.Record()) {}
+
+ using (mockery.Playback()) {
+ CreateSUT().BelongsTo(fileMenu).ShouldBeEqualTo(true);
+ }
+ }
+
+ private IMenuItem CreateSUT() {
+ return new SaveMenuItem(null);
+ }
+ }
+
+ [TestFixture]
+ public class when_asking_the_save_menu_item_if_it_belongs_to_a_menu_item_that_it_does_not {
+ private MockRepository mockery;
+ private ISubMenu unknownMenu;
+
+ [SetUp]
+ public void SetUp() {
+ mockery = new MockRepository();
+ unknownMenu = mockery.DynamicMock<ISubMenu>();
+
+ SetupResult.For(unknownMenu.Name()).Return("blah");
+ }
+
+ [Test]
+ public void should_return_false() {
+ using (mockery.Record()) {}
+
+ using (mockery.Playback()) {
+ CreateSUT().BelongsTo(unknownMenu).ShouldBeEqualTo(false);
+ }
+ }
+
+ private IMenuItem CreateSUT() {
+ return new SaveMenuItem(null);
+ }
+ }
+} \ No newline at end of file