39
39
* Then the {@code stereotype} must contain the same values.
40
40
* </ul>
41
41
*
42
- * <p>One thing to note is that extension capabilities are not considered when matching slots, since
43
- * the matching of these is implementation-specific to each driver.
42
+ * <p>Note that extension capabilities are considered for slot matching, with the following exceptions:
43
+ *
44
+ * <ul>
45
+ * <li>Extension capabilities with these prefixes:
46
+ * <ul>
47
+ * <li>"goog:" - Google
48
+ * <li>"moz:" - Mozilla
49
+ * <li>"ms:" - Microsoft
50
+ * <li>"se:" - Selenium
51
+ * </ul>
52
+ * <li>Extension capabilities with these suffixes:
53
+ * <ul>
54
+ * <li>"Options"
55
+ * <li>"options"
56
+ * <li>"loggingPrefs"
57
+ * <li>"debuggerAddress"
58
+ * </ul>
59
+ * </ul>
44
60
*/
45
61
public class DefaultSlotMatcher implements SlotMatcher , Serializable {
46
62
@@ -51,6 +67,13 @@ public class DefaultSlotMatcher implements SlotMatcher, Serializable {
51
67
private static final List <String > EXTENSION_CAPABILITIES_PREFIXES =
52
68
Arrays .asList ("goog:" , "moz:" , "ms:" , "se:" );
53
69
70
+ /*
71
+ List of extension capability suffixes we never should try to match, they should be
72
+ matched in the Node or in the browser driver.
73
+ */
74
+ private static final List <String > EXTENSION_CAPABILITY_SUFFIXES =
75
+ Arrays .asList ("Options" , "options" , "loggingPrefs" , "debuggerAddress" );
76
+
54
77
@ Override
55
78
public boolean matches (Capabilities stereotype , Capabilities capabilities ) {
56
79
@@ -76,14 +99,14 @@ public boolean matches(Capabilities stereotype, Capabilities capabilities) {
76
99
77
100
// At the end, a simple browser, browserVersion and platformName match
78
101
boolean browserNameMatch =
79
- (capabilities .getBrowserName () == null || capabilities .getBrowserName ().isEmpty ())
102
+ capabilities .getBrowserName () == null
103
+ || capabilities .getBrowserName ().isEmpty ()
80
104
|| Objects .equals (stereotype .getBrowserName (), capabilities .getBrowserName ());
81
105
boolean browserVersionMatch =
82
- (capabilities .getBrowserVersion () == null
83
- || capabilities .getBrowserVersion ().isEmpty ()
84
- || Objects .equals (capabilities .getBrowserVersion (), "stable" ))
85
- || browserVersionMatch (
86
- stereotype .getBrowserVersion (), capabilities .getBrowserVersion ());
106
+ capabilities .getBrowserVersion () == null
107
+ || capabilities .getBrowserVersion ().isEmpty ()
108
+ || Objects .equals (capabilities .getBrowserVersion (), "stable" )
109
+ || browserVersionMatch (stereotype .getBrowserVersion (), capabilities .getBrowserVersion ());
87
110
boolean platformNameMatch =
88
111
capabilities .getPlatformName () == null
89
112
|| Objects .equals (stereotype .getPlatformName (), capabilities .getPlatformName ())
@@ -102,21 +125,17 @@ private Boolean initialMatch(Capabilities stereotype, Capabilities capabilities)
102
125
.filter (name -> !name .contains (":" ))
103
126
// Platform matching is special, we do it later
104
127
.filter (name -> !"platformName" .equalsIgnoreCase (name ))
105
- .map (
128
+ .filter (name -> capabilities .getCapability (name ) != null )
129
+ .allMatch (
106
130
name -> {
107
- if (capabilities .getCapability (name ) instanceof String ) {
108
- return stereotype
109
- .getCapability (name )
110
- .toString ()
111
- .equalsIgnoreCase (capabilities .getCapability (name ).toString ());
112
- } else {
113
- return capabilities .getCapability (name ) == null
114
- || Objects .equals (
115
- stereotype .getCapability (name ), capabilities .getCapability (name ));
116
- }
117
- })
118
- .reduce (Boolean ::logicalAnd )
119
- .orElse (true );
131
+ if (stereotype .getCapability (name ) instanceof String
132
+ && capabilities .getCapability (name ) instanceof String ) {
133
+ return ((String ) stereotype .getCapability (name ))
134
+ .equalsIgnoreCase ((String ) capabilities .getCapability (name ));
135
+ }
136
+ return Objects .equals (
137
+ stereotype .getCapability (name ), capabilities .getCapability (name ));
138
+ });
120
139
}
121
140
122
141
private Boolean managedDownloadsEnabled (Capabilities stereotype , Capabilities capabilities ) {
@@ -140,13 +159,11 @@ private Boolean platformVersionMatch(Capabilities stereotype, Capabilities capab
140
159
*/
141
160
return capabilities .getCapabilityNames ().stream ()
142
161
.filter (name -> name .contains ("platformVersion" ))
143
- .map (
162
+ .allMatch (
144
163
platformVersionCapName ->
145
164
Objects .equals (
146
165
stereotype .getCapability (platformVersionCapName ),
147
- capabilities .getCapability (platformVersionCapName )))
148
- .reduce (Boolean ::logicalAnd )
149
- .orElse (true );
166
+ capabilities .getCapability (platformVersionCapName )));
150
167
}
151
168
152
169
private Boolean extensionCapabilitiesMatch (Capabilities stereotype , Capabilities capabilities ) {
@@ -156,23 +173,25 @@ private Boolean extensionCapabilitiesMatch(Capabilities stereotype, Capabilities
156
173
of the new session request contains that specific extension capability.
157
174
*/
158
175
return stereotype .getCapabilityNames ().stream ()
176
+ // examine only extension capabilities
159
177
.filter (name -> name .contains (":" ))
160
- . filter ( name -> capabilities . asMap (). containsKey ( name ))
178
+ // ignore special extension capability prefixes
161
179
.filter (name -> EXTENSION_CAPABILITIES_PREFIXES .stream ().noneMatch (name ::contains ))
162
- .map (
180
+ // ignore special extension capability suffixes
181
+ .filter (name -> EXTENSION_CAPABILITY_SUFFIXES .stream ().noneMatch (name ::endsWith ))
182
+ // ignore capabilities not specified in the request
183
+ .filter (name -> capabilities .getCapability (name ) != null )
184
+ .allMatch (
163
185
name -> {
164
- if (capabilities .getCapability (name ) instanceof String ) {
165
- return stereotype
166
- .getCapability (name )
167
- .toString ()
168
- .equalsIgnoreCase (capabilities .getCapability (name ).toString ());
169
- } else {
170
- return capabilities .getCapability (name ) == null
171
- || Objects .equals (
172
- stereotype .getCapability (name ), capabilities .getCapability (name ));
173
- }
174
- })
175
- .reduce (Boolean ::logicalAnd )
176
- .orElse (true );
186
+ // evaluate capabilities with String values
187
+ if (stereotype .getCapability (name ) instanceof String
188
+ && capabilities .getCapability (name ) instanceof String ) {
189
+ return ((String ) stereotype .getCapability (name ))
190
+ .equalsIgnoreCase ((String ) capabilities .getCapability (name ));
191
+ }
192
+ // evaluate capabilities with non-String values
193
+ return Objects .equals (
194
+ stereotype .getCapability (name ), capabilities .getCapability (name ));
195
+ });
177
196
}
178
197
}
0 commit comments