I have a number of objects which are used repeatedly as navigating though the pages of web application. I check each page for an error dialog as I navigate. As I repeatedly use these tests, if I do encounter an error, each test case which uses the navigation functions will fail. I don't want to maintain two sets of navigation functions so I am wondering if anyone knows of a good approach to take?
Thanks
You should not do assertions in your navigation classes. As much as I understand from you question, you have at the moment something similar to:
class Navigation{
public void navigateToSomePlace(){
navigate();
assertTrue(isInExpectedPlace());
}
}
But you should remove the validation from that method and implement it as a separate method which you can call when you need it. If you want better explanation, show some code.
Edit, how I would implement it:
class Navigation{
public void navigateToSomePlace(){
navigate();
}
public void validateIsInSomePlace(){
assertTrue(isInExpectedPlace());
}
}
So basically, when you are doing the navigation test you would call both of them, but if you only use it for navigating, you would only call the navigate()
Related
I'm trying to figure out the best way of making my Page Objects simple, and whether to put absolutely all logic elsewhere. And whether all Selenium code/functionality should be in the Page Object, or in the Step Definition methods I use to access it.
I have the following structure:
Cucumber.feature files
Given blablabla
Java/Kotlin step definitions
#Given("^blablabla$") {
}
And the page object files
fun getOwnerFields(): MutableList<WebElement> {
return driver.findElements(By.if("owner-fields")
}
As a simple example.
Now, what I cannot come to an agreement with myself on, or find much of other's opinions about, is:
Should I do page actions - for instance, a button click, in the Step Definition class OR in the Page Object?
This:
#Given("^I click on the Next button$") {
startPage.nextButton().click()
}
PO:
fun nextButton(): WebElement {
return driver.findElement(By.id("next-button")
}
Or:v
#Given("^I click on the Next button$") {
startPage.clickNextButton()
}
PO:
fun clickNextButton(): WebElement {
return driver.findElement(By.id("next-button").click()
}
I've tended to think that it's best to keep all the page and selenium code in the Page Object. But in cases like this, it makes the PO bigger, because I'll need different methods for clicking, checking for visibility, counting etc. While if all this is done in the step definitions, the PO can practically contain nothing but getters and setters for the page elements.
Anyone got any light to shed? I know it's not THAT important, but I tend to be quite occupied with the best and/or cleanest way of organizing my code.
This is indeed opinion based question. It depends on the bunch of factors including what your app can and how flexible the user interaction is assumed to be.
As to me since your core abstraction is assumed to be on Gherkin statement level I would say I does not make sense to put a lot of abstraction on lower levels.
Button is not that good example actually because normally you only can click it so there would hardly be other types of interactions. But for other elements my choice would definitely fall on your first approach.
Such the approach would let you to concentrate on the logic that is specific for the step so that being in the step definition you can clearly see what's happening there without extra navigation through the classes.
my question is, what is the best way to let a child class communicate with the parent class.
For example:
I have a main class simply called Main, and another class SomeClass.
Now the Main class creates an instance of SomeClass, once the state of the SomeClass-object changes, the Main class should execute different code, depending on what changed.
Yeah I know, that already sounds like the Observer design pattern, but how would I implement it with state changes treated differently?
I'm currently writing an Android app with a database to make it more specific.
In my project I have the main class, a class to connect, read from/write to the database and a GUI container class. (oversimplified, there are a few more)
The main class creates an instance of both the GUI and database class.
Now if I press a button A, it should write A-data to the database,
if I press button B, it should write B-data to the database.
As I think that a gui class shouldn't have direct access to the database, I tried other options, than just accessing the database from the gui-class
Currently, I defined a placeholder abstract class with only one method, that I am just overwriting with the functionality.
So right now I have to create a one-method-class A for the click of button A and a one-method-class B for the click of button B.
It doesn't sound like the best way to me, I mean It's working, but I'd like to improve my code, so if you have any idea, please write your solution. :)
As a good practice it is better to avoid write code in GUI class. So we can use MVVM pattern here.
Let me show a simple example for your case. This is a ViewModel class. View model does not have reference to view class:
public class YourViewModel
{
public void LoadA()
{
// here you can interact with your database
}
public void LoadB()
{
// here you can interact with your database
}
}
This is your view class. It handles button clicking, user interactions with view and forwards to the view model. It has a reference to view model.
public class YourView
{
YourViewModel yourViewModel;
public YourView()
{
yourViewModel = new YourViewModel();
}
public void ButtonA_Handler()
{
yourViewModel.LoadA();
}
public void ButtonB_Handler()
{
yourViewModel.LoadB();
}
}
If you want to handle many events, then you can try to use this approach How to: Handle Multiple Events Using Event Properties.
It seems like a good way to approach this would be to use a pattern like that described in this previous Stack Overflow answer.
They provide sample implementations there but to apply to your case, you don't need to give the GUI direct access, you can have a parent class which implements the "listener" functionality, and a child (GUI) class which just calls its parent, with those details abstracted away from the child.
If you feel like you need more details/examples on implementing this pattern see https://refactoring.guru/design-patterns/observer/java/example
I'm following the Page Object model approach. I’m working on implementing a SearchResultsPage where a bunch of search results are displayed. In thinking about this page, I would like to implement it in such a way that it would support a getSearchResultByIndex(int index) method. Ideally, I would like the return type of this method to be a SearchResult, which would be a mini-page object (aka panel) that encapsulates the functionality found on a search result item since there are a number of attributes of a search result that the user can interact with. I don’t see how to accomplish this though. I was hoping to find a method like PageFactory.initElements() that would take in the WebDriver, a WebElement or selector (that identified an individual search result), and an instance of my SearchResult, but haven’t seen anything.
For clarity. Here's the basic structure of a SearchResults page.
<div class="searchResultsContainer">
<div class="searchResult">various internal fields to interact with/inspect</div>
<div class="searchResult">various internal fields to interact with/inspect</div>
...
<div class="searchResult">various internal fields to interact with/inspect</div>
</div>
It seems like this has to be a common problem out there that people have solved. I've used this "panel" notion for other common page elements like header, footer, etc, but never in the case where multiple instances of the same panel type are on the same page.
Any thoughts would be appreciated. Thanks.
If it were me I would approach it differently. I would split this into 2 page object classes. One for SearchResults, and one for SearchResultPage. The SearchResults would be the generic results list and actions you can take on those results. Within that class you would add a method to click on an individual search result, to pop up the details of that result, that would be what returns your SearchResultPage object.
Here is a rough sketch of what that method could look like inside your SearchResults page object. Not sure what language you are using but this is in C# (Java would be similar, Python much different but you'll get the general idea):
public SearchResultPage GetSearchResult()
{
// do something to click and show search details
return new SearchResultPage(_driver);
}
And then a skeleton of the SearchResultPage class object itself:
public class SearchResultPage
{
IWebDriver _driver;
// add whatever elements you want to work with specific to that single record view
//constructor
public SearchResultPage(IWebDriver driver)
{
_driver = driver;
}
// add whatever methods you want to interact with the elements in that view
}
The good thing about keeping the page objects separate in this case is SearchResults could actually be used in other areas of the application as well, if there are results on other pages that use the same elements etc. I find myself taking out common page elements (drop down menus, grids, etc) into their own objects all the time. Otherwise you end up repeating a lot of code if you stick to strict Page Object model where common functionality exists on multiple pages.
I think I've got this solved. I ended up abandoning PageFactory.initElements(), which I think I've learned is really key and likely an old-school way of implementing the page/object model. Adopting the use of By rather than FindBy seems to work much better as long as the appropriate conditional WebDriverWait.until(ExpectedConditions.elementToBeClickable(elementLocator)) is used.
After coming to this understanding, introducing the concept of a panel locator in my base Panel class allowed me to combine that locator with a nth-of-type(idx) locator to get things wired up and working as expected. Here's a simplified example of that in use in my SearchResultsPage:
public SearchResult getSearchResult(int idx) {
SearchResult res = new SearchResult(getWebDriver(),
By.cssSelector(".searchResultsContainer .seachResult:nth-of-type(" + idx + ")"));
return res;
}
My SearchResult class then just has a number of By locators defined that essentially call new ByChained(panelLocator, locator);
So glad to have solved this!
Hi there I have asked this on Gitter, but hope that someone here may be able to help.
I have two different routes that have the same moduleId. I have also set up a setting object within the routes with some data to differentiate what gets rendered. Everything works fine when I navigate to one of these routes from somewhere else, but if I navigate from one to the other neither the constructor or the activate are fired. am i missing something??
I had this problem and it took me a while to find a solution - this should help you I hope;
You need to add the determineActivationStrategy() method into your class, and then return as below.
import {activationStrategy} from "aurelia-router";
export class ExampleViewModel {
determineActivationStrategy() {
return activationStrategy.replace;
}
}
This will force the VM to be replaced when you're routing to it from itself.
Here's some more info on the different Activation Strategy types;
activationStrategy.no-change – reuse instance with no lifecycle events
activationStrategy.invokeLifecycle – call lifecycle methods on the ViewModel instance each time the route switches
activationStrategy.replace – construct new instance of ViewModel and invoke full lifecycle on it
Taken from here ZombieCodeKill - Aurelia Routing Beyond the Basics
Found the answer here :) Although not a complete fix out of the box, the implementation is possible
I started to use GWTP for my project and I'm currently re-writing all my code to let it work with this library.
However, I struggle to understand how I use GWTP if I want e.g. a ListView with ListItemView items.
#Inject
public ToolsPresenter(PlaceManager placeManager, EventBus eventBus, MyView view, MyProxy proxy) {
super(eventBus, view, proxy, AdminToolPresenter.SLOT_AdminToolMainContent);
this.placeManager = placeManager;
ToolListView toolListView = new ToolListView(...)
ToolListPresenter toolListPresenter = new ToolListPresenter(....);
this.setInSlot(SLOT_ToolList, toolListPresenter);
}
What I want is to place my ListView inside a slot. I am very certain that I can't do what is shown up there but I just don't get how I use just simple Widgets with GWTP.
Or am I doing this completely wrong and I should just extend a Composite for ListView and not use GWTP stuff here at all?
There is a lot of information missing from your question so this is a difficult one to answer.
Assumption 1 - Your GWTP artifacts (ToolListView, ToolListPresenter, ToolListView.ui.xml, and ToolListModule) are setup correctly and ToolListModule is installed in a parent module.
Assumption 2 - You are using GWTP version 1.5+ which has typed slots.
You should not be instantiating your ToolListView or ToolListPresenter.
Simply add:
#Inject ToolListPresenter toolListPresenter;
If you are trying to call the setInSlot method then
Make sure ToolListPresenter is a PresenterWidget
Make sure your slot is not a NestedSlot.
Finally try moving the call to setInSlot outside of your constructor and into the overridden onBind() method.