Appium Java client 8.3.0 not detecting @AndroidFindBy and @iOSXCUITFindBy

appiumDriver = (AppiumDriver) driver;
PageFactory.initElements(new AppiumFieldDecorator(appiumDriver, Duration.ofSeconds(30)), this);

I tried above and i can see it’s taking AppiumDriver instead of WebDriver. But same error when i use @AndroidFindBy
rg.openqa.selenium.InvalidSelectorException: Unsupported CSS selector ‘*[name=‘xxxxx’]’. Reason: ‘‘name’ is not a valid attribute. Supported attributes are ‘checkable, checked, clickable, enabled, focusable, focused, long-clickable, scrollable, selected, index, instance, description, resource-id, text, class-name, package-name’’

But you can not casting the driver to the appium driver, but declare it as such?

Tried that. I removed my base class extends pageObject class. but throwing error like blow

java.lang.NullPointerException: Cannot invoke “xxx.Page.click_Btn(String)” because “this.page” is null. How do i invoke page class from step class without PageObject class extends?

I have exactly same problem using PageFactory.

Same code works when I use AppiumBy or even By but fails when I try to use Page Object Model concept. It always points toward CSS selector in java console and appium console.

Maybe I will ask different question - I don’t have to use POM concept. I have to write a single test, which will choose pick from one of two locators. I was using
AndroidFindBy
iOSFindBy
public WebElement X

but I don’t know what happend, it stopped working with iosXCUITFindBy and AndroidFindBy in Appium 8.3.0

Now I am using:
FindAll ({
FindBy xpath
FindBy xpath
)}
And the script chooses whatever is available, but I am literally limited to xpath. I tried different things, waits, AppiumFieldDecorator (which gives me NullPointerExeption), using specific IOSDriver/AndroidDriver instead of Appium Driver. I cant find solution for that for MONTHS now. topics are literally dying. Is this Appium version bugged or what?

1 Like

Thanks for suggestion:) It works for me too. Just wanna confirm FindAll is not working with id? Is it works only with xpath?

It works only with xpath.

But it is not a solution. It is not even a workaround. Thats like riding a bike with one leg.

I spent countless hours looking for a solutions and most of the topic have either:

  • appium field decorator (sometimes works)
  • wait (never worked)
  • incorrect passing of the driver (never worked)

99% are unsolved. The truth is that is the bug and nobody knows the real reason for it.

The workaround would be using something else but I cant find any alternative to the need I posted - idk maybe try catch blocks for each elements?

That sucks. :frowning:

the real reason in your code. put it all into git. give link. it should help more to understand your issue.

I was hoping to hear something like that. I will do that ~2hrs

Here:

  1. POM: (Although recently I removed that exlcusion from java client)
<dependencies>

    <dependency>
        <groupId>io.appium</groupId>
        <artifactId>java-client</artifactId>
        <version>8.3.0</version>
        <exclusions>
            <exclusion>
                <groupId>org.seleniumhq.selenium</groupId>
                <artifactId>selenium-java</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
    
    <!-- https://mvnrepository.com/artifact/org.seleniumhq.selenium/selenium-java -->
    <dependency>
    <groupId>org.seleniumhq.selenium</groupId>
    <artifactId>selenium-java</artifactId>
    <version>4.5.3</version>
    </dependency>


</dependencies>
  1. Page with locators: (this allow is like "Accessibility, so this might be wrong, but I tried a bunch of them)
public class loginPage {

    public static void initializePageObjects(AppiumDriver driver) {
        PageFactory.initElements(new AppiumFieldDecorator(driver), loginPage.class);
    }
    @iOSXCUITFindBy(id = "Allow")
    public static WebElement allowButton;
    @iOSXCUITFindBy (iOSClassChain = "**/XCUIElementTypeOther[`label == The App"`]/XCUIElementTypeOther/XCUIElementTypeImage")
    public static WebElement logo;
    
}
  1. Main method: (sam with driver, now is IOS driver, i tried with Appium or Remote as well
 MutableCapabilities caps = new MutableCapabilities();
        caps.setCapability("platformName", "iOS");
        caps.setCapability("appium:deviceName", "iPhone 14 Simulator");
        caps.setCapability("appium:deviceOrientation", "portrait");
        caps.setCapability("appium:platformVersion", "16.4");
       caps.setCapability("appium:automationName", "XCUITest");
        caps.setCapability("appium:app","/Users/XXX/Documents/Apps/iOS/XXX.app");
        caps.setCapability("appium:udid","509860CD-4C17-4C62-9523-715AE37C2603");

        URL url = new URL("http://localhost:4723");


        Appium driver = new IOSDriver(url, caps);

        loginPage.initializePageObjects(driver);

        Thread.sleep(5000);
        allowButton.click();
        Thread.sleep(2000);
        System.out.println(logo.isDisplayed());

Errors:
With appium field decorator:

Exception in thread “main” java.lang.NullPointerException
    at org.example.Main.main(Main.java:30)
Process finished with exit code 1

Without:

Exception in thread “main” org.openqa.selenium.NoSuchElementException: An element could not be located on the page using the given search parameters.
For documentation on this error, please visit: https://www.selenium.dev/documentation/webdriver/troubleshooting/errors#no-such-element-exception
Build info: version: ‘4.10.0’, revision: ‘c14d967899’
System info: os.name: ‘Mac OS X’, os.arch: ‘x86_64’, os.version: ‘11.4’, java.version: ‘11.0.13’
Driver info: io.appium.java_client.ios.IOSDriver
Command: [fe0e3508-eec0-4511-9ad8-66bcb6f55603, findElement {using=css selector, value=*[name=‘allowButton’]}]
Capabilities {appium:app: /Users/XXX/Docume..., appium:automationName: XCUITest, appium:databaseEnabled: false, appium:deviceName: iPhone 14 Pro Simulator, appium:deviceOrientation: portrait, appium:javascriptEnabled: true, appium:locationContextEnabled: false, appium:networkConnectionEnabled: false, appium:platformVersion: 16.4, appium:takesScreenshot: true, appium:udid: 509860CD-4C17-4C62-9523-715..., appium:webStorageEnabled: false, platformName: IOS}
Session ID: fe0e3508-eec0-4511-9ad8-66bcb6f55603
    at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:490)
    at org.openqa.selenium.remote.codec.w3c.W3CHttpResponseCodec.createException(W3CHttpResponseCodec.java:199)
    at org.openqa.selenium.remote.codec.w3c.W3CHttpResponseCodec.decode(W3CHttpResponseCodec.java:132)
    at org.openqa.selenium.remote.codec.w3c.W3CHttpResponseCodec.decode(W3CHttpResponseCodec.java:51)
    at org.openqa.selenium.remote.HttpCommandExecutor.execute(HttpCommandExecutor.java:191)
    at io.appium.java_client.remote.AppiumCommandExecutor.execute(AppiumCommandExecutor.java:262)
    at org.openqa.selenium.remote.RemoteWebDriver.execute(RemoteWebDriver.java:531)
    at org.openqa.selenium.remote.ElementLocation$ElementFinder$2.findElement(ElementLocation.java:165)
    at org.openqa.selenium.remote.ElementLocation.findElement(ElementLocation.java:59)
    at org.openqa.selenium.remote.RemoteWebDriver.findElement(RemoteWebDriver.java:350)
    at org.openqa.selenium.remote.RemoteWebDriver.findElement(RemoteWebDriver.java:344)
    at org.openqa.selenium.By$PreW3CLocator.findElement(By.java:427)
    at org.openqa.selenium.By$ByName.findElement(By.java:236)
    at org.openqa.selenium.support.ByIdOrName.findElement(ByIdOrName.java:49)
    at org.openqa.selenium.remote.ElementLocation$ElementFinder$1.findElement(ElementLocation.java:139)
    at org.openqa.selenium.remote.ElementLocation.findElement(ElementLocation.java:81)
    at org.openqa.selenium.remote.RemoteWebDriver.findElement(RemoteWebDriver.java:350)
    at org.openqa.selenium.remote.RemoteWebDriver.findElement(RemoteWebDriver.java:344)
    at org.openqa.selenium.support.pagefactory.DefaultElementLocator.findElement(DefaultElementLocator.java:68)
    at org.openqa.selenium.support.pagefactory.internal.LocatingElementHandler.invoke(LocatingElementHandler.java:38)
    at com.sun.proxy.$Proxy8.click(Unknown Source)
    at org.example.Main.main(Main.java:30)
Process finished with exit code 1

“Help me Obi Wan Kenobi, you are my only hope” :smiley:

remove static here and EVERYWHERE in elements.

replace with

PageFactory.initElements(new AppiumFieldDecorator(driver, Duration.ofSeconds(sec)), this);

better use constructor like

public class LoginPage {
    @iOSXCUITFindBy(id = "Allow")
    private WebElement allowButton; // elements ARE private. it is better not share them outside class. ONLY actions are public!

    @iOSXCUITFindBy (id = "xxx")
    private WebElement logo;

   public LoginPage(AppiumDriver driver) {
        PageFactory.initElements(new AppiumFieldDecorator(driver, Duration.ofSeconds(sec)), this);
    }
}

after open driver use something like:

LoginPage loginPage = new LoginPage(driver);
// now any actions
loginPage
.setEmail("my_email")
.tapLoginButton()...

Yes Sir, working on it, I will let you know in a minute

I used getters to get the private values.

Anyway, I added whatever you posted here and:

  • using appium field decorator gives me NPE
  • using constructor with initElements gives me NPE
  • using default constructor and calling the method gives me NPE

NPE is in the line where it checks if the element is displayed

That’s my LoginPage now:

public LoginPage(AppiumDriver driver){
        PageFactory.initElements(new AppiumFieldDecorator(driver, Duration.ofSeconds(10)),LoginPage.class);
}
@iOSXCUITFindBy(xpath= "//XCUIElementTypeOther[@name=\"Sauce Labs Backpack\"]")
private WebElement backpack;
@iOSXCUITFindBy(accessibility = "longpress reset app")
private WebElement logo;

public WebElement getLogo(){
        return logo;
}

public WebElement getBackpack(){
        return backpack;
}

And that is my main (without caps)

 AppiumDriver driver = new AppiumDriver(url, caps);

LoginPage loginPage = new LoginPage(driver);

Thread.sleep(3000);

System.out.println(loginPage.getLogo().isDisplayed());
System.out.println(loginPage.getBackpack().isDisplayed());

EDIT:

I made it work, with your requirements, but with a slight change. It was not working with LoginPage.class in initElements method, but I had to use “this”.

I’ve added locators for Android and it worked.

@Aleksei, Please accept my sincere apologies for ever doubting the Appium Team and saying such a bad words.

@IMOBILETester try to follow Aleksei’s advices, but use “this” in the method. If not, let me know, I will share the working code with you.

1 Like

Can anybody help me to resolve mine?

1)I have initialised iOS driver with AppiumDriver.

XCUITestOptions ios =
new XCUITestOptions()
.setPlatformName(“iOS”)
.setDeviceName(“iPhone 14 Plus”)
.setOrientation(PORTRAIT)
.setBundleId((“xxx”))
.setAutomationName(“XCUITest”)
.setNoReset(true)
.setApp(app.getAbsolutePath());

driver = new AppiumDriver(url, ios);

  1. Base class which extends pageObject to initiate driver

public class baseClass extends PageObject {

public BaseClass(WebDriver driver) {
    PageFactory.initElements(new AppiumFieldDecorator(driver, Duration.ofSeconds(30)), this);
}.  **// I can't use AppiumDriver as parameter as PageObject din't have AppiumDriver. So it will throw error.** But still it's invoking AppiumDriver only even in my page class when i try to print the driver name
  1. Page class

public class page extends baseClass {

public page(WebDriver driver) {
    super(driver);   //** I can't use AppiumDriver as parameter as PageObject din't have AppiumDriver. So it will throw error.** But still it's invoking AppiumDriver only even in my page class when i try to print the driver name

}
@iOSXCUITFindBy(accessibility = "Account")
public WebElement account;

public void click_Btn() {
account.click();
}

4)POM
>

        <groupId>io.appium</groupId>
        <artifactId>java-client</artifactId>
        <version>8.5.1</version>
              </dependency>
    <dependency>
        <groupId>org.seleniumhq.selenium</groupId>
        <artifactId>selenium-java</artifactId>
        <version>4.5.3</version>
    </dependency>

Can anybody please correct my code?

Try

PageFactory.initElements(new AppiumFieldDecorator((AppiumDriver) driver, Duration.ofSeconds(30)), this);

Thanks @Aleksei for suggestion. i tried above ,no luck same error from appium

Calling AppiumDriver.findElement() with args: [“css selector”,“#account”,“c55e4a7d-4896-42f4-8643-35ff9008c7b2”]
[debug] [XCUITestDriver@1d7a (c55e4a7d)] Executing command ‘findElement’
[debug] [XCUITestDriver@1d7a (c55e4a7d)] Valid locator strategies for this request: xpath, id, name, class name, -ios predicate string, -ios class chain, accessibility id, css selector
[debug] [XCUITestDriver@1d7a (c55e4a7d)] Waiting up to 0 ms for condition
[debug] [XCUITestDriver@1d7a (c55e4a7d)] Setting custom timeout to 300000 ms for ‘findElement’ command
[debug] [XCUITestDriver@1d7a (c55e4a7d)] Matched ‘/element’ to command name ‘findElement’
[debug] [XCUITestDriver@1d7a (c55e4a7d)] Proxying [POST /element] to [POST http://127.0.0.1:8100/session/68CF454E-1E58-4067-846B-0FFC31DF7170/element] with body: {“using”:“class chain”,“value”:“**/*[name == \"account\"]”}

eventhough i gave accessibility or xpath in locator.

So what issue? Element not found? Share page source.

Responding to client with driver.getPageSource() result: "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\n <XCUIElementTypeApplication type="XCUIElementTypeApplication" name="UAT" label="UAT" enabled="true" visible="true" accessible="false" x="0" y="0" width="428" height="926" index="0">\n <XCUIElementTypeWindow type="XCUIElementTypeWindow" enabled="true" visible="true" accessible="false" x="0" y="0" width="428" height="926" index="0">\n <XCUIElementTypeOther type="XCUIElementTypeOther" enabled="true" visible="true" accessible="false" x="0" y="0" width="428" height="926" index="0">\n <XCUIElementTypeOther type="XCUIElementTypeOther" enabled="true" visible="true" accessible="false" x="0" y="0" width="428" height="926" index="0">\n <XCUIElementTypeOther type="XCUIElementTypeOther" enabled="true" visible="true" accessible="false" x="0" y="0" width="428" height="926" index="0">\n <XCUIElementTypeOther type="XCUIElementTypeOther.…
[HTTP] ← GET /wd/hub/session/0ffbff32-34b8-417c-8328-7a0d6c272d2c/source 200 333 ms - 11947

Yes, org.openqa.selenium.NoSuchElementException: Timed out after 2 seconds. Element not found It’s thrown.I increased time,but still same issue.

In my pagesource ,it says accessible false. but in appium inspector i can see it’s true for same locator. Is that the issue?

resolved this issue by passing -Dcontext=ios in property and it’s detecting properly. Not sure is there any other way to achieve this?