Added smoke tests to verify on Nano server
This commit is contained in:
parent
10a1a15881
commit
40abffefcb
|
|
@ -25,7 +25,7 @@ namespace MusicStore
|
||||||
{
|
{
|
||||||
public class StartupSocialTesting
|
public class StartupSocialTesting
|
||||||
{
|
{
|
||||||
private readonly IRuntimeEnvironment _runtimeEnvironment;
|
private readonly Platform _platform;
|
||||||
|
|
||||||
public StartupSocialTesting(IApplicationEnvironment appEnvironment, IRuntimeEnvironment runtimeEnvironment)
|
public StartupSocialTesting(IApplicationEnvironment appEnvironment, IRuntimeEnvironment runtimeEnvironment)
|
||||||
{
|
{
|
||||||
|
|
@ -38,7 +38,7 @@ namespace MusicStore
|
||||||
.AddJsonFile("configoverride.json", optional: true); // Used to override some configuration parameters that cannot be overridden by environment.
|
.AddJsonFile("configoverride.json", optional: true); // Used to override some configuration parameters that cannot be overridden by environment.
|
||||||
|
|
||||||
Configuration = builder.Build();
|
Configuration = builder.Build();
|
||||||
_runtimeEnvironment = runtimeEnvironment;
|
_platform = new Platform(runtimeEnvironment);
|
||||||
}
|
}
|
||||||
|
|
||||||
public IConfiguration Configuration { get; private set; }
|
public IConfiguration Configuration { get; private set; }
|
||||||
|
|
@ -48,7 +48,9 @@ namespace MusicStore
|
||||||
services.Configure<AppSettings>(Configuration.GetSection("AppSettings"));
|
services.Configure<AppSettings>(Configuration.GetSection("AppSettings"));
|
||||||
|
|
||||||
//Sql client not available on mono
|
//Sql client not available on mono
|
||||||
var useInMemoryStore = !_runtimeEnvironment.OperatingSystem.Equals("Windows", StringComparison.OrdinalIgnoreCase);
|
var useInMemoryStore = !_platform.IsRunningOnWindows
|
||||||
|
|| _platform.IsRunningOnMono
|
||||||
|
|| _platform.IsRunningOnNanoServer;
|
||||||
|
|
||||||
// Add EF services to the services container
|
// Add EF services to the services container
|
||||||
if (useInMemoryStore)
|
if (useInMemoryStore)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
namespace E2ETests
|
||||||
|
{
|
||||||
|
public class RemoteDeploymentConfig
|
||||||
|
{
|
||||||
|
public string ServerName { get; set; }
|
||||||
|
|
||||||
|
public string AccountName { get; set; }
|
||||||
|
|
||||||
|
public string AccountPassword { get; set; }
|
||||||
|
|
||||||
|
public string FileSharePath { get; set; }
|
||||||
|
|
||||||
|
public string ExecutableRelativePath { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,124 @@
|
||||||
|
using System;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.AspNetCore.Server.Testing;
|
||||||
|
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(5),
|
||||||
|
};
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
await validator.VerifyHomePage(response);
|
||||||
|
|
||||||
|
// Verify the static file middleware can serve static content.
|
||||||
|
await validator.VerifyStaticContentServed();
|
||||||
|
|
||||||
|
// Making a request to a protected resource should automatically redirect to login page.
|
||||||
|
await validator.AccessStoreWithoutPermissions();
|
||||||
|
|
||||||
|
// Register a user - Negative scenario where the Password & ConfirmPassword do not match.
|
||||||
|
await validator.RegisterUserWithNonMatchingPasswords();
|
||||||
|
|
||||||
|
// Register a valid user.
|
||||||
|
var generatedEmail = await validator.RegisterValidUser();
|
||||||
|
|
||||||
|
await validator.SignInWithUser(generatedEmail, "Password~1");
|
||||||
|
|
||||||
|
// Register a user - Negative scenario : Trying to register a user name that's already registered.
|
||||||
|
await validator.RegisterExistingUser(generatedEmail);
|
||||||
|
|
||||||
|
// Logout from this user session - This should take back to the home page
|
||||||
|
await validator.SignOutUser(generatedEmail);
|
||||||
|
|
||||||
|
// Sign in scenarios: Invalid password - Expected an invalid user name password error.
|
||||||
|
await validator.SignInWithInvalidPassword(generatedEmail, "InvalidPassword~1");
|
||||||
|
|
||||||
|
// Sign in scenarios: Valid user name & password.
|
||||||
|
await validator.SignInWithUser(generatedEmail, "Password~1");
|
||||||
|
|
||||||
|
// Change password scenario
|
||||||
|
await validator.ChangePassword(generatedEmail);
|
||||||
|
|
||||||
|
// SignIn with old password and verify old password is not allowed and new password is allowed
|
||||||
|
await validator.SignOutUser(generatedEmail);
|
||||||
|
await validator.SignInWithInvalidPassword(generatedEmail, "Password~1");
|
||||||
|
await validator.SignInWithUser(generatedEmail, "Password~2");
|
||||||
|
|
||||||
|
// Making a request to a protected resource that this user does not have access to - should
|
||||||
|
// automatically redirect to the configured access denied page
|
||||||
|
await validator.AccessStoreWithoutPermissions(generatedEmail);
|
||||||
|
|
||||||
|
// Logout from this user session - This should take back to the home page
|
||||||
|
await validator.SignOutUser(generatedEmail);
|
||||||
|
|
||||||
|
// Login as an admin user
|
||||||
|
await validator.SignInWithUser("Administrator@test.com", "YouShouldChangeThisPassword1!");
|
||||||
|
|
||||||
|
// Now navigating to the store manager should work fine as this user has
|
||||||
|
// the necessary permission to administer the store.
|
||||||
|
await validator.AccessStoreWithPermissions();
|
||||||
|
|
||||||
|
// Create an album
|
||||||
|
var albumName = await validator.CreateAlbum();
|
||||||
|
var albumId = await validator.FetchAlbumIdFromName(albumName);
|
||||||
|
|
||||||
|
// Get details of the album
|
||||||
|
await validator.VerifyAlbumDetails(albumId, albumName);
|
||||||
|
|
||||||
|
// Verify status code pages acts on non-existing items.
|
||||||
|
await validator.VerifyStatusCodePages();
|
||||||
|
|
||||||
|
// Get the non-admin view of the album.
|
||||||
|
await validator.GetAlbumDetailsFromStore(albumId, albumName);
|
||||||
|
|
||||||
|
// Add an album to cart and checkout the same
|
||||||
|
await validator.AddAlbumToCart(albumId, albumName);
|
||||||
|
await validator.CheckOutCartItems();
|
||||||
|
|
||||||
|
// Delete the album from store
|
||||||
|
await validator.DeleteAlbum(albumId, albumName);
|
||||||
|
|
||||||
|
// Logout from this user session - This should take back to the home page
|
||||||
|
await validator.SignOutUser("Administrator");
|
||||||
|
|
||||||
|
// Google login
|
||||||
|
await validator.LoginWithGoogle();
|
||||||
|
|
||||||
|
// Facebook login
|
||||||
|
await validator.LoginWithFacebook();
|
||||||
|
|
||||||
|
// Twitter login
|
||||||
|
await validator.LoginWithTwitter();
|
||||||
|
|
||||||
|
// MicrosoftAccountLogin
|
||||||
|
await validator.LoginWithMicrosoftAccount();
|
||||||
|
|
||||||
|
logger.LogInformation("Variation completed successfully.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -122,7 +122,7 @@ namespace E2ETests
|
||||||
[OSSkipCondition(OperatingSystems.MacOSX)]
|
[OSSkipCondition(OperatingSystems.MacOSX)]
|
||||||
[OSSkipCondition(OperatingSystems.Linux)]
|
[OSSkipCondition(OperatingSystems.Linux)]
|
||||||
[SkipIfCurrentRuntimeIsCoreClr]
|
[SkipIfCurrentRuntimeIsCoreClr]
|
||||||
[SkipIfIISVariationsNotEnabled]
|
[SkipIfEnvironmentVariableNotEnabled("IIS_VARIATIONS_ENABLED")]
|
||||||
//[InlineData(ServerType.IIS, RuntimeFlavor.Clr, RuntimeArchitecture.x86, "http://localhost:5015/")]
|
//[InlineData(ServerType.IIS, RuntimeFlavor.Clr, RuntimeArchitecture.x86, "http://localhost:5015/")]
|
||||||
[InlineData(ServerType.IIS, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, "http://localhost:5016/")]
|
[InlineData(ServerType.IIS, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, "http://localhost:5016/")]
|
||||||
public async Task SmokeTestSuite_On_IIS_X86(
|
public async Task SmokeTestSuite_On_IIS_X86(
|
||||||
|
|
@ -186,113 +186,10 @@ namespace E2ETests
|
||||||
using (var deployer = ApplicationDeployerFactory.Create(deploymentParameters, _logger))
|
using (var deployer = ApplicationDeployerFactory.Create(deploymentParameters, _logger))
|
||||||
{
|
{
|
||||||
var deploymentResult = deployer.Deploy();
|
var deploymentResult = deployer.Deploy();
|
||||||
|
|
||||||
Helpers.SetInMemoryStoreForIIS(deploymentParameters, _logger);
|
Helpers.SetInMemoryStoreForIIS(deploymentParameters, _logger);
|
||||||
|
|
||||||
var httpClientHandler = new HttpClientHandler();
|
await SmokeTestHelper.RunTestsAsync(deploymentResult, _logger);
|
||||||
var httpClient = new HttpClient(httpClientHandler)
|
|
||||||
{
|
|
||||||
BaseAddress = new Uri(deploymentResult.ApplicationBaseUri),
|
|
||||||
Timeout = TimeSpan.FromSeconds(5),
|
|
||||||
};
|
|
||||||
|
|
||||||
// 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);
|
|
||||||
|
|
||||||
await validator.VerifyHomePage(response);
|
|
||||||
|
|
||||||
// Verify the static file middleware can serve static content.
|
|
||||||
await validator.VerifyStaticContentServed();
|
|
||||||
|
|
||||||
// Making a request to a protected resource should automatically redirect to login page.
|
|
||||||
await validator.AccessStoreWithoutPermissions();
|
|
||||||
|
|
||||||
// Register a user - Negative scenario where the Password & ConfirmPassword do not match.
|
|
||||||
await validator.RegisterUserWithNonMatchingPasswords();
|
|
||||||
|
|
||||||
// Register a valid user.
|
|
||||||
var generatedEmail = await validator.RegisterValidUser();
|
|
||||||
|
|
||||||
await validator.SignInWithUser(generatedEmail, "Password~1");
|
|
||||||
|
|
||||||
// Register a user - Negative scenario : Trying to register a user name that's already registered.
|
|
||||||
await validator.RegisterExistingUser(generatedEmail);
|
|
||||||
|
|
||||||
// Logout from this user session - This should take back to the home page
|
|
||||||
await validator.SignOutUser(generatedEmail);
|
|
||||||
|
|
||||||
// Sign in scenarios: Invalid password - Expected an invalid user name password error.
|
|
||||||
await validator.SignInWithInvalidPassword(generatedEmail, "InvalidPassword~1");
|
|
||||||
|
|
||||||
// Sign in scenarios: Valid user name & password.
|
|
||||||
await validator.SignInWithUser(generatedEmail, "Password~1");
|
|
||||||
|
|
||||||
// Change password scenario
|
|
||||||
await validator.ChangePassword(generatedEmail);
|
|
||||||
|
|
||||||
// SignIn with old password and verify old password is not allowed and new password is allowed
|
|
||||||
await validator.SignOutUser(generatedEmail);
|
|
||||||
await validator.SignInWithInvalidPassword(generatedEmail, "Password~1");
|
|
||||||
await validator.SignInWithUser(generatedEmail, "Password~2");
|
|
||||||
|
|
||||||
// Making a request to a protected resource that this user does not have access to - should
|
|
||||||
// automatically redirect to the configured access denied page
|
|
||||||
await validator.AccessStoreWithoutPermissions(generatedEmail);
|
|
||||||
|
|
||||||
// Logout from this user session - This should take back to the home page
|
|
||||||
await validator.SignOutUser(generatedEmail);
|
|
||||||
|
|
||||||
// Login as an admin user
|
|
||||||
await validator.SignInWithUser("Administrator@test.com", "YouShouldChangeThisPassword1!");
|
|
||||||
|
|
||||||
// Now navigating to the store manager should work fine as this user has
|
|
||||||
// the necessary permission to administer the store.
|
|
||||||
await validator.AccessStoreWithPermissions();
|
|
||||||
|
|
||||||
// Create an album
|
|
||||||
var albumName = await validator.CreateAlbum();
|
|
||||||
var albumId = await validator.FetchAlbumIdFromName(albumName);
|
|
||||||
|
|
||||||
// Get details of the album
|
|
||||||
await validator.VerifyAlbumDetails(albumId, albumName);
|
|
||||||
|
|
||||||
// Verify status code pages acts on non-existing items.
|
|
||||||
await validator.VerifyStatusCodePages();
|
|
||||||
|
|
||||||
// Get the non-admin view of the album.
|
|
||||||
await validator.GetAlbumDetailsFromStore(albumId, albumName);
|
|
||||||
|
|
||||||
// Add an album to cart and checkout the same
|
|
||||||
await validator.AddAlbumToCart(albumId, albumName);
|
|
||||||
await validator.CheckOutCartItems();
|
|
||||||
|
|
||||||
// Delete the album from store
|
|
||||||
await validator.DeleteAlbum(albumId, albumName);
|
|
||||||
|
|
||||||
// Logout from this user session - This should take back to the home page
|
|
||||||
await validator.SignOutUser("Administrator");
|
|
||||||
|
|
||||||
// Google login
|
|
||||||
await validator.LoginWithGoogle();
|
|
||||||
|
|
||||||
// Facebook login
|
|
||||||
await validator.LoginWithFacebook();
|
|
||||||
|
|
||||||
// Twitter login
|
|
||||||
await validator.LoginWithTwitter();
|
|
||||||
|
|
||||||
// MicrosoftAccountLogin
|
|
||||||
await validator.LoginWithMicrosoftAccount();
|
|
||||||
|
|
||||||
_logger.LogInformation("Variation completed successfully.");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,81 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using E2ETests.Common;
|
||||||
|
using Microsoft.AspNetCore.Server.Testing;
|
||||||
|
using Microsoft.AspNetCore.Testing.xunit;
|
||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Xunit;
|
||||||
|
using Xunit.Abstractions;
|
||||||
|
|
||||||
|
namespace E2ETests
|
||||||
|
{
|
||||||
|
public class SmokeTestsOnNanoServer : IDisposable
|
||||||
|
{
|
||||||
|
private readonly XunitLogger _logger;
|
||||||
|
private readonly RemoteDeploymentConfig _remoteDeploymentConfig;
|
||||||
|
|
||||||
|
public SmokeTestsOnNanoServer(ITestOutputHelper output)
|
||||||
|
{
|
||||||
|
_logger = new XunitLogger(output, LogLevel.Information);
|
||||||
|
|
||||||
|
var configuration = new ConfigurationBuilder()
|
||||||
|
.SetBasePath(Directory.GetCurrentDirectory())
|
||||||
|
.AddJsonFile("remoteDeploymentConfig.json")
|
||||||
|
.AddEnvironmentVariables()
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
_remoteDeploymentConfig = new RemoteDeploymentConfig();
|
||||||
|
configuration.GetSection("NanoServer").Bind(_remoteDeploymentConfig);
|
||||||
|
}
|
||||||
|
|
||||||
|
[ConditionalTheory, Trait("E2Etests", "NanoServer")]
|
||||||
|
[OSSkipCondition(OperatingSystems.Linux)]
|
||||||
|
[OSSkipCondition(OperatingSystems.MacOSX)]
|
||||||
|
[SkipIfEnvironmentVariableNotEnabled("RUN_TESTS_ON_NANO")]
|
||||||
|
[InlineData(ServerType.Kestrel, 5000)]
|
||||||
|
[InlineData(ServerType.WebListener, 5000)]
|
||||||
|
public async Task Test(ServerType serverType, int portToListen)
|
||||||
|
{
|
||||||
|
var applicationBaseUrl = $"http://{_remoteDeploymentConfig.ServerName}:{portToListen}/";
|
||||||
|
await RunTestsAsync(serverType, applicationBaseUrl);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task RunTestsAsync(ServerType serverType, string applicationBaseUrl)
|
||||||
|
{
|
||||||
|
using (_logger.BeginScope("SmokeTestSuite"))
|
||||||
|
{
|
||||||
|
var deploymentParameters = new RemoteWindowsDeploymentParameters(
|
||||||
|
Helpers.GetApplicationPath(),
|
||||||
|
serverType,
|
||||||
|
RuntimeFlavor.CoreClr,
|
||||||
|
RuntimeArchitecture.x64,
|
||||||
|
_remoteDeploymentConfig.FileSharePath,
|
||||||
|
_remoteDeploymentConfig.ServerName,
|
||||||
|
_remoteDeploymentConfig.AccountName,
|
||||||
|
_remoteDeploymentConfig.AccountPassword,
|
||||||
|
_remoteDeploymentConfig.ExecutableRelativePath)
|
||||||
|
{
|
||||||
|
PublishTargetFramework = "netstandardapp1.5",
|
||||||
|
ApplicationBaseUriHint = applicationBaseUrl
|
||||||
|
};
|
||||||
|
deploymentParameters.EnvironmentVariables.Add(
|
||||||
|
new KeyValuePair<string, string>("ASPNETCORE_ENVIRONMENT", "SocialTesting"));
|
||||||
|
|
||||||
|
using (var deployer = new RemoteWindowsDeployer(deploymentParameters, _logger))
|
||||||
|
{
|
||||||
|
var deploymentResult = deployer.Deploy();
|
||||||
|
|
||||||
|
await SmokeTestHelper.RunTestsAsync(deploymentResult, _logger);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
_logger.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -11,7 +11,9 @@
|
||||||
"Microsoft.AspNetCore.Identity": "1.0.0-*",
|
"Microsoft.AspNetCore.Identity": "1.0.0-*",
|
||||||
"Microsoft.AspNetCore.Server.Testing": "1.0.0-*",
|
"Microsoft.AspNetCore.Server.Testing": "1.0.0-*",
|
||||||
"Microsoft.AspNetCore.WebUtilities": "1.0.0-*",
|
"Microsoft.AspNetCore.WebUtilities": "1.0.0-*",
|
||||||
|
"Microsoft.Extensions.Configuration.Binder": "1.0.0-*",
|
||||||
"Microsoft.Extensions.Configuration.EnvironmentVariables": "1.0.0-*",
|
"Microsoft.Extensions.Configuration.EnvironmentVariables": "1.0.0-*",
|
||||||
|
"Microsoft.Extensions.Configuration.Json": "1.0.0-*",
|
||||||
"Microsoft.Extensions.Logging": "1.0.0-*",
|
"Microsoft.Extensions.Logging": "1.0.0-*",
|
||||||
"Microsoft.Extensions.Logging.Console": "1.0.0-*",
|
"Microsoft.Extensions.Logging.Console": "1.0.0-*",
|
||||||
"xunit": "2.1.0"
|
"xunit": "2.1.0"
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
{
|
||||||
|
"NanoServer": {
|
||||||
|
"ServerName": "",
|
||||||
|
"AccountName": "",
|
||||||
|
"AccountPassword": "",
|
||||||
|
"FileSharePath": "",
|
||||||
|
"ExecutableRelativePath": ""
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue