View Javadoc
1   /**
2    * This file Copyright (c) 2017 Magnolia International
3    * Ltd.  (http://www.magnolia-cms.com). All rights reserved.
4    *
5    *
6    * This file is dual-licensed under both the Magnolia
7    * Network Agreement and the GNU General Public License.
8    * You may elect to use one or the other of these licenses.
9    *
10   * This file is distributed in the hope that it will be
11   * useful, but AS-IS and WITHOUT ANY WARRANTY; without even the
12   * implied warranty of MERCHANTABILITY or FITNESS FOR A
13   * PARTICULAR PURPOSE, TITLE, or NONINFRINGEMENT.
14   * Redistribution, except as permitted by whichever of the GPL
15   * or MNA you select, is prohibited.
16   *
17   * 1. For the GPL license (GPL), you can redistribute and/or
18   * modify this file under the terms of the GNU General
19   * Public License, Version 3, as published by the Free Software
20   * Foundation.  You should have received a copy of the GNU
21   * General Public License, Version 3 along with this program;
22   * if not, write to the Free Software Foundation, Inc., 51
23   * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
24   *
25   * 2. For the Magnolia Network Agreement (MNA), this file
26   * and the accompanying materials are made available under the
27   * terms of the MNA which accompanies this distribution, and
28   * is available at http://www.magnolia-cms.com/mna.html
29   *
30   * Any modifications to this file must keep this entire header
31   * intact.
32   *
33   */
34  package info.magnolia.integrationtests;
35  
36  import java.util.Optional;
37  import java.util.function.Function;
38  
39  import org.apache.commons.beanutils.BeanUtilsBean;
40  
41  /**
42   * Aggregates common settings and parameters useful in UI tests.
43   */
44  public final class IntegrationTestSettings {
45  
46      private static final IntegrationTestSettings INSTANCE = new IntegrationTestSettings();
47  
48      public static IntegrationTestSettings access() {
49          return INSTANCE;
50      }
51  
52      private BeanUtilsBean beanUtils = BeanUtilsBean.getInstance();
53  
54      private Function<String, Integer> toInt = converter(Integer.class);
55      private Function<String, Boolean> toBool = converter(Boolean.class);
56  
57  
58      public String testOutputDirectory() {
59          return property("test.output.dir").orElse("target/failsafe-reports");
60      }
61  
62      public String recordingsDirectory() {
63          return property("recordings.dir").orElse(String.format("%s/recordings/", testOutputDirectory()));
64      }
65  
66      public String uploadDirectory() {
67          return property("upload.dir").orElse("target/test-classes");
68      }
69  
70      public String seleniumHubContainerName() {
71          return property("selenium.hub.name").orElse("selenium-hub");
72      }
73  
74      public String seleniumHubHost() {
75          return property("selenium.hub.host").orElse("localhost");
76      }
77  
78      public int concurrentTestInstances() {
79          return property("concurrent.instances").map(toInt).orElse(1);
80      }
81  
82      /**
83       * The name of the custom docker network which will be created and used
84       * for the docker containers.
85       */
86      public String testNetworkName() {
87          return property("selenium.network").orElse("mgnl-integration-tests");
88      }
89  
90      public String vncPassword() {
91          return property("vnc.password").orElse("secret");
92      }
93  
94      public String seleniumBrowser() {
95          return property("seleniumBrowser").orElse("chrome");
96      }
97  
98      public boolean testEnvironmentSetupRequired() {
99          return property("setup.test.env").map(toBool).orElse(true);
100     }
101 
102     public int defaultDelayInSeconds() {
103         return 2;
104     }
105 
106     public int driverTimeoutInSeconds() {
107         return property("selenium.timeout").map(toInt).orElse(30);
108     }
109 
110     public int vncPort() {
111         return property("vnc.port").map(toInt).orElse(5900);
112     }
113 
114     /**
115      * When running a test class, this property determines how many test cases can be run
116      * concurrently.
117      */
118     public int concurrentTestCases() {
119         return property("concurrent.test.cases").map(toInt).orElse(1);
120     }
121 
122     public int seleniumHubPort() {
123         return property("selenium.hub.port").map(toInt).orElse(4444);
124     }
125 
126     public boolean debugMode() {
127         return property("debug.mode").map(toBool).orElse(true);
128     }
129 
130     public boolean keepSuccessfulTestRecordings() {
131         return property("keep.successful").map(toBool).orElse(false);
132     }
133 
134     public boolean useHeadlessSeleniumNodes() {
135         return property("run.headless").map(toBool).orElse(false);
136     }
137 
138     private Optional<String> property(String key) {
139         return Optional.ofNullable(System.getProperty(key));
140     }
141 
142     @SuppressWarnings("unchecked")
143     private <T> Function<String, T> converter(Class<T> clazz) {
144         return str -> (T) beanUtils.getConvertUtils().convert(str, clazz);
145     }
146 
147     public String authorWarLocation() {
148         return property("author.war.location").orElse("target/wars/magnoliaAuthor.war");
149     }
150 
151     public String publicWarLocation() {
152         return property("public.war.location").orElse("target/wars/magnoliaPublic.war");
153     }
154 
155     public String authorContextPath() {
156         return property("authorContextPath").orElse("magnoliaAuthor");
157     }
158 
159     public String publicContextPath() {
160         return property("publicContextPath").orElse("magnoliaPublic");
161     }
162 
163 
164     /**
165      * Test instance URL accessible from outside of the test environment.
166      * E.g. if the test env is deployed as a Docker setup (maybe even remote)
167      * and integration tests are executed outside of such setup, this URL can
168      * still provide "direct" access to the Magnolia deployment. This might be useful
169      * for interacting with the instance bypassing the Selenium driver (e.g. via REST).
170      */
171     public String directContainerRootURL() {
172         return String.format("http://%s:%d", publicHostName(), publicPort());
173     }
174 
175     /**
176      * Instance host name by it is known with the test environment.
177      * E.g. when Selenium and test Magnolia instances are deployed
178      * in the same Docker network, Selenium driver can use this
179      * host name for navigation. However, this host name is not
180      * accessible to the outer world.
181      *
182      * @see #containerRootUrl()
183      */
184     public String privateHostName() {
185         return property("privateHostName").orElse("server");
186     }
187 
188     /**
189      * Test environment-specific port which corresponds to the {@link #privateHostName()}.
190      *
191      * @see #containerRootUrl()
192      */
193     public int privatePort() {
194         return property("privateContainerHttpPort").map(toInt).orElse(8080);
195     }
196 
197     /**
198      * Test Magnolia instance host name available from outside of the test environment.
199      * When the test environment setup is deployed on the same machine on which the
200      * integration tests are executed, then typically this would be 'localhost'. In
201      * case of the remote test env deployment, some other host name should be configured.
202      *
203      * @see #containerRootUrl()
204      */
205     public String publicHostName() {
206         return property("containerHostName").orElse("localhost");
207     }
208 
209     /**
210      * Magnolia instance port open to the outer world. Unlike {@link #privatePort()},
211      * this port is used for Mgnl instance access from outside of the Docker environment.
212      *
213      * @see #publicHostName()
214      * @see #directContainerRootURL() ()
215      */
216     public int publicPort() {
217         return property(String.format("%s.public.port", privateHostName())).map(toInt).orElseGet(() ->
218                 property("containerHttpPort")
219                     .map(toInt)
220                     .orElse(8599));
221     }
222 
223     /**
224      * Test instance's URL available within the [Docker] test environment and
225      * not exposed to the outer world.
226      */
227     public String containerRootUrl() {
228         return String.format("http://%s:%d", privateHostName(), privatePort());
229     }
230 
231     public Integer startupTimeout() {
232         return property("startupTimeout").map(toInt).orElse(7);
233     }
234 
235     public String tomcatDockerImage() {
236         return property("tomcatDockerImage").orElse("amd64/tomcat:9.0-jre8");
237     }
238 }