+ * Use the WebAppFixture to temporary change the active environment for your web tests. + *
Changes are not rollbacked automatically to the previous value after the test.
+ *To use the AppFixture annotate your test class with the {@link IvyWebTest} annotation. + * Then add the AppFixture as parameter to any {@link Test}, {@link BeforeEach}, {@link AfterEach}, + * methods or the constructor of the test class.
+ *Example: + *
+ * {@literal @IvyWebTest}
+ * class Test {
+ * {@literal @Test}
+ * void test(WebAppFixture fixture) {
+ * open(EngineUrl.create().toUrl());
+ * $(By.id("sessionUserName")).shouldBe(Condition.exactText("Developer"));
+ * fixture.login("test", "test");
+ * $(By.id("sessionUserName")).shouldBe(Condition.exactText("test"));
+ * }
+ * }
+ *
+ * @since 10.0.14
+ */
+public class WebAppFixture {
+
+ private static final String VAR_PATH = "variables";
+ private static final String CONFIG_PATH = "configs";
+
+ /**
+ * Login to a user. + * This user will be used as long as the browser context isn't closed or the {@link #logout()} method is called. + * It uses the login form of the Dev-Workflow-UI.
+ *Example: + *
+ * {@literal @Test}
+ * void test(WebAppFixture fixture) {
+ * open(EngineUrl.create().toUrl());
+ * $(By.id("sessionUserName")).shouldBe(Condition.exactText("Developer"));
+ * fixture.login("test", "test");
+ * $(By.id("sessionUserName")).shouldBe(Condition.exactText("test"));
+ * }
+ *
+ * @param username the name of the user
+ * @param password the password of the user
+ */
+ public void login(String username, String password) {
+ var currentUrl = Selenide.webdriver().driver().url();
+ open(EngineUrl.create().app("").path("dev-workflow-ui/faces/login.xhtml").toUrl());
+ $(By.id("loginForm:userName")).shouldBe(visible).sendKeys(username);
+ $(By.id("loginForm:password")).shouldBe(visible).sendKeys(password);
+ $(By.id("loginForm:login")).shouldBe(visible).click();
+ $(By.id("loginForm:login")).shouldNotBe(visible);
+ if (!"about:blank".equals(currentUrl)) {
+ open(currentUrl);
+ }
+ }
+
+ /**
+ * Logout the current user. + * This method logout the current user by using the Dev-Workflow-UI.
+ *Example: + *
+ * {@literal @Test}
+ * void test(WebAppFixture fixture) {
+ * open(EngineUrl.create().toUrl());
+ * $(By.id("sessionUserName")).shouldBe(Condition.exactText("Developer"));
+ * fixture.logout();
+ * $(By.id("sessionUserName")).shouldBe(Condition.exactText("test"));
+ * }
+ *
+ */
+ public void logout() {
+ var currentUrl = Selenide.webdriver().driver().url();
+ open(EngineUrl.create().app("").path("dev-workflow-ui/faces/home.xhtml").toUrl());
+ $(By.id("sessionUserName")).shouldBe(visible).click();
+ $(By.id("sessionLogoutBtn")).shouldBe(visible).click();
+ open(currentUrl);
+ }
+
+ /**
+ * Set a variable to a given value. + * This variable will be set as long it is not been {@link #resetVar(String)}.
+ *Example: + *
+ * {@literal @Test}
+ * void test(WebAppFixture fixture) {
+ * fixture.var("myVar", "myNewValue");
+ * }
+ *
+ */
+ public void var(String name, String value) {
+ try {
+ var url = configRestUrl(VAR_PATH + "/" + name) + "?value=" + value;
+ sendRequest(HttpRequest.newBuilder(new URI(url)).POST(BodyPublishers.noBody()));
+ } catch (Exception ex) {
+ throw new RuntimeException("Couldn't set variable", ex);
+ }
+ }
+
+ /**
+ * Reset a variable to the initial value.
+ *Example: + *
+ * {@literal @Test}
+ * void test(WebAppFixture fixture) {
+ * fixture.var("myVar", "myNewValue");
+ * //do some tests
+ * fixture.resetVar("myVar");
+ * }
+ *
+ */
+ public void resetVar(String name) {
+ try {
+ var url = configRestUrl(VAR_PATH + "/" + name);
+ sendRequest(HttpRequest.newBuilder(new URI(url)).DELETE());
+ } catch (Exception ex) {
+ throw new RuntimeException("Couldn't remove variable", ex);
+ }
+ }
+
+ /**
+ * Set an app configuration (like rest or web service,...) to a given value. + * This configuration will be set as long it is not been {@link #resetConfig(String)}.
+ *Example: + *
+ * {@literal @Test}
+ * void test(WebAppFixture fixture) {
+ * fixture.config("RestClients.MyRestClient.Url", "${ivy.app.baseurl}/api/myCoolMockService");
+ * }
+ *
+ */
+ public void config(String name, String value) {
+ try {
+ var url = configRestUrl(CONFIG_PATH + "/" + name) + "?value=" + value;
+ sendRequest(HttpRequest.newBuilder(new URI(url)).POST(BodyPublishers.noBody()));
+ } catch (Exception ex) {
+ throw new RuntimeException("Couldn't set config", ex);
+ }
+ }
+
+ /**
+ * Reset an app configuration (like rest or web service,...) to an initial value.
+ *Example: + *
+ * {@literal @Test}
+ * void test(WebAppFixture fixture) {
+ * fixture.config("RestClients.MyRestClient.Url", "${ivy.app.baseurl}/api/myCoolMockService");
+ * //do some tests
+ * fixture.resetConfig("RestClients.MyRestClient.Url");
+ * }
+ *
+ */
+ public void resetConfig(String name) {
+ try {
+ var url = configRestUrl(CONFIG_PATH + "/" + name);
+ sendRequest(HttpRequest.newBuilder(new URI(url)).DELETE());
+ } catch (Exception ex) {
+ throw new RuntimeException("Couldn't remove config", ex);
+ }
+ }
+
+ private static String configRestUrl(String path) {
+ return EngineUrl.create().app("system").rest("apps/" + EngineUrl.applicationName() + "/" + path).toUrl();
+ }
+
+ private void sendRequest(HttpRequest.Builder requestBuilder) throws Exception {
+ var client = HttpClient.newBuilder()
+ .authenticator(new RestConfigAuthentication())
+ .build();
+ var request = requestBuilder.header("X-Requested-By", "webtest").build();
+ var response = client.send(request, BodyHandlers.ofString());
+ if (response.statusCode() > 399) {
+ throw new RuntimeException("Couldn't send web app fixture request (status code: " + response.statusCode() + "): " + response.body());
+ }
+ }
+
+ private static class RestConfigAuthentication extends Authenticator {
+ @Override
+ protected PasswordAuthentication getPasswordAuthentication() {
+ return new PasswordAuthentication("admin", "admin".toCharArray());
+ }
+ }
+}