using System; using System.Diagnostics; using System.Collections.Generic; using System.Net; using System.Net.Http; using Xunit; namespace E2ETests { public class SmokeTests { private const string Connection_string_Format = "Server=(localdb)\\MSSQLLocalDB;Database={0};Trusted_Connection=True;MultipleActiveResultSets=true"; private string ApplicationBaseUrl; private HttpClient httpClient; private HttpClientHandler httpClientHandler; public static bool RunningOnMono; public SmokeTests() { RunningOnMono = Type.GetType("Mono.Runtime") != null; } [Theory] [InlineData(ServerType.Helios, KreFlavor.DesktopClr, KreArchitecture.x86, "http://localhost:5001/", false)] [InlineData(ServerType.WebListener, KreFlavor.DesktopClr, KreArchitecture.x86, "http://localhost:5002/", false)] [InlineData(ServerType.Kestrel, KreFlavor.DesktopClr, KreArchitecture.x86, "http://localhost:5004/", false)] [InlineData(ServerType.Helios, KreFlavor.CoreClr, KreArchitecture.x86, "http://localhost:5001/", false)] [InlineData(ServerType.WebListener, KreFlavor.CoreClr, KreArchitecture.x86, "http://localhost:5002/", false)] [InlineData(ServerType.Kestrel, KreFlavor.CoreClr, KreArchitecture.x86, "http://localhost:5004/", false)] [InlineData(ServerType.WebListener, KreFlavor.DesktopClr, KreArchitecture.x64, "http://localhost:5002/", false)] [InlineData(ServerType.Kestrel, KreFlavor.Mono, KreArchitecture.x86, "http://localhost:5004/", true)] [InlineData(ServerType.Helios, KreFlavor.CoreClr, KreArchitecture.x64, "http://localhost:5001/", false)] [InlineData(ServerType.Kestrel, KreFlavor.CoreClr, KreArchitecture.x64, "http://localhost:5004/", false)] public void SmokeTestSuite(ServerType hostType, KreFlavor kreFlavor, KreArchitecture architecture, string applicationBaseUrl, bool RunTestOnMono = false) { Console.WriteLine("Variation Details : HostType = {0}, KreFlavor = {1}, Architecture = {2}, applicationBaseUrl = {3}", hostType, kreFlavor, architecture, applicationBaseUrl); if (RunTestOnMono && !RunningOnMono) { //Skip Mono variations on Windows Console.WriteLine("Skipping mono variation on .NET"); Assert.True(true); return; } if (!RunTestOnMono && RunningOnMono) { //Skip .net variations on mono Console.WriteLine("Skipping .NET variation on mono"); Assert.True(true); return; } // Check if processor architecture is x64, else skip test if (architecture == KreArchitecture.x64 && !Environment.Is64BitOperatingSystem) { Console.WriteLine("Skipping x64 test since machine is of type x86"); Assert.True(true); return; } var testStartTime = DateTime.Now; var musicStoreDbName = Guid.NewGuid().ToString().Replace("-", string.Empty); Console.WriteLine("Pointing MusicStore DB to '{0}'", string.Format(Connection_string_Format, musicStoreDbName)); //Override the connection strings using environment based configuration Environment.SetEnvironmentVariable("SQLAZURECONNSTR_DefaultConnection", string.Format(Connection_string_Format, musicStoreDbName)); ApplicationBaseUrl = applicationBaseUrl; Process hostProcess = null; bool testSuccessful = false; try { //Deployment helpers not setup for mono yet. Until then set the ApplicationBaseUrl to some static url. hostProcess = DeploymentUtility.StartApplication(hostType, kreFlavor, architecture, musicStoreDbName); httpClientHandler = new HttpClientHandler(); httpClient = new HttpClient(httpClientHandler) { BaseAddress = new Uri(applicationBaseUrl) }; //Request to base address and check if various parts of the body are rendered & measure the cold startup time. var response = httpClient.GetAsync(string.Empty).Result; var responseContent = response.Content.ReadAsStringAsync().Result; var initializationCompleteTime = DateTime.Now; Console.WriteLine("[Time]: Approximate time taken for application initialization : '{0}' seconds", (initializationCompleteTime - testStartTime).TotalSeconds); VerifyHomePage(response, responseContent); //Verify the static file middleware can serve static content VerifyStaticContentServed(); //Making a request to a protected resource should automatically redirect to login page AccessStoreWithoutPermissions(); //Register a user - Negative scenario where the Password & ConfirmPassword do not match RegisterUserWithNonMatchingPasswords(); //Register a valid user var generatedEmail = RegisterValidUser(); //Register a user - Negative scenario : Trying to register a user name that's already registered. RegisterExistingUser(generatedEmail); //Logout from this user session - This should take back to the home page SignOutUser(generatedEmail); //Sign in scenarios: Invalid password - Expected an invalid user name password error. SignInWithInvalidPassword(generatedEmail, "InvalidPassword~1"); //Sign in scenarios: Valid user name & password. SignInWithUser(generatedEmail, "Password~1"); //Change password scenario ChangePassword(generatedEmail); //SignIn with old password and verify old password is not allowed and new password is allowed SignOutUser(generatedEmail); SignInWithInvalidPassword(generatedEmail, "Password~1"); SignInWithUser(generatedEmail, "Password~2"); //Making a request to a protected resource that this user does not have access to - should automatically redirect to login page again AccessStoreWithoutPermissions(generatedEmail); //Logout from this user session - This should take back to the home page SignOutUser(generatedEmail); //Login as an admin user 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. AccessStoreWithPermissions(); //Create an album var albumName = CreateAlbum(); var albumId = FetchAlbumIdFromName(albumName); //Get details of the album VerifyAlbumDetails(albumId, albumName); //Add an album to cart and checkout the same AddAlbumToCart(albumId, albumName); CheckOutCartItems(); //Delete the album from store DeleteAlbum(albumId, albumName); //Logout from this user session - This should take back to the home page SignOutUser("Administrator"); var testCompletionTime = DateTime.Now; Console.WriteLine("[Time]: All tests completed in '{0}' seconds", (testCompletionTime - initializationCompleteTime).TotalSeconds); Console.WriteLine("[Time]: Total time taken for this test variation '{0}' seconds", (testCompletionTime - testStartTime).TotalSeconds); testSuccessful = true; } finally { if (!testSuccessful) { Console.WriteLine("Some tests failed. Proceeding with cleanup."); } if (!RunningOnMono) { if (hostProcess != null && !hostProcess.HasExited) { //Shutdown the host process hostProcess.Kill(); hostProcess.WaitForExit(5 * 1000); if (!hostProcess.HasExited) { Console.WriteLine("Unable to terminate the host process with process Id '{0}", hostProcess.Id); } else { Console.WriteLine("Successfully terminated host process with process Id '{0}'", hostProcess.Id); } } else { Console.WriteLine("Host process already exited or never started successfully."); } DbUtils.DropDatabase(musicStoreDbName); } } } private void VerifyStaticContentServed() { Console.WriteLine("Validating if static contents are served.."); Console.WriteLine("Fetching favicon.ico.."); var response = httpClient.GetAsync("favicon.ico").Result; ThrowIfResponseStatusNotOk(response); Console.WriteLine("Fetching /Content/bootstrap.css.."); response = httpClient.GetAsync("Content/bootstrap.css").Result; ThrowIfResponseStatusNotOk(response); Console.WriteLine("Verified static contents are served successfully"); } private void VerifyHomePage(HttpResponseMessage response, string responseContent) { Console.WriteLine("Home page content : {0}", responseContent); Assert.Equal(HttpStatusCode.OK, response.StatusCode); ValidateLayoutPage(responseContent); Assert.Contains("Home Page – MVC Music Store", responseContent, StringComparison.OrdinalIgnoreCase); Assert.Contains("Register", responseContent, StringComparison.OrdinalIgnoreCase); Assert.Contains("Login", responseContent, StringComparison.OrdinalIgnoreCase); Assert.Contains("mvcmusicstore.codeplex.com", responseContent, StringComparison.OrdinalIgnoreCase); Assert.Contains("/Images/home-showcase.png", responseContent, StringComparison.OrdinalIgnoreCase); Console.WriteLine("Application initialization successful."); } private void ValidateLayoutPage(string responseContent) { Assert.Contains("ASP.NET MVC Music Store", responseContent, StringComparison.OrdinalIgnoreCase); Assert.Contains("
  • Home
  • ", responseContent, StringComparison.OrdinalIgnoreCase); Assert.Contains("Store ", responseContent, StringComparison.OrdinalIgnoreCase); Assert.Contains("