From 03da654d354f10015246df7f7ab2aa61b7816b68 Mon Sep 17 00:00:00 2001 From: Steve Gordon Date: Tue, 2 Jan 2018 16:36:45 +0000 Subject: [PATCH 1/5] Fixes hard coded dates which break since we are now in 2018! --- .../FeaturedCampaignQueryHandlerShould.cs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/AllReadyApp/Web-App/AllReady.UnitTest/Features/Campaigns/FeaturedCampaignQueryHandlerShould.cs b/AllReadyApp/Web-App/AllReady.UnitTest/Features/Campaigns/FeaturedCampaignQueryHandlerShould.cs index 55b3f5ddc..bd8c2f96a 100644 --- a/AllReadyApp/Web-App/AllReady.UnitTest/Features/Campaigns/FeaturedCampaignQueryHandlerShould.cs +++ b/AllReadyApp/Web-App/AllReady.UnitTest/Features/Campaigns/FeaturedCampaignQueryHandlerShould.cs @@ -1,4 +1,4 @@ -using System; +using System; using AllReady.Features.Campaigns; using System.Linq; using System.Threading.Tasks; @@ -15,7 +15,7 @@ public async Task ReturnASingleCampaignThatIsFeaturedAndHasNotEnded() // Arrange var handler = new FeaturedCampaignQueryHandler(Context) { - DateTimeOffsetUtcNow = () => new DateTime(2017, 01, 07) + DateTimeOffsetUtcNow = () => DateTime.Now }; // Act @@ -105,7 +105,7 @@ protected override void LoadTestData() Featured = true, ManagingOrganization = org, Published = true, - EndDateTime = new DateTime(2012, 1, 1) + EndDateTime = DateTime.Now.AddDays(-10) }); Context.Campaigns.Add(new Campaign @@ -115,7 +115,7 @@ protected override void LoadTestData() Featured = true, ManagingOrganization = org, Published = true, - EndDateTime = new DateTime(2018, 1, 1) + EndDateTime = DateTime.Now.AddDays(90) // future date }); Context.Campaigns.Add(new Campaign @@ -125,7 +125,7 @@ protected override void LoadTestData() Featured = false, ManagingOrganization = org, Published = true, - EndDateTime = new DateTime(2018, 1, 1) + EndDateTime = DateTime.Now.AddDays(90) // future date }); Context.Campaigns.Add(new Campaign @@ -135,10 +135,10 @@ protected override void LoadTestData() Featured = true, ManagingOrganization = org, Published = true, - EndDateTime = new DateTime(2018, 1, 1) + EndDateTime = DateTime.Now.AddDays(90) // future date }); Context.SaveChanges(); } } -} \ No newline at end of file +} From e54ce626824f1db926e69dd080716260e6e11e62 Mon Sep 17 00:00:00 2001 From: Steve Gordon Date: Mon, 11 Dec 2017 12:57:54 +0000 Subject: [PATCH 2/5] Adding framework for integration tests using TestServer --- .../AllReady.IntegrationTests.csproj | 23 ++++++ .../AllReady.IntegrationTests/IndexTests.cs | 27 +++++++ .../AllReady.IntegrationTests/TestFixture.cs | 79 +++++++++++++++++++ AllReadyApp/AllReadyWebOnly.sln | 15 +++- .../AllReady/IntegrationTestStartup.cs | 47 +++++++++++ AllReadyApp/Web-App/AllReady/Startup.cs | 66 +++++++++++----- 6 files changed, 234 insertions(+), 23 deletions(-) create mode 100644 AllReadyApp/AllReady.IntegrationTests/AllReady.IntegrationTests.csproj create mode 100644 AllReadyApp/AllReady.IntegrationTests/IndexTests.cs create mode 100644 AllReadyApp/AllReady.IntegrationTests/TestFixture.cs create mode 100644 AllReadyApp/Web-App/AllReady/IntegrationTestStartup.cs diff --git a/AllReadyApp/AllReady.IntegrationTests/AllReady.IntegrationTests.csproj b/AllReadyApp/AllReady.IntegrationTests/AllReady.IntegrationTests.csproj new file mode 100644 index 000000000..6f323cdb9 --- /dev/null +++ b/AllReadyApp/AllReady.IntegrationTests/AllReady.IntegrationTests.csproj @@ -0,0 +1,23 @@ + + + + + + netcoreapp2.0 + false + + + + + + + + + + + + + + + + diff --git a/AllReadyApp/AllReady.IntegrationTests/IndexTests.cs b/AllReadyApp/AllReady.IntegrationTests/IndexTests.cs new file mode 100644 index 000000000..43775c2d9 --- /dev/null +++ b/AllReadyApp/AllReady.IntegrationTests/IndexTests.cs @@ -0,0 +1,27 @@ +using System.Net; +using System.Net.Http; +using System.Threading.Tasks; +using Xunit; + +namespace AllReady.IntegrationTests +{ + public class IndexTests : IClassFixture> + { + private readonly HttpClient _client; + + public IndexTests(TestFixture fixture) + { + _client = fixture.Client; + } + + [Fact] + public async Task CanGetHomePage() + { + // Act + var response = await _client.GetAsync("/"); + + // Assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + } + } +} diff --git a/AllReadyApp/AllReady.IntegrationTests/TestFixture.cs b/AllReadyApp/AllReady.IntegrationTests/TestFixture.cs new file mode 100644 index 000000000..41c495608 --- /dev/null +++ b/AllReadyApp/AllReady.IntegrationTests/TestFixture.cs @@ -0,0 +1,79 @@ +using System; +using System.IO; +using System.Net.Http; +using System.Reflection; +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Mvc.ApplicationParts; +using Microsoft.AspNetCore.Mvc.Controllers; +using Microsoft.AspNetCore.Mvc.ViewComponents; +using Microsoft.AspNetCore.TestHost; +using Microsoft.Extensions.DependencyInjection; + +namespace AllReady.IntegrationTests +{ + // A test fixture which hosts the target project (project we wish to test) in an in-memory server. + public class TestFixture : IDisposable + { + private readonly TestServer _server; + + public TestFixture() + { + var startupAssembly = typeof(TStartup).GetTypeInfo().Assembly; + var contentRoot = GetProjectPath(startupAssembly); + + var builder = new WebHostBuilder() + .UseContentRoot(contentRoot) + .ConfigureServices(InitializeServices) + .UseEnvironment("Development") + .UseStartup(typeof(TStartup)); + + _server = new TestServer(builder); + + Client = _server.CreateClient(); + Client.BaseAddress = new Uri("http://localhost"); + } + + public HttpClient Client { get; } + + public void Dispose() + { + Client.Dispose(); + _server.Dispose(); + } + + protected virtual void InitializeServices(IServiceCollection services) + { + var startupAssembly = typeof(TStartup).GetTypeInfo().Assembly; + var manager = new ApplicationPartManager(); + manager.ApplicationParts.Add(new AssemblyPart(startupAssembly)); + manager.FeatureProviders.Add(new ControllerFeatureProvider()); + manager.FeatureProviders.Add(new ViewComponentFeatureProvider()); + services.AddSingleton(manager); + } + + // Get the full path to the target project for testing + private static string GetProjectPath(Assembly startupAssembly) + { + var projectName = startupAssembly.GetName().Name; + var applicationBasePath = System.AppContext.BaseDirectory; + var directoryInfo = new DirectoryInfo(applicationBasePath); + do + { + directoryInfo = directoryInfo.Parent.Parent.Parent.Parent; + + var projectDirectoryInfo = new DirectoryInfo(Path.Combine(directoryInfo.FullName, "Web-App")); + if (projectDirectoryInfo.Exists) + { + var projectFileInfo = new FileInfo(Path.Combine(projectDirectoryInfo.FullName, projectName, $"{projectName}.csproj")); + if (projectFileInfo.Exists) + { + return Path.Combine(projectDirectoryInfo.FullName, projectName); + } + } + } + while (directoryInfo.Parent != null); + + throw new Exception($"Project root could not be located using the application root {applicationBasePath}."); + } + } +} diff --git a/AllReadyApp/AllReadyWebOnly.sln b/AllReadyApp/AllReadyWebOnly.sln index 11f806661..d005445f1 100644 --- a/AllReadyApp/AllReadyWebOnly.sln +++ b/AllReadyApp/AllReadyWebOnly.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 15 -VisualStudioVersion = 15.0.26730.8 +VisualStudioVersion = 15.0.27130.0 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Web", "Web", "{2C1DD2C4-73FF-4D1D-9E88-6B413317FC29}" EndProject @@ -32,6 +32,10 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Builds", "Builds", "{79E5CF EndProject Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "AllReady.ScenarioTest", "AllReady.IntegrationTest\AllReady.ScenarioTest.fsproj", "{44055C15-5757-4822-908B-C66B60251C54}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AllReady.IntegrationTests", "AllReady.IntegrationTests\AllReady.IntegrationTests.csproj", "{B45509F1-9C64-4A90-8143-C5D7CDB57904}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "build", "build", "{AECA1833-B3D9-4E87-B64C-042FDDBEFF7B}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -58,6 +62,10 @@ Global {44055C15-5757-4822-908B-C66B60251C54}.Debug|Any CPU.Build.0 = Debug|Any CPU {44055C15-5757-4822-908B-C66B60251C54}.Release|Any CPU.ActiveCfg = Release|Any CPU {44055C15-5757-4822-908B-C66B60251C54}.Release|Any CPU.Build.0 = Release|Any CPU + {B45509F1-9C64-4A90-8143-C5D7CDB57904}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B45509F1-9C64-4A90-8143-C5D7CDB57904}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B45509F1-9C64-4A90-8143-C5D7CDB57904}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B45509F1-9C64-4A90-8143-C5D7CDB57904}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -69,9 +77,8 @@ Global {BFF4752B-274B-47E5-82FD-9B351792FF2D} = {CB31A2DF-9F47-41D5-AD0F-491C98A8D4CB} {79E5CFB4-6FF7-4F89-B560-9342FFE91898} = {364DE571-98D2-4F69-8D93-F25F832E7D7A} {44055C15-5757-4822-908B-C66B60251C54} = {1475C1FD-CE7D-4E6B-83B1-F7F82EA24FF8} - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {645EFF42-0422-4249-B544-6038D44E3CDE} + {B45509F1-9C64-4A90-8143-C5D7CDB57904} = {1475C1FD-CE7D-4E6B-83B1-F7F82EA24FF8} + {AECA1833-B3D9-4E87-B64C-042FDDBEFF7B} = {1475C1FD-CE7D-4E6B-83B1-F7F82EA24FF8} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {FCAA194F-AD24-45C2-AA51-78C71433DCC0} diff --git a/AllReadyApp/Web-App/AllReady/IntegrationTestStartup.cs b/AllReadyApp/Web-App/AllReady/IntegrationTestStartup.cs new file mode 100644 index 000000000..ec81c08f3 --- /dev/null +++ b/AllReadyApp/Web-App/AllReady/IntegrationTestStartup.cs @@ -0,0 +1,47 @@ +using AllReady.DataAccess; +using AllReady.Models; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Hosting; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; + +namespace AllReady +{ + public class IntegrationTestStartup : Startup + { + public IntegrationTestStartup(IConfiguration configuration) : base(configuration) + { + } + + protected override void AddDatabaseServices(IServiceCollection services) + { + services + .AddEntityFrameworkInMemoryDatabase() + .AddDbContext(options => + { + options.UseInMemoryDatabase("InMemory").UseInternalServiceProvider(services.BuildServiceProvider()); + options.EnableSensitiveDataLogging(); + }); + } + + protected override void LoadSeedData(bool purgeRefreshSampleData, SampleDataGenerator sampleDataGenerator) + { + } + + protected override void MigrateDatabase(bool purgeRefreshSampleData, IHostingEnvironment hostingEnvironment, AllReadyContext context) + { + // do not migrate in memory + } + + protected override void AddHangFire(IServiceCollection services) + { + // do nothing for now - will need to be added later in some form + } + + protected override void RegisterHangFire(IApplicationBuilder app) + { + // do nothing for now - will need to be added later in some form + } + } +} \ No newline at end of file diff --git a/AllReadyApp/Web-App/AllReady/Startup.cs b/AllReadyApp/Web-App/AllReady/Startup.cs index c4b8766de..21c50082c 100644 --- a/AllReadyApp/Web-App/AllReady/Startup.cs +++ b/AllReadyApp/Web-App/AllReady/Startup.cs @@ -39,7 +39,7 @@ public Startup(IConfiguration configuration) Configuration = configuration; Configuration["version"] = new ApplicationEnvironment().ApplicationVersion; } - + public IConfiguration Configuration { get; } public IServiceProvider ConfigureServices(IServiceCollection services) @@ -51,8 +51,7 @@ public IServiceProvider ConfigureServices(IServiceCollection services) options.AddPolicy("allReady", AllReadyCorsPolicyFactory.BuildAllReadyOpenCorsPolicy()); }); - // Add Entity Framework services to the services container. - services.AddDbContext(options => options.UseSqlServer(Configuration["Data:DefaultConnection:ConnectionString"])); + AddDatabaseServices(services); Options.LoadConfigurationOptions(services, Configuration); @@ -77,7 +76,8 @@ public IServiceProvider ConfigureServices(IServiceCollection services) if (Configuration["Authentication:Facebook:AppId"] != null) { services.AddAuthentication() - .AddFacebook(options => { + .AddFacebook(options => + { options.AppId = Configuration["authentication:facebook:appid"]; options.AppSecret = Configuration["authentication:facebook:appsecret"]; options.BackchannelHttpHandler = new FacebookBackChannelHandler(); @@ -92,7 +92,8 @@ public IServiceProvider ConfigureServices(IServiceCollection services) if (Configuration["Authentication:MicrosoftAccount:ClientId"] != null) { services.AddAuthentication() - .AddMicrosoftAccount(options => { + .AddMicrosoftAccount(options => + { options.ClientId = Configuration["Authentication:MicrosoftAccount:ClientId"]; options.ClientSecret = Configuration["Authentication:MicrosoftAccount:ClientSecret"]; options.Events = new OAuthEvents() @@ -105,7 +106,8 @@ public IServiceProvider ConfigureServices(IServiceCollection services) if (Configuration["Authentication:Twitter:ConsumerKey"] != null) { services.AddAuthentication() - .AddTwitter(options => { + .AddTwitter(options => + { options.ConsumerKey = Configuration["Authentication:Twitter:ConsumerKey"]; options.ConsumerSecret = Configuration["Authentication:Twitter:ConsumerSecret"]; options.RetrieveUserDetails = true; @@ -119,7 +121,8 @@ public IServiceProvider ConfigureServices(IServiceCollection services) if (Configuration["Authentication:Google:ClientId"] != null) { services.AddAuthentication() - .AddGoogle(options => { + .AddGoogle(options => + { options.ClientId = Configuration["Authentication:Google:ClientId"]; options.ClientSecret = Configuration["Authentication:Google:ClientSecret"]; options.Events = new OAuthEvents() @@ -167,8 +170,7 @@ public IServiceProvider ConfigureServices(IServiceCollection services) options.IdleTimeout = TimeSpan.FromMinutes(20); }); - //Hangfire - services.AddHangfire(configuration => configuration.UseSqlServerStorage(Configuration["Data:HangfireConnection:ConnectionString"])); + AddHangFire(services); services.AddScoped(); services.AddScoped(); @@ -179,6 +181,18 @@ public IServiceProvider ConfigureServices(IServiceCollection services) return container.Resolve(); } + protected virtual void AddDatabaseServices(IServiceCollection services) + { + // Add Entity Framework services to the services container. + services.AddDbContext(options => options.UseSqlServer(Configuration["Data:DefaultConnection:ConnectionString"])); + } + + protected virtual void AddHangFire(IServiceCollection services) + { + //Hangfire + services.AddHangfire(configuration => configuration.UseSqlServerStorage(Configuration["Data:HangfireConnection:ConnectionString"])); + } + // Configure is called after ConfigureServices is called. public void Configure(IApplicationBuilder app, IHostingEnvironment env, AllReadyContext context, SampleDataGenerator sampleData) { @@ -224,15 +238,9 @@ public void Configure(IApplicationBuilder app, IHostingEnvironment env, AllReady context.Database.EnsureDeleted(); } - //call Migrate here to force the creation of the AllReady database so Hangfire can create its schema under it - if (purgeRefreshSampleData || !env.IsProduction()) - { - context.Database.Migrate(); - } + MigrateDatabase(purgeRefreshSampleData, env, context); - ////Hangfire - app.UseHangfireDashboard("/hangfire", new DashboardOptions { Authorization = new[] { new HangfireDashboardAuthorizationFilter() } }); - app.UseHangfireServer(); + RegisterHangFire(app); // Add MVC to the request pipeline. app.UseMvc(routes => @@ -241,16 +249,36 @@ public void Configure(IApplicationBuilder app, IHostingEnvironment env, AllReady routes.MapRoute(name: "default", template: "{controller=Home}/{action=Index}/{id?}"); }); + LoadSeedData(purgeRefreshSampleData, sampleData); + } + + protected virtual void RegisterHangFire(IApplicationBuilder app) + { + app.UseHangfireDashboard("/hangfire", new DashboardOptions { Authorization = new[] { new HangfireDashboardAuthorizationFilter() } }); + app.UseHangfireServer(); + } + + protected virtual void LoadSeedData(bool purgeRefreshSampleData, SampleDataGenerator sampleDataGenerator) + { // Add sample data and test admin accounts if specified in Config.Json. // for production applications, this should either be set to false or deleted. if (purgeRefreshSampleData || Configuration["SampleData:InsertSampleData"] == "true") { - sampleData.InsertTestData(); + sampleDataGenerator.InsertTestData(); } if (Configuration["SampleData:InsertTestUsers"] == "true") { - sampleData.CreateAdminUser().GetAwaiter().GetResult(); + sampleDataGenerator.CreateAdminUser().GetAwaiter().GetResult(); + } + } + + protected virtual void MigrateDatabase(bool purgeRefreshSampleData, IHostingEnvironment hostingEnvironment, AllReadyContext context) + { + //call Migrate here to force the creation of the AllReady database so Hangfire can create its schema under it + if (purgeRefreshSampleData || !hostingEnvironment.IsProduction()) + { + context.Database.Migrate(); } } } From 0ecb3a09fc17b403f74115bdace94ae4cee10a10 Mon Sep 17 00:00:00 2001 From: Steve Gordon Date: Tue, 12 Dec 2017 08:05:15 +0000 Subject: [PATCH 3/5] Restructuring integration tests --- AllReadyApp/AllReady.IntegrationTests/{ => Pages}/IndexTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename AllReadyApp/AllReady.IntegrationTests/{ => Pages}/IndexTests.cs (93%) diff --git a/AllReadyApp/AllReady.IntegrationTests/IndexTests.cs b/AllReadyApp/AllReady.IntegrationTests/Pages/IndexTests.cs similarity index 93% rename from AllReadyApp/AllReady.IntegrationTests/IndexTests.cs rename to AllReadyApp/AllReady.IntegrationTests/Pages/IndexTests.cs index 43775c2d9..01eaf3439 100644 --- a/AllReadyApp/AllReady.IntegrationTests/IndexTests.cs +++ b/AllReadyApp/AllReady.IntegrationTests/Pages/IndexTests.cs @@ -3,7 +3,7 @@ using System.Threading.Tasks; using Xunit; -namespace AllReady.IntegrationTests +namespace AllReady.IntegrationTests.Pages { public class IndexTests : IClassFixture> { From cda797566b4a30f1373dca29b4350225d368b110 Mon Sep 17 00:00:00 2001 From: Steve Gordon Date: Tue, 12 Dec 2017 11:42:22 +0000 Subject: [PATCH 4/5] Continued work on integration testing --- .../AllReady.IntegrationTests.csproj | 1 + .../IntegrationTestStartup.cs | 12 ++--- .../Pages/AboutTests.cs | 28 ++++++++++ .../Pages/IndexTests.cs | 53 ++++++++++++++++++- .../Pages/PrivacyPolicyTests.cs | 28 ++++++++++ .../AllReady.IntegrationTests/TestFixture.cs | 6 ++- AllReadyApp/Web-App/AllReady/Startup.cs | 8 +++ 7 files changed, 128 insertions(+), 8 deletions(-) rename AllReadyApp/{Web-App/AllReady => AllReady.IntegrationTests}/IntegrationTestStartup.cs (77%) create mode 100644 AllReadyApp/AllReady.IntegrationTests/Pages/AboutTests.cs create mode 100644 AllReadyApp/AllReady.IntegrationTests/Pages/PrivacyPolicyTests.cs diff --git a/AllReadyApp/AllReady.IntegrationTests/AllReady.IntegrationTests.csproj b/AllReadyApp/AllReady.IntegrationTests/AllReady.IntegrationTests.csproj index 6f323cdb9..c5311150f 100644 --- a/AllReadyApp/AllReady.IntegrationTests/AllReady.IntegrationTests.csproj +++ b/AllReadyApp/AllReady.IntegrationTests/AllReady.IntegrationTests.csproj @@ -9,6 +9,7 @@ + diff --git a/AllReadyApp/Web-App/AllReady/IntegrationTestStartup.cs b/AllReadyApp/AllReady.IntegrationTests/IntegrationTestStartup.cs similarity index 77% rename from AllReadyApp/Web-App/AllReady/IntegrationTestStartup.cs rename to AllReadyApp/AllReady.IntegrationTests/IntegrationTestStartup.cs index ec81c08f3..03721bcaa 100644 --- a/AllReadyApp/Web-App/AllReady/IntegrationTestStartup.cs +++ b/AllReadyApp/AllReady.IntegrationTests/IntegrationTestStartup.cs @@ -6,7 +6,7 @@ using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; -namespace AllReady +namespace AllReady.IntegrationTests { public class IntegrationTestStartup : Startup { @@ -20,13 +20,13 @@ protected override void AddDatabaseServices(IServiceCollection services) .AddEntityFrameworkInMemoryDatabase() .AddDbContext(options => { - options.UseInMemoryDatabase("InMemory").UseInternalServiceProvider(services.BuildServiceProvider()); - options.EnableSensitiveDataLogging(); + options.UseInMemoryDatabase("InMemory"); }); } protected override void LoadSeedData(bool purgeRefreshSampleData, SampleDataGenerator sampleDataGenerator) { + // tests will load their own data? Possibly have some default data instead } protected override void MigrateDatabase(bool purgeRefreshSampleData, IHostingEnvironment hostingEnvironment, AllReadyContext context) @@ -36,12 +36,12 @@ protected override void MigrateDatabase(bool purgeRefreshSampleData, IHostingEnv protected override void AddHangFire(IServiceCollection services) { - // do nothing for now - will need to be added later in some form + // do nothing for now - may need to be added later in some form } protected override void RegisterHangFire(IApplicationBuilder app) { - // do nothing for now - will need to be added later in some form + // do nothing for now - may need to be added later in some form } } -} \ No newline at end of file +} diff --git a/AllReadyApp/AllReady.IntegrationTests/Pages/AboutTests.cs b/AllReadyApp/AllReady.IntegrationTests/Pages/AboutTests.cs new file mode 100644 index 000000000..0720c56de --- /dev/null +++ b/AllReadyApp/AllReady.IntegrationTests/Pages/AboutTests.cs @@ -0,0 +1,28 @@ +using System.Net; +using System.Net.Http; +using System.Threading.Tasks; +using Shouldly; +using Xunit; + +namespace AllReady.IntegrationTests.Pages +{ + public class AboutTests : IClassFixture> + { + private readonly HttpClient _client; + + public AboutTests(TestFixture fixture) + { + _client = fixture.Client; + } + + [Fact] + public async Task CanGetAboutPage() + { + // Act + var response = await _client.GetAsync("/about"); + + // Assert + response.StatusCode.ShouldBe(HttpStatusCode.OK); + } + } +} diff --git a/AllReadyApp/AllReady.IntegrationTests/Pages/IndexTests.cs b/AllReadyApp/AllReady.IntegrationTests/Pages/IndexTests.cs index 01eaf3439..7296bd49d 100644 --- a/AllReadyApp/AllReady.IntegrationTests/Pages/IndexTests.cs +++ b/AllReadyApp/AllReady.IntegrationTests/Pages/IndexTests.cs @@ -1,6 +1,10 @@ +using System; using System.Net; using System.Net.Http; +using System.Text.RegularExpressions; using System.Threading.Tasks; +using AllReady.Models; +using Shouldly; using Xunit; namespace AllReady.IntegrationTests.Pages @@ -9,9 +13,33 @@ public class IndexTests : IClassFixture> { private readonly HttpClient _client; + private const string CampaignName = "Featured Campaign Name"; + public IndexTests(TestFixture fixture) { _client = fixture.Client; + + var campaign = new Campaign + { + EndDateTime = DateTimeOffset.UtcNow.AddDays(10), + Featured = true, + Published = true, + Locked = false, + Name = CampaignName, + Description = "This is a featured campaign", + Headline = "This is a featured headline", + ManagingOrganization = new Organization + { + Name = "Test Organisation" + } + }; + + fixture.DbContext.Campaigns.Add(campaign); + + fixture.DbContext.Events.Add(new Event { Campaign = campaign, Name = "Event Name 1", EndDateTime = DateTimeOffset.UtcNow.AddDays(2) }); + fixture.DbContext.Events.Add(new Event { Campaign = campaign, Name = "Event Name 2", EndDateTime = DateTimeOffset.UtcNow.AddDays(2) }); + + fixture.DbContext.SaveChanges(); } [Fact] @@ -19,9 +47,32 @@ public async Task CanGetHomePage() { // Act var response = await _client.GetAsync("/"); + + // Assert + response.StatusCode.ShouldBe(HttpStatusCode.OK); + } + + [Fact] + public async Task IncludesFeaturedCampaign_WhenSet() + { + // Act + var response = await _client.GetAsync("/"); + var content = await response.Content.ReadAsStringAsync(); + + // Assert + content.ShouldContain(CampaignName); + } + + [Fact] + public async Task IncludesExpectedNumberOfEvents() + { + // Act + var response = await _client.GetAsync("/"); + var content = await response.Content.ReadAsStringAsync(); // Assert - Assert.Equal(HttpStatusCode.OK, response.StatusCode); + var newLineFreeContent = Regex.Replace(content, @"\t|\n|\r|\s+", string.Empty); + Regex.Matches(newLineFreeContent, "

Campaign:").Count.ShouldBe(2); } } } diff --git a/AllReadyApp/AllReady.IntegrationTests/Pages/PrivacyPolicyTests.cs b/AllReadyApp/AllReady.IntegrationTests/Pages/PrivacyPolicyTests.cs new file mode 100644 index 000000000..28fe1c53d --- /dev/null +++ b/AllReadyApp/AllReady.IntegrationTests/Pages/PrivacyPolicyTests.cs @@ -0,0 +1,28 @@ +using System.Net; +using System.Net.Http; +using System.Threading.Tasks; +using Shouldly; +using Xunit; + +namespace AllReady.IntegrationTests.Pages +{ + public class PrivacyPolicyTests : IClassFixture> + { + private readonly HttpClient _client; + + public PrivacyPolicyTests(TestFixture fixture) + { + _client = fixture.Client; + } + + [Fact] + public async Task CanGetAboutPage() + { + // Act + var response = await _client.GetAsync("/privacypolicy"); + + // Assert + response.StatusCode.ShouldBe(HttpStatusCode.OK); + } + } +} diff --git a/AllReadyApp/AllReady.IntegrationTests/TestFixture.cs b/AllReadyApp/AllReady.IntegrationTests/TestFixture.cs index 41c495608..5bf247626 100644 --- a/AllReadyApp/AllReady.IntegrationTests/TestFixture.cs +++ b/AllReadyApp/AllReady.IntegrationTests/TestFixture.cs @@ -2,6 +2,7 @@ using System.IO; using System.Net.Http; using System.Reflection; +using AllReady.Models; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Mvc.ApplicationParts; using Microsoft.AspNetCore.Mvc.Controllers; @@ -11,7 +12,6 @@ namespace AllReady.IntegrationTests { - // A test fixture which hosts the target project (project we wish to test) in an in-memory server. public class TestFixture : IDisposable { private readonly TestServer _server; @@ -29,12 +29,16 @@ public TestFixture() _server = new TestServer(builder); + DbContext = _server.Host.Services.GetService(typeof(AllReadyContext)) as AllReadyContext; + Client = _server.CreateClient(); Client.BaseAddress = new Uri("http://localhost"); } public HttpClient Client { get; } + public AllReadyContext DbContext { get; } + public void Dispose() { Client.Dispose(); diff --git a/AllReadyApp/Web-App/AllReady/Startup.cs b/AllReadyApp/Web-App/AllReady/Startup.cs index 21c50082c..833bc0890 100644 --- a/AllReadyApp/Web-App/AllReady/Startup.cs +++ b/AllReadyApp/Web-App/AllReady/Startup.cs @@ -181,6 +181,14 @@ public IServiceProvider ConfigureServices(IServiceCollection services) return container.Resolve(); } + + protected virtual void GetDbContext(IServiceCollection services) + { + // Add Entity Framework services to the services container. + services.AddDbContext(options => options.UseSqlServer(Configuration["Data:DefaultConnection:ConnectionString"])); + } + + protected virtual void AddDatabaseServices(IServiceCollection services) { // Add Entity Framework services to the services container. From be4cea2d90c5cabf258467a7c725cd9957209a7f Mon Sep 17 00:00:00 2001 From: Steve Gordon Date: Tue, 2 Jan 2018 16:45:17 +0000 Subject: [PATCH 5/5] Finalising the first iteration of integration testing --- .../IntegrationTestStartup.cs | 25 ++++++++++++++++- .../Pages/IndexTests.cs | 28 ++----------------- .../AllReady.IntegrationTests/TestFixture.cs | 2 +- .../build/testing.targets | 25 +++++++++++++++++ 4 files changed, 52 insertions(+), 28 deletions(-) create mode 100644 AllReadyApp/AllReady.IntegrationTests/build/testing.targets diff --git a/AllReadyApp/AllReady.IntegrationTests/IntegrationTestStartup.cs b/AllReadyApp/AllReady.IntegrationTests/IntegrationTestStartup.cs index 03721bcaa..902ec9ade 100644 --- a/AllReadyApp/AllReady.IntegrationTests/IntegrationTestStartup.cs +++ b/AllReadyApp/AllReady.IntegrationTests/IntegrationTestStartup.cs @@ -1,3 +1,4 @@ +using System; using AllReady.DataAccess; using AllReady.Models; using Microsoft.AspNetCore.Builder; @@ -31,7 +32,29 @@ protected override void LoadSeedData(bool purgeRefreshSampleData, SampleDataGene protected override void MigrateDatabase(bool purgeRefreshSampleData, IHostingEnvironment hostingEnvironment, AllReadyContext context) { - // do not migrate in memory + // for now we load up a default set of data used by all tests - this works for now, but needs review + + var campaign = new Campaign + { + EndDateTime = DateTimeOffset.UtcNow.AddDays(10), + Featured = true, + Published = true, + Locked = false, + Name = "Featured Campaign Name", + Description = "This is a featured campaign", + Headline = "This is a featured headline", + ManagingOrganization = new Organization + { + Name = "Test Organisation" + } + }; + + context.Campaigns.Add(campaign); + + context.Events.Add(new Event { Campaign = campaign, Name = "Event Name 1", EndDateTime = DateTimeOffset.UtcNow.AddDays(2) }); + context.Events.Add(new Event { Campaign = campaign, Name = "Event Name 2", EndDateTime = DateTimeOffset.UtcNow.AddDays(2) }); + + context.SaveChanges(); } protected override void AddHangFire(IServiceCollection services) diff --git a/AllReadyApp/AllReady.IntegrationTests/Pages/IndexTests.cs b/AllReadyApp/AllReady.IntegrationTests/Pages/IndexTests.cs index 7296bd49d..015cc5548 100644 --- a/AllReadyApp/AllReady.IntegrationTests/Pages/IndexTests.cs +++ b/AllReadyApp/AllReady.IntegrationTests/Pages/IndexTests.cs @@ -1,9 +1,7 @@ -using System; using System.Net; using System.Net.Http; using System.Text.RegularExpressions; using System.Threading.Tasks; -using AllReady.Models; using Shouldly; using Xunit; @@ -13,33 +11,11 @@ public class IndexTests : IClassFixture> { private readonly HttpClient _client; - private const string CampaignName = "Featured Campaign Name"; + private const string FeaturedCampaignName = "Featured Campaign Name"; public IndexTests(TestFixture fixture) { _client = fixture.Client; - - var campaign = new Campaign - { - EndDateTime = DateTimeOffset.UtcNow.AddDays(10), - Featured = true, - Published = true, - Locked = false, - Name = CampaignName, - Description = "This is a featured campaign", - Headline = "This is a featured headline", - ManagingOrganization = new Organization - { - Name = "Test Organisation" - } - }; - - fixture.DbContext.Campaigns.Add(campaign); - - fixture.DbContext.Events.Add(new Event { Campaign = campaign, Name = "Event Name 1", EndDateTime = DateTimeOffset.UtcNow.AddDays(2) }); - fixture.DbContext.Events.Add(new Event { Campaign = campaign, Name = "Event Name 2", EndDateTime = DateTimeOffset.UtcNow.AddDays(2) }); - - fixture.DbContext.SaveChanges(); } [Fact] @@ -60,7 +36,7 @@ public async Task IncludesFeaturedCampaign_WhenSet() var content = await response.Content.ReadAsStringAsync(); // Assert - content.ShouldContain(CampaignName); + content.ShouldContain(FeaturedCampaignName); } [Fact] diff --git a/AllReadyApp/AllReady.IntegrationTests/TestFixture.cs b/AllReadyApp/AllReady.IntegrationTests/TestFixture.cs index 5bf247626..c44c70ad5 100644 --- a/AllReadyApp/AllReady.IntegrationTests/TestFixture.cs +++ b/AllReadyApp/AllReady.IntegrationTests/TestFixture.cs @@ -18,7 +18,7 @@ public class TestFixture : IDisposable public TestFixture() { - var startupAssembly = typeof(TStartup).GetTypeInfo().Assembly; + var startupAssembly = typeof(TStartup).GetTypeInfo().BaseType.Assembly; var contentRoot = GetProjectPath(startupAssembly); var builder = new WebHostBuilder() diff --git a/AllReadyApp/AllReady.IntegrationTests/build/testing.targets b/AllReadyApp/AllReady.IntegrationTests/build/testing.targets new file mode 100644 index 000000000..3982282d3 --- /dev/null +++ b/AllReadyApp/AllReady.IntegrationTests/build/testing.targets @@ -0,0 +1,25 @@ + + + + + + + true + + + + + + + + + + \ No newline at end of file