Skip to content

Commit 7aa6bfe

Browse files
committed
Modularize into RemoteWebElementListener
1 parent 5f657cc commit 7aa6bfe

File tree

5 files changed

+138
-51
lines changed

5 files changed

+138
-51
lines changed

src/main/java/io/appium/java_client/proxy/Helpers.java

Lines changed: 5 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,10 @@
2727
import net.bytebuddy.matcher.ElementMatcher;
2828
import net.bytebuddy.matcher.ElementMatchers;
2929
import org.jspecify.annotations.Nullable;
30-
import org.openqa.selenium.remote.RemoteWebDriver;
31-
import org.openqa.selenium.remote.RemoteWebElement;
3230

3331
import java.lang.reflect.Method;
3432
import java.util.Collection;
3533
import java.util.Collections;
36-
import java.util.List;
3734
import java.util.Map;
3835
import java.util.Set;
3936
import java.util.WeakHashMap;
@@ -148,6 +145,11 @@ public static <T> T createProxy(
148145
try {
149146
T result = cls.cast(proxyClass.getConstructor(constructorArgTypes).newInstance(constructorArgs));
150147
((HasMethodCallListeners) result).setMethodCallListeners(listeners.toArray(MethodCallListener[]::new));
148+
149+
listeners.stream()
150+
.filter(ProxyAwareListener.class::isInstance)
151+
.forEach(listener -> ((ProxyAwareListener) listener).attachProxyInstance(result));
152+
151153
return result;
152154
} catch (SecurityException | ReflectiveOperationException e) {
153155
throw new IllegalStateException(String.format("Unable to create a proxy of %s", cls.getName()), e);
@@ -225,28 +227,4 @@ private static class ProxyClassSignature {
225227
Class<?>[] constructorArgTypes;
226228
ElementMatcher<MethodDescription> extraMethodMatcher;
227229
}
228-
229-
public static RemoteWebElement wrapElement(
230-
RemoteWebElement original,
231-
HasMethodCallListeners parent,
232-
MethodCallListener[] listeners
233-
) {
234-
RemoteWebElement proxy = createProxy(
235-
RemoteWebElement.class,
236-
new Object[]{},
237-
new Class[]{},
238-
List.of(listeners),
239-
ElementMatchers.not(
240-
namedOneOf(
241-
OBJECT_METHOD_NAMES.toArray(new String[0]))
242-
.or(ElementMatchers.named("setId").or(ElementMatchers.named("setParent")))
243-
)
244-
);
245-
246-
proxy.setId(original.getId());
247-
248-
proxy.setParent((RemoteWebDriver) parent);
249-
250-
return proxy;
251-
}
252230
}

src/main/java/io/appium/java_client/proxy/Interceptor.java

Lines changed: 0 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -114,29 +114,6 @@ public static Object intercept(
114114
}
115115
}
116116

117-
if (result instanceof RemoteWebElement) {
118-
result = Helpers.wrapElement(
119-
(RemoteWebElement) result,
120-
(HasMethodCallListeners) self,
121-
listeners);
122-
} else if (result instanceof List) {
123-
List<?> originalList = (List<?>) result;
124-
125-
if (!originalList.isEmpty()) {
126-
result = originalList.stream()
127-
.map(item -> {
128-
if (item instanceof RemoteWebElement) {
129-
return Helpers.wrapElement(
130-
(RemoteWebElement) item,
131-
(HasMethodCallListeners) self,
132-
listeners);
133-
}
134-
return item;
135-
})
136-
.collect(Collectors.toList());
137-
}
138-
}
139-
140117
final Object endResult = result == UNSET ? null : result;
141118
for (var listener : listeners) {
142119
try {
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
/*
2+
* Licensed under the Apache License, Version 2.0 (the "License");
3+
* you may not use this file except in compliance with the License.
4+
* See the NOTICE file distributed with this work for additional
5+
* information regarding copyright ownership.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package io.appium.java_client.proxy;
18+
19+
public interface ProxyAwareListener extends MethodCallListener {
20+
void attachProxyInstance(Object proxy);
21+
}
22+
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
/*
2+
* Licensed under the Apache License, Version 2.0 (the "License");
3+
* you may not use this file except in compliance with the License.
4+
* See the NOTICE file distributed with this work for additional
5+
* information regarding copyright ownership.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package io.appium.java_client.proxy;
18+
19+
import com.google.common.base.Preconditions;
20+
import net.bytebuddy.matcher.ElementMatchers;
21+
import org.openqa.selenium.WebDriver;
22+
import org.openqa.selenium.remote.RemoteWebDriver;
23+
import org.openqa.selenium.remote.RemoteWebElement;
24+
25+
import java.lang.reflect.Method;
26+
import java.util.Collection;
27+
import java.util.Collections;
28+
import java.util.List;
29+
import java.util.concurrent.Callable;
30+
import java.util.stream.Collectors;
31+
32+
import static io.appium.java_client.proxy.Helpers.OBJECT_METHOD_NAMES;
33+
import static io.appium.java_client.proxy.Helpers.createProxy;
34+
import static net.bytebuddy.matcher.ElementMatchers.namedOneOf;
35+
36+
public class RemoteWebElementListener implements MethodCallListener, ProxyAwareListener {
37+
private WebDriver parent;
38+
private final Collection<MethodCallListener> listeners;
39+
40+
public RemoteWebElementListener(MethodCallListener listener) {
41+
this.listeners = Collections.singletonList(listener);
42+
}
43+
44+
public RemoteWebElementListener(Collection<MethodCallListener> listeners) {
45+
this.listeners = listeners;
46+
}
47+
48+
@Override
49+
public void attachProxyInstance(Object proxy) {
50+
Preconditions.checkArgument(proxy instanceof WebDriver);
51+
this.parent = (WebDriver) proxy;
52+
}
53+
54+
@Override
55+
public Object call(Object obj, Method method, Object[] args, Callable<?> original) throws Throwable {
56+
Object result = original.call();
57+
58+
if (result instanceof RemoteWebElement) {
59+
result = wrapElement(
60+
(RemoteWebElement) result,
61+
parent,
62+
listeners);
63+
} else if (result instanceof List) {
64+
List<?> originalList = (List<?>) result;
65+
66+
if (!originalList.isEmpty()) {
67+
result = originalList.stream()
68+
.map(item -> {
69+
if (item instanceof RemoteWebElement) {
70+
return wrapElement(
71+
(RemoteWebElement) item,
72+
parent,
73+
listeners);
74+
}
75+
return item;
76+
})
77+
.collect(Collectors.toList());
78+
}
79+
}
80+
81+
return result;
82+
}
83+
84+
private RemoteWebElement wrapElement(
85+
RemoteWebElement original,
86+
WebDriver parent,
87+
Collection<MethodCallListener> listeners
88+
) {
89+
RemoteWebElement proxy = createProxy(
90+
RemoteWebElement.class,
91+
new Object[]{},
92+
new Class[]{},
93+
listeners,
94+
ElementMatchers.not(
95+
namedOneOf(
96+
OBJECT_METHOD_NAMES.toArray(new String[0]))
97+
.or(ElementMatchers.named("setId").or(ElementMatchers.named("setParent")))
98+
)
99+
);
100+
101+
proxy.setId(original.getId());
102+
103+
proxy.setParent((RemoteWebDriver) parent);
104+
105+
return proxy;
106+
}
107+
108+
}

src/test/java/io/appium/java_client/proxy/ProxyHelpersTest.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,11 +176,13 @@ public void beforeCall(Object target, Method method, Object[] args) {
176176
}
177177
};
178178

179+
RemoteWebElementListener remoteWebElementListener = new RemoteWebElementListener(listener);
180+
179181
FakeIOSDriver driver = createProxy(
180182
FakeIOSDriver.class,
181183
new Object[] {new URL("http://localhost:4723/"), new XCUITestOptions()},
182184
new Class[] {URL.class, Capabilities.class},
183-
listener
185+
List.of(remoteWebElementListener, listener)
184186
);
185187

186188
WebElement element = driver.findElement(By.id("button"));

0 commit comments

Comments
 (0)