Skip to content

Commit ff10d91

Browse files
feat: Add Mac2Driver (#1439)
1 parent e9ca490 commit ff10d91

File tree

8 files changed

+406
-0
lines changed

8 files changed

+406
-0
lines changed
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
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.mac;
18+
19+
import io.appium.java_client.FindsByFluentSelector;
20+
import io.appium.java_client.MobileSelector;
21+
import org.openqa.selenium.WebElement;
22+
23+
import java.util.List;
24+
25+
public interface FindsByClassChain<T extends WebElement> extends FindsByFluentSelector<T> {
26+
27+
/**
28+
* Perform single element lookup by class chain expression.
29+
* Read https://github.com/appium/appium-mac2-driver#element-location
30+
* for more details on elements location strategies supported by Mac2 driver.
31+
*
32+
* @param using A valid class chain lookup expression.
33+
* @return The found element
34+
*/
35+
default T findElementByClassChain(String using) {
36+
return findElement(MobileSelector.IOS_CLASS_CHAIN.toString(), using);
37+
}
38+
39+
/**
40+
* Perform multiple elements lookup by class chain search expression.
41+
* Read https://github.com/appium/appium-mac2-driver#element-location
42+
* for more details on elements location strategies supported by Mac2 driver.
43+
*
44+
* @param using A valid class chain lookup expression.
45+
* @return The array of found elements or an empty one if no matches have been found.
46+
*/
47+
default List<T> findElementsByClassChain(String using) {
48+
return findElements(MobileSelector.IOS_CLASS_CHAIN.toString(), using);
49+
}
50+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
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.mac;
18+
19+
import io.appium.java_client.FindsByFluentSelector;
20+
import io.appium.java_client.MobileSelector;
21+
import org.openqa.selenium.WebElement;
22+
23+
import java.util.List;
24+
25+
public interface FindsByNsPredicate<T extends WebElement> extends FindsByFluentSelector<T> {
26+
27+
/**
28+
* Perform single element lookup by predicate search expression.
29+
* Read https://github.com/appium/appium-mac2-driver#element-location
30+
* for more details on elements location strategies supported by Mac2 driver.
31+
*
32+
* @param using A valid predicate lookup expression.
33+
* @return The found element
34+
*/
35+
default T findElementByNsPredicate(String using) {
36+
return findElement(MobileSelector.IOS_PREDICATE_STRING.toString(), using);
37+
}
38+
39+
/**
40+
* Perform multiple elements lookup by predicate search expression.
41+
* Read https://github.com/appium/appium-mac2-driver#element-location
42+
* for more details on elements location strategies supported by Mac2 driver.
43+
*
44+
* @param using A valid predicate lookup expression.
45+
* @return The array of found elements or an empty one if no matches have been found.
46+
*/
47+
default List<T> findElementsByNsPredicate(String using) {
48+
return findElements(MobileSelector.IOS_PREDICATE_STRING.toString(), using);
49+
}
50+
}
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
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.mac;
18+
19+
import io.appium.java_client.AppiumDriver;
20+
import io.appium.java_client.HasSettings;
21+
import io.appium.java_client.internal.CapabilityHelpers;
22+
import io.appium.java_client.remote.AutomationName;
23+
import io.appium.java_client.remote.MobileCapabilityType;
24+
import io.appium.java_client.screenrecording.CanRecordScreen;
25+
import io.appium.java_client.service.local.AppiumDriverLocalService;
26+
import io.appium.java_client.service.local.AppiumServiceBuilder;
27+
import org.openqa.selenium.Capabilities;
28+
import org.openqa.selenium.WebElement;
29+
import org.openqa.selenium.remote.DesiredCapabilities;
30+
import org.openqa.selenium.remote.HttpCommandExecutor;
31+
import org.openqa.selenium.remote.http.HttpClient;
32+
33+
import java.net.URL;
34+
35+
import static io.appium.java_client.remote.MobilePlatform.MAC;
36+
import static org.openqa.selenium.remote.CapabilityType.PLATFORM_NAME;
37+
38+
/**
39+
* Mac2Driver is an officially supported Appium driver
40+
* created to automate Mac OS apps. The driver uses W3C
41+
* WebDriver protocol and is built on top of Apple's XCTest
42+
* automation framework. Read https://github.com/appium/appium-mac2-driver
43+
* for more details on how to configure and use it.
44+
*
45+
* @since Appium 1.20.0
46+
*/
47+
public class Mac2Driver<T extends WebElement>
48+
extends AppiumDriver<T> implements CanRecordScreen, FindsByClassChain<T>,
49+
FindsByNsPredicate<T>, HasSettings {
50+
public Mac2Driver(HttpCommandExecutor executor, Capabilities capabilities) {
51+
super(executor, prepareCaps(capabilities));
52+
}
53+
54+
public Mac2Driver(URL remoteAddress, Capabilities desiredCapabilities) {
55+
super(remoteAddress, prepareCaps(desiredCapabilities));
56+
}
57+
58+
public Mac2Driver(URL remoteAddress, HttpClient.Factory httpClientFactory, Capabilities desiredCapabilities) {
59+
super(remoteAddress, httpClientFactory, prepareCaps(desiredCapabilities));
60+
}
61+
62+
public Mac2Driver(AppiumDriverLocalService service, Capabilities desiredCapabilities) {
63+
super(service, prepareCaps(desiredCapabilities));
64+
}
65+
66+
public Mac2Driver(AppiumDriverLocalService service, HttpClient.Factory httpClientFactory,
67+
Capabilities desiredCapabilities) {
68+
super(service, httpClientFactory, prepareCaps(desiredCapabilities));
69+
}
70+
71+
public Mac2Driver(AppiumServiceBuilder builder, Capabilities desiredCapabilities) {
72+
super(builder, prepareCaps(desiredCapabilities));
73+
}
74+
75+
public Mac2Driver(AppiumServiceBuilder builder, HttpClient.Factory httpClientFactory,
76+
Capabilities desiredCapabilities) {
77+
super(builder, httpClientFactory, prepareCaps(desiredCapabilities));
78+
}
79+
80+
public Mac2Driver(HttpClient.Factory httpClientFactory, Capabilities desiredCapabilities) {
81+
super(httpClientFactory, prepareCaps(desiredCapabilities));
82+
}
83+
84+
public Mac2Driver(Capabilities desiredCapabilities) {
85+
super(prepareCaps(desiredCapabilities));
86+
}
87+
88+
private static Capabilities prepareCaps(Capabilities originalCaps) {
89+
DesiredCapabilities dc = new DesiredCapabilities(originalCaps);
90+
if (originalCaps.getCapability(PLATFORM_NAME) == null) {
91+
dc.setCapability(PLATFORM_NAME, MAC);
92+
}
93+
String automationName = CapabilityHelpers.getCapability(originalCaps,
94+
MobileCapabilityType.AUTOMATION_NAME, String.class);
95+
if (!AutomationName.MAC2.equalsIgnoreCase(automationName)) {
96+
dc.setCapability(CapabilityHelpers.APPIUM_PREFIX
97+
+ MobileCapabilityType.AUTOMATION_NAME, AutomationName.MAC2);
98+
}
99+
return dc;
100+
}
101+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
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.mac;
18+
19+
import io.appium.java_client.MobileElement;
20+
21+
public class Mac2Element extends MobileElement implements
22+
FindsByClassChain<MobileElement>, FindsByNsPredicate<MobileElement> {
23+
}
Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
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.mac;
18+
19+
import com.google.common.collect.ImmutableMap;
20+
import io.appium.java_client.screenrecording.BaseStartScreenRecordingOptions;
21+
22+
import java.time.Duration;
23+
import java.util.Map;
24+
25+
import static java.util.Optional.ofNullable;
26+
27+
public class Mac2StartScreenRecordingOptions
28+
extends BaseStartScreenRecordingOptions<Mac2StartScreenRecordingOptions> {
29+
private Integer fps;
30+
private String videoFilter;
31+
private String preset;
32+
private Boolean captureCursor;
33+
private Boolean captureClicks;
34+
private Integer deviceId;
35+
36+
public static Mac2StartScreenRecordingOptions startScreenRecordingOptions() {
37+
return new Mac2StartScreenRecordingOptions();
38+
}
39+
40+
/**
41+
* The count of frames per second in the resulting video.
42+
* Increasing fps value also increases the size of the resulting
43+
* video file and the CPU usage.
44+
*
45+
* @param fps The actual frames per second value.
46+
* The default value is 15.
47+
* @return self instance for chaining.
48+
*/
49+
public Mac2StartScreenRecordingOptions withFps(int fps) {
50+
this.fps = fps;
51+
return this;
52+
}
53+
54+
/**
55+
* Whether to capture the mouse cursor while recording
56+
* the screen. Disabled by default.
57+
*
58+
* @return self instance for chaining.
59+
*/
60+
public Mac2StartScreenRecordingOptions enableCursorCapture() {
61+
this.captureCursor = true;
62+
return this;
63+
}
64+
65+
/**
66+
* Whether to capture the click gestures while recording
67+
* the screen. Disabled by default.
68+
*
69+
* @return self instance for chaining.
70+
*/
71+
public Mac2StartScreenRecordingOptions enableClicksCapture() {
72+
this.captureClicks = true;
73+
return this;
74+
}
75+
76+
/**
77+
* Screen device index to use for the recording.
78+
* The list of available devices could be retrieved using
79+
* `ffmpeg -f avfoundation -list_devices true -i` command.
80+
* This option is mandatory and must be always provided.
81+
*
82+
* @param deviceId The valid screen device identifier.
83+
* @return self instance for chaining.
84+
*/
85+
public Mac2StartScreenRecordingOptions withDeviceId(Integer deviceId) {
86+
this.deviceId = deviceId;
87+
return this;
88+
}
89+
90+
/**
91+
* The video filter spec to apply for ffmpeg.
92+
* See https://trac.ffmpeg.org/wiki/FilteringGuide for more details on the possible values.
93+
* Example: Set it to `scale=ifnot(gte(iw\,1024)\,iw\,1024):-2` in order to limit the video width
94+
* to 1024px. The height will be adjusted automatically to match the actual screen aspect ratio.
95+
*
96+
* @param videoFilter Valid ffmpeg video filter spec string.
97+
* @return self instance for chaining.
98+
*/
99+
public Mac2StartScreenRecordingOptions withVideoFilter(String videoFilter) {
100+
this.videoFilter = videoFilter;
101+
return this;
102+
}
103+
104+
/**
105+
* A preset is a collection of options that will provide a certain encoding speed to compression ratio.
106+
* A slower preset will provide better compression (compression is quality per filesize).
107+
* This means that, for example, if you target a certain file size or constant bit rate, you will
108+
* achieve better quality with a slower preset. Read https://trac.ffmpeg.org/wiki/Encode/H.264
109+
* for more details.
110+
*
111+
* @param preset One of the supported encoding presets. Possible values are:
112+
* - ultrafast
113+
* - superfast
114+
* - veryfast (default)
115+
* - faster
116+
* - fast
117+
* - medium
118+
* - slow
119+
* - slower
120+
* - veryslow
121+
* @return self instance for chaining.
122+
*/
123+
public Mac2StartScreenRecordingOptions withPreset(String preset) {
124+
this.preset = preset;
125+
return this;
126+
}
127+
128+
/**
129+
* The maximum recording time. The default value is 600 seconds (10 minutes).
130+
* The minimum time resolution unit is one second.
131+
*
132+
* @param timeLimit The actual time limit of the recorded video.
133+
* @return self instance for chaining.
134+
*/
135+
@Override
136+
public Mac2StartScreenRecordingOptions withTimeLimit(Duration timeLimit) {
137+
return super.withTimeLimit(timeLimit);
138+
}
139+
140+
@Override
141+
public Map<String, Object> build() {
142+
final ImmutableMap.Builder<String, Object> builder = ImmutableMap.builder();
143+
builder.putAll(super.build());
144+
ofNullable(fps).map(x -> builder.put("fps", x));
145+
ofNullable(preset).map(x -> builder.put("preset", x));
146+
ofNullable(videoFilter).map(x -> builder.put("videoFilter", x));
147+
ofNullable(captureClicks).map(x -> builder.put("captureClicks", x));
148+
ofNullable(captureCursor).map(x -> builder.put("captureCursor", x));
149+
ofNullable(deviceId).map(x -> builder.put("deviceId", x));
150+
return builder.build();
151+
}
152+
}

0 commit comments

Comments
 (0)