Skip to content
This repository has been archived by the owner on Sep 19, 2019. It is now read-only.

Rob Haden's Work for the TNTP Coding Exercise #10

Open
wants to merge 17 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Tntp.Solution exclusions - .vs, packages, bin, and obj directories; .dbmdl, .jfm, and .user files
Tntp.Solution/.vs/
Tntp.Solution/packages/
Tntp.Solution/Tntp.Database/bin/
Tntp.Solution/Tntp.Database/obj/
Tntp.Solution/Tntp.Database/Tntp.Database.dbmdl
Tntp.Solution/Tntp.Database/Tntp.Database.jfm
Tntp.Solution/Tntp.Database/Tntp.Database.sqlproj.user
Tntp.Solution/Tntp.WebApplication/bin/
Tntp.Solution/Tntp.WebApplication/obj/
Tntp.Solution/Tntp.WebApplication/Tntp.WebApplication.csproj.user
Tntp.Solution/Tntp.WebApplication.Tests/bin/
Tntp.Solution/Tntp.WebApplication.Tests/obj/
11 changes: 11 additions & 0 deletions Tntp.Solution/Tntp.Database/Comments.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
CREATE TABLE [dbo].[Comments]
(
[Id] INT NOT NULL PRIMARY KEY IDENTITY,
[Username] NVARCHAR(15) NOT NULL,
[Content] NVARCHAR(140) NOT NULL,
[CreationTimestamp] DATETIME2 NOT NULL DEFAULT sysdatetime()
)

GO

CREATE INDEX [IX_Comments_CreationTimestamp] ON [dbo].[Comments] ([CreationTimestamp] DESC)
64 changes: 64 additions & 0 deletions Tntp.Solution/Tntp.Database/Tntp.Database.sqlproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<Name>Tntp.Database</Name>
<SchemaVersion>2.0</SchemaVersion>
<ProjectVersion>4.1</ProjectVersion>
<ProjectGuid>{ee3ce98d-6e0d-4b23-b524-763b5b65ba47}</ProjectGuid>
<DSP>Microsoft.Data.Tools.Schema.Sql.Sql130DatabaseSchemaProvider</DSP>
<OutputType>Database</OutputType>
<RootPath>
</RootPath>
<RootNamespace>Tntp.Database</RootNamespace>
<AssemblyName>Tntp.Database</AssemblyName>
<ModelCollation>1033, CI</ModelCollation>
<DefaultFileStructure>BySchemaAndSchemaType</DefaultFileStructure>
<DeployToDatabase>True</DeployToDatabase>
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
<TargetLanguage>CS</TargetLanguage>
<AppDesignerFolder>Properties</AppDesignerFolder>
<SqlServerVerification>False</SqlServerVerification>
<IncludeCompositeObjects>True</IncludeCompositeObjects>
<TargetDatabaseSet>True</TargetDatabaseSet>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<OutputPath>bin\Release\</OutputPath>
<BuildScriptName>$(MSBuildProjectName).sql</BuildScriptName>
<TreatWarningsAsErrors>False</TreatWarningsAsErrors>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<DefineDebug>false</DefineDebug>
<DefineTrace>true</DefineTrace>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<OutputPath>bin\Debug\</OutputPath>
<BuildScriptName>$(MSBuildProjectName).sql</BuildScriptName>
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<DefineDebug>true</DefineDebug>
<DefineTrace>true</DefineTrace>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">11.0</VisualStudioVersion>
<!-- Default to the v11.0 targets path if the targets file for the current VS version is not found -->
<SSDTExists Condition="Exists('$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v$(VisualStudioVersion)\SSDT\Microsoft.Data.Tools.Schema.SqlTasks.targets')">True</SSDTExists>
<VisualStudioVersion Condition="'$(SSDTExists)' == ''">11.0</VisualStudioVersion>
</PropertyGroup>
<Import Condition="'$(SQLDBExtensionsRefPath)' != ''" Project="$(SQLDBExtensionsRefPath)\Microsoft.Data.Tools.Schema.SqlTasks.targets" />
<Import Condition="'$(SQLDBExtensionsRefPath)' == ''" Project="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v$(VisualStudioVersion)\SSDT\Microsoft.Data.Tools.Schema.SqlTasks.targets" />
<ItemGroup>
<Folder Include="Properties" />
</ItemGroup>
<ItemGroup>
<Build Include="Comments.sql" />
</ItemGroup>
</Project>
36 changes: 36 additions & 0 deletions Tntp.Solution/Tntp.Solution.sln
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14
VisualStudioVersion = 14.0.25420.1
MinimumVisualStudioVersion = 10.0.40219.1
Project("{00D1A9C2-B5F0-4AF3-8072-F6C62B433612}") = "Tntp.Database", "Tntp.Database\Tntp.Database.sqlproj", "{EE3CE98D-6E0D-4B23-B524-763B5B65BA47}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tntp.WebApplication", "Tntp.WebApplication\Tntp.WebApplication.csproj", "{A5487DA2-BDEB-4DF3-99BB-E983BCBB66CA}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tntp.WebApplication.Tests", "Tntp.WebApplication.Tests\Tntp.WebApplication.Tests.csproj", "{42453A53-3307-432C-8ACA-04940576906B}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{EE3CE98D-6E0D-4B23-B524-763B5B65BA47}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{EE3CE98D-6E0D-4B23-B524-763B5B65BA47}.Debug|Any CPU.Build.0 = Debug|Any CPU
{EE3CE98D-6E0D-4B23-B524-763B5B65BA47}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
{EE3CE98D-6E0D-4B23-B524-763B5B65BA47}.Release|Any CPU.ActiveCfg = Release|Any CPU
{EE3CE98D-6E0D-4B23-B524-763B5B65BA47}.Release|Any CPU.Build.0 = Release|Any CPU
{EE3CE98D-6E0D-4B23-B524-763B5B65BA47}.Release|Any CPU.Deploy.0 = Release|Any CPU
{A5487DA2-BDEB-4DF3-99BB-E983BCBB66CA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A5487DA2-BDEB-4DF3-99BB-E983BCBB66CA}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A5487DA2-BDEB-4DF3-99BB-E983BCBB66CA}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A5487DA2-BDEB-4DF3-99BB-E983BCBB66CA}.Release|Any CPU.Build.0 = Release|Any CPU
{42453A53-3307-432C-8ACA-04940576906B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{42453A53-3307-432C-8ACA-04940576906B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{42453A53-3307-432C-8ACA-04940576906B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{42453A53-3307-432C-8ACA-04940576906B}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
101 changes: 101 additions & 0 deletions Tntp.Solution/Tntp.WebApplication.Tests/CommentsControllerTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
using System;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using System.Web.Http.Results;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Tntp.WebApplication.Controllers;
using Tntp.WebApplication.Models;

namespace Tntp.WebApplication.Tests
{
[TestClass]
public class CommentsControllerTests
{
private readonly IRepository _repository = new MockRepository();
private readonly CommentsController _controller;

public CommentsControllerTests()
{
_repository.Comments.Add(new Comment { Username = "Eddard", Content = "Stark", CreationTimestamp = DateTime.Now.AddDays(-1) });
_repository.Comments.Add(new Comment { Username = "Jon", Content = "Snow", CreationTimestamp = DateTime.Now });

_controller = new CommentsController(_repository, new MockWebSocketHub());
_controller.Request = new HttpRequestMessage();
_controller.Configuration = new HttpConfiguration();
}

[TestMethod]
public void GetCommentsTest()
{
var results = _controller.GetComments();
Assert.AreEqual("Jon", results.ElementAt(0).Username);
Assert.AreEqual("Snow", results.ElementAt(0).Content);
Assert.AreEqual("Eddard", results.ElementAt(1).Username);
Assert.AreEqual("Stark", results.ElementAt(1).Content);
}

[TestMethod]
public void AddCommentTest_NullUsername()
{
var result = _controller.AddComment(new Comment { Content = "Seaworth" }) as BadRequestErrorMessageResult;
Assert.IsNotNull(result);
Assert.AreEqual("A username is required.", result.Message);
}

[TestMethod]
public void AddCommentTest_EmptyUsername()
{
var result = _controller.AddComment(new Comment { Username = "", Content = "Seaworth" }) as BadRequestErrorMessageResult;
Assert.IsNotNull(result);
Assert.AreEqual("A username is required.", result.Message);
}

[TestMethod]
public void AddCommentTest_TooLongUsername()
{
var result = _controller.AddComment(new Comment { Username = "Stannnnnnnnnnnis", Content = "Baratheon" }) as BadRequestErrorMessageResult;
Assert.IsNotNull(result);
Assert.AreEqual("A username must not exceed 15 characters.", result.Message);
}

[TestMethod]
public void AddCommentTest_NullContent()
{
var result = _controller.AddComment(new Comment { Username = "Davos" }) as BadRequestErrorMessageResult;
Assert.IsNotNull(result);
Assert.AreEqual("A comment is required.", result.Message);
}

[TestMethod]
public void AddCommentTest_EmptyContent()
{
var result = _controller.AddComment(new Comment { Username = "Davos", Content = "" }) as BadRequestErrorMessageResult;
Assert.IsNotNull(result);
Assert.AreEqual("A comment is required.", result.Message);
}

[TestMethod]
public void AddCommentTest_TooLongContent()
{
var result = _controller.AddComment(new Comment
{
Username = "Hodor",
Content = "Hodor hodor hodor hodor hodor hodor hodor hodor hodor hodor hodor hodor hodor hodor hodor hodor hodor hodor hodor hodor hodor hodor hodor hodor hodor"
}) as BadRequestErrorMessageResult;

Assert.IsNotNull(result);
Assert.AreEqual("A comment must not exceed 140 characters.", result.Message);
}

[TestMethod]
public void AddCommentTest_Successful()
{
var result = _controller.AddComment(new Comment { Username = "Davos", Content = "Seaworth" }) as StatusCodeResult;
Assert.IsNotNull(result);
Assert.AreEqual(HttpStatusCode.OK, result.StatusCode);
Assert.AreEqual(3, _repository.Comments.Count());
}
}
}
76 changes: 76 additions & 0 deletions Tntp.Solution/Tntp.WebApplication.Tests/MockDbSet.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Data.Entity;
using System.Linq;
using System.Linq.Expressions;

namespace Tntp.WebApplication.Tests
{
public class MockDbSet<T> : IDbSet<T> where T : class
{
private readonly List<T> _entities = new List<T>();

public Type ElementType
{
get { return typeof(T); }
}

public Expression Expression
{
get { return _entities.AsQueryable().Expression; }
}

public ObservableCollection<T> Local
{
get { throw new NotImplementedException(); }
}

public IQueryProvider Provider
{
get { return _entities.AsQueryable().Provider; }
}

public T Add(T entity)
{
_entities.Add(entity);
return entity;
}

public T Attach(T entity)
{
throw new NotImplementedException();
}

public T Create()
{
throw new NotImplementedException();
}

public TDerivedEntity Create<TDerivedEntity>() where TDerivedEntity : class, T
{
throw new NotImplementedException();
}

public T Find(params object[] keyValues)
{
throw new NotImplementedException();
}

public IEnumerator<T> GetEnumerator()
{
return _entities.GetEnumerator();
}

public T Remove(T entity)
{
throw new NotImplementedException();
}

IEnumerator IEnumerable.GetEnumerator()
{
return _entities.GetEnumerator();
}
}
}
19 changes: 19 additions & 0 deletions Tntp.Solution/Tntp.WebApplication.Tests/MockRepository.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
using System.Data.Entity;
using Tntp.WebApplication.Models;

namespace Tntp.WebApplication.Tests
{
public class MockRepository : IRepository
{
private readonly IDbSet<Comment> _comments = new MockDbSet<Comment>();

public IDbSet<Comment> Comments
{
get { return _comments; }
}

public void SaveChanges() { }

public void Dispose() { }
}
}
11 changes: 11 additions & 0 deletions Tntp.Solution/Tntp.WebApplication.Tests/MockWebSocketHandler.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
using Microsoft.Web.WebSockets;

namespace Tntp.WebApplication.Tests
{
public class MockWebSocketHandler : WebSocketHandler
{
public override void OnOpen() { }
public override void OnMessage(string message) { }
public override void OnClose() { }
}
}
16 changes: 16 additions & 0 deletions Tntp.Solution/Tntp.WebApplication.Tests/MockWebSocketHub.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
using Microsoft.Web.WebSockets;
using Tntp.WebApplication.Controllers;

namespace Tntp.WebApplication.Tests
{
public class MockWebSocketHub : IWebSocketHub
{
public void AddHandler(WebSocketHandler handler) { }

public void Broadcast(string message) { }

public void CreateHandler() { }

public void RemoveHandler(WebSocketHandler handler) { }
}
}
36 changes: 36 additions & 0 deletions Tntp.Solution/Tntp.WebApplication.Tests/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;

// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("Tntp.WebApplication.Tests")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Tntp.WebApplication.Tests")]
[assembly: AssemblyCopyright("Copyright © 2018")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]

// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]

// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("42453a53-3307-432c-8aca-04940576906b")]

// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
Loading