Skip to content

Unable to initialise PageFactory for PageObject  #73

Closed

Description

@ashishkumar1000

I have updated the java-client jar and tried to initialise PageFactory as mention below.

PageObject PageObject1 = PageFactory.initElements(new AppiumFieldDecorator(driver),PageObject.class);

But I am getting type mismatch error.
Is there something I am missing ???

Activity

  1. amedvedjev commented on Jul 31, 2014

    @amedvedjev

    same problem

  2. TikhomirovSergey commented on Jul 31, 2014

    @TikhomirovSergey
    Contributor

    Hi! Let see this (is taken from here https://github.com/SeleniumHQ/selenium/blob/master/java/client/src/org/openqa/selenium/support/PageFactory.java):

       * @param pageClassToProxy A class which will be initialised.
       * @return An instantiated instance of the class with WebElement and List<WebElement> fields proxied
       */
      public static <T> T initElements(WebDriver driver, Class<T> pageClassToProxy)
    
      /**
       * As
       * {@link org.openqa.selenium.support.PageFactory#initElements(org.openqa.selenium.WebDriver, Class)}
       * but will only replace the fields of an already instantiated Page Object.
       * 
       * @param driver The driver that will be used to look up the elements
       * @param page The object with WebElement and List<WebElement> fields that should be proxied.
       */
      public static void initElements(WebDriver driver, Object page)
    
    
      /**
       * Similar to the other "initElements" methods, but takes an {@link ElementLocatorFactory} which
       * is used for providing the mechanism for fniding elements. If the ElementLocatorFactory returns
       * null then the field won't be decorated.
       * 
       * @param factory The factory to use
       * @param page The object to decorate the fields of
       */
      public static void initElements(ElementLocatorFactory factory, Object page)
    
    
      /**
       * Similar to the other "initElements" methods, but takes an {@link FieldDecorator} which is used
       * for decorating each of the fields.
       * 
       * @param decorator the decorator to use
       * @param page The object to decorate the fields of
       */
      public static void initElements(FieldDecorator decorator, Object page)

    You should istantiate your "page object" before
    PageFactory.initElements

    PageObject po = new PageObject();
    PageFactory.initElements(new AppiumFieldDecorator(driver),po)

    Please pay attention: PageFactory.initElements is "void".

  3. amedvedjev commented on Jul 31, 2014

    @amedvedjev

    "You should istantiate your "page object" before " - before what?

    let say in test class we have following

    Abstract Page:

    public abstract class Page {
    protected AppiumDriver driver;
    public Page(AppiumDriver driver) {
    this.driver = driver;
    }
    }

    Test Page:

    public class FirstPage extends Page {
    @findby(id = "something")
    private List elemList;
    public FirstPage(AppiumDriver driver) {
    super(driver);
    }
    //some staff
    }

    Test class:

    private FirstPage firstPage;
    @test
    public void doTest() {
    // was before: firstPage = PageFactory.initElements(driver, FirstPage.class);
    PageFactory.initElements(new AppiumFieldDecorator(driver), FirstPage.class);
    }

  4. TikhomirovSergey commented on Jul 31, 2014

    @TikhomirovSergey
    Contributor

    Ok.
    Let see two different examples below:

    public class Test {
    
        public static class PageObject {
    
            private final WebDriver driver;
    
            @FindBy(className = "android.widget.TextView")
            private WebElement element;
    
            public PageObject(WebDriver driver){
                this.driver = driver;
            }
    
            public void click(){
                element.click();
            }
        }
    
        private PageObject po;
    
        @Before
        public void setup() throws Exception {
            File appDir = new File("src/test/java/io/appium/java_client");
            File app = new File(appDir, "ApiDemos-debug.apk");
            DesiredCapabilities capabilities = new DesiredCapabilities();
            capabilities.setCapability(MobileCapabilityType.BROWSER_NAME, "");
            capabilities.setCapability(MobileCapabilityType.DEVICE_NAME, "Android Emulator");
            capabilities.setCapability(MobileCapabilityType.PLATFORM_NAME, "Android");
            capabilities.setCapability(MobileCapabilityType.APP, app.getAbsolutePath());
            /**
             * Attention please
             */
            po = PageFactory.initElements(new AppiumDriver(new URL("http://127.0.0.1:4723/wd/hub"), capabilities), PageObject.class);
    
        }
    
        @org.junit.Test
        public void test() {
            po.click();     
        }
    
        @After
        public void tearDown() throws Exception {
            po.driver.quit();
        }   
    
    }

    If you use PageFactory only with @findby, there is nothing to change. Your example will work well without AppiumFieldDecorator.

    But... Are you sure that all your browser locators are suitable for Android\iOS native\hybrid app?

    /**
     * 
     * Imagine, that we have application API Demos with the same UI
     * But different locators (browser/Android) 
     *
     */
    public class Test2 {
    
        public static class PageObject {
    
            private final WebDriver driver;
    
            @FindBy(className = "someDOMClass")
            @AndroidFindBy(className = "android.widget.TextView")
            private WebElement element;
    
            public PageObject(WebDriver driver){
                this.driver = driver;
                /**
                 * Attention please
                 */
                PageFactory.initElements(new AppiumFieldDecorator(driver), this);
            }
    
            public void click(){
                element.click();
            }
        }
    
        private PageObject po;
    
        @Before
        public void setup() throws Exception {
            File appDir = new File("src/test/java/io/appium/java_client");
            File app = new File(appDir, "ApiDemos-debug.apk");
            DesiredCapabilities capabilities = new DesiredCapabilities();
            capabilities.setCapability(MobileCapabilityType.BROWSER_NAME, "");
            capabilities.setCapability(MobileCapabilityType.DEVICE_NAME, "Android Emulator");
            capabilities.setCapability(MobileCapabilityType.PLATFORM_NAME, "Android");
            capabilities.setCapability(MobileCapabilityType.APP, app.getAbsolutePath());
            /**
             * Attention please
             */
            po = new PageObject(new AppiumDriver(new URL("http://127.0.0.1:4723/wd/hub"), capabilities));
    
        }
    
        @org.junit.Test
        public void test() {
            po.click();     
        }
    
        @After
        public void tearDown() throws Exception {
            po.driver.quit();
        }

    AppiumFieldDecorator decorates Webelement-fields which marked by @AndroidFindBy/@iOSFindBy. This decorator supports @findby too.

  5. amedvedjev commented on Jul 31, 2014

    @amedvedjev

    thanks!

  6. amedvedjev commented on Jul 31, 2014

    @amedvedjev

    Sergey,

    still not clear how to initiate pages one by one inside test class?

    I can't start this with every page change.
    /**
    * Attention please
    */
    po = PageFactory.initElements(new AppiumDriver(new URL("http://127.0.0.1:4723/wd/hub"), capabilities), PageObject.class);

    mine example:

    Abstract Page:

    public abstract class Page {
    protected AppiumDriver driver;
    public Page(AppiumDriver driver) {
    this.driver = driver;
    PageFactory.initElements(new AppiumFieldDecorator(driver), this);
    }
    }

    Test Page:

    public class FirstPage extends Page {
    @findby(id = "something")
    private List elemList;
    public FirstPage(AppiumDriver driver) {
    super(driver);
    }
    //some staff
    }

    Test class:

    public class testDoTests extends AppiumSetup {
    private FirstPage firstPage;
    private SecondPage secondPage;
    @test
    public void doTest1() {
    firstPage = PageFactory.initElements(driver, FirstPage.class); // CRASH HERE!
    //do some tests on first page
    secondPage = PageFactory.initElements(driver, SecondPage.class);
    //do some tests on second page
    }
    }

    Appium Setup class:

    public class AppiumSetup {
    protected static AppiumDriver driver = null;
    driver = new AppiumDriver(new URL("http://0.0.0.0:4723/wd/hub"), capabilities);
    }

  7. TikhomirovSergey commented on Jul 31, 2014

    @TikhomirovSergey
    Contributor

    Please, let me see stacktrace.

  8. amedvedjev commented on Jul 31, 2014

    @amedvedjev

    java.lang.RuntimeException: java.lang.InstantiationException: com.cardola.tests.page.android.KeywordPage
    at org.openqa.selenium.support.PageFactory.instantiatePage(PageFactory.java:136)
    at org.openqa.selenium.support.PageFactory.initElements(PageFactory.java:66)
    at com.cardola.tests.test.android.testKeywordPage.testKeywordPage(testKeywordPage.java:22)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:84)
    at org.testng.internal.Invoker.invokeMethod(Invoker.java:714)
    at org.testng.internal.Invoker.invokeTestMethod(Invoker.java:901)
    at org.testng.internal.Invoker.invokeTestMethods(Invoker.java:1231)
    at org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:127)
    at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:111)
    at org.testng.TestRunner.privateRun(TestRunner.java:767)
    at org.testng.TestRunner.run(TestRunner.java:617)
    at org.testng.SuiteRunner.runTest(SuiteRunner.java:348)
    at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:343)
    at org.testng.SuiteRunner.privateRun(SuiteRunner.java:305)
    at org.testng.SuiteRunner.run(SuiteRunner.java:254)
    at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:52)
    at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:86)
    at org.testng.TestNG.runSuitesSequentially(TestNG.java:1224)
    at org.testng.TestNG.runSuitesLocally(TestNG.java:1149)
    at org.testng.TestNG.run(TestNG.java:1057)
    at org.testng.remote.RemoteTestNG.run(RemoteTestNG.java:111)
    at org.testng.remote.RemoteTestNG.initAndRun(RemoteTestNG.java:204)
    at org.testng.remote.RemoteTestNG.main(RemoteTestNG.java:175)
    at org.testng.RemoteTestNGStarter.main(RemoteTestNGStarter.java:125)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:134)
    Caused by: java.lang.InstantiationException: com.cardola.tests.page.android.KeywordPage
    at java.lang.Class.newInstance0(Class.java:342)
    at java.lang.Class.newInstance(Class.java:310)
    at org.openqa.selenium.support.PageFactory.instantiatePage(PageFactory.java:133)
    ... 32 more

  9. TikhomirovSergey commented on Jul 31, 2014

    @TikhomirovSergey
    Contributor

    It looks strange....

        public static abstract class AbstractPageObject {
    
            protected final WebDriver driver;       
            public AbstractPageObject(WebDriver driver){
                this.driver = driver;
                /**
                 * Attention please
                 */
                PageFactory.initElements(new AppiumFieldDecorator(driver), this);
            }
        }   
    
        public static class PageObject extends AbstractPageObject {
    
            public PageObject(WebDriver driver) {
                super(driver);
            }
    
            @FindBy(className = "android.widget.TextView")
            private WebElement element;
    
            public void click(){
                element.click();
            }
        }
    
        protected static AppiumDriver driver;
    
        @Before
        public void setup() throws Exception {
            File appDir = new File("src/test/java/io/appium/java_client");
            File app = new File(appDir, "ApiDemos-debug.apk");
            DesiredCapabilities capabilities = new DesiredCapabilities();
            capabilities.setCapability(MobileCapabilityType.BROWSER_NAME, "");
            capabilities.setCapability(MobileCapabilityType.DEVICE_NAME, "Android Emulator");
            capabilities.setCapability(MobileCapabilityType.PLATFORM_NAME, "Android");
            capabilities.setCapability(MobileCapabilityType.APP, app.getAbsolutePath());
    
            driver = new AppiumDriver(new URL("http://127.0.0.1:4723/wd/hub"), capabilities);       
        }
    
        @org.junit.Test
        public void test() {
            PageObject po = PageFactory.initElements(driver, PageObject.class);
            po.click();     
        }
    
    }

    This code works!

  10. TikhomirovSergey commented on Jul 31, 2014

    @TikhomirovSergey
    Contributor

    I could reproduce the similar exception on this code:

        public static abstract class AbstractPageObject {
    
            protected final WebDriver driver;       
            public AbstractPageObject(WebDriver driver){
                this.driver = driver;
                /**
                 * Attention please
                 */
                PageFactory.initElements(new AppiumFieldDecorator(driver), this);
            }
        }   
    
                            //!!!
        public static abstract class PageObject extends AbstractPageObject {
    
            public PageObject(WebDriver driver) {
                super(driver);
            }
    
            @FindBy(className = "android.widget.TextView")
            private WebElement element;
    
            public void click(){
                element.click();
            }
        }
    
        protected static AppiumDriver driver;
    
        @Before
        public void setup() throws Exception {
            File appDir = new File("src/test/java/io/appium/java_client");
            File app = new File(appDir, "ApiDemos-debug.apk");
            DesiredCapabilities capabilities = new DesiredCapabilities();
            capabilities.setCapability(MobileCapabilityType.BROWSER_NAME, "");
            capabilities.setCapability(MobileCapabilityType.DEVICE_NAME, "Android Emulator");
            capabilities.setCapability(MobileCapabilityType.PLATFORM_NAME, "Android");
            capabilities.setCapability(MobileCapabilityType.APP, app.getAbsolutePath());
    
            driver = new AppiumDriver(new URL("http://127.0.0.1:4723/wd/hub"), capabilities);       
        }
    
        @org.junit.Test
        public void test() {
            PageObject po = PageFactory.initElements(driver, PageObject.class);
            po.click();     
        }

    java.lang.RuntimeException: java.lang.InstantiationException
    at org.openqa.selenium.support.PageFactory.instantiatePage(PageFactory.java:136)
    at org.openqa.selenium.support.PageFactory.initElements(PageFactory.java:66)
    at io.appium.java_client.Test2.test(Test2.java:68)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
    Caused by: java.lang.InstantiationException
    at sun.reflect.InstantiationExceptionConstructorAccessorImpl.newInstance(Unknown Source)
    at java.lang.reflect.Constructor.newInstance(Unknown Source)
    at org.openqa.selenium.support.PageFactory.instantiatePage(PageFactory.java:131)
    ... 26 more

  11. TikhomirovSergey commented on Jul 31, 2014

    @TikhomirovSergey
    Contributor

    How does your code fall? See listing from Selenium:

      private static <T> T instantiatePage(WebDriver driver, Class<T> pageClassToProxy) {
        try {
          try {
            Constructor<T> constructor = pageClassToProxy.getConstructor(WebDriver.class);
            return constructor.newInstance(driver);
          } catch (NoSuchMethodException e) {
            return pageClassToProxy.newInstance(); //cause
          }
        } catch (InstantiationException e) {
          throw new RuntimeException(e); //thrown
        } catch (IllegalAccessException e) {
          throw new RuntimeException(e);
        } catch (InvocationTargetException e) {
          throw new RuntimeException(e);
        }
      }
    }
  12. amedvedjev commented on Jul 31, 2014

    @amedvedjev

    so you reproduced same problem with:

    at org.openqa.selenium.support.PageFactory.instantiatePage(PageFactory.java:136)
    at org.openqa.selenium.support.PageFactory.initElements(PageFactory.java:66)

    Questions:

    • Do you want me to try make code changes as with your succeeded example?
    • or do i need wait for a fix?
  13. TikhomirovSergey commented on Jul 31, 2014

    @TikhomirovSergey
    Contributor

    Please, make sure that your target class is not abstract and has constructor like this: new PageObject(driver)

    Anyway, the best way to use AppiumDecorator is (if it really need to be used, I wrote above):

    po = new PageObject(some params);
    PageFactory.PageFactory.initElements(new AppiumFieldDecorator(driver), po);

    The reason I will describe over five minutes.

  14. TikhomirovSergey commented on Jul 31, 2014

    @TikhomirovSergey
    Contributor

    So, let see this code:

       * @see FindBy
       * @see CacheLookup
       * @param driver The driver that will be used to look up the elements
       * @param pageClassToProxy A class which will be initialised.
       * @return An instantiated instance of the class with WebElement and List<WebElement> fields proxied
       */
      public static <T> T initElements(WebDriver driver, Class<T> pageClassToProxy) {
        T page = instantiatePage(driver, pageClassToProxy); (1)
        initElements(driver, page); (2)
        return page;
      }

    At (1) constructor of page object will populate fields.

    You attempted to use this

    public Page(AppiumDriver driver) {
    this.driver = driver;
    PageFactory.initElements(new AppiumFieldDecorator(driver), this);
    }
    }

    If there is a field
    @AndroidFindBy(someLocator)
    //iOSFildBy(someLocator)
    WebElement semeElement

    at (2) it turns into null because of

       * 
       * @param driver The driver that will be used to look up the elements
       * @param page The object with WebElement and List<WebElement> fields that should be proxied.
       */
      public static void initElements(WebDriver driver, Object page) {
        final WebDriver driverRef = driver;
        initElements(new DefaultElementLocatorFactory(driverRef), page); //(!!!)
     //All webelement fields which 
    //are not annotated by @FindBy turn into null here
    //This is made by Selenium developers. It is so frustrating. 
      }
  15. lolemouine commented on Aug 4, 2014

    @lolemouine

    Still not understanding how I could use PageFactory with other classes...

  16. 11 remaining items

  17. mbelyaeva91 commented on Aug 24, 2015

    @mbelyaeva91

    Did someone manage to implement Page Factory for iOS so far?

  18. amedvedjev commented on Aug 24, 2015

    @amedvedjev

    we do not have any problem with iOS and Android.

  19. mbelyaeva91 commented on Aug 24, 2015

    @mbelyaeva91

    I tried to follow the examples above and nothing works for me. What if we have more than one page? Do I initialize them all in @before setUp()? I followed this sample https://github.com/appium/sample-code/blob/master/sample-code/examples/java/junit/src/test/java/com/saucelabs/appium/iOSPageObjectTest.java and it works fine with one page. I still don't get how to deal with multiple pages

  20. amedvedjev commented on Aug 24, 2015

    @amedvedjev

    "I tried to follow the examples above and nothing works for me. What if we have more than one page? Do I initialize them all in @before setUp()?" - NOT. you should do this in test code.
    sample you follow is not perfect for creating multiple pages.

  21. JasonSmiley208 commented on Feb 23, 2016

    @JasonSmiley208

    There is so much going on in this thread that its hard to follow what we are saying is broken and what should be working so I am just going to provide my code and can someone explain why I am getting a NullPointerException? (Note, I have a similar setup in a selenium project and no issues).

    public class AgentLoginPage extends BasePageClass {
    
        @iOSFindBy(xpath = "//UITextFieldLabel[@label = 'Email']")
        public static MobileElement emailInput;
    
        @iOSFindBy(xpath = "//UITextFieldLabel[@label = 'Password']")
        public static MobileElement passwordInput;
    
        public static void initialize(){
            // driver is pulled in from BasePageClass.
            PageFactory.initElements(new AppiumFieldDecorator(driver), AgentLoginPage.class);
        }
    
        @When("^I submit a \"(.*)\" agent login form$")  //Code for Cucumber.
        public static void I_submit_a_X_agent_login_form(String loginType){
            String email = "", password = "";
    
            switch (loginType.toLowerCase()){
                case "valid":
                    email = "Some@Email.com";
                    password = "Password";
                    break;
                default:
                    throw new PendingException("Unknown Login Type: " + loginType);
            }
    
            emailInput.sendKeys(email);   //NullPointerException here
            passwordInput.sendKeys(password);
    
            passwordInput.sendKeys(Keys.ENTER); //Submits form
    
        }
    }
    

    In my before Hooks:

            AppiumDriverLocalService service = AppiumDriverLocalService.buildDefaultService();
            service.start();
    
            DesiredCapabilities capabilities = new DesiredCapabilities();
            capabilities.setCapability(MobileCapabilityType.BROWSER_NAME, "");
            capabilities.setCapability(MobileCapabilityType.PLATFORM_VERSION, "9.2");
            capabilities.setCapability(MobileCapabilityType.DEVICE_NAME, "iPhone 6 Plus");
            capabilities.setCapability(MobileCapabilityType.APP, appPath);
            capabilities.setCapability("name", "Java iOS tutorial " + date);
    
            driver = new IOSDriver(service.getUrl(), capabilities);
    
            driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
            AgentLoginPage.initialize();
    

    Can I not do this via a static variable? I would think it would be a non issue.

  22. amedvedjev commented on Feb 24, 2016

    @amedvedjev

    @JasonSmiley208 you do init in wrong place.

    simplest example:

    public abstract class Page {
    
        protected WebDriver driver;
    
        public Page(WebDriver driver) {
            this.driver = driver;
            PageFactory.initElements(new AppiumFieldDecorator(driver, 20, TimeUnit.SECONDS), this);
        }
    }
    
    public class MainPage extends Page {
    
        //Action bar
        @AndroidFindBy(id = "action_bar_title")
        private List<AndroidElement> actionBarTitle;
    
        //List Elements
        @AndroidFindBy(id = "list")
        private List<AndroidElement> listView;
        @AndroidFindBy(id = "text1")
        private List<AndroidElement> cellText;
    
        public MainPage(WebDriver driver) {
            super(driver);
        }
    
        public boolean isMainPageLoaded() {
            return !actionBarTitle.isEmpty() && !listView.isEmpty();
        }
    }
    
    public class BaseTest {
        protected static AppiumDriver driver = null;
        private static DesiredCapabilities capabilities = null;
        ....
    
        @BeforeMethod(alwaysRun=true)
        public void beforeMethod(ITestContext iTestContext) {
            capabilities = DesiredCapabilities.android();
            capabilities.setCapability(MobileCapabilityType.AUTOMATION_NAME, "Appium");
            capabilities.setCapability(MobileCapabilityType.DEVICE_NAME, "Android");
            capabilities.setCapability(MobileCapabilityType.PLATFORM_NAME, MobilePlatform.ANDROID);
            File appDir = new File(userDir, fileName);
            capabilities.setCapability(MobileCapabilityType.APP, appDir.getAbsolutePath());
            capabilities.setCapability(MobileCapabilityType.APP_WAIT_ACTIVITY, ".ApiDemos");
            capabilities.setCapability("fullReset", true);
            capabilities.setCapability("noReset", true);
    
            driver = new AndroidDriver(new URL("http://127.0.0.1:4723/wd/hub"), capabilities);
        }
    
        @AfterMethod(alwaysRun=true)
        public void afterMethod(ITestResult iTestResult, ITestContext iTestContext) throws Exception {
            try {
                driver.quit();
            } catch (Exception e) {}
        }
    
        //... so on continue with @BeforeSuite, @AfterSuite, ..... whatever needed
    }
    
    public class test_1 extends BaseTest {
        private MainPage mainPage;
    
        @Test
        public void testMainPage() {
            mainPage = PageFactory.initElements(driver, MainPage.class);
            assertTrue("Main screen NOT loaded", mainPage.isMainPageLoaded());
       }
    }
    
  23. JasonSmiley208 commented on Feb 24, 2016

    @JasonSmiley208

    Quick question - I see you are using

    mainPage = PageFactory.initElements(driver, MainPage.class);

    instead of

    new AppiumFieldDecorator(driver)

    Is that intended or a typo?

    Or is this because you are using the Page(Webdriver) constructor?

  24. amedvedjev commented on Feb 24, 2016

    @amedvedjev

    are you sure - ?
    see:

    public Page(WebDriver driver) {
            this.driver = driver;
            PageFactory.initElements(new AppiumFieldDecorator(driver, 20, TimeUnit.SECONDS), this);
        }
    
  25. idcmurali commented on Dec 1, 2016

    @idcmurali

    I am trying to setup POM with Appium and running into issue .
    I used the same code provided by TikhomirovSergey commented on Jul 31, 2014 ( Says : This code works) But I still get the Pagefactory error message . It is also looking and saying source jar not found looking in my selenium-server-standalone jar3.0.1

    java.lang.IllegalArgumentException: Can not set static io.appium.java_client.MobileElement field wfm.appium.testcases.FinalApp$LandPageObject.CreateAccountnew to com.sun.proxy.$Proxy6
    at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:167)
    at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:171)
    at sun.reflect.UnsafeStaticObjectFieldAccessorImpl.set(UnsafeStaticObjectFieldAccessorImpl.java:79)
    at java.lang.reflect.Field.set(Field.java:764)
    at org.openqa.selenium.support.PageFactory.proxyFields(PageFactory.java:117)
    at org.openqa.selenium.support.PageFactory.initElements(PageFactory.java:105)
    at org.openqa.selenium.support.PageFactory.initElements(PageFactory.java:92)
    at org.openqa.selenium.support.PageFactory.initElements(PageFactory.java:79)
    at org.openqa.selenium.support.PageFactory.initElements(PageFactory.java:65)
    at wfm.appium.testcases.FinalApp.test(FinalApp.java:73)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:678)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)

  26. klzeng commented on Jul 7, 2017

    @klzeng

    Hi @TikhomirovSergey , I use the "legal way"(2) you mentioned above, but it doesn't work, I got noSuchMethod error when using sendKeys.

    In Abstract BasePage:
    protected BasePage(AndroidDriver<AndroidElement> driver){ this.driver = driver; PageFactory.initElements(new AppiumFieldDecorator(driver, 5, TimeUnit.SECONDS), this); }

    LoginPage extends BasePage:
    `
    @AndroidFindBy(id = "et_login_username")
    private AndroidElement usernameField;

    public LoginPage(AndroidDriver driver){
    super(driver);
    }`

    In LoginTest:
    `@Override
    @BeforeClass
    public void setUpPage() {

    objLogin = new LoginPage(driver);
    

    }
    And I got NoSuchMethodError on usernameField.sendKeys(strUsername);`

    Appreciate it if you could help out!

  27. rmeenasuresh commented on Jul 10, 2017

    @rmeenasuresh

    Hi i got the same error NoSuchMethodError. please anyone help me. i upgrade dependencies to latest versions .

    Pageobjectpage,
    Note: static import the iosDriver
    Class LoginPage(){
    public LoginPage() {
    PageFactory.initElements(new AppiumFieldDecorator(iosDriver,15, TimeUnit.SECONDS), this);}

    @iOSFindBy(xpath="//XCUIElementTypeButton[7]")
    private MobileElement Number1Btn;

    public void login(){
    Number1Btn.click();
    }
    }

    LoginTest

    public class LoginTest extends BaseTest{
    private LoginPage loginPage;
    @BeforeClass
    public void setup()
    {
    loginpage = new LoginPage();
    }

    @test
    public void loginTest()
    {
    loginPage.login();-----------------this line shows Nosuch method error
    }

    my reports,

    java.lang.NoSuchMethodError: org.openqa.selenium.support.ui.FluentWait.until(Lcom/google/common/base/Function;)Ljava/lang/Object;
    at io.appium.java_client.pagefactory.AppiumElementLocator.waitFor(AppiumElementLocator.java:88)
    at io.appium.java_client.pagefactory.AppiumElementLocator.findElement(AppiumElementLocator.java:103)
    at io.appium.java_client.pagefactory.interceptors.InterceptorOfASingleElement.intercept(InterceptorOfASingleElement.java:57)
    at io.appium.java_client.ios.IOSElement$$EnhancerByCGLIB$$184e91dc.click()

  28. narendra-chandratre commented on Aug 8, 2018

    @narendra-chandratre

    Its still reproducible on Appium 1.8.1 :(
    Anyone resolve this?

  29. dikako commented on Jul 6, 2020

    @dikako

    This Working with Me, My Project Selenium, TestNG and Appium use PageFactory.initElements

    public class Login extends Setup {
    
        @Test
        public void loginAlert() throws InterruptedException {
            
    
        Button button = new Button(driver);
                PageFactory.initElements(driver, button);
                Input input = new Input(driver);
                PageFactory.initElements(driver, input);
            
            
            Input input1 = new Input(driver);
            System.out.println("Test Alert Login");
            button.ById("navigation_more");
            button.ById("btnLogin");
            input.ById("et_email_or_phone_number", "dikakoko.com");
            input1.ById("tet_password", "dikakoko");
            
        }
    }
    

    Below this is the function I called above.

    public class Input {
        AppiumDriver<MobileElement> driver;
        Root root = new Root();
    
        public Input(AppiumDriver<MobileElement> driver) {
            this.driver = driver;
        }
    
        public void ById(String selector, String textValue) {
            MobileElement element = driver.findElement(By.id(root.element() + ":id/" + selector));
            waitForVisible(driver, element);
            Actions actions = new Actions(driver);
            actions.moveToElement(element);
            actions.click();
            actions.sendKeys(textValue);
            actions.build().perform();
            System.out.println("Input: " + textValue);
        }
        
        private void waitForVisible(AppiumDriver<MobileElement> driver, MobileElement element) {
            try {
                Thread.sleep(5000);
                System.out.println("Waiting for element visibility");
                WebDriverWait wait = new WebDriverWait(driver, 20);
                wait.until(ExpectedConditions.visibilityOf(element));
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    

    and This

    
    public class Button {
    
        AppiumDriver<MobileElement> driver;
        Root root = new Root();
    
        public Button(AppiumDriver<MobileElement> driver) {
            this.driver = driver;
        }
    
        public void ById(String selector) {
            MobileElement element = driver.findElement(By.id(root.element() + ":id/" + selector));
            Actions actions = new Actions(driver);
            actions.moveToElement(element);
            actions.click();
            actions.build().perform();
            System.out.println("Button is Clicked!");
        }
    }
    

    I Use This

                 Button button = new Button(driver);
                PageFactory.initElements(driver, button);
                Input input = new Input(driver);
                PageFactory.initElements(driver, input);
    

    References : www.seleniumeasy.com

  30. MukeshHalaPlay commented on Feb 17, 2022

    @MukeshHalaPlay

    Try these steps: This might help (Works in my case with same initElement NoSuchMethod Exception)

    Open Eclipse>
    Windows>
    Preferences>
    Java>
    Installed JREs>
    Change the selected JRE to the JDK: (Follow the steps:)
    Add the Java folder(C:\Program Files\Java\jdk-11.0.14) as JDK (Installed)
    Select that added JDK, then Apply and close.

    image

    Try retest your scripts after this change.

  31. Demudu1995 commented on Oct 30, 2022

    @Demudu1995

    Hai guys any one please help me !
    I'm not able to use appiumfielddecorator, if I use appiumfielddecorator, I'm getting this exception:
    java.lang.ExceptionInInitializerError at
    io.appium.java_client.pagefactory.u tils.ProxyFactory.getEnhanced Prox y(ProxyFactory.java:53)

    : I am automating Mobile app (Android ).
    So If I use
    PageFactory.initElements (driver, this);
    and try to find elements by using annotation as @findby MY CODE WORKS.

    But if try to use
    PageFactory.initElements (new
    AppiumFieldDecorator (driver), this);
    and try to find elements by using annotation as @AndroidFindBy
    My CODE is not working, and
    I'm getting the exception java.lang.ExceptionInInitializerError.

    I'm using jdk version 17
    Java client 8.2.0
    Appium also latest 1.2.3
    This is my code :
    public class Page1 { // page object class

    public static AppiumDriver driver;
    
    public Page1(AppiumDriver driver) {
        PageFactory.initElements(new AppiumFieldDecorator(driver), this);
        this.driver = driver;
    }
    
    
    @AndroidFindBy(id = "com.tva.z5:id/homeIcon")
    public WebElement homeIcon;
    
    public void logo() {
        homeIcon.click();
    
    }
    

    }


    package appiumtests; // this is my test

    public class Test1 {

    @Test
    public void test() throws InterruptedException {
    
        Page1 lg = new Page1(driver);
    
          lg.logo();
        Thread.sleep(5000);
    
    }
    
    }
    
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions