2929import org .apache .http .client .utils .URIBuilder ;
3030import org .openqa .selenium .Capabilities ;
3131import org .openqa .selenium .SearchContext ;
32+ import org .openqa .selenium .net .PortProber ;
3233import org .slf4j .Logger ;
3334import org .slf4j .LoggerFactory ;
3435
4445import com .nordstrom .automation .selenium .servlet .ExamplePageServlet .FrameC_Servlet ;
4546import com .nordstrom .automation .selenium .servlet .ExamplePageServlet .FrameD_Servlet ;
4647import com .nordstrom .automation .selenium .support .SearchContextWait ;
48+ import com .nordstrom .automation .selenium .utility .GridHubPortAllocator ;
4749import com .nordstrom .automation .selenium .utility .HostUtils ;
4850import com .nordstrom .automation .settings .SettingsCore ;
4951import com .nordstrom .common .base .UncheckedThrow ;
@@ -159,8 +161,8 @@ public enum SeleniumSettings implements SettingsCore.SettingsAPI {
159161 * name: <b>selenium.grid.launcher</b><br>
160162 * default: (populated by {@link SeleniumConfig#getDefaults() getDefaults()})
161163 * <ul>
162- * <li>Selenium 3: <b>org.openqa.grid.selenium.GridLauncherV3</b></li>
163164 * <li>Selenium 4: <b>org.openqa.selenium.grid.Bootstrap</b></li>
165+ * <li>Selenium 3: <b>org.openqa.grid.selenium.GridLauncherV3</b></li>
164166 * </ul>
165167 */
166168 GRID_LAUNCHER ("selenium.grid.launcher" , null ),
@@ -178,29 +180,45 @@ public enum SeleniumSettings implements SettingsCore.SettingsAPI {
178180 * This setting specifies the configuration file name/path for the local <b>Selenium Grid</b> hub server.
179181 * <p>
180182 * name: <b>selenium.hub.config</b><br>
181- * Selenium 3 : <b>hubConfig-s3 .json</b><br>
182- * Selenium 4 : <b>hubConfig-s4 .json</b>
183+ * Selenium 4 : <b>hubConfig-s4 .json</b><br>
184+ * Selenium 3 : <b>hubConfig-s3 .json</b>
183185 */
184186 HUB_CONFIG ("selenium.hub.config" , null ),
185187
186188 /**
187189 * This is the URL for the <b>Selenium Grid</b> endpoint: [scheme:][//authority]/wd/hub
188190 * <p>
189191 * name: <b>selenium.hub.host</b><br>
190- * Selenium 3 : <b>http://<{@code localhost}>:4445 /wd/hub</b><br>
191- * Selenium 4 : <b>http://<{@code localhost}>:4446 /wd/hub</b>
192+ * Selenium 4 : <b>http://<{@code localhost}>:4444 /wd/hub</b><br>
193+ * Selenium 3 : <b>http://<{@code localhost}>:4445 /wd/hub</b>
192194 */
193195 HUB_HOST ("selenium.hub.host" , null ),
194196
195197 /**
196198 * This is the port assigned to the local <b>Selenium Grid</b> hub server.
197199 * <p>
198200 * name: <b>selenium.hub.port</b><br>
199- * Selenium 3 : <b>4445 </b><br>
200- * Selenium 4 : <b>4446 </b>
201+ * Selenium 4 : <b>4444 </b><br>
202+ * Selenium 3 : <b>4445 </b>
201203 */
202204 HUB_PORT ("selenium.hub.port" , null ),
203205
206+ /**
207+ * This is the port used by local <b>Selenium Grid</b> components for publishing events.
208+ * <p>
209+ * name: <b>selenium.publish.port</b><br>
210+ * default: <b>4442</b>
211+ */
212+ PUBLISH_PORT ("selenium.publish.port" , "4442" ),
213+
214+ /**
215+ * This is the port used by local <b>Selenium Grid</b> components for subscribing to events.
216+ * <p>
217+ * name: <b>selenium.subscribe.port</b><br>
218+ * default: <b>4443</b>
219+ */
220+ SUBSCRIBE_PORT ("selenium.subscribe.port" , "4443" ),
221+
204222 /**
205223 * This setting specifies the slot matcher used by the local <b>Selenium Grid</b> hub server.
206224 *
@@ -221,8 +239,8 @@ public enum SeleniumSettings implements SettingsCore.SettingsAPI {
221239 * This setting specifies the configuration template name/path for local <b>Selenium Grid</b> node servers.
222240 * <p>
223241 * name: <b>selenium.node.config</b><br>
224- * Selenium 3 : <b>nodeConfig-s3 .json</b><br>
225- * Selenium 4 : <b>nodeConfig-s4 .json</b>
242+ * Selenium 4 : <b>nodeConfig-s4 .json</b><br>
243+ * Selenium 3 : <b>nodeConfig-s3 .json</b>
226244 */
227245 NODE_CONFIG ("selenium.node.config" , null ),
228246
@@ -354,11 +372,20 @@ public enum SeleniumSettings implements SettingsCore.SettingsAPI {
354372 */
355373 CONTEXT_PLATFORM ("selenium.context.platform" , "support" ),
356374
375+ /**
376+ * This setting specifies the port that the {@code Appium} server listens on.
377+ * <p>
378+ * name: <b>appium.server.port</b><br>
379+ * default: <b>4723</b>
380+ */
381+ APPIUM_SERVER_PORT ("appium.server.port" , "4723" ),
382+
357383 /**
358384 * This setting specifies the path to an {@code Appium} configuration file provided to the server
359385 * when it's launched as a local <b>Selenium Grid</b> node server.
360386 * <p>
361- * <b>NOTE</b>: If specified, this setting
387+ * <b>NOTE</b>: If specified, the config file indicated by this setting provides base values for the options
388+ * it declares. These values can be supplemented or overridden via the {@link #APPIUM_CLI_ARGS} setting.
362389 * <p>
363390 * name: <b>appium.config.path</b><br>
364391 * default: {@code null}
@@ -693,6 +720,22 @@ public synchronized URL getHubUrl() {
693720 return hubUrl ;
694721 }
695722
723+ /**
724+ * Get the <b>Selenium Grid</b> event bus 'publish' URL.
725+ *
726+ * @return URL for publishing <b>Grid</b> events
727+ * @see SeleniumSettings#PUBLISH_PORT
728+ */
729+ public abstract String getPublishUrl ();
730+
731+ /**
732+ * Get the <b>Selenium Grid</b> event bus 'subscribe' URL.
733+ *
734+ * @return URL for subscribing to <b>Grid</b> events
735+ * @see SeleniumSettings#SUBSCRIBE_PORT
736+ */
737+ public abstract String getSubscribeUrl ();
738+
696739 /**
697740 * Get object that represents the active Selenium Grid.
698741 *
@@ -822,6 +865,16 @@ public Path getHubConfigPath() {
822865 return hubConfigPath ;
823866 }
824867
868+ /**
869+ * Get the port that the {@code Appium} server listens on.
870+ *
871+ * @return {@link SeleniumSettings#APPIUM_SERVER_PORT APPIUM_SERVER_PORT} if defined and available;
872+ * otherwise random available port
873+ */
874+ public int getAppiumServerPort () {
875+ return getAvailablePort (SeleniumSettings .APPIUM_SERVER_PORT );
876+ }
877+
825878 /**
826879 * Get the path to the Appium configuration.
827880 *
@@ -1117,4 +1170,25 @@ public boolean appiumWithPM2() {
11171170 public String getSettingsPath () {
11181171 return SETTINGS_FILE ;
11191172 }
1173+
1174+ /**
1175+ * Get available port for the specified setting.
1176+ *
1177+ * @param setting setting to check for port availability
1178+ * @return value of setting if defined and available; otherwise random available port
1179+ */
1180+ protected int getAvailablePort (final SeleniumSettings setting ) {
1181+ int port = getInt (setting .key (), -1 );
1182+ if (port != -1 ) {
1183+ if (!GridHubPortAllocator .isFree (port )) {
1184+ LOGGER .warn ("{} port '{}' is unavailable; finding free port" , setting .name (), port );
1185+ port = -1 ;
1186+ }
1187+ }
1188+ if (port == -1 ) {
1189+ port = PortProber .findFreePort ();
1190+ System .setProperty (setting .key (), Integer .toString (port ));
1191+ }
1192+ return port ;
1193+ }
11201194}
0 commit comments