Skip to content

Commit e75c1eb

Browse files
author
Jonathan Dick
authored
Feat: Add support for Android Espresso's ViewMatcher (#447)
1 parent 8561e7c commit e75c1eb

File tree

6 files changed

+130
-0
lines changed

6 files changed

+130
-0
lines changed

src/Appium.Net/Appium/Android/AndroidDriver.cs

+10
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,16 @@ public IReadOnlyCollection<W> FindElementsByAndroidDataMatcher(string selector)
154154

155155
#endregion IFindByAndroidDataMatcher Members
156156

157+
#region IFindByAndroidViewMatcher Members
158+
159+
public W FindElementByAndroidViewMatcher(string selector) =>
160+
FindElement(MobileSelector.AndroidViewMatcher, selector);
161+
162+
public IReadOnlyCollection<W> FindElementsByAndroidViewMatcher(string selector) =>
163+
ConvertToExtendedWebElementCollection<W>(FindElements(MobileSelector.AndroidViewMatcher, selector));
164+
165+
#endregion IFindByAndroidViewMatcher Members
166+
157167
public void StartActivity(string appPackage, string appActivity, string appWaitPackage = "",
158168
string appWaitActivity = "", bool stopApp = true) =>
159169
AndroidCommandExecutionHelper.StartActivity(this, appPackage, appActivity, appWaitPackage, appWaitActivity,

src/Appium.Net/Appium/Android/AndroidElement.cs

+10
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,16 @@ public IReadOnlyCollection<AppiumWebElement> FindElementsByAndroidDataMatcher(st
5757

5858
#endregion IFindByAndroidDataMatcher Members
5959

60+
#region IFindByAndroidViewMatcher Members
61+
62+
public AppiumWebElement FindElementByAndroidViewMatcher(string selector) =>
63+
FindElement(MobileSelector.AndroidViewMatcher, selector);
64+
65+
public IReadOnlyCollection<AppiumWebElement> FindElementsByAndroidViewMatcher(string selector) =>
66+
FindElements(MobileSelector.AndroidViewMatcher, selector);
67+
68+
#endregion IFindByAndroidViewMatcher Members
69+
6070
public void ReplaceValue(string value) => AndroidCommandExecutionHelper.ReplaceValue(this, Id, value);
6171
}
6272
}

src/Appium.Net/Appium/Enums/MobileSelector.cs

+1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ public class MobileSelector
2525
public static readonly string Accessibility = "accessibility id";
2626
public static readonly string AndroidUIAutomator = "-android uiautomator";
2727
public static readonly string AndroidDataMatcher = "-android datamatcher";
28+
public static readonly string AndroidViewMatcher = "-android viewmatcher";
2829
public static readonly string iOSAutomatoion = "-ios uiautomation";
2930
public static readonly string iOSPredicateString = "-ios predicate string";
3031
public static readonly string iOSClassChain = "-ios class chain";
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
//Licensed under the Apache License, Version 2.0 (the "License");
2+
//you may not use this file except in compliance with the License.
3+
//See the NOTICE file distributed with this work for additional
4+
//information regarding copyright ownership.
5+
//You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
//Unless required by applicable law or agreed to in writing, software
10+
//distributed under the License is distributed on an "AS IS" BASIS,
11+
//WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
//See the License for the specific language governing permissions and
13+
//limitations under the License.
14+
15+
using System.Collections.Generic;
16+
17+
namespace OpenQA.Selenium.Appium.Interfaces
18+
{
19+
public interface IFindByAndroidViewMatcher<out W> : IFindsByFluentSelector<W> where W : IWebElement
20+
{
21+
/// <summary>
22+
/// Finds the first element in the page that matches the Android Espresso's View Matcher selector supplied
23+
/// </summary>
24+
/// <param name="selector">Selector for the element.</param>
25+
/// <returns>IWebElement object so that you can interact that object</returns>
26+
/// <example>
27+
/// <code>
28+
/// IWebDriver driver = new RemoteWebDriver(new DriverOptions());
29+
/// IWebElement elem = driver.FindElementByAndroidViewMatcher('elements()'))
30+
/// </code>
31+
/// </example>
32+
W FindElementByAndroidViewMatcher(string selector);
33+
34+
/// <summary>
35+
/// Finds a list of elements that match the Android Espresso's View Matcher selector supplied
36+
/// </summary>
37+
/// <param name="selector">Selector for the elements.</param>
38+
/// <returns>ReadOnlyCollection of IWebElement object so that you can interact with those objects</returns>
39+
/// <example>
40+
/// <code>
41+
/// IWebDriver driver = new RemoteWebDriver(new FirefoxOptions());
42+
/// ReadOnlyCollection<![CDATA[<IWebElement>]]> elem = driver.FindElementsByAndroidViewMatcher(elements())
43+
/// </code>
44+
/// </example>
45+
IReadOnlyCollection<W> FindElementsByAndroidViewMatcher(string selector);
46+
}
47+
}

src/Appium.Net/Appium/MobileBy.cs

+41
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,15 @@ public static By AndroidUIAutomator(IUiAutomatorStatementBuilder selector) =>
104104
/// <returns></returns>
105105
public static By AndroidDataMatcher(string selector) => new ByAndroidDataMatcher(selector);
106106

107+
/// <summary>
108+
/// This method creates a <see cref="OpenQA.Selenium.By"/> strategy
109+
/// that searches for elements using Espresso's View Matcher.
110+
/// <see cref="https://developer.android.com/training/testing/espresso/basics#finding-view"/>
111+
/// </summary>
112+
/// <param name="selector">The selector to use in finding the element.</param>
113+
/// <returns></returns>
114+
public static By AndroidViewMatcher(string selector) => new ByAndroidViewMatcher(selector);
115+
107116
/// <summary>
108117
/// This method creates a <see cref="OpenQA.Selenium.By"/> strategy
109118
/// that searches for elements using iOS UI automation.
@@ -232,6 +241,38 @@ public override string ToString() =>
232241
$"ByAndroidDataMatcher({selector})";
233242
}
234243

244+
/// <summary>
245+
/// Finds element when the Espresso's View Matcher selector has the specified value.
246+
/// <see cref="https://developer.android.com/training/testing/espresso/basics#finding-view"/>
247+
/// </summary>
248+
public class ByAndroidViewMatcher : MobileBy
249+
{
250+
/// <summary>
251+
/// Initializes a new instance of the <see cref="ByAndroidViewMatcher"/> class.
252+
/// </summary>
253+
/// <param name="selector">The selector to use in finding the element.</param>
254+
public ByAndroidViewMatcher(string selector) : base(selector, MobileSelector.AndroidViewMatcher)
255+
{
256+
}
257+
258+
public override IWebElement FindElement(ISearchContext context)
259+
{
260+
if (context is IFindByAndroidViewMatcher<IWebElement> finder)
261+
return finder.FindElementByAndroidViewMatcher(selector);
262+
return base.FindElement(context);
263+
}
264+
265+
public override ReadOnlyCollection<IWebElement> FindElements(ISearchContext context)
266+
{
267+
if (context is IFindByAndroidViewMatcher<IWebElement> finder)
268+
return finder.FindElementsByAndroidViewMatcher(selector).ToList().AsReadOnly();
269+
return base.FindElements(context);
270+
}
271+
272+
public override string ToString() =>
273+
$"ByAndroidViewMatcher({selector})";
274+
}
275+
235276
/// <summary>
236277
/// Finds element when the Ios UIAutomation selector has the specified value.
237278
/// <see cref="https://developer.apple.com/library/tvos/documentation/DeveloperTools/Conceptual/InstrumentsUserGuide/UIAutomation.html"/>

test/integration/Android/ElementTestEspresso.cs

+21
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,27 @@ public void FindByAndroidDataMatcherTest()
4343
1);
4444
}
4545

46+
[Test]
47+
public void FindByAndroidViewMatcherTest()
48+
{
49+
const string selectorData = @"{
50+
'name':'withText',
51+
'args':[{
52+
'name':'containsString',
53+
'args':['Preference']
54+
}
55+
}]";
56+
57+
By byAndroidViewMatcher = new ByAndroidViewMatcher(selectorData);
58+
59+
Assert.AreNotEqual(
60+
_driver.FindElementById("android:id/list").FindElement(byAndroidViewMatcher).Text,
61+
null);
62+
Assert.GreaterOrEqual(
63+
_driver.FindElementById("android:id/list").FindElements(byAndroidViewMatcher).Count,
64+
1);
65+
}
66+
4667
[OneTimeTearDown]
4768
public void AfterAll()
4869
{

0 commit comments

Comments
 (0)