Files
JIMRI/java/acceptancetest/step_definitions/jmri/web/WebServerAcceptanceSteps.java
T
2026-06-17 14:00:51 +02:00

214 lines
8.5 KiB
Java

package jmri.web;
import cucumber.api.java8.En;
import java.io.File;
import java.util.List;
import java.util.logging.Level;
import jmri.InstanceManager;
import jmri.ConfigureManager;
import org.assertj.core.api.Condition;
import org.assertj.core.api.SoftAssertions;
import org.openqa.selenium.By;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.html5.WebStorage;
import org.openqa.selenium.logging.LogEntries;
import org.openqa.selenium.logging.LogEntry;
import org.openqa.selenium.logging.LogType;
import org.openqa.selenium.support.events.EventFiringWebDriver;
import org.openqa.selenium.support.ui.ExpectedCondition;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import static org.assertj.core.api.Assertions.allOf;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Cucumber step definitions for Web Server Acceptance tests.
*
* @author Paul Bender Copyright (C) 2017
*/
public class WebServerAcceptanceSteps implements En {
private EventFiringWebDriver webDriver;
String[] firefoxtags = {"@webtest", "@firefox"};
String[] chrometags = {"@webtest", "@chrome"};
String[] tags = {"@webtest"};
String[] paneltags = {"@webpanel"};
public WebServerAcceptanceSteps(jmri.InstanceManager instance) {
Given("^I am using firefox$", () -> {
webDriver = jmri.util.web.BrowserFactory.getBrowser("Firefox");
});
Given("^I am using chrome$", () -> {
webDriver = jmri.util.web.BrowserFactory.getBrowser("Chrome");
});
When("^I ask for the url (.*)$", (String url) -> {
webDriver.get(url);
});
Given("^panel (.*) is loaded$", (String path) -> {
InstanceManager.getDefault(ConfigureManager.class).load(new File(path));
});
Then("^a page with title (.*) is returned$", (String pageTitle) -> {
waitLoad();
assertThat(webDriver.getTitle()).isEqualTo(pageTitle);
});
Then("^(.*) is set as the title$", (String pageTitle) -> {
waitLoad(); //wait for page to load
//additional conditional wait for javascript to run and set the title
WebDriverWait wait = new WebDriverWait(webDriver, 10);
wait.until(ExpectedConditions.titleIs(pageTitle));
assertThat(webDriver.getTitle()).isEqualTo(pageTitle);
});
Then("^(.*) is visible$", (String table) -> {
webDriver.get("http://localhost:12080/");
waitLoad();
// navigate to the table.
(webDriver.findElement(By.linkText("Tables"))).click();
(webDriver.findElement(By.linkText(table))).click();
waitLoad();
// wait for the table to load.
WebDriverWait wait = new WebDriverWait(webDriver, 10);
wait.until(ExpectedConditions.visibilityOfElementLocated(By.tagName("table")));
});
Then("item (.*) with entry (.*) has state (.*)$", (String item, String column, String state) -> {
WebElement element = findTableCellItemNameAndCollumn("name", column, item);
assertThat(element.getText()).isEqualTo(state);
});
When("^(.*) for (.*) in (.*) is clicked$", (String column, String item, String table) -> {
WebDriverWait wait = new WebDriverWait(webDriver, 10);
//set xpath paths to item of interest
String tablePath = "//table[@id='jmri-data']";
String cellPath = tablePath + "//tr[@data-name='" + item + "']//td[@class='" + column + "']";
//wait until the requested cell is visible (twice, since row is immed. repainted from json update)
wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath(cellPath)));
wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath(cellPath)));
//must be only one cell that matches
assertThat((Integer) webDriver.findElements(By.xpath(cellPath)).size()).isEqualTo(1);
//click on the target cell
webDriver.findElement(By.xpath(cellPath)).click();
});
// the order of After operations is controlled by the 3rd parameter
// lower numbers happen earlier (0 first).
After(chrometags, NO_TIMEOUT, 0, () -> {
LogEntries logEntries = webDriver.manage().logs().get(LogType.BROWSER);
Condition<LogEntry> error = new Condition<>( o -> o.getMessage().contains("ERROR:"),"error");
Condition<LogEntry> severe = new Condition<>( o -> o.getLevel().equals(Level.SEVERE),"severe");
SoftAssertions softly = new SoftAssertions();
for (LogEntry logEntry : logEntries) {
softly.assertThat(logEntry)
.withFailMessage(String.format("%s:%s:%s",webDriver.getWrappedDriver().getClass(),logEntry.getLevel().getName(),logEntry.getMessage()))
.isNot(allOf(severe,error));
}
softly.assertAll();
});
After(paneltags, NO_TIMEOUT, 2, () -> {
// navigate back home to prevent the webpage from reloading.
try {
webDriver.get("http://localhost:12080/");
} catch (org.openqa.selenium.WebDriverException wde) {
log.warn("Ignoring error navigating back to home.");
}
});
After(tags, NO_TIMEOUT, 6, () -> {
// Clear out all local storage
if (webDriver instanceof WebStorage) {
WebStorage storage = (WebStorage) webDriver;
storage.getLocalStorage().clear();
storage.getSessionStorage().clear();
}
});
After(paneltags, NO_TIMEOUT, 4, () -> {
jmri.util.JUnitUtil.closeAllPanels();
});
}
private void waitLoad() {
WebDriverWait wait = new WebDriverWait(webDriver, 10);
wait.until((ExpectedCondition<Boolean>) (WebDriver driver) -> {
// this ExpectedCondition code is derived from code posted by user
// Jeff Vincent to
// https://stackoverflow.com/questions/12858972/how-can-i-ask-the-selenium-webdriver-to-wait-for-few-seconds-in-java
String script = "if (typeof window != 'undefined' && window.document) { return window.document.readyState; } else { return 'notready'; }";
Boolean result = Boolean.FALSE;
if (driver != null) {
try {
result = ((JavascriptExecutor) driver).executeScript(script).equals("complete");
} catch (Exception ex) {
// nothing to do, but silence the error
}
}
return result;
});
}
private WebElement findTableCellItemNameAndCollumn(String rowName, String columnName, String itemName) {
WebElement webTable = webDriver.findElement(By.xpath("//div[@id='wrap']//div[@class='container']//table"));
// find the columns containing the nameName and the column label in the table header.
WebElement tableHeader = webTable.findElement(By.tagName("thead"));
List<WebElement> headerRows = tableHeader.findElements(By.tagName("tr"));
List<WebElement> header = headerRows.get(0).findElements(By.tagName("th"));
int rowNameCol = 0;
int desiredCol = 3;
for (int i = 0; i < header.size(); i++) {
if (header.get(i).getText().equals(rowName)) {
rowNameCol = i;
}
if (header.get(i).getText().equals(columnName)) {
desiredCol = i;
}
}
// find the table body.
WebElement tableBody = webTable.findElement(By.tagName("tbody"));
List<WebElement> rows = tableBody.findElements(By.tagName("tr"));
for (int i = 0; i < rows.size(); i++) {
List<WebElement> cols = rows.get(i).findElements(By.tagName("td"));
if (cols.size() > 0 && cols.get(rowNameCol).getText().equals(itemName)) {
return cols.get(desiredCol);
}
}
throw new ItemNotFoundException("Unable to find row with " + rowName + " = " + itemName);
}
private final class ItemNotFoundException extends RuntimeException {
public ItemNotFoundException(String reason) {
super(reason);
}
}
private static final Logger log = LoggerFactory.getLogger(WebServerAcceptanceSteps.class);
}