@@ -50,6 +50,10 @@ public class DefaultSlotMatcher implements SlotMatcher, Serializable {
5050 */
5151 private static final List <String > EXTENSION_CAPABILITIES_PREFIXES =
5252 Arrays .asList ("goog:" , "moz:" , "ms:" , "se:" );
53+ public static final List <String > SPECIFIC_RELAY_CAPABILITIES_APP =
54+ Arrays .asList ("appium:app" , "appium:appPackage" , "appium:bundleId" );
55+ public static final List <String > MANDATORY_CAPABILITIES =
56+ Arrays .asList ("platformName" , "browserName" , "browserVersion" );
5357
5458 @ Override
5559 public boolean matches (Capabilities stereotype , Capabilities capabilities ) {
@@ -75,33 +79,22 @@ public boolean matches(Capabilities stereotype, Capabilities capabilities) {
7579 }
7680
7781 // At the end, a simple browser, browserVersion and platformName match
78- boolean browserNameMatch =
79- (capabilities .getBrowserName () == null || capabilities .getBrowserName ().isEmpty ())
80- || Objects .equals (stereotype .getBrowserName (), capabilities .getBrowserName ());
81- boolean browserVersionMatch =
82- (capabilities .getBrowserVersion () == null
83- || capabilities .getBrowserVersion ().isEmpty ()
84- || Objects .equals (capabilities .getBrowserVersion (), "stable" ))
85- || browserVersionMatch (
86- stereotype .getBrowserVersion (), capabilities .getBrowserVersion ());
87- boolean platformNameMatch =
88- capabilities .getPlatformName () == null
89- || Objects .equals (stereotype .getPlatformName (), capabilities .getPlatformName ())
90- || (stereotype .getPlatformName () != null
91- && stereotype .getPlatformName ().is (capabilities .getPlatformName ()));
92- return browserNameMatch && browserVersionMatch && platformNameMatch ;
93- }
82+ boolean browserNameMatch = browserNameMatch (stereotype , capabilities );
83+ boolean browserVersionMatch = browserVersionMatch (stereotype , capabilities );
84+ boolean platformNameMatch = platformNameMatch (stereotype , capabilities );
9485
95- private boolean browserVersionMatch (String stereotype , String capabilities ) {
96- return new SemanticVersionComparator ().compare (stereotype , capabilities ) == 0 ;
86+ return browserNameMatch && browserVersionMatch && platformNameMatch ;
9787 }
9888
99- private Boolean initialMatch (Capabilities stereotype , Capabilities capabilities ) {
89+ private boolean initialMatch (Capabilities stereotype , Capabilities capabilities ) {
10090 return stereotype .getCapabilityNames ().stream ()
10191 // Matching of extension capabilities is implementation independent. Skip them
10292 .filter (name -> !name .contains (":" ))
103- // Platform matching is special, we do it later
104- .filter (name -> !"platformName" .equalsIgnoreCase (name ))
93+ // Mandatory capabilities match is done at the end
94+ .filter (
95+ name ->
96+ MANDATORY_CAPABILITIES .stream ()
97+ .noneMatch (mandatory -> mandatory .equalsIgnoreCase (name )))
10598 .map (
10699 name -> {
107100 if (capabilities .getCapability (name ) instanceof String ) {
@@ -119,7 +112,7 @@ private Boolean initialMatch(Capabilities stereotype, Capabilities capabilities)
119112 .orElse (true );
120113 }
121114
122- private Boolean managedDownloadsEnabled (Capabilities stereotype , Capabilities capabilities ) {
115+ private boolean managedDownloadsEnabled (Capabilities stereotype , Capabilities capabilities ) {
123116 // First lets check if user wanted a Node with managed downloads enabled
124117 Object raw = capabilities .getCapability ("se:downloadsEnabled" );
125118 if (raw == null || !Boolean .parseBoolean (raw .toString ())) {
@@ -132,7 +125,7 @@ private Boolean managedDownloadsEnabled(Capabilities stereotype, Capabilities ca
132125 return raw != null && Boolean .parseBoolean (raw .toString ());
133126 }
134127
135- private Boolean platformVersionMatch (Capabilities stereotype , Capabilities capabilities ) {
128+ private boolean platformVersionMatch (Capabilities stereotype , Capabilities capabilities ) {
136129 /*
137130 This platform version match is not W3C compliant but users can add Appium servers as
138131 Nodes, so we avoid delaying the match until the Slot, which makes the whole matching
@@ -149,7 +142,7 @@ private Boolean platformVersionMatch(Capabilities stereotype, Capabilities capab
149142 .orElse (true );
150143 }
151144
152- private Boolean extensionCapabilitiesMatch (Capabilities stereotype , Capabilities capabilities ) {
145+ private boolean extensionCapabilitiesMatch (Capabilities stereotype , Capabilities capabilities ) {
153146 /*
154147 We match extension capabilities when they are not prefixed with any of the
155148 EXTENSION_CAPABILITIES_PREFIXES items. Also, we match them only when the capabilities
@@ -175,4 +168,44 @@ private Boolean extensionCapabilitiesMatch(Capabilities stereotype, Capabilities
175168 .reduce (Boolean ::logicalAnd )
176169 .orElse (true );
177170 }
171+
172+ private boolean browserNameMatch (Capabilities stereotype , Capabilities capabilities ) {
173+ return (capabilities .getBrowserName () == null || capabilities .getBrowserName ().isEmpty ())
174+ || Objects .equals (stereotype .getBrowserName (), capabilities .getBrowserName ())
175+ || specificRelayCapabilitiesAppMatch (capabilities );
176+ }
177+
178+ private boolean browserVersionMatch (String stereotype , String capabilities ) {
179+ return new SemanticVersionComparator ().compare (stereotype , capabilities ) == 0 ;
180+ }
181+
182+ private boolean browserVersionMatch (Capabilities stereotype , Capabilities capabilities ) {
183+ return (capabilities .getBrowserVersion () == null
184+ || capabilities .getBrowserVersion ().isEmpty ()
185+ || Objects .equals (capabilities .getBrowserVersion (), "stable" ))
186+ || browserVersionMatch (stereotype .getBrowserVersion (), capabilities .getBrowserVersion ())
187+ || specificRelayCapabilitiesAppMatch (capabilities );
188+ }
189+
190+ private boolean platformNameMatch (Capabilities stereotype , Capabilities capabilities ) {
191+ return capabilities .getPlatformName () == null
192+ || Objects .equals (stereotype .getPlatformName (), capabilities .getPlatformName ())
193+ || (stereotype .getPlatformName () != null
194+ && stereotype .getPlatformName ().is (capabilities .getPlatformName ()));
195+ }
196+
197+ public static boolean specificRelayCapabilitiesAppMatch (Capabilities capabilities ) {
198+ /*
199+ This match is specific for the Relay capabilities that are related to the Appium server for native application.
200+ - If browserName is defined then we always assume it’s a hybrid browser session, so no app-related caps should be provided
201+ - If app is provided then the assumption is that app should be fetched from somewhere first and then installed on the destination device
202+ - If only appPackage is provided for uiautomator2 driver or bundleId for xcuitest then the assumption is we want to automate an app that is already installed on the device under test
203+ - If both (app and appPackage) or (app and bundleId). This will then save some small-time for the driver as by default it tries to autodetect these values anyway by analyzing the fetched package’s manifest
204+ */
205+ return SPECIFIC_RELAY_CAPABILITIES_APP .stream ()
206+ .anyMatch (
207+ name ->
208+ capabilities .getCapability (name ) != null
209+ && !capabilities .getCapability (name ).toString ().isEmpty ());
210+ }
178211}
0 commit comments