diff --git a/src/Server/Coderr.Server.SqlServer.Tests/Helpers/TestDataManager.cs b/src/Server/Coderr.Server.SqlServer.Tests/Helpers/TestDataManager.cs index a6bef543..f89c1c07 100644 --- a/src/Server/Coderr.Server.SqlServer.Tests/Helpers/TestDataManager.cs +++ b/src/Server/Coderr.Server.SqlServer.Tests/Helpers/TestDataManager.cs @@ -12,6 +12,7 @@ using codeRR.Server.SqlServer.Core.Accounts; using codeRR.Server.SqlServer.Core.Applications; using codeRR.Server.SqlServer.Core.Users; +using codeRR.Server.SqlServer.Tests.Models; using Coderr.Server.PluginApi.Config; using Griffin.Data; using Griffin.Data.Mapper; @@ -38,6 +39,8 @@ public TestDataManager(Func connectionFactory) /// public int AccountId { get; private set; } + public TestUser TestUser { get; set; } + public Application Application { get; private set; } /// @@ -119,7 +122,7 @@ private void EnsureServerSettings(string baseUrl) } var sql = $@"INSERT INTO Settings (Section, Name, Value) VALUES -('BaseConfig', 'AllowRegistrations', 'False'), +('BaseConfig', 'AllowRegistrations', 'True'), ('BaseConfig', 'BaseUrl', '{baseUrl}'), ('BaseConfig', 'SenderEmail', 'webtests@coderrapp.com'), ('BaseConfig', 'SupportEmail', 'webtests@coderrapp.com'), @@ -184,11 +187,11 @@ public void ResetDatabase(string baseUrl) protected void CreateUserAndApplication(IAdoNetUnitOfWork uow, out int accountId, out int applicationId) { var accountRepos = new AccountRepository(uow); - var account = new Account("arne", "123456") {Email = "arne@som.com"}; + var account = new Account(TestUser.Username, TestUser.Password) {Email = TestUser.Email}; account.Activate(); accountRepos.Create(account); var userRepos = new UserRepository(uow); - var user = new User(account.Id, "arne") {EmailAddress = "arne@som.com"}; + var user = new User(account.Id, TestUser.Username) {EmailAddress =TestUser.Email}; userRepos.CreateAsync(user).GetAwaiter().GetResult(); var appRepos = new ApplicationRepository(uow); diff --git a/src/Server/Coderr.Server.SqlServer.Tests/Models/TestUser.cs b/src/Server/Coderr.Server.SqlServer.Tests/Models/TestUser.cs new file mode 100644 index 00000000..95acace5 --- /dev/null +++ b/src/Server/Coderr.Server.SqlServer.Tests/Models/TestUser.cs @@ -0,0 +1,9 @@ +namespace codeRR.Server.SqlServer.Tests.Models +{ + public class TestUser + { + public string Username { get; set; } + public string Password { get; set; } + public string Email { get; set; } + } +} diff --git a/src/Server/Coderr.Server.Web.Tests/Helpers/Extensions/WebDriverExtensions.cs b/src/Server/Coderr.Server.Web.Tests/Helpers/Extensions/WebDriverExtensions.cs index 0eeb5757..f749751c 100644 --- a/src/Server/Coderr.Server.Web.Tests/Helpers/Extensions/WebDriverExtensions.cs +++ b/src/Server/Coderr.Server.Web.Tests/Helpers/Extensions/WebDriverExtensions.cs @@ -20,12 +20,31 @@ public static bool ElementIsPresent(this IWebDriver driver, By by) return present; } + public static bool ElementIsPresent(this IWebDriver driver, IWebElement element) + { + var present = false; + try + { + present = element.Displayed; + } + catch (NoSuchElementException) + { + } + return present; + } + public static bool WaitUntilElementIsPresent(this IWebDriver driver, By by, int timeout = 5) { var wait = new WebDriverWait(driver, TimeSpan.FromSeconds(timeout)); return wait.Until(d => d.ElementIsPresent(by)); } + public static bool WaitUntilElementIsPresent(this IWebDriver driver, IWebElement element, int timeout = 5) + { + var wait = new WebDriverWait(driver, TimeSpan.FromSeconds(timeout)); + return wait.Until(d => d.ElementIsPresent(element)); + } + public static string WaitUntilTitleEquals(this IWebDriver driver, string title, int timeout = 5) { try diff --git a/src/Server/Coderr.Server.Web.Tests/Pages/Account/ActivationRequestedPage.cs b/src/Server/Coderr.Server.Web.Tests/Pages/Account/ActivationRequestedPage.cs new file mode 100644 index 00000000..7d3e506c --- /dev/null +++ b/src/Server/Coderr.Server.Web.Tests/Pages/Account/ActivationRequestedPage.cs @@ -0,0 +1,17 @@ +using OpenQA.Selenium; +using OpenQA.Selenium.Support.UI; + +namespace codeRR.Server.Web.Tests.Pages.Account +{ + public class ActivationRequestedPage : BasePage + { + public ActivationRequestedPage(IWebDriver webDriver) : base(webDriver, (string) "Account/ActivationRequested", (string) "Account registered - codeRR") + { + } + + public void VerifyIsCurrentPage() + { + Wait.Until(ExpectedConditions.TitleIs(Title)); + } + } +} diff --git a/src/Server/Coderr.Server.Web.Tests/Pages/LoginPage.cs b/src/Server/Coderr.Server.Web.Tests/Pages/Account/LoginPage.cs similarity index 54% rename from src/Server/Coderr.Server.Web.Tests/Pages/LoginPage.cs rename to src/Server/Coderr.Server.Web.Tests/Pages/Account/LoginPage.cs index b6fb8f9a..2a803b4a 100644 --- a/src/Server/Coderr.Server.Web.Tests/Pages/LoginPage.cs +++ b/src/Server/Coderr.Server.Web.Tests/Pages/Account/LoginPage.cs @@ -2,14 +2,11 @@ using OpenQA.Selenium.Support.PageObjects; using OpenQA.Selenium.Support.UI; -namespace codeRR.Server.Web.Tests.Pages +namespace codeRR.Server.Web.Tests.Pages.Account { public class LoginPage : BasePage { - private const string UserName = "arne"; - private const string Password = "123456"; - - public LoginPage(IWebDriver webDriver) : base(webDriver, "Account/Login", "Login - codeRR") + public LoginPage(IWebDriver webDriver) : base(webDriver, (string) "Account/Login", (string) "Login - codeRR") { } @@ -27,16 +24,45 @@ public HomePage LoginWithValidCredentials() NavigateToPage(); UserNameField.Clear(); - UserNameField.SendKeys(UserName); + UserNameField.SendKeys(TestUser.Username); PasswordField.Clear(); - PasswordField.SendKeys(Password); + PasswordField.SendKeys(TestUser.Password); SignInButton.Click(); return new HomePage(WebDriver); } + public LoginPage LoginWithNonExistingUserWithoutPasswordSpecified() + { + NavigateToPage(); + + UserNameField.Clear(); + UserNameField.SendKeys("NonExistingUsername"); + + PasswordField.Clear(); + + SignInButton.Click(); + + return this; + } + + public LoginPage LoginWithNonExistingUserWithPasswordSpecified() + { + NavigateToPage(); + + UserNameField.Clear(); + UserNameField.SendKeys("NonExistingUsername"); + + PasswordField.Clear(); + PasswordField.SendKeys(TestUser.Password); + + SignInButton.Click(); + + return this; + } + public LoginPage LoginWithNoUserNameSpecified() { NavigateToPage(); @@ -44,7 +70,20 @@ public LoginPage LoginWithNoUserNameSpecified() UserNameField.Clear(); PasswordField.Clear(); - PasswordField.SendKeys(Password); + PasswordField.SendKeys(TestUser.Password); + + SignInButton.Click(); + + return this; + } + + public LoginPage LoginWithNoUserNameAndNoPasswordSpecified() + { + NavigateToPage(); + + UserNameField.Clear(); + + PasswordField.Clear(); SignInButton.Click(); @@ -56,7 +95,7 @@ public LoginPage LoginWithNoPasswordSpecified() NavigateToPage(); UserNameField.Clear(); - UserNameField.SendKeys(UserName); + UserNameField.SendKeys(TestUser.Username); PasswordField.Clear(); @@ -70,10 +109,10 @@ public LoginPage LoginWithWrongPasswordSpecified() NavigateToPage(); UserNameField.Clear(); - UserNameField.SendKeys(UserName); + UserNameField.SendKeys(TestUser.Username); PasswordField.Clear(); - PasswordField.SendKeys(Password.Substring(1)); + PasswordField.SendKeys(TestUser.Password.Substring(1)); SignInButton.Click(); diff --git a/src/Server/Coderr.Server.Web.Tests/Pages/LogoutPage.cs b/src/Server/Coderr.Server.Web.Tests/Pages/Account/LogoutPage.cs similarity index 77% rename from src/Server/Coderr.Server.Web.Tests/Pages/LogoutPage.cs rename to src/Server/Coderr.Server.Web.Tests/Pages/Account/LogoutPage.cs index 25400d1a..7504d5a0 100644 --- a/src/Server/Coderr.Server.Web.Tests/Pages/LogoutPage.cs +++ b/src/Server/Coderr.Server.Web.Tests/Pages/Account/LogoutPage.cs @@ -1,10 +1,10 @@ using OpenQA.Selenium; -namespace codeRR.Server.Web.Tests.Pages +namespace codeRR.Server.Web.Tests.Pages.Account { public class LogoutPage : BasePage { - public LogoutPage(IWebDriver webDriver) : base(webDriver, "Account/Logout", "") + public LogoutPage(IWebDriver webDriver) : base(webDriver, (string) "Account/Logout", (string) "") { } diff --git a/src/Server/Coderr.Server.Web.Tests/Pages/Account/RegisterPage.cs b/src/Server/Coderr.Server.Web.Tests/Pages/Account/RegisterPage.cs new file mode 100644 index 00000000..b61746ff --- /dev/null +++ b/src/Server/Coderr.Server.Web.Tests/Pages/Account/RegisterPage.cs @@ -0,0 +1,105 @@ +using codeRR.Server.Web.Tests.Helpers.Extensions; +using OpenQA.Selenium; +using OpenQA.Selenium.Support.PageObjects; +using OpenQA.Selenium.Support.UI; + +namespace codeRR.Server.Web.Tests.Pages.Account +{ + public class RegisterPage : BasePage + { + public RegisterPage(IWebDriver webDriver) : base(webDriver, (string) "Account/Register", (string) "Register account - codeRR") + { + } + + [FindsBy(How = How.Id, Using = "UserName")] + public IWebElement UserNameField { get; set; } + + [FindsBy(How = How.Id, Using = "Password")] + public IWebElement PasswordField { get; set; } + + [FindsBy(How = How.Id, Using = "Password2")] + public IWebElement RetypePasswordField { get; set; } + + [FindsBy(How = How.Id, Using = "Email")] + public IWebElement EmailField { get; set; } + + [FindsBy(How = How.ClassName, Using = "btn-primary")] + public IWebElement SignUpButton { get; set; } + + [FindsBy(How = How.ClassName, Using = "field-validation-error")] + public IWebElement ValidationErrorField { get; set; } + + public void VerifyIsCurrentPage() + { + Wait.Until(ExpectedConditions.TitleIs(Title)); + } + + public RegisterPage RegisterUsingAlreadyTakenUsername() + { + NavigateToPage(); + + ClearForm(); + + UserNameField.SendKeys(TestUser.Username); + PasswordField.SendKeys(TestUser.Password); + RetypePasswordField.SendKeys(TestUser.Password); + EmailField.SendKeys(TestUser.Email); + + SignUpButton.Click(); + + return this; + } + + public RegisterPage RegisterUsingAlreadyTakenEmail() + { + NavigateToPage(); + + ClearForm(); + + UserNameField.SendKeys(TestUser.Username + "2"); + PasswordField.SendKeys(TestUser.Password); + RetypePasswordField.SendKeys(TestUser.Password); + EmailField.SendKeys(TestUser.Email); + + SignUpButton.Click(); + + return this; + } + + public ActivationRequestedPage RegisterNewUser() + { + NavigateToPage(); + + ClearForm(); + + UserNameField.SendKeys(TestUser.Username + "2"); + PasswordField.SendKeys(TestUser.Password); + RetypePasswordField.SendKeys(TestUser.Password); + EmailField.SendKeys("TestUser2@coderrapp.com"); + + SignUpButton.Click(); + + return new ActivationRequestedPage(WebDriver); + } + + public RegisterPage VerifyUsernameIsAlreadyTaken() + { + WebDriver.WaitUntilElementIsPresent(ValidationErrorField); + return this; + } + + public RegisterPage VerifyEmailIsAlreadyTaken() + { + WebDriver.WaitUntilElementIsPresent(ValidationErrorField); + return this; + } + + private void ClearForm() + { + UserNameField.Clear(); + PasswordField.Clear(); + RetypePasswordField.Clear(); + EmailField.Clear(); + } + } +} diff --git a/src/Server/Coderr.Server.Web.Tests/Pages/BasePage.cs b/src/Server/Coderr.Server.Web.Tests/Pages/BasePage.cs index fdfe92aa..3fb0fa89 100644 --- a/src/Server/Coderr.Server.Web.Tests/Pages/BasePage.cs +++ b/src/Server/Coderr.Server.Web.Tests/Pages/BasePage.cs @@ -1,4 +1,5 @@ using System; +using codeRR.Server.SqlServer.Tests.Models; using OpenQA.Selenium; using OpenQA.Selenium.Support.PageObjects; using OpenQA.Selenium.Support.UI; @@ -11,7 +12,9 @@ public class BasePage protected WebDriverWait Wait; protected string BaseUrl { get; } protected string Url { get; set; } - protected string Title { get; } + public string Title { get; } + + protected readonly TestUser TestUser = WebTest.TestUser; public BasePage(IWebDriver webDriver, string url, string title) { diff --git a/src/Server/Coderr.Server.Web.Tests/Pages/HomePage.cs b/src/Server/Coderr.Server.Web.Tests/Pages/HomePage.cs index 6d2a99cb..0c8f3fa2 100644 --- a/src/Server/Coderr.Server.Web.Tests/Pages/HomePage.cs +++ b/src/Server/Coderr.Server.Web.Tests/Pages/HomePage.cs @@ -11,7 +11,7 @@ public HomePage(IWebDriver webDriver) : base(webDriver, "", "Overview") } [FindsBy(How = How.XPath, Using = "//a/span[.=' MyTestApp ']")] - public IWebElement FirstApplication { get; set; } + public IWebElement NavigationMyTestApp { get; set; } [FindsBy(How = How.Id, Using = "pageTitle")] public IWebElement PageTitle { get; set; } @@ -41,9 +41,9 @@ public void VerifyIsCurrentPage() Wait.Until(ExpectedConditions.TitleIs("Overview")); } - public void VerifyNavigatedToFirstApplication() + public void VerifyNavigatedToMyTestApp() { - Wait.Until(ExpectedConditions.TextToBePresentInElement(PageTitle, Title)); + Wait.Until(ExpectedConditions.TextToBePresentInElement(PageTitle, "MyTestApp")); } } } diff --git a/src/Server/Coderr.Server.Web.Tests/Tests/HomePageTests.cs b/src/Server/Coderr.Server.Web.Tests/Tests/HomePageTests.cs index 761299b3..bc631ca6 100644 --- a/src/Server/Coderr.Server.Web.Tests/Tests/HomePageTests.cs +++ b/src/Server/Coderr.Server.Web.Tests/Tests/HomePageTests.cs @@ -7,7 +7,7 @@ namespace codeRR.Server.Web.Tests.Tests public class HomePageTests : LoggedInTest { [Fact] - public void Should_be_able_to_navigate_to_application() + public void Should_be_able_to_navigate_to_myfirstapp_application() { UITest(() => { @@ -16,9 +16,9 @@ public void Should_be_able_to_navigate_to_application() var sut = new HomePage(WebDriver); sut.NavigateToPage(); - sut.FirstApplication.Click(); + sut.NavigationMyTestApp.Click(); - sut.VerifyNavigatedToFirstApplication(); + sut.VerifyNavigatedToMyTestApp(); Logout(); }); diff --git a/src/Server/Coderr.Server.Web.Tests/Tests/LoggedInTest.cs b/src/Server/Coderr.Server.Web.Tests/Tests/LoggedInTest.cs index 06e1e09c..bcde6f9c 100644 --- a/src/Server/Coderr.Server.Web.Tests/Tests/LoggedInTest.cs +++ b/src/Server/Coderr.Server.Web.Tests/Tests/LoggedInTest.cs @@ -1,4 +1,5 @@ using codeRR.Server.Web.Tests.Pages; +using codeRR.Server.Web.Tests.Pages.Account; using Xunit; namespace codeRR.Server.Web.Tests.Tests diff --git a/src/Server/Coderr.Server.Web.Tests/Tests/LoginPageTests.cs b/src/Server/Coderr.Server.Web.Tests/Tests/LoginPageTests.cs index f907d0bc..958f5c51 100644 --- a/src/Server/Coderr.Server.Web.Tests/Tests/LoginPageTests.cs +++ b/src/Server/Coderr.Server.Web.Tests/Tests/LoginPageTests.cs @@ -1,4 +1,5 @@ using codeRR.Server.Web.Tests.Pages; +using codeRR.Server.Web.Tests.Pages.Account; using Xunit; namespace codeRR.Server.Web.Tests.Tests @@ -32,6 +33,45 @@ public void Should_not_be_able_to_login_with_empty_password() }); } + [Fact] + public void Should_not_be_able_to_login_with_empty_username_and_empty_password() + { + UITest(() => + { + var sut = new LoginPage(WebDriver) + .LoginWithNoUserNameAndNoPasswordSpecified(); + + Assert.IsType(sut); + sut.VerifyIsCurrentPage(); + }); + } + + [Fact] + public void Should_not_be_able_to_login_with_non_existing_user() + { + UITest(() => + { + var sut = new LoginPage(WebDriver) + .LoginWithNonExistingUserWithPasswordSpecified(); + + Assert.IsType(sut); + sut.VerifyIsCurrentPage(); + }); + } + + [Fact] + public void Should_not_be_able_to_login_with_non_existing_user_with_empty_password() + { + UITest(() => + { + var sut = new LoginPage(WebDriver) + .LoginWithNonExistingUserWithoutPasswordSpecified(); + + Assert.IsType(sut); + sut.VerifyIsCurrentPage(); + }); + } + [Fact] public void Should_not_be_able_to_login_with_wrong_password() { diff --git a/src/Server/Coderr.Server.Web.Tests/Tests/RegisterPageTests.cs b/src/Server/Coderr.Server.Web.Tests/Tests/RegisterPageTests.cs new file mode 100644 index 00000000..db142f1e --- /dev/null +++ b/src/Server/Coderr.Server.Web.Tests/Tests/RegisterPageTests.cs @@ -0,0 +1,52 @@ +using codeRR.Server.Web.Tests.Helpers.Extensions; +using codeRR.Server.Web.Tests.Pages.Account; +using Xunit; + +namespace codeRR.Server.Web.Tests.Tests +{ + [Trait("Category", "Integration")] + public class RegisterPageTests : LoggedInTest + { + [Fact] + public void Should_not_be_able_to_register_using_already_taken_username() + { + UITest(() => + { + var sut = new RegisterPage(WebDriver) + .RegisterUsingAlreadyTakenUsername(); + + Assert.IsType(sut); + sut.VerifyIsCurrentPage(); + + sut.VerifyUsernameIsAlreadyTaken(); + }); + } + + [Fact] + public void Should_not_be_able_to_register_using_already_taken_email() + { + UITest(() => + { + var sut = new RegisterPage(WebDriver) + .RegisterUsingAlreadyTakenEmail(); + + Assert.IsType(sut); + sut.VerifyIsCurrentPage(); + + sut.VerifyEmailIsAlreadyTaken(); + }); + } + + [Fact] + public void Should_be_able_to_register_user() + { + UITest(() => + { + var sut = new RegisterPage(WebDriver) + .RegisterNewUser(); + + Assert.Equal("Account registered - codeRR", WebDriver.WaitUntilTitleEquals(sut.Title)); + }); + } + } +} diff --git a/src/Server/Coderr.Server.Web.Tests/WebTest.cs b/src/Server/Coderr.Server.Web.Tests/WebTest.cs index 56978375..bca6fe48 100644 --- a/src/Server/Coderr.Server.Web.Tests/WebTest.cs +++ b/src/Server/Coderr.Server.Web.Tests/WebTest.cs @@ -1,11 +1,11 @@ using System; using System.Collections.Generic; -using System.Configuration; using System.IO; using System.Net; using System.Web.Configuration; using codeRR.Server.SqlServer.Core.Accounts; using codeRR.Server.SqlServer.Tests.Helpers; +using codeRR.Server.SqlServer.Tests.Models; using codeRR.Server.Web.Tests.Helpers; using codeRR.Server.Web.Tests.Helpers.Selenium; using Griffin.Data.Mapper; @@ -41,7 +41,7 @@ static WebTest() // Disables database migration in codeRR.Server.Web project, should be up-to-date already // SchemaUpdateModule does not handle coderr_ConnectionString environment variable // This should only be run on build server due to changes in web.config - if (Environment.GetEnvironmentVariable("BUILD_SERVER") != null) + if (Environment.GetEnvironmentVariable("TF_BUILD") != null) { DisableDatabaseMigrations(); } @@ -62,13 +62,16 @@ static WebTest() _iisExpress.Start("codeRR.Server.Web"); // Warmup request only on build server - if (Environment.GetEnvironmentVariable("BUILD_SERVER") != null) + if (Environment.GetEnvironmentVariable("TF_BUILD") != null) { var webClient = new WebClient(); webClient.DownloadString(_iisExpress.BaseUrl); } - TestData = new TestDataManager(_databaseManager.OpenConnection); + TestUser = new TestUser {Username = "TestUser", Password = "123456", Email = "TestUser@coderrapp.com"}; + + TestData = new TestDataManager(_databaseManager.OpenConnection) { TestUser = TestUser }; + WebDriver = DriverFactory.Create(BrowserType.Chrome); AppDomain.CurrentDomain.DomainUnload += (o, e) => { DisposeWebDriver(); }; } @@ -110,6 +113,8 @@ protected WebTest() public static IWebDriver WebDriver { get; private set; } + public static TestUser TestUser { get; set; } + private static void DisposeWebDriver() { try