diff --git a/MusicStore.sln b/MusicStore.sln index 1742ad517a..0c409e95f2 100644 --- a/MusicStore.sln +++ b/MusicStore.sln @@ -1,7 +1,6 @@ - Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 15 -VisualStudioVersion = 15.0.26228.10 +VisualStudioVersion = 15.0.26405.2 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{7D749BDA-4638-4517-B66A-D40DEDEEB141}" ProjectSection(SolutionItems) = preProject @@ -12,37 +11,65 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "samples", "samples", "{B7B1 EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{363D2681-31A6-48C9-90BB-9ACFF4A41F06}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "E2ETests", "test\E2ETests\E2ETests.csproj", "{A319ACCE-060B-4385-9534-9F2202F6180E}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MusicStore", "samples\MusicStore\MusicStore.csproj", "{3CFBED5D-2ED8-49DB-96FB-BDAA748DC5A0}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MusicStore.Test", "test\MusicStore.Test\MusicStore.Test.csproj", "{CA663205-77DE-4E55-B300-85594181B5A9}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MusicStore.E2ETests", "test\MusicStore.E2ETests\MusicStore.E2ETests.csproj", "{72A5F455-121F-4954-BF28-D712C6BE88EA}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 Release|Any CPU = Release|Any CPU + Release|x64 = Release|x64 + Release|x86 = Release|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {A319ACCE-060B-4385-9534-9F2202F6180E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {A319ACCE-060B-4385-9534-9F2202F6180E}.Debug|Any CPU.Build.0 = Debug|Any CPU - {A319ACCE-060B-4385-9534-9F2202F6180E}.Release|Any CPU.ActiveCfg = Release|Any CPU - {A319ACCE-060B-4385-9534-9F2202F6180E}.Release|Any CPU.Build.0 = Release|Any CPU {3CFBED5D-2ED8-49DB-96FB-BDAA748DC5A0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {3CFBED5D-2ED8-49DB-96FB-BDAA748DC5A0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3CFBED5D-2ED8-49DB-96FB-BDAA748DC5A0}.Debug|x64.ActiveCfg = Debug|Any CPU + {3CFBED5D-2ED8-49DB-96FB-BDAA748DC5A0}.Debug|x64.Build.0 = Debug|Any CPU + {3CFBED5D-2ED8-49DB-96FB-BDAA748DC5A0}.Debug|x86.ActiveCfg = Debug|Any CPU + {3CFBED5D-2ED8-49DB-96FB-BDAA748DC5A0}.Debug|x86.Build.0 = Debug|Any CPU {3CFBED5D-2ED8-49DB-96FB-BDAA748DC5A0}.Release|Any CPU.ActiveCfg = Release|Any CPU {3CFBED5D-2ED8-49DB-96FB-BDAA748DC5A0}.Release|Any CPU.Build.0 = Release|Any CPU + {3CFBED5D-2ED8-49DB-96FB-BDAA748DC5A0}.Release|x64.ActiveCfg = Release|Any CPU + {3CFBED5D-2ED8-49DB-96FB-BDAA748DC5A0}.Release|x64.Build.0 = Release|Any CPU + {3CFBED5D-2ED8-49DB-96FB-BDAA748DC5A0}.Release|x86.ActiveCfg = Release|Any CPU + {3CFBED5D-2ED8-49DB-96FB-BDAA748DC5A0}.Release|x86.Build.0 = Release|Any CPU {CA663205-77DE-4E55-B300-85594181B5A9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {CA663205-77DE-4E55-B300-85594181B5A9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CA663205-77DE-4E55-B300-85594181B5A9}.Debug|x64.ActiveCfg = Debug|Any CPU + {CA663205-77DE-4E55-B300-85594181B5A9}.Debug|x64.Build.0 = Debug|Any CPU + {CA663205-77DE-4E55-B300-85594181B5A9}.Debug|x86.ActiveCfg = Debug|Any CPU + {CA663205-77DE-4E55-B300-85594181B5A9}.Debug|x86.Build.0 = Debug|Any CPU {CA663205-77DE-4E55-B300-85594181B5A9}.Release|Any CPU.ActiveCfg = Release|Any CPU {CA663205-77DE-4E55-B300-85594181B5A9}.Release|Any CPU.Build.0 = Release|Any CPU + {CA663205-77DE-4E55-B300-85594181B5A9}.Release|x64.ActiveCfg = Release|Any CPU + {CA663205-77DE-4E55-B300-85594181B5A9}.Release|x64.Build.0 = Release|Any CPU + {CA663205-77DE-4E55-B300-85594181B5A9}.Release|x86.ActiveCfg = Release|Any CPU + {CA663205-77DE-4E55-B300-85594181B5A9}.Release|x86.Build.0 = Release|Any CPU + {72A5F455-121F-4954-BF28-D712C6BE88EA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {72A5F455-121F-4954-BF28-D712C6BE88EA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {72A5F455-121F-4954-BF28-D712C6BE88EA}.Debug|x64.ActiveCfg = Debug|Any CPU + {72A5F455-121F-4954-BF28-D712C6BE88EA}.Debug|x64.Build.0 = Debug|Any CPU + {72A5F455-121F-4954-BF28-D712C6BE88EA}.Debug|x86.ActiveCfg = Debug|Any CPU + {72A5F455-121F-4954-BF28-D712C6BE88EA}.Debug|x86.Build.0 = Debug|Any CPU + {72A5F455-121F-4954-BF28-D712C6BE88EA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {72A5F455-121F-4954-BF28-D712C6BE88EA}.Release|Any CPU.Build.0 = Release|Any CPU + {72A5F455-121F-4954-BF28-D712C6BE88EA}.Release|x64.ActiveCfg = Release|Any CPU + {72A5F455-121F-4954-BF28-D712C6BE88EA}.Release|x64.Build.0 = Release|Any CPU + {72A5F455-121F-4954-BF28-D712C6BE88EA}.Release|x86.ActiveCfg = Release|Any CPU + {72A5F455-121F-4954-BF28-D712C6BE88EA}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection GlobalSection(NestedProjects) = preSolution - {A319ACCE-060B-4385-9534-9F2202F6180E} = {363D2681-31A6-48C9-90BB-9ACFF4A41F06} {3CFBED5D-2ED8-49DB-96FB-BDAA748DC5A0} = {B7B176B6-8D4D-4EF1-BBD2-DDA650C78FFF} {CA663205-77DE-4E55-B300-85594181B5A9} = {363D2681-31A6-48C9-90BB-9ACFF4A41F06} + {72A5F455-121F-4954-BF28-D712C6BE88EA} = {363D2681-31A6-48C9-90BB-9ACFF4A41F06} EndGlobalSection EndGlobal diff --git a/test/E2ETests/NtlmAuthentationTest.cs b/test/E2ETests/NtlmAuthentationTest.cs deleted file mode 100644 index 440ed3c4b5..0000000000 --- a/test/E2ETests/NtlmAuthentationTest.cs +++ /dev/null @@ -1,110 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Net.Http; -using System.Threading.Tasks; -using E2ETests.Common; -using Microsoft.AspNetCore.Server.IntegrationTesting; -using Microsoft.AspNetCore.Testing.xunit; -using Microsoft.DotNet.PlatformAbstractions; -using Microsoft.Extensions.Logging; -using Xunit; -using Xunit.Abstractions; - -namespace E2ETests -{ - public class NtlmAuthenticationTests : IDisposable - { - private readonly ILoggerFactory _loggerFactory; - - public NtlmAuthenticationTests(ITestOutputHelper output) - { - _loggerFactory = new LoggerFactory() - .AddXunit(output); - } - - [ConditionalTheory, Trait("E2Etests", "E2Etests")] - [OSSkipCondition(OperatingSystems.Linux)] - [OSSkipCondition(OperatingSystems.MacOSX)] - [InlineData(ServerType.WebListener, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, ApplicationType.Portable)] - [InlineData(ServerType.WebListener, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, ApplicationType.Standalone, - Skip = "https://github.com/aspnet/MusicStore/issues/761")] - [InlineData(ServerType.IISExpress, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, ApplicationType.Portable)] - [InlineData(ServerType.IISExpress, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, ApplicationType.Standalone, - Skip = "https://github.com/aspnet/MusicStore/issues/761")] - public async Task NtlmAuthenticationTest(ServerType serverType, RuntimeFlavor runtimeFlavor, RuntimeArchitecture architecture, ApplicationType applicationType) - { - try - { - Console.WriteLine("NtlmAuthenticationTest"); - var logger = _loggerFactory.CreateLogger($"NtlmAuthentication:{serverType}:{runtimeFlavor}:{architecture}:{applicationType}"); - using (logger.BeginScope("NtlmAuthenticationTest")) - { - var musicStoreDbName = DbUtils.GetUniqueName(); - - var deploymentParameters = new DeploymentParameters(Helpers.GetApplicationPath(applicationType), serverType, runtimeFlavor, architecture) - { - PublishApplicationBeforeDeployment = true, - PreservePublishedApplicationForDebugging = Helpers.PreservePublishedApplicationForDebugging, - TargetFramework = runtimeFlavor == RuntimeFlavor.Clr ? "net46" : "netcoreapp2.0", - Configuration = Helpers.GetCurrentBuildConfiguration(), - ApplicationType = applicationType, - EnvironmentName = "NtlmAuthentication", //Will pick the Start class named 'StartupNtlmAuthentication' - ServerConfigTemplateContent = (serverType == ServerType.IISExpress) ? File.ReadAllText(Path.Combine(AppContext.BaseDirectory, "NtlmAuthentation.config")) : null, - SiteName = "MusicStoreNtlmAuthentication", //This is configured in the NtlmAuthentication.config - UserAdditionalCleanup = parameters => - { - DbUtils.DropDatabase(musicStoreDbName, logger); - } - }; - - if (applicationType == ApplicationType.Standalone) - { - deploymentParameters.AdditionalPublishParameters = " -r " + RuntimeEnvironment.GetRuntimeIdentifier(); - } - - // Override the connection strings using environment based configuration - deploymentParameters.EnvironmentVariables - .Add(new KeyValuePair( - MusicStoreConfig.ConnectionStringKey, - DbUtils.CreateConnectionString(musicStoreDbName))); - - using (var deployer = ApplicationDeployerFactory.Create(deploymentParameters, _loggerFactory)) - { - var deploymentResult = await deployer.DeployAsync(); - var httpClientHandler = new HttpClientHandler() { UseDefaultCredentials = true }; - var httpClient = new HttpClient(httpClientHandler) { BaseAddress = new Uri(deploymentResult.ApplicationBaseUri) }; - - // Request to base address and check if various parts of the body are rendered & measure the cold startup time. - var response = await RetryHelper.RetryRequest(async () => - { - return await httpClient.GetAsync(string.Empty); - }, logger: logger, cancellationToken: deploymentResult.HostShutdownToken); - - Assert.False(response == null, "Response object is null because the client could not " + - "connect to the server after multiple retries"); - - var validator = new Validator(httpClient, httpClientHandler, logger, deploymentResult); - - Console.WriteLine("Verifying home page"); - await validator.VerifyNtlmHomePage(response); - - Console.WriteLine("Verifying access to store with permissions"); - await validator.AccessStoreWithPermissions(); - - logger.LogInformation("Variation completed successfully."); - } - } - } - finally - { - Console.WriteLine("Finished NtlmAuthenticationTest"); - } - } - - public void Dispose() - { - _loggerFactory.Dispose(); - } - } -} diff --git a/test/E2ETests/OpenIdConnectTests.cs b/test/E2ETests/OpenIdConnectTests.cs deleted file mode 100644 index e9e8460d4d..0000000000 --- a/test/E2ETests/OpenIdConnectTests.cs +++ /dev/null @@ -1,134 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Net.Http; -using System.Threading.Tasks; -using E2ETests.Common; -using Microsoft.AspNetCore.Server.IntegrationTesting; -using Microsoft.AspNetCore.Testing.xunit; -using Microsoft.DotNet.PlatformAbstractions; -using Microsoft.Extensions.Logging; -using Xunit; -using Xunit.Abstractions; - -namespace E2ETests -{ - public class OpenIdConnectTests : IDisposable - { - private readonly ILoggerFactory _loggerFactory; - - public OpenIdConnectTests(ITestOutputHelper output) - { - _loggerFactory = new LoggerFactory() - .AddXunit(output); - } - - [ConditionalTheory, Trait("E2Etests", "E2Etests")] - [OSSkipCondition(OperatingSystems.Linux)] - [OSSkipCondition(OperatingSystems.MacOSX)] - //[InlineData(ServerType.Kestrel, RuntimeFlavor.Clr, RuntimeArchitecture.x64, ApplicationType.Portable)] - [InlineData(ServerType.Kestrel, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, ApplicationType.Portable)] - [InlineData(ServerType.Kestrel, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, ApplicationType.Standalone, - Skip = "https://github.com/aspnet/MusicStore/issues/761")] - public async Task OpenIdConnect_OnWindowsOS( - ServerType serverType, - RuntimeFlavor runtimeFlavor, - RuntimeArchitecture architecture, - ApplicationType applicationType) - { - await OpenIdConnectTestSuite(serverType, runtimeFlavor, architecture, applicationType); - } - - [ConditionalTheory, Trait("E2Etests", "E2Etests")] - [OSSkipCondition(OperatingSystems.Windows)] - [InlineData(ServerType.Kestrel, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, ApplicationType.Portable)] - [InlineData(ServerType.Kestrel, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, ApplicationType.Standalone, - Skip = "https://github.com/aspnet/MusicStore/issues/761")] - public async Task OpenIdConnect_OnNonWindows(ServerType serverType, RuntimeFlavor runtimeFlavor, RuntimeArchitecture architecture, ApplicationType applicationType) - { - await OpenIdConnectTestSuite(serverType, runtimeFlavor, architecture, applicationType); - } - - // TODO: temporarily disabling x86 tests as dotnet xunit test runner currently does not support 32-bit - - //[ConditionalTheory(Skip = "https://github.com/aspnet/MusicStore/issues/565"), Trait("E2Etests", "E2Etests")] - //[OSSkipCondition(OperatingSystems.Windows)] - //[InlineData(ServerType.Kestrel, RuntimeFlavor.Clr, RuntimeArchitecture.x86, ApplicationType.Portable)] - //public async Task OpenIdConnect_OnMono(ServerType serverType, RuntimeFlavor runtimeFlavor, RuntimeArchitecture architecture, ApplicationType applicationType) - //{ - // await OpenIdConnectTestSuite(serverType, runtimeFlavor, architecture); - //} - - private async Task OpenIdConnectTestSuite(ServerType serverType, RuntimeFlavor runtimeFlavor, RuntimeArchitecture architecture, ApplicationType applicationType) - { - try - { - Console.WriteLine($"Starting OpenIdConnectTestSuite:{serverType}:{runtimeFlavor}:{architecture}:{applicationType}"); - var logger = _loggerFactory.CreateLogger($"OpenIdConnectTestSuite:{serverType}:{runtimeFlavor}:{architecture}:{applicationType}"); - using (logger.BeginScope("OpenIdConnectTestSuite")) - { - var musicStoreDbName = DbUtils.GetUniqueName(); - - var deploymentParameters = new DeploymentParameters(Helpers.GetApplicationPath(applicationType), serverType, runtimeFlavor, architecture) - { - PublishApplicationBeforeDeployment = true, - PreservePublishedApplicationForDebugging = Helpers.PreservePublishedApplicationForDebugging, - TargetFramework = runtimeFlavor == RuntimeFlavor.Clr ? "net46" : "netcoreapp2.0", - Configuration = Helpers.GetCurrentBuildConfiguration(), - ApplicationType = applicationType, - EnvironmentName = "OpenIdConnectTesting", - UserAdditionalCleanup = parameters => - { - DbUtils.DropDatabase(musicStoreDbName, logger); - } - }; - - - deploymentParameters.AdditionalPublishParameters = - (applicationType == ApplicationType.Standalone ? $" -r {RuntimeEnvironment.GetRuntimeIdentifier()}" : "") - + " /p:PublishForTesting=true"; - - // Override the connection strings using environment based configuration - deploymentParameters.EnvironmentVariables - .Add(new KeyValuePair( - MusicStoreConfig.ConnectionStringKey, - DbUtils.CreateConnectionString(musicStoreDbName))); - - using (var deployer = ApplicationDeployerFactory.Create(deploymentParameters, _loggerFactory)) - { - var deploymentResult = await deployer.DeployAsync(); - var httpClientHandler = new HttpClientHandler(); - var httpClient = new HttpClient(httpClientHandler) { BaseAddress = new Uri(deploymentResult.ApplicationBaseUri) }; - - // Request to base address and check if various parts of the body are rendered & measure the cold startup time. - var response = await RetryHelper.RetryRequest(async () => - { - return await httpClient.GetAsync(string.Empty); - }, logger: logger, cancellationToken: deploymentResult.HostShutdownToken); - - Assert.False(response == null, "Response object is null because the client could not " + - "connect to the server after multiple retries"); - - var validator = new Validator(httpClient, httpClientHandler, logger, deploymentResult); - - Console.WriteLine("Verifying home page"); - await validator.VerifyHomePage(response); - - Console.WriteLine("Verifying login by OpenIdConnect"); - await validator.LoginWithOpenIdConnect(); - - logger.LogInformation("Variation completed successfully."); - } - } - } - finally - { - Console.WriteLine("Finished OpenIdConnectTestSuite"); - } - } - - public void Dispose() - { - _loggerFactory.Dispose(); - } - } -} \ No newline at end of file diff --git a/test/E2ETests/SmokeTestHelper.cs b/test/E2ETests/SmokeTestHelper.cs deleted file mode 100644 index 78d35dac7c..0000000000 --- a/test/E2ETests/SmokeTestHelper.cs +++ /dev/null @@ -1,120 +0,0 @@ -using System; -using System.Net.Http; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Server.IntegrationTesting; -using Microsoft.Extensions.Logging; -using Xunit; - -namespace E2ETests -{ - public static class SmokeTestHelper - { - public static async Task RunTestsAsync(DeploymentResult deploymentResult, ILogger logger) - { - var httpClientHandler = new HttpClientHandler(); - var httpClient = new HttpClient(httpClientHandler) - { - BaseAddress = new Uri(deploymentResult.ApplicationBaseUri), - Timeout = TimeSpan.FromSeconds(15), - }; - - using (httpClient) - { - // Request to base address and check if various parts of the body are rendered - // & measure the cold startup time. - var response = await RetryHelper.RetryRequest(async () => - { - return await httpClient.GetAsync(string.Empty); - }, logger, cancellationToken: deploymentResult.HostShutdownToken); - - Assert.False(response == null, "Response object is null because the client could not " + - "connect to the server after multiple retries"); - - var validator = new Validator(httpClient, httpClientHandler, logger, deploymentResult); - - Console.WriteLine("Verifying home page"); - await validator.VerifyHomePage(response); - - Console.WriteLine("Verifying static files are served from static file middleware"); - await validator.VerifyStaticContentServed(); - - Console.WriteLine("Verifying access to a protected resource should automatically redirect to login page."); - await validator.AccessStoreWithoutPermissions(); - - Console.WriteLine("Verifying mismatched passwords trigger validaton errors during user registration"); - await validator.RegisterUserWithNonMatchingPasswords(); - - Console.WriteLine("Verifying valid user registration"); - var generatedEmail = await validator.RegisterValidUser(); - - Console.WriteLine("Verifying duplicate user email registration"); - await validator.RegisterExistingUser(generatedEmail); - - Console.WriteLine("Verifying incorrect password login"); - await validator.SignInWithInvalidPassword(generatedEmail, "InvalidPassword~1"); - - Console.WriteLine("Verifying valid user log in"); - await validator.SignInWithUser(generatedEmail, "Password~1"); - - Console.WriteLine("Verifying change password"); - await validator.ChangePassword(generatedEmail); - - Console.WriteLine("Verifying old password is not valid anymore"); - await validator.SignOutUser(generatedEmail); - await validator.SignInWithInvalidPassword(generatedEmail, "Password~1"); - await validator.SignInWithUser(generatedEmail, "Password~2"); - - Console.WriteLine("Verifying authenticated user trying to access unauthorized resource"); - await validator.AccessStoreWithoutPermissions(generatedEmail); - - Console.WriteLine("Verifying user log out"); - await validator.SignOutUser(generatedEmail); - - Console.WriteLine("Verifying admin user login"); - await validator.SignInWithUser("Administrator@test.com", "YouShouldChangeThisPassword1!"); - - Console.WriteLine("Verifying admin user's access to store manager page"); - await validator.AccessStoreWithPermissions(); - - Console.WriteLine("Verifying creating a new album"); - var albumName = await validator.CreateAlbum(); - var albumId = await validator.FetchAlbumIdFromName(albumName); - - Console.WriteLine("Verifying retrieved album details"); - await validator.VerifyAlbumDetails(albumId, albumName); - - Console.WriteLine("Verifying status code pages for non-existing items"); - await validator.VerifyStatusCodePages(); - - Console.WriteLine("Verifying non-admin view of an album"); - await validator.GetAlbumDetailsFromStore(albumId, albumName); - - Console.WriteLine("Verifying adding album to a cart"); - await validator.AddAlbumToCart(albumId, albumName); - - Console.WriteLine("Verifying cart checkout"); - await validator.CheckOutCartItems(); - - Console.WriteLine("Verifying deletion of album from a cart"); - await validator.DeleteAlbum(albumId, albumName); - - Console.WriteLine("Verifying administrator log out"); - await validator.SignOutUser("Administrator"); - - Console.WriteLine("Verifying Google login scenarios"); - await validator.LoginWithGoogle(); - - Console.WriteLine("Verifying Facebook login scenarios"); - await validator.LoginWithFacebook(); - - Console.WriteLine("Verifying Twitter login scenarios"); - await validator.LoginWithTwitter(); - - Console.WriteLine("Verifying Microsoft login scenarios"); - await validator.LoginWithMicrosoftAccount(); - - logger.LogInformation("Variation completed successfully."); - } - } - } -} diff --git a/test/E2ETests/Common/DbUtils.cs b/test/MusicStore.E2ETests/Common/DbUtils.cs similarity index 100% rename from test/E2ETests/Common/DbUtils.cs rename to test/MusicStore.E2ETests/Common/DbUtils.cs diff --git a/test/E2ETests/Common/Extensions.cs b/test/MusicStore.E2ETests/Common/Extensions.cs similarity index 100% rename from test/E2ETests/Common/Extensions.cs rename to test/MusicStore.E2ETests/Common/Extensions.cs diff --git a/test/E2ETests/Common/Helpers.cs b/test/MusicStore.E2ETests/Common/Helpers.cs similarity index 100% rename from test/E2ETests/Common/Helpers.cs rename to test/MusicStore.E2ETests/Common/Helpers.cs diff --git a/test/E2ETests/Common/HtmlDOMHelper.cs b/test/MusicStore.E2ETests/Common/HtmlDOMHelper.cs similarity index 100% rename from test/E2ETests/Common/HtmlDOMHelper.cs rename to test/MusicStore.E2ETests/Common/HtmlDOMHelper.cs diff --git a/test/E2ETests/Common/XunitLogger.cs b/test/MusicStore.E2ETests/Common/XunitLogger.cs similarity index 100% rename from test/E2ETests/Common/XunitLogger.cs rename to test/MusicStore.E2ETests/Common/XunitLogger.cs diff --git a/test/E2ETests/Http.config b/test/MusicStore.E2ETests/Http.config similarity index 100% rename from test/E2ETests/Http.config rename to test/MusicStore.E2ETests/Http.config diff --git a/test/E2ETests/Implementation/FacebookLoginScenarios.cs b/test/MusicStore.E2ETests/Implementation/FacebookLoginScenarios.cs similarity index 100% rename from test/E2ETests/Implementation/FacebookLoginScenarios.cs rename to test/MusicStore.E2ETests/Implementation/FacebookLoginScenarios.cs diff --git a/test/E2ETests/Implementation/GoogleLoginScenarios.cs b/test/MusicStore.E2ETests/Implementation/GoogleLoginScenarios.cs similarity index 100% rename from test/E2ETests/Implementation/GoogleLoginScenarios.cs rename to test/MusicStore.E2ETests/Implementation/GoogleLoginScenarios.cs diff --git a/test/E2ETests/Implementation/MicrosoftAccountAuthenticationScenarios.cs b/test/MusicStore.E2ETests/Implementation/MicrosoftAccountAuthenticationScenarios.cs similarity index 100% rename from test/E2ETests/Implementation/MicrosoftAccountAuthenticationScenarios.cs rename to test/MusicStore.E2ETests/Implementation/MicrosoftAccountAuthenticationScenarios.cs diff --git a/test/E2ETests/Implementation/OpenIdConnectLoginScenarios.cs b/test/MusicStore.E2ETests/Implementation/OpenIdConnectLoginScenarios.cs similarity index 100% rename from test/E2ETests/Implementation/OpenIdConnectLoginScenarios.cs rename to test/MusicStore.E2ETests/Implementation/OpenIdConnectLoginScenarios.cs diff --git a/test/E2ETests/Implementation/TwitterLoginScenarios.cs b/test/MusicStore.E2ETests/Implementation/TwitterLoginScenarios.cs similarity index 100% rename from test/E2ETests/Implementation/TwitterLoginScenarios.cs rename to test/MusicStore.E2ETests/Implementation/TwitterLoginScenarios.cs diff --git a/test/E2ETests/Implementation/Validator.cs b/test/MusicStore.E2ETests/Implementation/Validator.cs similarity index 100% rename from test/E2ETests/Implementation/Validator.cs rename to test/MusicStore.E2ETests/Implementation/Validator.cs diff --git a/test/E2ETests/E2ETests.csproj b/test/MusicStore.E2ETests/MusicStore.E2ETests.csproj similarity index 100% rename from test/E2ETests/E2ETests.csproj rename to test/MusicStore.E2ETests/MusicStore.E2ETests.csproj diff --git a/test/E2ETests/MusicStoreConfig.cs b/test/MusicStore.E2ETests/MusicStoreConfig.cs similarity index 100% rename from test/E2ETests/MusicStoreConfig.cs rename to test/MusicStore.E2ETests/MusicStoreConfig.cs diff --git a/test/E2ETests/NtlmAuthentation.config b/test/MusicStore.E2ETests/NtlmAuthentation.config similarity index 100% rename from test/E2ETests/NtlmAuthentation.config rename to test/MusicStore.E2ETests/NtlmAuthentation.config diff --git a/test/MusicStore.E2ETests/NtlmAuthentationTest.cs b/test/MusicStore.E2ETests/NtlmAuthentationTest.cs new file mode 100644 index 0000000000..481cc28409 --- /dev/null +++ b/test/MusicStore.E2ETests/NtlmAuthentationTest.cs @@ -0,0 +1,94 @@ +using Microsoft.AspNetCore.Server.IntegrationTesting; +using Microsoft.AspNetCore.Server.IntegrationTesting.xunit; +using Microsoft.AspNetCore.Testing.xunit; +using Microsoft.DotNet.PlatformAbstractions; +using Microsoft.Extensions.Logging; +using System; +using System.Collections.Generic; +using System.IO; +using System.Net.Http; +using System.Threading.Tasks; +using Xunit; +using Xunit.Abstractions; + +namespace E2ETests +{ + public class NtlmAuthenticationTests : LoggedTest + { + public NtlmAuthenticationTests(ITestOutputHelper output) : base(output) + { + } + + [ConditionalTheory, Trait("E2Etests", "E2Etests")] + [OSSkipCondition(OperatingSystems.Linux)] + [OSSkipCondition(OperatingSystems.MacOSX)] + [InlineData(ServerType.WebListener, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, ApplicationType.Portable)] + [InlineData(ServerType.WebListener, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, ApplicationType.Standalone, + Skip = "https://github.com/aspnet/MusicStore/issues/761")] + [InlineData(ServerType.IISExpress, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, ApplicationType.Portable)] + [InlineData(ServerType.IISExpress, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, ApplicationType.Standalone, + Skip = "https://github.com/aspnet/MusicStore/issues/761")] + public async Task NtlmAuthenticationTest(ServerType serverType, RuntimeFlavor runtimeFlavor, RuntimeArchitecture architecture, ApplicationType applicationType) + { + var testName = $"NtlmAuthentication_{serverType}_{runtimeFlavor}_{architecture}_{applicationType}"; + using (StartLog(out var loggerFactory, testName)) + { + var logger = loggerFactory.CreateLogger("NtlmAuthenticationTest"); + var musicStoreDbName = DbUtils.GetUniqueName(); + + var deploymentParameters = new DeploymentParameters(Helpers.GetApplicationPath(applicationType), serverType, runtimeFlavor, architecture) + { + PublishApplicationBeforeDeployment = true, + PreservePublishedApplicationForDebugging = Helpers.PreservePublishedApplicationForDebugging, + TargetFramework = runtimeFlavor == RuntimeFlavor.Clr ? "net46" : "netcoreapp2.0", + Configuration = Helpers.GetCurrentBuildConfiguration(), + ApplicationType = applicationType, + EnvironmentName = "NtlmAuthentication", //Will pick the Start class named 'StartupNtlmAuthentication' + ServerConfigTemplateContent = (serverType == ServerType.IISExpress) ? File.ReadAllText(Path.Combine(AppContext.BaseDirectory, "NtlmAuthentation.config")) : null, + SiteName = "MusicStoreNtlmAuthentication", //This is configured in the NtlmAuthentication.config + UserAdditionalCleanup = parameters => + { + DbUtils.DropDatabase(musicStoreDbName, logger); + } + }; + + if (applicationType == ApplicationType.Standalone) + { + deploymentParameters.AdditionalPublishParameters = " -r " + RuntimeEnvironment.GetRuntimeIdentifier(); + } + + // Override the connection strings using environment based configuration + deploymentParameters.EnvironmentVariables + .Add(new KeyValuePair( + MusicStoreConfig.ConnectionStringKey, + DbUtils.CreateConnectionString(musicStoreDbName))); + + using (var deployer = ApplicationDeployerFactory.Create(deploymentParameters, loggerFactory)) + { + var deploymentResult = await deployer.DeployAsync(); + var httpClientHandler = new HttpClientHandler() { UseDefaultCredentials = true }; + var httpClient = deploymentResult.CreateHttpClient(httpClientHandler); + + // Request to base address and check if various parts of the body are rendered & measure the cold startup time. + var response = await RetryHelper.RetryRequest(async () => + { + return await httpClient.GetAsync(string.Empty); + }, logger: logger, cancellationToken: deploymentResult.HostShutdownToken); + + Assert.False(response == null, "Response object is null because the client could not " + + "connect to the server after multiple retries"); + + var validator = new Validator(httpClient, httpClientHandler, logger, deploymentResult); + + logger.LogInformation("Verifying home page"); + await validator.VerifyNtlmHomePage(response); + + logger.LogInformation("Verifying access to store with permissions"); + await validator.AccessStoreWithPermissions(); + + logger.LogInformation("Variation completed successfully."); + } + } + } + } +} diff --git a/test/MusicStore.E2ETests/OpenIdConnectTests.cs b/test/MusicStore.E2ETests/OpenIdConnectTests.cs new file mode 100644 index 0000000000..f892ca973a --- /dev/null +++ b/test/MusicStore.E2ETests/OpenIdConnectTests.cs @@ -0,0 +1,119 @@ +using System; +using System.Collections.Generic; +using System.Net.Http; +using System.Threading.Tasks; +using E2ETests.Common; +using Microsoft.AspNetCore.Server.IntegrationTesting; +using Microsoft.AspNetCore.Testing.xunit; +using Microsoft.DotNet.PlatformAbstractions; +using Microsoft.Extensions.Logging; +using Xunit; +using Xunit.Abstractions; +using Microsoft.AspNetCore.Server.IntegrationTesting.xunit; + +namespace E2ETests +{ + public class OpenIdConnectTests : LoggedTest + { + public OpenIdConnectTests(ITestOutputHelper output) : base(output) + { + } + + [ConditionalTheory, Trait("E2Etests", "E2Etests")] + [OSSkipCondition(OperatingSystems.Linux)] + [OSSkipCondition(OperatingSystems.MacOSX)] + //[InlineData(ServerType.Kestrel, RuntimeFlavor.Clr, RuntimeArchitecture.x64, ApplicationType.Portable)] + [InlineData(ServerType.Kestrel, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, ApplicationType.Portable)] + [InlineData(ServerType.Kestrel, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, ApplicationType.Standalone, + Skip = "https://github.com/aspnet/MusicStore/issues/761")] + public async Task OpenIdConnect_OnWindowsOS( + ServerType serverType, + RuntimeFlavor runtimeFlavor, + RuntimeArchitecture architecture, + ApplicationType applicationType) + { + await OpenIdConnectTestSuite(serverType, runtimeFlavor, architecture, applicationType); + } + + [ConditionalTheory, Trait("E2Etests", "E2Etests")] + [OSSkipCondition(OperatingSystems.Windows)] + [InlineData(ServerType.Kestrel, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, ApplicationType.Portable)] + [InlineData(ServerType.Kestrel, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, ApplicationType.Standalone, + Skip = "https://github.com/aspnet/MusicStore/issues/761")] + public async Task OpenIdConnect_OnNonWindows(ServerType serverType, RuntimeFlavor runtimeFlavor, RuntimeArchitecture architecture, ApplicationType applicationType) + { + await OpenIdConnectTestSuite(serverType, runtimeFlavor, architecture, applicationType); + } + + // TODO: temporarily disabling x86 tests as dotnet xunit test runner currently does not support 32-bit + + //[ConditionalTheory(Skip = "https://github.com/aspnet/MusicStore/issues/565"), Trait("E2Etests", "E2Etests")] + //[OSSkipCondition(OperatingSystems.Windows)] + //[InlineData(ServerType.Kestrel, RuntimeFlavor.Clr, RuntimeArchitecture.x86, ApplicationType.Portable)] + //public async Task OpenIdConnect_OnMono(ServerType serverType, RuntimeFlavor runtimeFlavor, RuntimeArchitecture architecture, ApplicationType applicationType) + //{ + // await OpenIdConnectTestSuite(serverType, runtimeFlavor, architecture); + //} + + private async Task OpenIdConnectTestSuite(ServerType serverType, RuntimeFlavor runtimeFlavor, RuntimeArchitecture architecture, ApplicationType applicationType) + { + var testName = $"OpenIdConnectTestSuite_{serverType}_{runtimeFlavor}_{architecture}_{applicationType}"; + using (StartLog(out var loggerFactory, testName)) + { + var logger = loggerFactory.CreateLogger("OpenIdConnectTestSuite"); + var musicStoreDbName = DbUtils.GetUniqueName(); + + var deploymentParameters = new DeploymentParameters(Helpers.GetApplicationPath(applicationType), serverType, runtimeFlavor, architecture) + { + PublishApplicationBeforeDeployment = true, + PreservePublishedApplicationForDebugging = Helpers.PreservePublishedApplicationForDebugging, + TargetFramework = runtimeFlavor == RuntimeFlavor.Clr ? "net46" : "netcoreapp2.0", + Configuration = Helpers.GetCurrentBuildConfiguration(), + ApplicationType = applicationType, + EnvironmentName = "OpenIdConnectTesting", + UserAdditionalCleanup = parameters => + { + DbUtils.DropDatabase(musicStoreDbName, logger); + } + }; + + + deploymentParameters.AdditionalPublishParameters = + (applicationType == ApplicationType.Standalone ? $" -r {RuntimeEnvironment.GetRuntimeIdentifier()}" : "") + + " /p:PublishForTesting=true"; + + // Override the connection strings using environment based configuration + deploymentParameters.EnvironmentVariables + .Add(new KeyValuePair( + MusicStoreConfig.ConnectionStringKey, + DbUtils.CreateConnectionString(musicStoreDbName))); + + using (var deployer = ApplicationDeployerFactory.Create(deploymentParameters, loggerFactory)) + { + var deploymentResult = await deployer.DeployAsync(); + var httpClientHandler = new HttpClientHandler(); + var httpClient = deploymentResult.CreateHttpClient(httpClientHandler); + + // Request to base address and check if various parts of the body are rendered & measure the cold startup time. + var response = await RetryHelper.RetryRequest(async () => + { + return await httpClient.GetAsync(string.Empty); + }, logger: logger, cancellationToken: deploymentResult.HostShutdownToken); + + Assert.False(response == null, "Response object is null because the client could not " + + "connect to the server after multiple retries"); + + var validator = new Validator(httpClient, httpClientHandler, logger, deploymentResult); + + logger.LogInformation("Verifying home page"); + await validator.VerifyHomePage(response); + + logger.LogInformation("Verifying login by OpenIdConnect"); + await validator.LoginWithOpenIdConnect(); + + logger.LogInformation("Variation completed successfully."); + } + } + } + } +} \ No newline at end of file diff --git a/test/E2ETests/Properties/AssemblyInfo.cs b/test/MusicStore.E2ETests/Properties/AssemblyInfo.cs similarity index 100% rename from test/E2ETests/Properties/AssemblyInfo.cs rename to test/MusicStore.E2ETests/Properties/AssemblyInfo.cs diff --git a/test/E2ETests/PublishAndRunTests.cs b/test/MusicStore.E2ETests/PublishAndRunTests.cs similarity index 52% rename from test/E2ETests/PublishAndRunTests.cs rename to test/MusicStore.E2ETests/PublishAndRunTests.cs index 12e4915c8f..3fe2fc9d40 100644 --- a/test/E2ETests/PublishAndRunTests.cs +++ b/test/MusicStore.E2ETests/PublishAndRunTests.cs @@ -9,17 +9,17 @@ using Microsoft.DotNet.PlatformAbstractions; using Microsoft.Extensions.Logging; using Xunit; using Xunit.Abstractions; +using Microsoft.AspNetCore.Server.IntegrationTesting.xunit; namespace E2ETests { - public class PublishAndRunTests_OnX64 : IDisposable + public class PublishAndRunTests_OnX64 { - private readonly ILoggerFactory _loggerFactory; + private readonly ITestOutputHelper _output; public PublishAndRunTests_OnX64(ITestOutputHelper output) { - _loggerFactory = new LoggerFactory() - .AddXunit(output); + _output = output; } [ConditionalTheory, Trait("E2Etests", "PublishAndRun")] @@ -40,7 +40,7 @@ namespace E2ETests ApplicationType applicationType, bool noSource) { - var testRunner = new PublishAndRunTests(_loggerFactory); + var testRunner = new PublishAndRunTests(_output); await testRunner.Publish_And_Run_Tests( serverType, runtimeFlavor, architecture, applicationType, noSource); } @@ -57,27 +57,21 @@ namespace E2ETests ApplicationType applicationType, bool noSource) { - var testRunner = new PublishAndRunTests(_loggerFactory); + var testRunner = new PublishAndRunTests(_output); await testRunner.Publish_And_Run_Tests( serverType, runtimeFlavor, architecture, applicationType, noSource); } - - public void Dispose() - { - _loggerFactory.Dispose(); - } } // TODO: temporarily disabling x86 tests as dotnet xunit test runner currently does not support 32-bit // public - class PublishAndRunTests_OnX86 : IDisposable + class PublishAndRunTests_OnX86 { - private readonly ILoggerFactory _loggerFactory; + private readonly ITestOutputHelper _output; public PublishAndRunTests_OnX86(ITestOutputHelper output) { - _loggerFactory = new LoggerFactory() - .AddXunit(output); + _output = output; } [ConditionalTheory, Trait("E2Etests", "PublishAndRun")] @@ -96,7 +90,7 @@ namespace E2ETests ApplicationType applicationType, bool noSource) { - var testRunner = new PublishAndRunTests(_loggerFactory); + var testRunner = new PublishAndRunTests(_output); await testRunner.Publish_And_Run_Tests( serverType, runtimeFlavor, architecture, applicationType, noSource); } @@ -111,24 +105,16 @@ namespace E2ETests ApplicationType applicationType, bool noSource) { - var testRunner = new PublishAndRunTests(_loggerFactory); + var testRunner = new PublishAndRunTests(_output); await testRunner.Publish_And_Run_Tests( serverType, runtimeFlavor, architecture, applicationType, noSource); } - - public void Dispose() - { - _loggerFactory.Dispose(); - } } - public class PublishAndRunTests + public class PublishAndRunTests : LoggedTest { - private ILoggerFactory _loggerFactory; - - public PublishAndRunTests(ILoggerFactory loggerFactory) + public PublishAndRunTests(ITestOutputHelper output) : base(output) { - _loggerFactory = loggerFactory; } public async Task Publish_And_Run_Tests( @@ -138,79 +124,71 @@ namespace E2ETests ApplicationType applicationType, bool noSource) { - var testName = $"PublishAndRunTests:{serverType}:{runtimeFlavor}:{architecture}:{applicationType}:NoSource={noSource}"; - try + var noSourceStr = noSource ? "NoSource" : "WithSource"; + var testName = $"PublishAndRunTests_{serverType}_{runtimeFlavor}_{architecture}_{applicationType}_{noSourceStr}"; + using (StartLog(out var loggerFactory, testName)) { - Console.WriteLine($"Starting {testName}"); - var logger = _loggerFactory.CreateLogger(testName); - using (logger.BeginScope("Publish_And_Run_Tests")) + var logger = loggerFactory.CreateLogger("Publish_And_Run_Tests"); + var musicStoreDbName = DbUtils.GetUniqueName(); + + var deploymentParameters = new DeploymentParameters( + Helpers.GetApplicationPath(applicationType), serverType, runtimeFlavor, architecture) { - var musicStoreDbName = DbUtils.GetUniqueName(); - - var deploymentParameters = new DeploymentParameters( - Helpers.GetApplicationPath(applicationType), serverType, runtimeFlavor, architecture) + PublishApplicationBeforeDeployment = true, + PreservePublishedApplicationForDebugging = Helpers.PreservePublishedApplicationForDebugging, + TargetFramework = runtimeFlavor == RuntimeFlavor.Clr ? "net46" : "netcoreapp2.0", + Configuration = Helpers.GetCurrentBuildConfiguration(), + ApplicationType = applicationType, + UserAdditionalCleanup = parameters => { - PublishApplicationBeforeDeployment = true, - PreservePublishedApplicationForDebugging = Helpers.PreservePublishedApplicationForDebugging, - TargetFramework = runtimeFlavor == RuntimeFlavor.Clr ? "net46" : "netcoreapp2.0", - Configuration = Helpers.GetCurrentBuildConfiguration(), - ApplicationType = applicationType, - UserAdditionalCleanup = parameters => - { - DbUtils.DropDatabase(musicStoreDbName, logger); - } - }; - - if (applicationType == ApplicationType.Standalone) - { - deploymentParameters.AdditionalPublishParameters = "-r " + RuntimeEnvironment.GetRuntimeIdentifier(); + DbUtils.DropDatabase(musicStoreDbName, logger); } + }; - // Override the connection strings using environment based configuration - deploymentParameters.EnvironmentVariables - .Add(new KeyValuePair( - MusicStoreConfig.ConnectionStringKey, - DbUtils.CreateConnectionString(musicStoreDbName))); - - using (var deployer = ApplicationDeployerFactory.Create(deploymentParameters, _loggerFactory)) - { - var deploymentResult = await deployer.DeployAsync(); - var httpClientHandler = new HttpClientHandler() { UseDefaultCredentials = true }; - var httpClient = new HttpClient(httpClientHandler); - httpClient.BaseAddress = new Uri(deploymentResult.ApplicationBaseUri); - - // Request to base address and check if various parts of the body are rendered & - // measure the cold startup time. - // Add retry logic since tests are flaky on mono due to connection issues - var response = await RetryHelper.RetryRequest(async () => await httpClient.GetAsync(string.Empty), logger: logger, cancellationToken: deploymentResult.HostShutdownToken); - - Assert.False(response == null, "Response object is null because the client could not " + - "connect to the server after multiple retries"); - - var validator = new Validator(httpClient, httpClientHandler, logger, deploymentResult); - - Console.WriteLine("Verifying home page"); - await validator.VerifyHomePage(response); - - Console.WriteLine("Verifying static files are served from static file middleware"); - await validator.VerifyStaticContentServed(); - - if (serverType != ServerType.IISExpress) - { - if (Directory.GetFiles( - deploymentParameters.ApplicationPath, "*.cmd", SearchOption.TopDirectoryOnly).Length > 0) - { - throw new Exception("publishExclude parameter values are not honored."); - } - } - - logger.LogInformation("Variation completed successfully."); - } + if (applicationType == ApplicationType.Standalone) + { + deploymentParameters.AdditionalPublishParameters = "-r " + RuntimeEnvironment.GetRuntimeIdentifier(); + } + + // Override the connection strings using environment based configuration + deploymentParameters.EnvironmentVariables + .Add(new KeyValuePair( + MusicStoreConfig.ConnectionStringKey, + DbUtils.CreateConnectionString(musicStoreDbName))); + + using (var deployer = ApplicationDeployerFactory.Create(deploymentParameters, loggerFactory)) + { + var deploymentResult = await deployer.DeployAsync(); + var httpClientHandler = new HttpClientHandler() { UseDefaultCredentials = true }; + var httpClient = deploymentResult.CreateHttpClient(httpClientHandler); + + // Request to base address and check if various parts of the body are rendered & + // measure the cold startup time. + // Add retry logic since tests are flaky on mono due to connection issues + var response = await RetryHelper.RetryRequest(async () => await httpClient.GetAsync(string.Empty), logger: logger, cancellationToken: deploymentResult.HostShutdownToken); + + Assert.False(response == null, "Response object is null because the client could not " + + "connect to the server after multiple retries"); + + var validator = new Validator(httpClient, httpClientHandler, logger, deploymentResult); + + logger.LogInformation("Verifying home page"); + await validator.VerifyHomePage(response); + + logger.LogInformation("Verifying static files are served from static file middleware"); + await validator.VerifyStaticContentServed(); + + if (serverType != ServerType.IISExpress) + { + if (Directory.GetFiles( + deploymentParameters.ApplicationPath, "*.cmd", SearchOption.TopDirectoryOnly).Length > 0) + { + throw new Exception("publishExclude parameter values are not honored."); + } + } + + logger.LogInformation("Variation completed successfully."); } - } - finally - { - Console.WriteLine($"Finished {testName}"); } } } diff --git a/test/E2ETests/RemoteDeploymentConfig.cs b/test/MusicStore.E2ETests/RemoteDeploymentConfig.cs similarity index 100% rename from test/E2ETests/RemoteDeploymentConfig.cs rename to test/MusicStore.E2ETests/RemoteDeploymentConfig.cs diff --git a/test/MusicStore.E2ETests/SmokeTestHelper.cs b/test/MusicStore.E2ETests/SmokeTestHelper.cs new file mode 100644 index 0000000000..ec4f7ee934 --- /dev/null +++ b/test/MusicStore.E2ETests/SmokeTestHelper.cs @@ -0,0 +1,114 @@ +using System; +using System.Net.Http; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Server.IntegrationTesting; +using Microsoft.Extensions.Logging; +using Xunit; + +namespace E2ETests +{ + public static class SmokeTestHelper + { + public static async Task RunTestsAsync(DeploymentResult deploymentResult, ILogger logger) + { + var httpClientHandler = new HttpClientHandler(); + var httpClient = deploymentResult.CreateHttpClient(httpClientHandler); + httpClient.Timeout = TimeSpan.FromSeconds(15); + + // Request to base address and check if various parts of the body are rendered + // & measure the cold startup time. + var response = await RetryHelper.RetryRequest(async () => + { + return await httpClient.GetAsync(string.Empty); + }, logger, cancellationToken: deploymentResult.HostShutdownToken); + + Assert.False(response == null, "Response object is null because the client could not " + + "connect to the server after multiple retries"); + + var validator = new Validator(httpClient, httpClientHandler, logger, deploymentResult); + + logger.LogInformation("Verifying home page"); + await validator.VerifyHomePage(response); + + logger.LogInformation("Verifying static files are served from static file middleware"); + await validator.VerifyStaticContentServed(); + + logger.LogInformation("Verifying access to a protected resource should automatically redirect to login page."); + await validator.AccessStoreWithoutPermissions(); + + logger.LogInformation("Verifying mismatched passwords trigger validaton errors during user registration"); + await validator.RegisterUserWithNonMatchingPasswords(); + + logger.LogInformation("Verifying valid user registration"); + var generatedEmail = await validator.RegisterValidUser(); + + logger.LogInformation("Verifying duplicate user email registration"); + await validator.RegisterExistingUser(generatedEmail); + + logger.LogInformation("Verifying incorrect password login"); + await validator.SignInWithInvalidPassword(generatedEmail, "InvalidPassword~1"); + + logger.LogInformation("Verifying valid user log in"); + await validator.SignInWithUser(generatedEmail, "Password~1"); + + logger.LogInformation("Verifying change password"); + await validator.ChangePassword(generatedEmail); + + logger.LogInformation("Verifying old password is not valid anymore"); + await validator.SignOutUser(generatedEmail); + await validator.SignInWithInvalidPassword(generatedEmail, "Password~1"); + await validator.SignInWithUser(generatedEmail, "Password~2"); + + logger.LogInformation("Verifying authenticated user trying to access unauthorized resource"); + await validator.AccessStoreWithoutPermissions(generatedEmail); + + logger.LogInformation("Verifying user log out"); + await validator.SignOutUser(generatedEmail); + + logger.LogInformation("Verifying admin user login"); + await validator.SignInWithUser("Administrator@test.com", "YouShouldChangeThisPassword1!"); + + logger.LogInformation("Verifying admin user's access to store manager page"); + await validator.AccessStoreWithPermissions(); + + logger.LogInformation("Verifying creating a new album"); + var albumName = await validator.CreateAlbum(); + var albumId = await validator.FetchAlbumIdFromName(albumName); + + logger.LogInformation("Verifying retrieved album details"); + await validator.VerifyAlbumDetails(albumId, albumName); + + logger.LogInformation("Verifying status code pages for non-existing items"); + await validator.VerifyStatusCodePages(); + + logger.LogInformation("Verifying non-admin view of an album"); + await validator.GetAlbumDetailsFromStore(albumId, albumName); + + logger.LogInformation("Verifying adding album to a cart"); + await validator.AddAlbumToCart(albumId, albumName); + + logger.LogInformation("Verifying cart checkout"); + await validator.CheckOutCartItems(); + + logger.LogInformation("Verifying deletion of album from a cart"); + await validator.DeleteAlbum(albumId, albumName); + + logger.LogInformation("Verifying administrator log out"); + await validator.SignOutUser("Administrator"); + + logger.LogInformation("Verifying Google login scenarios"); + await validator.LoginWithGoogle(); + + logger.LogInformation("Verifying Facebook login scenarios"); + await validator.LoginWithFacebook(); + + logger.LogInformation("Verifying Twitter login scenarios"); + await validator.LoginWithTwitter(); + + logger.LogInformation("Verifying Microsoft login scenarios"); + await validator.LoginWithMicrosoftAccount(); + + logger.LogInformation("Variation completed successfully."); + } + } +} diff --git a/test/E2ETests/SmokeTests.cs b/test/MusicStore.E2ETests/SmokeTests.cs similarity index 62% rename from test/E2ETests/SmokeTests.cs rename to test/MusicStore.E2ETests/SmokeTests.cs index ba891a73df..6961efc9fd 100644 --- a/test/E2ETests/SmokeTests.cs +++ b/test/MusicStore.E2ETests/SmokeTests.cs @@ -1,11 +1,10 @@ -using System; +using Microsoft.AspNetCore.Server.IntegrationTesting; +using Microsoft.AspNetCore.Server.IntegrationTesting.xunit; +using Microsoft.AspNetCore.Testing.xunit; +using Microsoft.DotNet.PlatformAbstractions; using System.Collections.Generic; using System.IO; using System.Threading.Tasks; -using Microsoft.AspNetCore.Server.IntegrationTesting; -using Microsoft.AspNetCore.Testing.xunit; -using Microsoft.DotNet.PlatformAbstractions; -using Microsoft.Extensions.Logging; using Xunit; using Xunit.Abstractions; @@ -13,14 +12,13 @@ namespace E2ETests { // Uses ports ranging 5001 - 5025. // TODO: temporarily disabling these tests as dotnet xunit runner does not support 32-bit yet. - internal class SmokeTests_X86 : IDisposable + internal class SmokeTests_X86 { - private readonly ILoggerFactory _loggerFactory; + private readonly ITestOutputHelper _output; public SmokeTests_X86(ITestOutputHelper output) { - _loggerFactory = new LoggerFactory() - .AddXunit(output); + _output = output; } [ConditionalTheory, Trait("E2Etests", "Smoke")] @@ -41,7 +39,7 @@ namespace E2ETests RuntimeArchitecture architecture, ApplicationType applicationType) { - var smokeTestRunner = new SmokeTests(_loggerFactory); + var smokeTestRunner = new SmokeTests(_output); await smokeTestRunner.SmokeTestSuite(serverType, runtimeFlavor, architecture, applicationType); } @@ -54,24 +52,18 @@ namespace E2ETests RuntimeArchitecture architecture, ApplicationType applicationType) { - var smokeTestRunner = new SmokeTests(_loggerFactory); + var smokeTestRunner = new SmokeTests(_output); await smokeTestRunner.SmokeTestSuite(serverType, runtimeFlavor, architecture, applicationType); } - - public void Dispose() - { - _loggerFactory.Dispose(); - } } - public class SmokeTests_X64 : IDisposable + public class SmokeTests_X64 { - private readonly ILoggerFactory _loggerFactory; + private readonly ITestOutputHelper _output; public SmokeTests_X64(ITestOutputHelper output) { - _loggerFactory = new LoggerFactory() - .AddXunit(output); + _output = output; } [ConditionalTheory, Trait("E2Etests", "Smoke")] @@ -95,7 +87,7 @@ namespace E2ETests RuntimeArchitecture architecture, ApplicationType applicationType) { - var smokeTestRunner = new SmokeTests(_loggerFactory); + var smokeTestRunner = new SmokeTests(_output); await smokeTestRunner.SmokeTestSuite(serverType, runtimeFlavor, architecture, applicationType); } @@ -110,23 +102,18 @@ namespace E2ETests RuntimeArchitecture architecture, ApplicationType applicationType) { - var smokeTestRunner = new SmokeTests(_loggerFactory); + var smokeTestRunner = new SmokeTests(_output); await smokeTestRunner.SmokeTestSuite(serverType, runtimeFlavor, architecture, applicationType); } - public void Dispose() - { - _loggerFactory.Dispose(); - } } - class SmokeTests_OnIIS : IDisposable + class SmokeTests_OnIIS { - private readonly ILoggerFactory _loggerFactory; + private readonly ITestOutputHelper _output; public SmokeTests_OnIIS(ITestOutputHelper output) { - _loggerFactory = new LoggerFactory() - .AddXunit(output); + _output = output; } [ConditionalTheory, Trait("E2Etests", "Smoke")] @@ -143,24 +130,16 @@ namespace E2ETests RuntimeArchitecture architecture, ApplicationType applicationType) { - var smokeTestRunner = new SmokeTests(_loggerFactory); + var smokeTestRunner = new SmokeTests(_output); await smokeTestRunner.SmokeTestSuite( serverType, runtimeFlavor, architecture, applicationType, noSource: true); } - - public void Dispose() - { - _loggerFactory.Dispose(); - } } - public class SmokeTests + public class SmokeTests : LoggedTest { - private ILoggerFactory _loggerFactory; - - public SmokeTests(ILoggerFactory loggerFactory) + public SmokeTests(ITestOutputHelper output) : base(output) { - _loggerFactory = loggerFactory; } public async Task SmokeTestSuite( @@ -170,56 +149,48 @@ namespace E2ETests ApplicationType applicationType, bool noSource = false) { - var testName = $"SmokeTestSuite:{serverType}:{runtimeFlavor}:{architecture}:{applicationType}"; - try + var testName = $"SmokeTestSuite_{serverType}_{runtimeFlavor}_{architecture}_{applicationType}"; + using (StartLog(out var loggerFactory, testName)) { - Console.WriteLine($"Starting {testName}"); - var logger = _loggerFactory.CreateLogger(testName); - using (logger.BeginScope("SmokeTestSuite")) + var logger = loggerFactory.CreateLogger("SmokeTestSuite"); + var musicStoreDbName = DbUtils.GetUniqueName(); + + var deploymentParameters = new DeploymentParameters( + Helpers.GetApplicationPath(applicationType), serverType, runtimeFlavor, architecture) { - var musicStoreDbName = DbUtils.GetUniqueName(); - - var deploymentParameters = new DeploymentParameters( - Helpers.GetApplicationPath(applicationType), serverType, runtimeFlavor, architecture) + EnvironmentName = "SocialTesting", + ServerConfigTemplateContent = (serverType == ServerType.IISExpress) ? File.ReadAllText("Http.config") : null, + SiteName = "MusicStoreTestSite", + PublishApplicationBeforeDeployment = true, + PreservePublishedApplicationForDebugging = Helpers.PreservePublishedApplicationForDebugging, + TargetFramework = runtimeFlavor == RuntimeFlavor.Clr ? "net46" : "netcoreapp2.0", + Configuration = Helpers.GetCurrentBuildConfiguration(), + ApplicationType = applicationType, + UserAdditionalCleanup = parameters => { - EnvironmentName = "SocialTesting", - ServerConfigTemplateContent = (serverType == ServerType.IISExpress) ? File.ReadAllText("Http.config") : null, - SiteName = "MusicStoreTestSite", - PublishApplicationBeforeDeployment = true, - PreservePublishedApplicationForDebugging = Helpers.PreservePublishedApplicationForDebugging, - TargetFramework = runtimeFlavor == RuntimeFlavor.Clr ? "net46" : "netcoreapp2.0", - Configuration = Helpers.GetCurrentBuildConfiguration(), - ApplicationType = applicationType, - UserAdditionalCleanup = parameters => - { - DbUtils.DropDatabase(musicStoreDbName, logger); - } - }; - - if (applicationType == ApplicationType.Standalone) - { - deploymentParameters.AdditionalPublishParameters = " -r " + RuntimeEnvironment.GetRuntimeIdentifier(); + DbUtils.DropDatabase(musicStoreDbName, logger); } + }; - // Override the connection strings using environment based configuration - deploymentParameters.EnvironmentVariables - .Add(new KeyValuePair( - MusicStoreConfig.ConnectionStringKey, - DbUtils.CreateConnectionString(musicStoreDbName))); - - using (var deployer = ApplicationDeployerFactory.Create(deploymentParameters, _loggerFactory)) - { - var deploymentResult = await deployer.DeployAsync(); - - Helpers.SetInMemoryStoreForIIS(deploymentParameters, logger); - - await SmokeTestHelper.RunTestsAsync(deploymentResult, logger); - } + if (applicationType == ApplicationType.Standalone) + { + deploymentParameters.AdditionalPublishParameters = " -r " + RuntimeEnvironment.GetRuntimeIdentifier(); + } + + // Override the connection strings using environment based configuration + deploymentParameters.EnvironmentVariables + .Add(new KeyValuePair( + MusicStoreConfig.ConnectionStringKey, + DbUtils.CreateConnectionString(musicStoreDbName))); + + using (var deployer = ApplicationDeployerFactory.Create(deploymentParameters, loggerFactory)) + { + var deploymentResult = await deployer.DeployAsync(); + + Helpers.SetInMemoryStoreForIIS(deploymentParameters, logger); + + await SmokeTestHelper.RunTestsAsync(deploymentResult, logger); } - } - finally - { - Console.WriteLine($"Finished {testName}"); } } } diff --git a/test/E2ETests/SmokeTestsOnNanoServer.cs b/test/MusicStore.E2ETests/SmokeTestsOnNanoServer.cs similarity index 78% rename from test/E2ETests/SmokeTestsOnNanoServer.cs rename to test/MusicStore.E2ETests/SmokeTestsOnNanoServer.cs index 850c8b9ac5..0b60795edd 100644 --- a/test/E2ETests/SmokeTestsOnNanoServer.cs +++ b/test/MusicStore.E2ETests/SmokeTestsOnNanoServer.cs @@ -1,12 +1,12 @@ -using System; +using Microsoft.AspNetCore.Server.IntegrationTesting; +using Microsoft.AspNetCore.Server.IntegrationTesting.xunit; +using Microsoft.AspNetCore.Testing.xunit; +using Microsoft.Extensions.Configuration; +using System; using System.Collections.Generic; using System.IO; using System.IO.Compression; using System.Threading.Tasks; -using Microsoft.AspNetCore.Server.IntegrationTesting; -using Microsoft.AspNetCore.Testing.xunit; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.Logging; using Xunit; using Xunit.Abstractions; @@ -14,18 +14,15 @@ namespace E2ETests { // These tests publish(on the machine where these tests on run) the MusicStore app to a local folder first // and then copy the published output to the target NanoServer and launch them. - public class SmokeTestsOnNanoServerUsingStandaloneRuntime : IDisposable + public class SmokeTestsOnNanoServerUsingStandaloneRuntime { private readonly SmokeTestsOnNanoServer _smokeTestsOnNanoServer; - private readonly ILoggerFactory _loggerFactory; private readonly RemoteDeploymentConfig _remoteDeploymentConfig; public SmokeTestsOnNanoServerUsingStandaloneRuntime(ITestOutputHelper output) { - _loggerFactory = new LoggerFactory() - .AddXunit(output); _remoteDeploymentConfig = RemoteDeploymentConfigHelper.GetConfiguration(); - _smokeTestsOnNanoServer = new SmokeTestsOnNanoServer(output, _remoteDeploymentConfig, _loggerFactory); + _smokeTestsOnNanoServer = new SmokeTestsOnNanoServer(output, _remoteDeploymentConfig); } [ConditionalTheory, Trait("E2ETests", "NanoServer")] @@ -43,11 +40,6 @@ namespace E2ETests var applicationBaseUrl = $"http://{_remoteDeploymentConfig.ServerName}:{portToListen}/"; await _smokeTestsOnNanoServer.RunTestsAsync(serverType, applicationBaseUrl, applicationType); } - - public void Dispose() - { - _loggerFactory.Dispose(); - } } // Tests here test portable app scenario, so we copy the dotnet runtime onto the @@ -55,20 +47,17 @@ namespace E2ETests // to have the path to this copied dotnet runtime folder in the share. // The dotnet runtime is copied only once for all the tests in this class. public class SmokeTestsOnNanoServerUsingSharedRuntime - : IClassFixture, IDisposable + : IClassFixture { private readonly SmokeTestsOnNanoServer _smokeTestsOnNanoServer; private readonly RemoteDeploymentConfig _remoteDeploymentConfig; - private readonly ILoggerFactory _loggerFactory; public SmokeTestsOnNanoServerUsingSharedRuntime( DotnetRuntimeSetupTestFixture dotnetRuntimeSetupTestFixture, ITestOutputHelper output) { - _loggerFactory = new LoggerFactory() - .AddXunit(output); _remoteDeploymentConfig = RemoteDeploymentConfigHelper.GetConfiguration(); _remoteDeploymentConfig.DotnetRuntimePathOnShare = dotnetRuntimeSetupTestFixture.DotnetRuntimePathOnShare; - _smokeTestsOnNanoServer = new SmokeTestsOnNanoServer(output, _remoteDeploymentConfig, _loggerFactory); + _smokeTestsOnNanoServer = new SmokeTestsOnNanoServer(output, _remoteDeploymentConfig); } [ConditionalTheory, Trait("E2Etests", "NanoServer")] @@ -84,11 +73,6 @@ namespace E2ETests await _smokeTestsOnNanoServer.RunTestsAsync(serverType, applicationBaseUrl, applicationType); } - public void Dispose() - { - _loggerFactory.Dispose(); - } - // Copies dotnet runtime to the target server's file share. public class DotnetRuntimeSetupTestFixture : IDisposable { @@ -236,14 +220,12 @@ namespace E2ETests } } - class SmokeTestsOnNanoServer + class SmokeTestsOnNanoServer : LoggedTest { - private readonly ILoggerFactory _loggerFactory; private readonly RemoteDeploymentConfig _remoteDeploymentConfig; - public SmokeTestsOnNanoServer(ITestOutputHelper output, RemoteDeploymentConfig config, ILoggerFactory loggerFactory) + public SmokeTestsOnNanoServer(ITestOutputHelper output, RemoteDeploymentConfig config) : base(output) { - _loggerFactory = loggerFactory; _remoteDeploymentConfig = config; } @@ -252,51 +234,43 @@ namespace E2ETests string applicationBaseUrl, ApplicationType applicationType) { - var testName = $"SmokeTestsOnNanoServer:{serverType}:{applicationType}"; - try + var testName = $"SmokeTestsOnNanoServer_{serverType}_{applicationType}"; + using (StartLog(out var loggerFactory, testName)) { - Console.WriteLine($"Started {testName}"); - var logger = _loggerFactory.CreateLogger(testName); - using (logger.BeginScope(nameof(SmokeTestsOnNanoServerUsingStandaloneRuntime))) + var logger = loggerFactory.CreateLogger(nameof(SmokeTestsOnNanoServerUsingStandaloneRuntime)); + var deploymentParameters = new RemoteWindowsDeploymentParameters( + Helpers.GetApplicationPath(applicationType), + _remoteDeploymentConfig.DotnetRuntimePathOnShare, + serverType, + RuntimeFlavor.CoreClr, + RuntimeArchitecture.x64, + _remoteDeploymentConfig.FileSharePath, + _remoteDeploymentConfig.ServerName, + _remoteDeploymentConfig.AccountName, + _remoteDeploymentConfig.AccountPassword) { - var deploymentParameters = new RemoteWindowsDeploymentParameters( - Helpers.GetApplicationPath(applicationType), - _remoteDeploymentConfig.DotnetRuntimePathOnShare, - serverType, - RuntimeFlavor.CoreClr, - RuntimeArchitecture.x64, - _remoteDeploymentConfig.FileSharePath, - _remoteDeploymentConfig.ServerName, - _remoteDeploymentConfig.AccountName, - _remoteDeploymentConfig.AccountPassword) - { - TargetFramework = "netcoreapp2.0", - ApplicationBaseUriHint = applicationBaseUrl, - ApplicationType = applicationType - }; + TargetFramework = "netcoreapp2.0", + ApplicationBaseUriHint = applicationBaseUrl, + ApplicationType = applicationType + }; - if (applicationType == ApplicationType.Standalone) - { - // Unable to use the RuntimeEnvironment.GetRuntimeIdentifier API here as NanoServer which is - // part of Windows Server 2016 has a RID of 'win10-x64' where as the CI servers currently - // run on Windows Server 2012 or less, which have different RIDs. - deploymentParameters.AdditionalPublishParameters = "-r win10-x64"; - } - - deploymentParameters.EnvironmentVariables.Add( - new KeyValuePair("ASPNETCORE_ENVIRONMENT", "SocialTesting")); - - using (var deployer = new RemoteWindowsDeployer(deploymentParameters, logger)) - { - var deploymentResult = await deployer.DeployAsync(); - - await SmokeTestHelper.RunTestsAsync(deploymentResult, logger); - } + if (applicationType == ApplicationType.Standalone) + { + // Unable to use the RuntimeEnvironment.GetRuntimeIdentifier API here as NanoServer which is + // part of Windows Server 2016 has a RID of 'win10-x64' where as the CI servers currently + // run on Windows Server 2012 or less, which have different RIDs. + deploymentParameters.AdditionalPublishParameters = "-r win10-x64"; + } + + deploymentParameters.EnvironmentVariables.Add( + new KeyValuePair("ASPNETCORE_ENVIRONMENT", "SocialTesting")); + + using (var deployer = new RemoteWindowsDeployer(deploymentParameters, loggerFactory)) + { + var deploymentResult = await deployer.DeployAsync(); + + await SmokeTestHelper.RunTestsAsync(deploymentResult, logger); } - } - finally - { - Console.WriteLine($"Finished {testName}"); } } } diff --git a/test/E2ETests/remoteDeploymentConfig.json b/test/MusicStore.E2ETests/remoteDeploymentConfig.json similarity index 100% rename from test/E2ETests/remoteDeploymentConfig.json rename to test/MusicStore.E2ETests/remoteDeploymentConfig.json