├── .gitignore ├── Guestbook ├── Global.asax ├── IoC.cs ├── Content │ └── Site.css ├── Views │ ├── Shared │ │ └── Site.Master │ ├── Guestbook │ │ ├── Post.aspx │ │ └── Index.aspx │ └── Web.config ├── Controllers │ └── GuestbookController.cs ├── Global.asax.cs ├── Web.Debug.config ├── Web.Release.config ├── Properties │ └── AssemblyInfo.cs ├── Guestbook.csproj └── Web.config ├── Guestbook.Spec ├── External Assemblies │ ├── Moq.dll │ ├── Deleporter.dll │ ├── WatiN.Core.dll │ ├── Interop.SHDocVw.dll │ └── TechTalk.SpecFlow.dll ├── App.config ├── Steps │ ├── Infrastructure │ │ ├── WebBrowser.cs │ │ ├── SerializableTable.cs │ │ └── TidyUp.cs │ ├── MockData.cs │ ├── ViewingGuestbook.cs │ └── Navigation.cs ├── Features │ ├── Posting.feature │ ├── Browsing.feature │ ├── Posting.feature.cs │ └── Browsing.feature.cs ├── PageWrappers │ └── GuestbookEntriesList.cs ├── Properties │ └── AssemblyInfo.cs └── Guestbook.Spec.csproj ├── Guestbook.Domain ├── Repositories │ ├── IGuestbookEntryRepository.cs │ └── GuestbookEntryRepository.cs ├── Entities │ └── GuestbookEntry.cs ├── Properties │ └── AssemblyInfo.cs └── Guestbook.Domain.csproj ├── Guestbook.sln └── Guestbook-vs2010.sln /.gitignore: -------------------------------------------------------------------------------- 1 | *.suo 2 | *.csproj.user 3 | bin 4 | obj 5 | *.pdb 6 | _ReSharper* 7 | *.ReSharper.user 8 | desktop.ini 9 | -------------------------------------------------------------------------------- /Guestbook/Global.asax: -------------------------------------------------------------------------------- 1 | <%@ Application Codebehind="Global.asax.cs" Inherits="Guestbook.MvcApplication" Language="C#" %> 2 | -------------------------------------------------------------------------------- /Guestbook.Spec/External Assemblies/Moq.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SteveSanderson/GuestbookDemo/HEAD/Guestbook.Spec/External Assemblies/Moq.dll -------------------------------------------------------------------------------- /Guestbook.Spec/External Assemblies/Deleporter.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SteveSanderson/GuestbookDemo/HEAD/Guestbook.Spec/External Assemblies/Deleporter.dll -------------------------------------------------------------------------------- /Guestbook.Spec/External Assemblies/WatiN.Core.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SteveSanderson/GuestbookDemo/HEAD/Guestbook.Spec/External Assemblies/WatiN.Core.dll -------------------------------------------------------------------------------- /Guestbook.Spec/External Assemblies/Interop.SHDocVw.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SteveSanderson/GuestbookDemo/HEAD/Guestbook.Spec/External Assemblies/Interop.SHDocVw.dll -------------------------------------------------------------------------------- /Guestbook.Spec/External Assemblies/TechTalk.SpecFlow.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SteveSanderson/GuestbookDemo/HEAD/Guestbook.Spec/External Assemblies/TechTalk.SpecFlow.dll -------------------------------------------------------------------------------- /Guestbook.Domain/Repositories/IGuestbookEntryRepository.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using Guestbook.Domain.Entities; 3 | 4 | namespace Guestbook.Domain.Repositories 5 | { 6 | public interface IGuestbookEntryRepository 7 | { 8 | IQueryable Entries { get; } 9 | void AddEntry(GuestbookEntry entry); 10 | } 11 | } -------------------------------------------------------------------------------- /Guestbook.Domain/Entities/GuestbookEntry.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Guestbook.Domain.Entities 4 | { 5 | public class GuestbookEntry 6 | { 7 | public int GuestbookEntryId { get; set; } 8 | public string Author { get; set; } 9 | public DateTime PostedDate { get; set; } 10 | public string Comment { get; set; } 11 | } 12 | } -------------------------------------------------------------------------------- /Guestbook/IoC.cs: -------------------------------------------------------------------------------- 1 | using Guestbook.Domain.Repositories; 2 | 3 | namespace Guestbook 4 | { 5 | /// 6 | /// Quick and simple stand-in for an IoC container. Perfectly good for this example. 7 | /// 8 | public static class IoC 9 | { 10 | public static IGuestbookEntryRepository CurrentGuestbookEntryRepository = new GuestbookEntryRepository(); 11 | } 12 | } -------------------------------------------------------------------------------- /Guestbook/Content/Site.css: -------------------------------------------------------------------------------- 1 | /* Styles for validation helpers 2 | -----------------------------------------------------------*/ 3 | .field-validation-error 4 | { 5 | color: #ff0000; 6 | } 7 | 8 | .field-validation-valid 9 | { 10 | display: none; 11 | } 12 | 13 | .input-validation-error 14 | { 15 | border: 1px solid #ff0000; 16 | background-color: #ffeeee; 17 | } 18 | 19 | .validation-summary-errors 20 | { 21 | font-weight: bold; 22 | color: #ff0000; 23 | } 24 | 25 | .validation-summary-valid 26 | { 27 | display: none; 28 | } 29 | -------------------------------------------------------------------------------- /Guestbook.Spec/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 |
6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /Guestbook/Views/Shared/Site.Master: -------------------------------------------------------------------------------- 1 | <%@ Master Language="C#" Inherits="System.Web.Mvc.ViewMasterPage" %> 2 | 3 | 4 | 5 | 6 | 7 | <asp:ContentPlaceHolder ID="TitleContent" runat="server" /> 8 | 9 | 10 | <% if(!string.IsNullOrEmpty((string)TempData["message"])) { %> 11 |
<%= Html.Encode(TempData["message"]) %>
12 | <% } %> 13 |
14 | 15 |
16 | 17 | 18 | -------------------------------------------------------------------------------- /Guestbook.Spec/Steps/Infrastructure/WebBrowser.cs: -------------------------------------------------------------------------------- 1 | using TechTalk.SpecFlow; 2 | using WatiN.Core; 3 | 4 | namespace Guestbook.Spec.Steps.Infrastructure 5 | { 6 | [Binding] 7 | public class WebBrowser 8 | { 9 | public static Browser Current 10 | { 11 | get 12 | { 13 | if (!ScenarioContext.Current.ContainsKey("browser")) 14 | ScenarioContext.Current["browser"] = new IE(); 15 | return (Browser)ScenarioContext.Current["browser"]; 16 | } 17 | } 18 | 19 | [AfterScenario] 20 | public static void Close() 21 | { 22 | if (ScenarioContext.Current.ContainsKey("browser")) 23 | WebBrowser.Current.Close(); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Guestbook/Views/Guestbook/Post.aspx: -------------------------------------------------------------------------------- 1 | <%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage" %> 2 | 3 | 4 | Guestbook : Post a New Entry 5 | 6 | 7 | 8 | 9 |

Post

10 | 11 | <% using(Html.BeginForm()) { %> 12 |
13 | 14 | <%= Html.EditorFor(x => x.Author) %> 15 |
16 |
17 | 18 | <%= Html.EditorFor(x => x.Comment) %> 19 |
20 | 21 | <% } %> 22 | 23 |
-------------------------------------------------------------------------------- /Guestbook/Controllers/GuestbookController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Web; 5 | using System.Web.Mvc; 6 | using Guestbook.Domain.Entities; 7 | using Guestbook.Domain.Repositories; 8 | 9 | namespace Guestbook.Controllers 10 | { 11 | public class GuestbookController : Controller 12 | { 13 | private readonly IGuestbookEntryRepository _repository = IoC.CurrentGuestbookEntryRepository; 14 | 15 | public ActionResult Index() 16 | { 17 | return View(_repository.Entries.OrderByDescending(x => x.PostedDate)); 18 | } 19 | 20 | public ActionResult Post() 21 | { 22 | return View(); 23 | } 24 | 25 | [HttpPost] 26 | public ActionResult Post(GuestbookEntry entry) 27 | { 28 | TempData["message"] = "Thanks for posting!"; 29 | _repository.AddEntry(entry); 30 | return RedirectToAction("Index"); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Guestbook.Domain/Repositories/GuestbookEntryRepository.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using Guestbook.Domain.Entities; 5 | 6 | namespace Guestbook.Domain.Repositories 7 | { 8 | public class GuestbookEntryRepository : IGuestbookEntryRepository 9 | { 10 | private readonly List _entries = new List { 11 | new GuestbookEntry { GuestbookEntryId = 1, Author = "Steve", PostedDate = DateTime.Now, Comment = "I like this" }, 12 | new GuestbookEntry { GuestbookEntryId = 2, Author = "Bert", PostedDate = DateTime.Now, Comment = "I don't like it" }, 13 | }; 14 | 15 | public IQueryable Entries { 16 | get { 17 | return _entries.AsQueryable(); 18 | } 19 | } 20 | 21 | public void AddEntry(GuestbookEntry entry) 22 | { 23 | entry.PostedDate = DateTime.Now; 24 | _entries.Add(entry); 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /Guestbook.Spec/Steps/Infrastructure/SerializableTable.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using TechTalk.SpecFlow; 5 | 6 | namespace Guestbook.Spec.Steps.Infrastructure 7 | { 8 | /// 9 | /// Just a way of sending a TechTalk.SpecFlow.Table's contents across a remoting boundary 10 | /// 11 | [Serializable] 12 | public class SerializableTable 13 | { 14 | private readonly List _header; 15 | private readonly List> _rows; 16 | 17 | public SerializableTable(Table table) 18 | { 19 | _header = table.Header.ToList(); 20 | _rows = (from row in table.Rows 21 | select _header.ToDictionary(key => key, key => row[key])).ToList(); 22 | } 23 | 24 | public IList Header { get { return _header.AsReadOnly(); } } 25 | public IList> Rows { get { return _rows.Select(x => new Dictionary(x)).ToList(); } } 26 | } 27 | } -------------------------------------------------------------------------------- /Guestbook/Global.asax.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Web; 5 | using System.Web.Mvc; 6 | using System.Web.Routing; 7 | 8 | namespace Guestbook 9 | { 10 | // Note: For instructions on enabling IIS6 or IIS7 classic mode, 11 | // visit http://go.microsoft.com/?LinkId=9394801 12 | 13 | public class MvcApplication : System.Web.HttpApplication 14 | { 15 | public static void RegisterRoutes(RouteCollection routes) 16 | { 17 | routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); 18 | 19 | routes.MapRoute( 20 | "Default", // Route name 21 | "{controller}/{action}/{id}", // URL with parameters 22 | new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults 23 | ); 24 | 25 | } 26 | 27 | protected void Application_Start() 28 | { 29 | AreaRegistration.RegisterAllAreas(); 30 | 31 | RegisterRoutes(RouteTable.Routes); 32 | } 33 | } 34 | } -------------------------------------------------------------------------------- /Guestbook/Views/Guestbook/Index.aspx: -------------------------------------------------------------------------------- 1 | <%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage>" %> 2 | 3 | 4 | Guestbook 5 | 6 | 7 | 8 | 9 |

Guestbook

10 | 11 | Here are the current entries: 12 | 13 |
    14 | <% foreach (var entry in Model) { %> 15 |
  • 16 | <%= Html.Encode(entry.Author) %> 17 | posted at 18 | <%= Html.Encode(entry.PostedDate) %> 19 |
    <%= Html.Encode(entry.Comment) %>
    20 |
  • 21 | <% } %> 22 |
23 | 24 | 27 |
28 | -------------------------------------------------------------------------------- /Guestbook.Spec/Features/Posting.feature: -------------------------------------------------------------------------------- 1 | Feature: Posting 2 | In order to express my views 3 | As a user 4 | I want to be able to post entries into the guestbook 5 | 6 | Scenario: Navigation to posting page 7 | Given I am on the guestbook page 8 | Then I should see a button labelled "Post a New Entry" 9 | When I click the button labelled "Post a New Entry" 10 | Then I am on the posting page 11 | 12 | Scenario: Viewing the posting page 13 | Given I am on the posting page 14 | Then I should see a field labelled "Your name" 15 | And I should see a field labelled "Your comment" 16 | 17 | Scenario: Posting a valid entry 18 | Given I am on the posting page 19 | And I have filled out the form as follows 20 | | Label | Value | 21 | | Your name | Jakob | 22 | | Your comment | Das ist gut! | 23 | When I click the button labelled "Post" 24 | Then I should be on the guestbook page 25 | And I see the flash message "Thanks for posting!" 26 | And the guestbook entries includes the following 27 | | Name | Comment | Posted date | 28 | | Jakob | Das ist gut! | (within last minute) | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /Guestbook.Spec/Features/Browsing.feature: -------------------------------------------------------------------------------- 1 | Feature: Browsing 2 | In order to see who's been on the site 3 | As a user 4 | I want to be able to view the list of posts 5 | 6 | Scenario: Navigation to homepage 7 | When I navigate to /Guestbook 8 | Then I should be on the guestbook page 9 | 10 | Scenario: Viewing existing entries 11 | Given I am on the guestbook page 12 | Then I should see a list of guestbook entries 13 | And guestbook entries have an author 14 | And guestbook entries have a posted date 15 | And guestbook entries have a comment 16 | 17 | Scenario: Most recent entries are displayed first 18 | Given we have the following existing entries 19 | | Name | Comment | Posted date | 20 | | Mr. A | I like A | 2008-10-01 09:20 | 21 | | Mrs. B | I like B | 2010-03-05 02:15 | 22 | | Dr. C | I like C | 2010-02-20 12:21 | 23 | And I am on the guestbook page 24 | Then the guestbook entries includes the following, in this order 25 | | Name | Comment | Posted date | 26 | | Mrs. B | I like B | 2010-03-05 02:15 | 27 | | Dr. C | I like C | 2010-02-20 12:21 | 28 | | Mr. A | I like A | 2008-10-01 09:20 | 29 | -------------------------------------------------------------------------------- /Guestbook.Spec/PageWrappers/GuestbookEntriesList.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using Guestbook.Spec.Steps.Infrastructure; 6 | using WatiN.Core; 7 | 8 | namespace Guestbook.Spec.PageWrappers 9 | { 10 | class GuestbookEntriesList 11 | { 12 | public static IEnumerable DisplayedEntries 13 | { 14 | get 15 | { 16 | var entriesContainer = (IElementContainer)WebBrowser.Current.Element("entries"); 17 | return from li in entriesContainer.ElementsWithTag("li") 18 | select new Entry { Container = li as IElementContainer }; 19 | } 20 | } 21 | 22 | public class Entry 23 | { 24 | public IElementContainer Container { get; internal set; } 25 | 26 | public string Author { get { return this["author"]; } } 27 | public string PostedDate { get { return this["postedDate"]; } } 28 | public string Comment { get { return this["comment"]; } } 29 | 30 | public string this[string key] 31 | { 32 | get { return Container.Element(Find.ByClass(key)).Text; } 33 | } 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /Guestbook/Web.Debug.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 17 | 18 | 29 | 30 | -------------------------------------------------------------------------------- /Guestbook/Web.Release.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 17 | 18 | 19 | 30 | 31 | -------------------------------------------------------------------------------- /Guestbook/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("Guestbook")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("Microsoft")] 12 | [assembly: AssemblyProduct("Guestbook")] 13 | [assembly: AssemblyCopyright("Copyright © Microsoft 2010")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("cb9ac2c1-6fd1-4699-b1ed-daeb38b63250")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Revision and Build Numbers 33 | // by using the '*' as shown below: 34 | [assembly: AssemblyVersion("1.0.0.0")] 35 | [assembly: AssemblyFileVersion("1.0.0.0")] 36 | -------------------------------------------------------------------------------- /Guestbook.Spec/Steps/MockData.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using DeleporterCore.Client; 4 | using Guestbook.Domain.Entities; 5 | using Guestbook.Domain.Repositories; 6 | using Guestbook.Spec.Steps.Infrastructure; 7 | using Moq; 8 | using TechTalk.SpecFlow; 9 | 10 | namespace Guestbook.Spec.Steps 11 | { 12 | [Binding] 13 | public class MockData 14 | { 15 | [Given(@"we have the following existing entries")] 16 | public void GivenWeHaveTheFollowingExistingEntries(Table table) 17 | { 18 | var tableSerialized = new SerializableTable(table); 19 | 20 | Deleporter.Run(() => 21 | { 22 | var originalRepository = IoC.CurrentGuestbookEntryRepository; 23 | TidyUp.AddTask(() => { IoC.CurrentGuestbookEntryRepository = originalRepository; }); 24 | 25 | var mockRepository = new Mock(); 26 | mockRepository.Setup(x => x.Entries) 27 | .Returns((from row in tableSerialized.Rows 28 | select new GuestbookEntry 29 | { 30 | Author = row["Name"], 31 | Comment = row["Comment"], 32 | PostedDate = Convert.ToDateTime(row["Posted date"]) 33 | }).AsQueryable()); 34 | 35 | IoC.CurrentGuestbookEntryRepository = mockRepository.Object; 36 | }); 37 | } 38 | } 39 | } -------------------------------------------------------------------------------- /Guestbook.Spec/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("Guestbook.Spec")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("Microsoft")] 12 | [assembly: AssemblyProduct("Guestbook.Spec")] 13 | [assembly: AssemblyCopyright("Copyright © Microsoft 2010")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("b330de00-896b-436c-a5e2-c7e93bff0879")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /Guestbook.Domain/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("Guestbook.Domain")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("Microsoft")] 12 | [assembly: AssemblyProduct("Guestbook.Domain")] 13 | [assembly: AssemblyCopyright("Copyright © Microsoft 2010")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("b0601292-7e38-4f87-aaca-3ee696d93f8c")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /Guestbook/Views/Web.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 16 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /Guestbook.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 10.00 3 | # Visual Studio 2008 4 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Guestbook.Domain", "Guestbook.Domain\Guestbook.Domain.csproj", "{D7CDFBBF-7F13-44E1-8C56-D8884AFEDB5F}" 5 | EndProject 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Guestbook.Spec", "Guestbook.Spec\Guestbook.Spec.csproj", "{B3DC5763-BF6F-4547-807E-B5470F342C28}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Guestbook", "Guestbook\Guestbook.csproj", "{A3B0F7DA-544C-4E7F-967C-9F2D2EAD78D0}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug|Any CPU = Debug|Any CPU 13 | Release|Any CPU = Release|Any CPU 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {D7CDFBBF-7F13-44E1-8C56-D8884AFEDB5F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 17 | {D7CDFBBF-7F13-44E1-8C56-D8884AFEDB5F}.Debug|Any CPU.Build.0 = Debug|Any CPU 18 | {D7CDFBBF-7F13-44E1-8C56-D8884AFEDB5F}.Release|Any CPU.ActiveCfg = Release|Any CPU 19 | {D7CDFBBF-7F13-44E1-8C56-D8884AFEDB5F}.Release|Any CPU.Build.0 = Release|Any CPU 20 | {B3DC5763-BF6F-4547-807E-B5470F342C28}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 21 | {B3DC5763-BF6F-4547-807E-B5470F342C28}.Debug|Any CPU.Build.0 = Debug|Any CPU 22 | {B3DC5763-BF6F-4547-807E-B5470F342C28}.Release|Any CPU.ActiveCfg = Release|Any CPU 23 | {B3DC5763-BF6F-4547-807E-B5470F342C28}.Release|Any CPU.Build.0 = Release|Any CPU 24 | {A3B0F7DA-544C-4E7F-967C-9F2D2EAD78D0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 25 | {A3B0F7DA-544C-4E7F-967C-9F2D2EAD78D0}.Debug|Any CPU.Build.0 = Debug|Any CPU 26 | {A3B0F7DA-544C-4E7F-967C-9F2D2EAD78D0}.Release|Any CPU.ActiveCfg = Release|Any CPU 27 | {A3B0F7DA-544C-4E7F-967C-9F2D2EAD78D0}.Release|Any CPU.Build.0 = Release|Any CPU 28 | EndGlobalSection 29 | GlobalSection(SolutionProperties) = preSolution 30 | HideSolutionNode = FALSE 31 | EndGlobalSection 32 | EndGlobal 33 | -------------------------------------------------------------------------------- /Guestbook-vs2010.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 11.00 3 | # Visual Studio 2010 4 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Guestbook", "Guestbook\Guestbook.csproj", "{A3B0F7DA-544C-4E7F-967C-9F2D2EAD78D0}" 5 | EndProject 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Guestbook.Spec", "Guestbook.Spec\Guestbook.Spec.csproj", "{B3DC5763-BF6F-4547-807E-B5470F342C28}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Guestbook.Domain", "Guestbook.Domain\Guestbook.Domain.csproj", "{D7CDFBBF-7F13-44E1-8C56-D8884AFEDB5F}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug|Any CPU = Debug|Any CPU 13 | Release|Any CPU = Release|Any CPU 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {A3B0F7DA-544C-4E7F-967C-9F2D2EAD78D0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 17 | {A3B0F7DA-544C-4E7F-967C-9F2D2EAD78D0}.Debug|Any CPU.Build.0 = Debug|Any CPU 18 | {A3B0F7DA-544C-4E7F-967C-9F2D2EAD78D0}.Release|Any CPU.ActiveCfg = Release|Any CPU 19 | {A3B0F7DA-544C-4E7F-967C-9F2D2EAD78D0}.Release|Any CPU.Build.0 = Release|Any CPU 20 | {B3DC5763-BF6F-4547-807E-B5470F342C28}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 21 | {B3DC5763-BF6F-4547-807E-B5470F342C28}.Debug|Any CPU.Build.0 = Debug|Any CPU 22 | {B3DC5763-BF6F-4547-807E-B5470F342C28}.Release|Any CPU.ActiveCfg = Release|Any CPU 23 | {B3DC5763-BF6F-4547-807E-B5470F342C28}.Release|Any CPU.Build.0 = Release|Any CPU 24 | {D7CDFBBF-7F13-44E1-8C56-D8884AFEDB5F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 25 | {D7CDFBBF-7F13-44E1-8C56-D8884AFEDB5F}.Debug|Any CPU.Build.0 = Debug|Any CPU 26 | {D7CDFBBF-7F13-44E1-8C56-D8884AFEDB5F}.Release|Any CPU.ActiveCfg = Release|Any CPU 27 | {D7CDFBBF-7F13-44E1-8C56-D8884AFEDB5F}.Release|Any CPU.Build.0 = Release|Any CPU 28 | EndGlobalSection 29 | GlobalSection(SolutionProperties) = preSolution 30 | HideSolutionNode = FALSE 31 | EndGlobalSection 32 | EndGlobal 33 | -------------------------------------------------------------------------------- /Guestbook.Domain/Guestbook.Domain.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Debug 5 | AnyCPU 6 | 9.0.30729 7 | 2.0 8 | {D7CDFBBF-7F13-44E1-8C56-D8884AFEDB5F} 9 | Library 10 | Properties 11 | Guestbook.Domain 12 | Guestbook.Domain 13 | v3.5 14 | 512 15 | 16 | 17 | 18 | true 19 | full 20 | false 21 | bin\Debug\ 22 | DEBUG;TRACE 23 | prompt 24 | 4 25 | 26 | 27 | pdbonly 28 | true 29 | bin\Release\ 30 | TRACE 31 | prompt 32 | 4 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 56 | -------------------------------------------------------------------------------- /Guestbook.Spec/Steps/Infrastructure/TidyUp.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Runtime.Remoting.Messaging; 4 | using DeleporterCore.Client; 5 | using TechTalk.SpecFlow; 6 | 7 | namespace Guestbook.Spec.Steps.Infrastructure 8 | { 9 | /// 10 | /// Store the actions in a dictionary keyed by a CallContext-specific Guid 11 | /// The test appdomain will set a new guid at the start of each scenario 12 | /// 13 | [Binding] 14 | public static class TidyUp 15 | { 16 | private const string CallContextKey = "__tidyUp_scenarioId"; 17 | private static readonly Dictionary> TaskStores = new Dictionary>(); 18 | private static Guid ScenarioGuid 19 | { 20 | get { return (Guid) CallContext.LogicalGetData(CallContextKey); } 21 | set { CallContext.LogicalSetData(CallContextKey, value);} 22 | } 23 | 24 | public static IEnumerable Tasks 25 | { 26 | get { 27 | if (!TaskStores.ContainsKey(ScenarioGuid)) 28 | TaskStores[ScenarioGuid] = new List(); 29 | return TaskStores[ScenarioGuid]; 30 | } 31 | } 32 | 33 | public static void AddTask(Action task) 34 | { 35 | ((List) Tasks).Add(task); 36 | } 37 | 38 | [BeforeScenario] 39 | public static void Prep() 40 | { 41 | ScenarioGuid = Guid.NewGuid(); 42 | AddTask(() => Deleporter.Run(PerformTidyUp)); 43 | } 44 | 45 | [AfterScenario] 46 | public static void PerformTidyUp() 47 | { 48 | try { 49 | var exceptions = new List(); 50 | foreach (var task in Tasks) { 51 | try { task(); } 52 | catch (Exception ex) { exceptions.Add(ex); } 53 | } 54 | if (exceptions.Count == 1) 55 | throw exceptions[0]; 56 | else if (exceptions.Count > 1) 57 | throw new MultiException(exceptions); 58 | } 59 | finally { 60 | TaskStores.Remove(ScenarioGuid); 61 | } 62 | } 63 | 64 | public class MultiException : Exception 65 | { 66 | protected IEnumerable InnerExceptions { get; private set; } 67 | 68 | public MultiException(IEnumerable exceptions) 69 | { 70 | InnerExceptions = exceptions; 71 | } 72 | } 73 | } 74 | } -------------------------------------------------------------------------------- /Guestbook.Spec/Steps/ViewingGuestbook.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using Guestbook.Spec.PageWrappers; 5 | using NUnit.Framework; 6 | using TechTalk.SpecFlow; 7 | 8 | namespace Guestbook.Spec.Steps 9 | { 10 | [Binding] 11 | public class ViewingGuestbook 12 | { 13 | [Then(@"I should see a list of guestbook entries")] 14 | public void ThenIShouldSeeAListOfGuestbookEntries() 15 | { 16 | Assert.IsTrue(GuestbookEntriesList.DisplayedEntries.Any()); 17 | } 18 | 19 | [Then(@"guestbook entries have an? (.*)")] 20 | public void ThenGuestbookEntriesHaveA(string propertyName) 21 | { 22 | var entries = GuestbookEntriesList.DisplayedEntries; 23 | switch (propertyName) 24 | { 25 | case "author": AssertNotAllAreEmpty(entries.Select(x => x.Author)); break; 26 | case "comment": AssertNotAllAreEmpty(entries.Select(x => x.Comment)); break; 27 | case "posted date": AssertNotAllAreEmpty(entries.Select(x => x.PostedDate)); break; 28 | default: throw new ArgumentException("Unknown property", "propertyName"); 29 | } 30 | } 31 | 32 | [Then(@"the guestbook entries includes the following(, in this order)?")] 33 | public void ThenTheGuestbookEntriesIncludesTheFollowing(string inThisOrder, Table table) 34 | { 35 | bool requiresExactOrder = !string.IsNullOrEmpty(inThisOrder); 36 | List entries = GuestbookEntriesList.DisplayedEntries.ToList(); 37 | 38 | Func equalityComparer = (entry, row) => { 39 | return (row["Name"] == entry.Author 40 | && row["Comment"] == entry.Comment 41 | && IsValidPostedDate(entry, row["Posted date"])); 42 | }; 43 | 44 | int lastMatchIndex = -1; 45 | foreach (var row in table.Rows) { 46 | lastMatchIndex = entries.FindIndex(requiresExactOrder ? lastMatchIndex + 1 : 0, entry => equalityComparer(entry, row)); 47 | if (lastMatchIndex < 0) 48 | Assert.Fail("No match for " + row); 49 | } 50 | } 51 | 52 | private static bool IsValidPostedDate(GuestbookEntriesList.Entry entry, string postedDateSpecifier) 53 | { 54 | switch (postedDateSpecifier) 55 | { 56 | case "(within last minute)": 57 | return DateTime.Now.Subtract(DateTime.Parse(entry.PostedDate)).TotalSeconds < 60; 58 | default: return Convert.ToDateTime(postedDateSpecifier) == Convert.ToDateTime(entry.PostedDate); 59 | } 60 | } 61 | 62 | private static void AssertNotAllAreEmpty(IEnumerable strings) 63 | { 64 | CollectionAssert.IsNotEmpty(strings.Where(x => !string.IsNullOrEmpty(x))); 65 | } 66 | } 67 | } -------------------------------------------------------------------------------- /Guestbook.Spec/Steps/Navigation.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Configuration; 3 | using TechTalk.SpecFlow; 4 | using Guestbook.Spec.Steps.Infrastructure; 5 | using NUnit.Framework; 6 | using WatiN.Core; 7 | 8 | namespace Guestbook.Spec.Steps 9 | { 10 | [Binding] 11 | class Navigation 12 | { 13 | [When(@"I navigate to (.*)")] 14 | public void WhenINavigateTo(string relativeUrl) 15 | { 16 | var rootUrl = new Uri(ConfigurationManager.AppSettings["RootUrl"]); 17 | var absoluteUrl = new Uri(rootUrl, relativeUrl); 18 | WebBrowser.Current.GoTo(absoluteUrl); 19 | } 20 | 21 | [Then(@"I should be on the guestbook page")] 22 | public void ThenIShouldBeOnTheGuestbookPage() 23 | { 24 | Assert.That(WebBrowser.Current.Title, Is.EqualTo("Guestbook")); 25 | } 26 | 27 | [Given(@"I am on the guestbook page")] 28 | public void GivenIAmOnTheGuestbookPage() 29 | { 30 | WhenINavigateTo("/Guestbook"); 31 | } 32 | 33 | [Then(@"I am on the posting page")] 34 | public void ThenIAmOnThePostingPage() 35 | { 36 | Assert.That(WebBrowser.Current.Title, Is.EqualTo("Guestbook : Post a New Entry")); 37 | } 38 | 39 | [Given(@"I am on the posting page")] 40 | public void GivenIAmOnThePostingPage() 41 | { 42 | GivenIAmOnTheGuestbookPage(); 43 | WhenIClickTheButtonLabelled("Post a New Entry"); 44 | } 45 | 46 | [Then(@"I should see a button labelled ""(.*)""")] 47 | public void ThenIShouldSeeAButtonLabelled(string label) 48 | { 49 | var matchingButtons = WebBrowser.Current.Buttons.Filter(Find.ByText(label)); 50 | Assert.That(matchingButtons.Count, Is.EqualTo(1)); 51 | } 52 | 53 | [When(@"I click the button labelled ""(.*)""")] 54 | public void WhenIClickTheButtonLabelled(string label) 55 | { 56 | WebBrowser.Current.Buttons.First(Find.ByText(label)).Click(); 57 | } 58 | 59 | [Then(@"I see the flash message ""(.*)""")] 60 | public void ThenISeeTheFlashMessage(string message) 61 | { 62 | var flashElement = WebBrowser.Current.Element("flashMessage"); 63 | Assert.That(flashElement.Text, Is.EqualTo(message)); 64 | } 65 | 66 | [Then(@"I should see a field labelled ""(.*)""")] 67 | public void ThenIShouldSeeAFieldLabelled(string label) 68 | { 69 | var matchingFields = WebBrowser.Current.TextFields.Filter(Find.ByLabelText(label+":")); 70 | Assert.That(matchingFields.Count, Is.EqualTo(1)); 71 | } 72 | 73 | [Given(@"I have filled out the form as follows")] 74 | public void GivenIHaveFilledOutTheFormAsFollows(TechTalk.SpecFlow.Table table) 75 | { 76 | foreach (var row in table.Rows) 77 | { 78 | var labelText = row["Label"] + ":"; 79 | var value = row["Value"]; 80 | WebBrowser.Current.TextFields.First(Find.ByLabelText(labelText)).TypeText(value); 81 | } 82 | } 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /Guestbook.Spec/Guestbook.Spec.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Debug 5 | AnyCPU 6 | 9.0.30729 7 | 2.0 8 | {B3DC5763-BF6F-4547-807E-B5470F342C28} 9 | Library 10 | Properties 11 | Guestbook.Spec 12 | Guestbook.Spec 13 | v3.5 14 | 512 15 | 16 | 17 | 18 | true 19 | full 20 | false 21 | bin\Debug\ 22 | DEBUG;TRACE 23 | prompt 24 | 4 25 | 26 | 27 | pdbonly 28 | true 29 | bin\Release\ 30 | TRACE 31 | prompt 32 | 4 33 | 34 | 35 | 36 | External Assemblies\Deleporter.dll 37 | 38 | 39 | External Assemblies\Interop.SHDocVw.dll 40 | False 41 | 42 | 43 | External Assemblies\Moq.dll 44 | 45 | 46 | False 47 | ..\..\..\..\..\..\..\Program Files (x86)\NUnit 2.5.3\bin\net-2.0\framework\nunit.framework.dll 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | False 59 | External Assemblies\TechTalk.SpecFlow.dll 60 | 61 | 62 | External Assemblies\WatiN.Core.dll 63 | False 64 | 65 | 66 | 67 | 68 | True 69 | True 70 | Browsing.feature 71 | 72 | 73 | True 74 | True 75 | Posting.feature 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | SpecFlowSingleFileGenerator 90 | Browsing.feature.cs 91 | 92 | 93 | SpecFlowSingleFileGenerator 94 | Posting.feature.cs 95 | 96 | 97 | 98 | 99 | {D7CDFBBF-7F13-44E1-8C56-D8884AFEDB5F} 100 | Guestbook.Domain 101 | 102 | 103 | {A3B0F7DA-544C-4E7F-967C-9F2D2EAD78D0} 104 | Guestbook 105 | 106 | 107 | 108 | 115 | -------------------------------------------------------------------------------- /Guestbook.Spec/Features/Posting.feature.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by SpecFlow (http://www.specflow.org/). 4 | // SpecFlow Version:1.2.0.0 5 | // Runtime Version:4.0.30128.1 6 | // 7 | // Changes to this file may cause incorrect behavior and will be lost if 8 | // the code is regenerated. 9 | // 10 | // ------------------------------------------------------------------------------ 11 | namespace Guestbook.Spec.Features 12 | { 13 | using TechTalk.SpecFlow; 14 | 15 | 16 | [NUnit.Framework.TestFixtureAttribute()] 17 | [NUnit.Framework.DescriptionAttribute("Posting")] 18 | public partial class PostingFeature 19 | { 20 | 21 | private static TechTalk.SpecFlow.ITestRunner testRunner; 22 | 23 | #line 1 "Posting.feature" 24 | #line hidden 25 | 26 | [NUnit.Framework.TestFixtureSetUpAttribute()] 27 | public virtual void FeatureSetup() 28 | { 29 | testRunner = TechTalk.SpecFlow.TestRunnerManager.GetTestRunner(); 30 | TechTalk.SpecFlow.FeatureInfo featureInfo = new TechTalk.SpecFlow.FeatureInfo(new System.Globalization.CultureInfo("en-US"), "Posting", "In order to express my views\r\nAs a user\r\nI want to be able to post entries into t" + 31 | "he guestbook", ((string[])(null))); 32 | testRunner.OnFeatureStart(featureInfo); 33 | } 34 | 35 | [NUnit.Framework.TestFixtureTearDownAttribute()] 36 | public virtual void FeatureTearDown() 37 | { 38 | testRunner.OnFeatureEnd(); 39 | testRunner = null; 40 | } 41 | 42 | public virtual void ScenarioSetup(TechTalk.SpecFlow.ScenarioInfo scenarioInfo) 43 | { 44 | testRunner.OnScenarioStart(scenarioInfo); 45 | } 46 | 47 | [NUnit.Framework.TearDownAttribute()] 48 | public virtual void ScenarioTearDown() 49 | { 50 | testRunner.OnScenarioEnd(); 51 | } 52 | 53 | [NUnit.Framework.TestAttribute()] 54 | [NUnit.Framework.DescriptionAttribute("Navigation to posting page")] 55 | public virtual void NavigationToPostingPage() 56 | { 57 | TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("Navigation to posting page", ((string[])(null))); 58 | #line 6 59 | this.ScenarioSetup(scenarioInfo); 60 | #line 7 61 | testRunner.Given("I am on the guestbook page"); 62 | #line 8 63 | testRunner.Then("I should see a button labelled \"Post a New Entry\""); 64 | #line 9 65 | testRunner.When("I click the button labelled \"Post a New Entry\""); 66 | #line 10 67 | testRunner.Then("I am on the posting page"); 68 | #line hidden 69 | testRunner.CollectScenarioErrors(); 70 | } 71 | 72 | [NUnit.Framework.TestAttribute()] 73 | [NUnit.Framework.DescriptionAttribute("Viewing the posting page")] 74 | public virtual void ViewingThePostingPage() 75 | { 76 | TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("Viewing the posting page", ((string[])(null))); 77 | #line 12 78 | this.ScenarioSetup(scenarioInfo); 79 | #line 13 80 | testRunner.Given("I am on the posting page"); 81 | #line 14 82 | testRunner.Then("I should see a field labelled \"Your name\""); 83 | #line 15 84 | testRunner.And("I should see a field labelled \"Your comment\""); 85 | #line hidden 86 | testRunner.CollectScenarioErrors(); 87 | } 88 | 89 | [NUnit.Framework.TestAttribute()] 90 | [NUnit.Framework.DescriptionAttribute("Posting a valid entry")] 91 | public virtual void PostingAValidEntry() 92 | { 93 | TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("Posting a valid entry", ((string[])(null))); 94 | #line 17 95 | this.ScenarioSetup(scenarioInfo); 96 | #line 18 97 | testRunner.Given("I am on the posting page"); 98 | #line hidden 99 | TechTalk.SpecFlow.Table table1 = new TechTalk.SpecFlow.Table(new string[] { 100 | "Label", 101 | "Value"}); 102 | table1.AddRow(new string[] { 103 | "Your name", 104 | "Jakob"}); 105 | table1.AddRow(new string[] { 106 | "Your comment", 107 | "Das ist gut!"}); 108 | #line 19 109 | testRunner.And("I have filled out the form as follows", ((string)(null)), table1); 110 | #line 23 111 | testRunner.When("I click the button labelled \"Post\""); 112 | #line 24 113 | testRunner.Then("I should be on the guestbook page"); 114 | #line 25 115 | testRunner.And("I see the flash message \"Thanks for posting!\""); 116 | #line hidden 117 | TechTalk.SpecFlow.Table table2 = new TechTalk.SpecFlow.Table(new string[] { 118 | "Name", 119 | "Comment", 120 | "Posted date"}); 121 | table2.AddRow(new string[] { 122 | "Jakob", 123 | "Das ist gut!", 124 | "(within last minute)"}); 125 | #line 26 126 | testRunner.And("the guestbook entries includes the following", ((string)(null)), table2); 127 | #line hidden 128 | testRunner.CollectScenarioErrors(); 129 | } 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /Guestbook/Guestbook.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Debug 5 | AnyCPU 6 | 9.0.30729 7 | 2.0 8 | {A3B0F7DA-544C-4E7F-967C-9F2D2EAD78D0} 9 | {F85E285D-A4E0-4152-9332-AB1D724D3325};{349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc} 10 | Library 11 | Properties 12 | Guestbook 13 | Guestbook 14 | v3.5 15 | false 16 | 17 | 18 | 19 | true 20 | full 21 | false 22 | bin\ 23 | DEBUG;TRACE 24 | prompt 25 | 4 26 | 27 | 28 | pdbonly 29 | true 30 | bin\ 31 | TRACE 32 | prompt 33 | 4 34 | 35 | 36 | 37 | ..\Guestbook.Spec\External Assemblies\Deleporter.dll 38 | 39 | 40 | 41 | 3.5 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 3.5 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | Global.asax 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | Web.config 78 | 79 | 80 | Web.config 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | {D7CDFBBF-7F13-44E1-8C56-D8884AFEDB5F} 91 | Guestbook.Domain 92 | 93 | 94 | 95 | 96 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | False 108 | False 109 | 8080 110 | / 111 | 112 | 113 | False 114 | False 115 | 116 | 117 | False 118 | 119 | 120 | 121 | 122 | -------------------------------------------------------------------------------- /Guestbook.Spec/Features/Browsing.feature.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by SpecFlow (http://www.specflow.org/). 4 | // SpecFlow Version:1.2.0.0 5 | // Runtime Version:4.0.30128.1 6 | // 7 | // Changes to this file may cause incorrect behavior and will be lost if 8 | // the code is regenerated. 9 | // 10 | // ------------------------------------------------------------------------------ 11 | namespace Guestbook.Spec.Features 12 | { 13 | using TechTalk.SpecFlow; 14 | 15 | 16 | [NUnit.Framework.TestFixtureAttribute()] 17 | [NUnit.Framework.DescriptionAttribute("Browsing")] 18 | public partial class BrowsingFeature 19 | { 20 | 21 | private static TechTalk.SpecFlow.ITestRunner testRunner; 22 | 23 | #line 1 "Browsing.feature" 24 | #line hidden 25 | 26 | [NUnit.Framework.TestFixtureSetUpAttribute()] 27 | public virtual void FeatureSetup() 28 | { 29 | testRunner = TechTalk.SpecFlow.TestRunnerManager.GetTestRunner(); 30 | TechTalk.SpecFlow.FeatureInfo featureInfo = new TechTalk.SpecFlow.FeatureInfo(new System.Globalization.CultureInfo("en-US"), "Browsing", "In order to see who\'s been on the site\r\nAs a user\r\nI want to be able to view the " + 31 | "list of posts", ((string[])(null))); 32 | testRunner.OnFeatureStart(featureInfo); 33 | } 34 | 35 | [NUnit.Framework.TestFixtureTearDownAttribute()] 36 | public virtual void FeatureTearDown() 37 | { 38 | testRunner.OnFeatureEnd(); 39 | testRunner = null; 40 | } 41 | 42 | public virtual void ScenarioSetup(TechTalk.SpecFlow.ScenarioInfo scenarioInfo) 43 | { 44 | testRunner.OnScenarioStart(scenarioInfo); 45 | } 46 | 47 | [NUnit.Framework.TearDownAttribute()] 48 | public virtual void ScenarioTearDown() 49 | { 50 | testRunner.OnScenarioEnd(); 51 | } 52 | 53 | [NUnit.Framework.TestAttribute()] 54 | [NUnit.Framework.DescriptionAttribute("Navigation to homepage")] 55 | public virtual void NavigationToHomepage() 56 | { 57 | TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("Navigation to homepage", ((string[])(null))); 58 | #line 6 59 | this.ScenarioSetup(scenarioInfo); 60 | #line 7 61 | testRunner.When("I navigate to /Guestbook"); 62 | #line 8 63 | testRunner.Then("I should be on the guestbook page"); 64 | #line hidden 65 | testRunner.CollectScenarioErrors(); 66 | } 67 | 68 | [NUnit.Framework.TestAttribute()] 69 | [NUnit.Framework.DescriptionAttribute("Viewing existing entries")] 70 | public virtual void ViewingExistingEntries() 71 | { 72 | TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("Viewing existing entries", ((string[])(null))); 73 | #line 10 74 | this.ScenarioSetup(scenarioInfo); 75 | #line 11 76 | testRunner.Given("I am on the guestbook page"); 77 | #line 12 78 | testRunner.Then("I should see a list of guestbook entries"); 79 | #line 13 80 | testRunner.And("guestbook entries have an author"); 81 | #line 14 82 | testRunner.And("guestbook entries have a posted date"); 83 | #line 15 84 | testRunner.And("guestbook entries have a comment"); 85 | #line hidden 86 | testRunner.CollectScenarioErrors(); 87 | } 88 | 89 | [NUnit.Framework.TestAttribute()] 90 | [NUnit.Framework.DescriptionAttribute("Most recent entries are displayed first")] 91 | public virtual void MostRecentEntriesAreDisplayedFirst() 92 | { 93 | TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("Most recent entries are displayed first", ((string[])(null))); 94 | #line 17 95 | this.ScenarioSetup(scenarioInfo); 96 | #line hidden 97 | TechTalk.SpecFlow.Table table1 = new TechTalk.SpecFlow.Table(new string[] { 98 | "Name", 99 | "Comment", 100 | "Posted date"}); 101 | table1.AddRow(new string[] { 102 | "Mr. A", 103 | "I like A", 104 | "2008-10-01 09:20"}); 105 | table1.AddRow(new string[] { 106 | "Mrs. B", 107 | "I like B", 108 | "2010-03-05 02:15"}); 109 | table1.AddRow(new string[] { 110 | "Dr. C", 111 | "I like C", 112 | "2010-02-20 12:21"}); 113 | #line 18 114 | testRunner.Given("we have the following existing entries", ((string)(null)), table1); 115 | #line 23 116 | testRunner.And("I am on the guestbook page"); 117 | #line hidden 118 | TechTalk.SpecFlow.Table table2 = new TechTalk.SpecFlow.Table(new string[] { 119 | "Name", 120 | "Comment", 121 | "Posted date"}); 122 | table2.AddRow(new string[] { 123 | "Mrs. B", 124 | "I like B", 125 | "2010-03-05 02:15"}); 126 | table2.AddRow(new string[] { 127 | "Dr. C", 128 | "I like C", 129 | "2010-02-20 12:21"}); 130 | table2.AddRow(new string[] { 131 | "Mr. A", 132 | "I like A", 133 | "2008-10-01 09:20"}); 134 | #line 24 135 | testRunner.Then("the guestbook entries includes the following, in this order", ((string)(null)), table2); 136 | #line hidden 137 | testRunner.CollectScenarioErrors(); 138 | } 139 | } 140 | } 141 | -------------------------------------------------------------------------------- /Guestbook/Web.config: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 |
11 | 12 |
13 |
14 |
15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | --------------------------------------------------------------------------------