diff --git a/src/main/java/de/deadlocker8/budgetmaster/accounts/AccountService.java b/src/main/java/de/deadlocker8/budgetmaster/accounts/AccountService.java index d503af26f6d5f193a7c4abb427038ea340e43609..583074e9eba63fbc1335fe63817df98a9d1ddba6 100644 --- a/src/main/java/de/deadlocker8/budgetmaster/accounts/AccountService.java +++ b/src/main/java/de/deadlocker8/budgetmaster/accounts/AccountService.java @@ -104,6 +104,7 @@ public class AccountService implements Resetable LOGGER.debug("Created default account"); } + // handle null values for new field "isReadOnly" for(Account account : accountRepository.findAll()) { if(account.isReadOnly() == null) diff --git a/src/main/resources/templates/accounts/accounts.ftl b/src/main/resources/templates/accounts/accounts.ftl index 73b5a452bb4e4e65c7f3af2754b7fbb72f22bbf7..e0aaf64843f4eef044406efe6ffbd6ffb8e9c264 100644 --- a/src/main/resources/templates/accounts/accounts.ftl +++ b/src/main/resources/templates/accounts/accounts.ftl @@ -16,9 +16,9 @@ </div> </div> <br> - <div class="center-align"><a href="<@s.url '/accounts/newAccount'/>" class="waves-effect waves-light btn budgetmaster-blue"><i class="material-icons left">add</i>${locale.getString("title.account.new")}</a></div> + <div class="center-align"><a href="<@s.url '/accounts/newAccount'/>" id="button-new-account" class="waves-effect waves-light btn budgetmaster-blue"><i class="material-icons left">add</i>${locale.getString("title.account.new")}</a></div> <br> - <div class="container"> + <div class="container account-container"> <table class="bordered"> <#list accounts as account> <#if (account.getType().name() == "CUSTOM")> diff --git a/src/main/resources/templates/accounts/newAccount.ftl b/src/main/resources/templates/accounts/newAccount.ftl index 271694ec144cdb1e1416469336f19dd15050883b..671d1a9016c9d9cefb196726a4fa88bad1443a10 100644 --- a/src/main/resources/templates/accounts/newAccount.ftl +++ b/src/main/resources/templates/accounts/newAccount.ftl @@ -40,7 +40,7 @@ </div> <div class="col s6 left-align"> - <button class="btn waves-effect waves-light budgetmaster-blue" type="submit" name="action"> + <button id="button-save-account" class="btn waves-effect waves-light budgetmaster-blue" type="submit" name="action"> <i class="material-icons left">save</i>${locale.getString("save")} </button> </div> @@ -53,7 +53,7 @@ </div> <div class="row center-align"> <div class="col s12"> - <button class="btn waves-effect waves-light budgetmaster-blue" type="submit" name="buttonSave"> + <button id="button-save-account" class="btn waves-effect waves-light budgetmaster-blue" type="submit" name="buttonSave"> <i class="material-icons left">save</i>${locale.getString("save")} </button> </div> diff --git a/src/test/java/de/deadlocker8/budgetmaster/integration/selenium/AccountTest.java b/src/test/java/de/deadlocker8/budgetmaster/integration/selenium/AccountTest.java new file mode 100644 index 0000000000000000000000000000000000000000..988b87da2579d4e6650f2f8a14a689509c9a3c19 --- /dev/null +++ b/src/test/java/de/deadlocker8/budgetmaster/integration/selenium/AccountTest.java @@ -0,0 +1,179 @@ +package de.deadlocker8.budgetmaster.integration.selenium; + +import de.deadlocker8.budgetmaster.Main; +import de.deadlocker8.budgetmaster.authentication.UserService; +import de.deadlocker8.budgetmaster.integration.helpers.IntegrationTestHelper; +import de.deadlocker8.budgetmaster.integration.helpers.SeleniumTest; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TestName; +import org.junit.rules.TestWatcher; +import org.junit.runner.Description; +import org.junit.runner.RunWith; +import org.openqa.selenium.By; +import org.openqa.selenium.WebDriver; +import org.openqa.selenium.WebElement; +import org.openqa.selenium.firefox.FirefoxDriver; +import org.openqa.selenium.firefox.FirefoxOptions; +import org.openqa.selenium.support.ui.ExpectedConditions; +import org.openqa.selenium.support.ui.WebDriverWait; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.web.server.LocalServerPort; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.context.junit4.SpringRunner; + +import java.io.File; +import java.util.Arrays; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; + +@RunWith(SpringRunner.class) +@SpringBootTest(classes = Main.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD) +@SeleniumTest +public class AccountTest +{ + private IntegrationTestHelper helper; + private WebDriver driver; + + @LocalServerPort + int port; + + @Rule + public TestName name = new TestName(); + + @Rule + public TestWatcher testWatcher = new TestWatcher() + { + @Override + protected void finished(Description description) + { + driver.quit(); + } + + @Override + protected void failed(Throwable e, Description description) + { + IntegrationTestHelper.saveScreenshots(driver, name, AccountTest.class); + } + }; + + @Before + public void prepare() + { + FirefoxOptions options = new FirefoxOptions(); + options.setHeadless(true); + driver = new FirefoxDriver(options); + + // prepare + helper = new IntegrationTestHelper(driver, port); + helper.start(); + helper.login(UserService.DEFAULT_PASSWORD); + helper.hideBackupReminder(); + + String path = getClass().getClassLoader().getResource("SearchDatabase.json").getFile().replace("/", File.separator); + helper.uploadDatabase(path, Arrays.asList("DefaultAccount0815", "sfsdf"), Arrays.asList("DefaultAccount0815", "Account2")); + } + + @Test + public void test_newAccount_cancel() + { + driver.get(helper.getUrl() + "/accounts"); + driver.findElement(By.id("button-new-account")).click(); + + // click cancel button + driver.findElement(By.xpath("//a[contains(text(),'Cancel')]")).click(); + + WebDriverWait wait = new WebDriverWait(driver, 5); + wait.until(ExpectedConditions.textToBePresentInElementLocated(By.cssSelector(".headline"), "Accounts")); + + // assert + assertThat(driver.getCurrentUrl()).endsWith("/accounts"); + + List<WebElement> accountRows = driver.findElements(By.cssSelector(".account-container tr")); + assertThat(accountRows).hasSize(3); + } + + @Test + public void test_newAccount() + { + driver.get(helper.getUrl() + "/accounts"); + driver.findElement(By.id("button-new-account")).click(); + + String name = "My new account"; + + // fill form + driver.findElement(By.id("account-name")).sendKeys(name); + + // submit form + driver.findElement(By.id("button-save-account")).click(); + + WebDriverWait wait = new WebDriverWait(driver, 5); + wait.until(ExpectedConditions.textToBePresentInElementLocated(By.cssSelector(".headline"), "Accounts")); + + // assert + assertThat(driver.getCurrentUrl()).endsWith("/accounts"); + + List<WebElement> accountRows = driver.findElements(By.cssSelector(".account-container tr")); + assertThat(accountRows).hasSize(4); + + assertAccountColumns(accountRows.get(0).findElements(By.tagName("td")), true, false, true, false, "Account2"); + assertAccountColumns(accountRows.get(1).findElements(By.tagName("td")), true, true, false, false, "Default Account"); + assertAccountColumns(accountRows.get(2).findElements(By.tagName("td")), true, false, true, false, "DefaultAccount0815"); + assertAccountColumns(accountRows.get(3).findElements(By.tagName("td")), true, false, true, false, name); + } + + @Test + public void test_edit() + { + driver.get(helper.getUrl() + "/accounts/2/edit"); + + assertThat(driver.findElement(By.id("account-name")).getAttribute("value")).isEqualTo("Default Account"); + } + + public static void assertAccountColumns(List<WebElement> columns, boolean isDefaultIconVisible, boolean isDefaultIconSelected, boolean isReadOnlyIconVisible, boolean isReadOnlyIconSelected, String name) + { + // icons + final List<WebElement> icons = columns.get(0).findElements(By.tagName("i")); + int numberOfVisibleIcons = 0; + + if(isDefaultIconVisible) + { + final WebElement icon = icons.get(numberOfVisibleIcons); + assertThat(icon.isDisplayed()).isTrue(); + if(isDefaultIconSelected) + { + assertThat(icon).hasFieldOrPropertyWithValue("text", "star"); + } + else + { + assertThat(icon).hasFieldOrPropertyWithValue("text", "star_border"); + } + + numberOfVisibleIcons++; + } + + if(isReadOnlyIconVisible) + { + final WebElement icon = icons.get(numberOfVisibleIcons); + assertThat(icon.isDisplayed()).isTrue(); + if(isReadOnlyIconSelected) + { + assertThat(icon.getAttribute("class")).contains("fa-lock"); + } + else + { + assertThat(icon.getAttribute("class")).contains("fa-lock-open"); + } + + numberOfVisibleIcons++; + } + + assertThat(icons).hasSize(numberOfVisibleIcons); + + // name + assertThat(columns.get(1)).hasFieldOrPropertyWithValue("text", name); + } +} \ No newline at end of file