I have the following issue:
I have a home page where I load the URL with the following structure:
public class HomePage extends BasePage {
public HomePage(WebDriver driver) {
super(driver);
getDriver().get("URL");
}
Then I have another page, which extends from the HomePage:
public class OptionsPage extends HomePage {
public OptionsPage(WebDriver driver) {
super(driver);
}
Now, the issue is on the test, where I want to get the OptionsPage from an action (let's say clicking a button present on HomePage). It seems that the page just loads again once I call it:
// Open page
HomePage home = getHomePage(); //loads URL from BasePage
// click on some option which takes me to the OptionsPage
OptionsPage options = home.clickOnRandomOption(); //this method right here loads the URL again, from there the assertion fails since the page just loads again.
Assert.assertTrue(options.isRandomOptionSelected(), "Obviously it wasn't selected.");
The method to click the option on the home page looks like this:
public OptionsPage clickOnRandomOption() {
getWait().until(ExpectedConditions.elementToBeClickable(RandomOption));
RandomOption.click();
return new FlightOptionsPage(getDriver());
}
Can anyone help me out?
Your challenge is that when you instantiate your optionsPage you're executing all constructors up the chain.
From your code structure, you're running: OptionsPage -> HomePage -> BasePage every time you want to create an optionsPage. It's the testing POM equivalent of the Gorilla-banana-jungle problem.
I can see that the return type from home.clickOnRandomOption() is an OptionsPage so I'm assuming that's where you instantiate the options page.
Two suggestions - either of them will fix your problem, but I recommend you think about implementing both:
Don't chain your pages like that. Keep each one separate and ONLY extend once i.e. each page only extends from BasePage. If there is a common method which more than one page needs, put it in your BasePage and there's no need to extend page from other pages.
Don't execute test-context-impacting code in your constructors - use contructors only for initating variables. By this, I mean that when you create your HomePage do not navigate (driver.get("URL")) in the constructor. This will cause future complications for you when you run tests. For example, what if, you wanted to start on pageX and navigate to home via an auto-redirect then do more actions on home? - your POM won't support it as when you create homePage you're going to navigate the URL to there.
Related
I am wring a PageFactory framework for a website using maven+TestNG,
I have page wise PageObject classes where all web elements and actions specific to page are present like LoginPageObject, AccountSelectionPageObject...
I have a class "Base" where the common elements like WebDriver, Logger are present.
I have a class "BasePage" where the common actions like click, scroll, select, refresh... are present
MyTestng.xml is having separate <class> entry for both all individual pages.
It's just that I am initializing the browser object in #BeforeSuiit and stored/placed it in the Base class which is being extended in my Test classes
Below is the flow/arch I came up for my project.
Issue:
I have multiple #Test in each of my test classes.
When my Test classes are executed individually, all #Test script executed,
but when I execute them continuously, i.e. my testng file have separate entries for all my test classes, my execution fails. Error says unable to find element on page, I have wait statements, but still it's not working.
I have tried debugging code, but not able to find the reason as the flow stops on starting of second page with exception saying element not found
Code:
#FindBy(id="listAccounts")
WebElement accountDropdown;
public void selectAccount(){
logger.info("Selecting Account");
implicitwait(10);
Select dropdown = new Select(accountDropdown);
logger.info("Drop down is multiple::"+ dropdown.isMultiple());
}
Expected:
Code should execute completely even when separated code page wise.
Actual:
When I have all pages code in one test class, code executed.
But when I place them separately in page wise test class, element not found exception is thrown.
org.openqa.selenium.NoSuchElementException: no such element: Unable to locate element: {"method":"id","selector":"listAccounts"}
In POM using PageFactory framework, one should initialise PageFactory in Constructor of PageClasses. Please find below code snippet which might work in your case.
public class LoginPage extends TestBase {
public LoginPage() {
PageFactory.initElements(driver, this);//Here driver is initialised in TestBase class and inherited in LoginPage class
}
//your code
#FindBy(id="listAccounts")
WebElement accountDropdown;
public void selectAccount(){
logger.info("Selecting Account");
implicitwait(10);
Select dropdown = new Select(accountDropdown);
logger.info("Drop down is multiple::"+ dropdown.isMultiple());
}
}
A complement to the Krishna answer:
PageFactory.initElements(driver, this);
The code above can be moved to the base class and from the LoginPage, you just pass the webdriver on the constructor like this.
public class LoginPage extends Base {
public LoginPage(Webdriver driver) {
super(driver);
}
...
public class Base {
public Base(Webdriver driver) {
PageFactory.initElements(driver, this);
}
...
I created a Wizard, then I created a WizardPage namely FrontPage and added it to wizard in wizard's addPage method.
Since I have only one page in addPage method, the Next button not shown. I want it to be shown.
In the nextPressed method of the FrontPage, I created an instance of another java class that the class runs the program written in another language. In several points of that program, I need to create wizardPage dynamically. For this purpose I created a java class to contribute to the program. This class namely interfaceRule create an instances of wizardPage in other plugin.
My questions is how can I add this wizardPages to the main wizard? And also how can I return the value that user select in wizardPage to interfaceRule class?
edit:
public IWizardPage getNextPage() {
boolean isNextPressed = "nextPressed".equalsIgnoreCase(Thread.currentThread().getStackTrace()[2].getMethodName());
if (isNextPressed) {
boolean validatedNextPress = this.nextPressed();
if (!validatedNextPress) {
return this;
}
}
return super.getNextPage();
}
There are several ways to control the Next button in your class extending Wizard
You can call setForcePreviousAndNextButtons(true) in the wizard constructor to force the buttons always to be shown.
You can override the needsPreviousAndNextButtons method to decide if the buttons are required dynamically.
You can override the getNextPage method:
public IWizardPage getNextPage(final IWizardPage page)
to control exactly which page is shown next (also getPreviousPage).
I have a problem how handle inheritance in my test project using Page Object Pattern. In our company we have one stable version of our web appliaction - something called Demo from which we copy ready modules. Kind like a base to other new versions of clients applications. They are in 90% all the same. So i think it would be great to make Base Page Objects Classes and in many projects inheritance from that classes.Sadly they are different in this 10% and I need to override xpaths in class fields. I have a problem when i inheritance from Base POP Class, make a field in child class, and method from parent class(Base POP Class) run on field in parent class not on child. Let show me your example. This is may parent class:
public class BaseHomePage {
#FindBy(xpath = "exampleXpath")
protected WebElement profileButton;
public BaseHomePage(WebDriver driver) {
PageFactory.initElements(driver, this);
}
public void goToProfile() {
profileButton.click();
}
and this is my child class:
public class HomePage extends BaseHomePage {
#FindBy(xpath = "otherXpath")
protected WebElement profileButton;
public HomePage(WebDriver driver) {
super(driver);
PageFactory.initElements(driver,this);
}
public void goToProfile() {
profileButton.click();
}
}
So problem is I need to use the same method goToProfile() in child class, because when i not method from parent call on field in parent class. I don't want to duplicate code and i search for answers but i'm not sure this is good use of POP in multiple projects. What i need to make it properly? Or maybe u would suggest me make it in another way? Thanks for help!
Using Java, I am trying to write a general check for a particular text on every page in a web application that existing tests visit. Instead of having to write it on each and every page individually, is it possible to do in one place at a high level (may be in the base class)?
public class BaseClassForUiTest {
public BaseClassForUiTest() {
...
}
public void test() throws Exception {
boolean isNewPage = checkIfNewPage();
if (isNewPage)
// perform a text check on the page
}
}
Every test extends from BaseClassForUiTest and overrides the test() method.
Instead of having to write it on each and every page individually, is it possible to do in one place at a high level (may be in the base class)?
Yes, it is possible by implementing WebDriverEventListener into BaseClassForUiTest and override event handler methods to handling the appropriate WebDriver events according to need in one place.
Here every method corresponds to an event. According to your requirement you need to handle afterNavigateTo() method. This one is called every time the navigate to a page is completed.
You have to do perform a text checker on the page code in this method so that your code is executed every time the page navigates to some other page.
public class BaseClassForUiTest implements WebDriverEventListener
{
---------
---------
public void afterNavigateTo(String arg0, WebDriver arg1) {
// perform desire text checker stuff on the page here
}
}
Now Create Event Throwing WebDriver to perform your test :-
Create a regular WebDriver.
FirefoxDriver driver = new FirefoxDriver();
Now create an EventThrowingWebDriver using our regular WebDriver created above.
EventFiringWebDriver eventDriver = new EventFiringWebDriver(driver);
Create an instance of your eventHandler class and register it for events using the register method of EventFiringWebDriver object created above as :-
BaseClassForUiTest handler = new BaseClassForUiTest();
eventDriver.register(handler);
Full code :-
import org.openqa.selenium.support.events.EventFiringWebDriver;
public class BaseClassForUiTest {
public void test() throws Exception {
FirefoxDriver driver = new FirefoxDriver();
EventFiringWebDriver eventDriver = new EventFiringWebDriver(driver);
BaseClassForUiTest handler = new BaseClassForUiTest();
eventDriver.register(handler);
eventDriver.get("your url");
//Now do your further stuff
}
}
As for me, you'd better create a separated test class for this check using Parameterized or JUnitParams and give it a urls to run where as parameters, but it depends on what is your common approach to running tests (we run all testpack at the same time, so it's a solution for us in this situation).
Also it is seems like well-logically-separated solution
If you are going to use this check as an assertion you can rewrite your current code for this case and call for it in #Before block (but it is still not a good solution, in my opinion)
I am a little confused about tags. I know from wicket 1.5 there was a change of head render strategy from parent->child to child->parent.
Now I use wicket 6.9 and I have simple menu panel which I want to use some jquery effects.
I want to use the same jquery (for example for google) file for whole application.
I cannot use jquery link only in main page, because in while rendering menu panel there is " $(document).ready" and it is not recognized. Reading some forum i found opinion that panel should contain jquery itselft - it is reasonable, because it can be reusable independently.
So now my page consist:
<head>
...
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.js"></script>
...
</head>
And my menu panel consist the same. As a result in rendered html I load jquery.js twice.
How should I resolve it? I want to load it only once. I know i can back to old strategy and do application.getResourcesSettings().setHeaderItemComparator() but as i read it is not the best solution.
I can found such class like PriorityHeaderItem in wicket, but documentation is very poor for wicket and did not found any example of use it.
Best regards
Since wicket 1.6 jQuery is now the javascript library used by the framework. So you may see jQuery twice because of the one you included and the wicket version? If you want to override the jQuery version you can create a Resource Reference and then set it in your init method of the Application class.
First you need the resource reference file and put the js file in same package structure.
public final class JQueryResourceReference extends JavaScriptResourceReference {
private static final JQueryResourceReference INSTANCE = new JQueryResourceReference();
private JQueryResourceReference() {
super(JQueryResourceReference.class, "jquery.js");
}
public static JQueryResourceReference get() {
return INSTANCE;
}
}
Then in the application init method do this:
public MyApplication extends AuthenticatedWebApplication {
#Override
protected void init() {
super.init();
getJavaScriptLibrarySettings().setJQueryReference(JQueryResourceReference.get());
....
}
....
}