A Page can implement this trait to get notified when the page gets activated and deactivated.
If you want to use geb-like at checker, use this trait.
A Page needs to implement AtChecker if you want to activate the page with PageBrowser.to().
A Page needs to implement AtChecker if you want to activate the page with PageBrowser.to(). Only active pages
can have access to the elements defined in the PageModule
s on a PageObject
.
Normally you are using PageObject, this trait already extends AtChecker. For a closer look please see comment in PageObject.
Because a PageObject will be chained to an PageBrowser, every PageBrowser needs an own instance of the error page.
Because a PageObject will be chained to an PageBrowser, every PageBrowser needs an own instance of the error page.
Because of this there are two traits, UnexpectedPages contain PageObjects and UnexpectedPagesFactory containg functions returning PageObjects
the type of pages, either "AtChecker" or "() => AtChecker"
Default implementation for PageReference, used by PageObject and PageReferenceProvider.
Default implementation of UnexpectedPages
Default implementation of UnexpectedPages
list of pages that should cancel a test when detected
list of pages that should fail a test when detected
Default UnexpectedPagesFactory implementation
Default implementation of UrlPage only contain an URL.
Trait to separate the domain and the path of the page to test.
Trait to separate the domain and the path of the page to test.
You can write your own implementation of domain
and
query e.g. the system environment to decide if a test server url or
a local development url should be returned.
Example:
trait GoogleDomainPage extends DomainPage {
val domain = sys.env.getOrElse("DEV_SERVER_PREFIX", "https://www.google.com")
}
Use this class if you want to create a PageModule chained to a Query.
Use this class if you want to create a PageModule chained to a Query.
It is required that the given Query will only return one Element, otherwise an Exception will be thrown.
If you want to create a list of PageModules, for every Element returned by Query, use PageBase.modules, implemented by PageObject and PageModule.
This class will requery the element every time it is accessed. Also see FixedQueryPageModule.
Example:
class FooterModule(implicit parent: ParentPageReference) extends DynamicQueryPageModule(IdQuery("footer"))
A trait representing a PageModule chained to an Element.
A trait representing a PageModule chained to an Element.
Example:
case class TodoEntryModule(element: Element)(implicit parent: ParentPageReference) extends ElementPageModule
Default implementation of UnexpectedPages with empty lists for cancelTestPages and failTestPages
Use this class if you want to create a PageModule chained to a Query.
Use this class if you want to create a PageModule chained to a Query.
It is required that the given Query will only return one Element, otherwise an Exception will be thrown.
If you want to create a list of PageModules, for every Element returned by Query, use PageBase.modules, implemented by PageObject and PageModule.
This class will query the element once and store it. When the Element will be removed from the DOM a StaleElementReferenceException will be thrown.
Example:
class FooterModule(implicit parent: ParentPageReference) extends FixedQueryPageModule(IdQuery("footer"))
PageModule for keyboard driven tests.
PageModule for keyboard driven tests.
For an example see WikipediaTest.
Because each PageModule has two implicit PageReferences, one pointing the PageModule itself, the other one pointing to the parent PageReference, we need two types to allow the compiler to decide which PageReference to use.
Because each PageModule has two implicit PageReferences, one pointing the PageModule itself, the other one pointing to the parent PageReference, we need two types to allow the compiler to decide which PageReference to use.
This type is used to implicit pass "this" into Locator calls.
Base trait for PageObject and PageModule.
A PageModule represents a logical unit inside a PageObject
.
A PageModule represents a logical unit inside a PageObject
. Speaking of a web site this is a
part of elements which are all closely related to each other such as the fields of a login box (username
and password) and the button to submit the information in order to log in. Apart from the definition of the
elements the PageModule also defines the actions possible within this part of the web site. Therefore access
to the web driver is needed. This access is provided by the implicit variable of webDriver which comes from
the encapsulating PageObject
.
On the technical side a PageModule has a reference to itself which is needed to get access to the elements
defined in the module. There is also the parent module (the encapsulating module or page) and the root element.
In order to get all children of this PageModule which satisfy a certain definition (in this case the definition
has the form of a Query
), you can call modules[T <: ElementPageModule](query: Query, factory: Element => T): Seq[T]
function.
A PageModule can contain other PageModules and has an implicit reference to the "parent",
either a PageObject
or a PageModule
.
There are 2 special cases for using the PageModule pattern:
1. The PageModule consists only of exactly one Element
. If the PageModule is chained to an Element
,
you should use ElementPageModule
insteade of PageModule.
2. The PageModule consists of all Element
s returned by a Query
. Such a PageModule can
be chained to a Query, use QueryPageModule
insteade of PageModule.
This trait is intended to be part of the testing pattern PageObject.
This trait is intended to be part of the testing pattern PageObject. Here it is implemented a bit different from
the basic PageObject pattern as depicted in many articles and books. In general a PageObject still represents a
page in the browser. But its content is composed by other traits and classes. A PageObject is always the outer
browser page itself. So a browser page is composed of a (root) PageObject which contains the actual content. Apart
from that it is possible to nest page into one another. Therefore for every PageObject its reference
to the encapsulating PageObject must be known. This is done using the val parent
. In this context
an implicit variable is needed for every PageObject to pass its reference through to its children. Also an
implicit reference to the WebDriver
access is needed in order to allow the content elements to be accessed by
functions provided by the modules. Last but not least a page defines its title. As it can be seen, the PageObject
trait just defines the outline of a page but not its real content, only that there is a content.
On the administrative level there is a private val which remembers the active page. If one wants access to
a content element on a non-active page an execption will be thrown using (TestHelper.failTest()
). Therefore
content can only be defined within a PageObject.
How to use a PageObject? This trait is extended with an AtChecker, a DefaultPageReference and a ParentPageReference.
The AtChecker only provides a function atChecker(): Boolean
which is executed when the page is called
using the to()
function. It also can be called seperately just to check if you landed on the correct page.
The atChecker()
function must be implemented on every page which extends the PageObject trait. The
atChecker()
function also cares about making the called page active such that elements on
it can be accessed.
The Default- and ParentPageReference are needed to model the tree of how the web site is built.
A PageObject can contain PageModules, at least one PageModule
named "content" is required. Within this the
actual content of what the web site look like is defined. Please note: There should be NO content definition at
all in PageObject. All content elements have to be declared in the content PageModule
. Also the actions which
are offered to the user (like clicking, filling fields etc.) have to be defined in the PageModule
s.
If you want the PageObject to be called using a URL, you need to extend UrlPage trait in your page class. If you furthermore have different domains your page you need to extend DomainPage trait.
As already mentioned above, you need to activate a PageObject before you can execute Selenium commands inside of
the PageModules, otherwise an exception will be thrown. This can be done either by using PageBrowser.to(page)
in order to call a page url or by using PageBrowser.at(page)
in order to check if landed on the
expected page.
A PageReference is used by PageModules to point to the parent PageObject or PageModule.
A PageReference is used by PageModules to point to the parent PageObject or PageModule.
It provides webDriver access, this is implemented for PageModules by delegating to the parent and for PageObjects by delegating to the PageBrowser.
All calls to Locator have an implicit PageReference, allowing the Locator to ask for the Element to search in. When root returns None the full page will be searched.
Helper trait needed to work with locators directly in Suites without using PageObjects.
Helper trait needed to work with locators directly in Suites without using PageObjects.
Normally you don't need this trait.
You should always prefer to use PageObjects in you Suites.
Because each PageModule has two implicit PageReferences, one pointing the PageModule itself, the other one pointing to the parent PageReference, we need two types to allow the compiler to decide which PageReference to use.
Because each PageModule has two implicit PageReferences, one pointing the PageModule itself, the other one pointing to the parent PageReference, we need two types to allow the compiler to decide which PageReference to use.
This type is used to implicit pass "parent" into the PageModule constructor, preventing boilerplace code.
This type is used by UnexpectedPagesFactory.createUnexpectedPages()
This type is used by UnexpectedPagesFactory.createUnexpectedPages()
This type is used by to represent a list of functions returning unexpected pages.
Use this trait if you want to provide a UnexpectedPagesFactory.
Trait for Pages that can be navigated to by using PageBrowser.via()
case class HomePage() extends UrlPage {
val url = "localhost:9000/index.html"
}
via(HomePage())
Trait for Pages that can be navigated to by using PageBrowser.via()
case class HomePage() extends UrlPage {
val url = "localhost:9000/index.html"
}
via(HomePage())
If you use UnexpectedPages.waitPages to implement a waiting page (like a loading screen or "please wait" message) you can implement this trait on the page to change the default wait time the PageBrowser will wait after this page was detected.
If you use UnexpectedPages.waitPages to implement a waiting page (like a loading screen or "please wait" message) you can implement this trait on the page to change the default wait time the PageBrowser will wait after this page was detected.
The default wait time is 500ms.
UnexpectedPages will be checked by PageBrowser.at()
to prevent
running in a timeout when waiting for an expected page.
UnexpectedPages will be checked by PageBrowser.at()
to prevent
running in a timeout when waiting for an expected page.
Unexpected PageObjects have normally no URL, are not implementing UrlPage, but this is not required.
Examples are BrowserErrorPage, "404 File Not Found" or "5xx Server Error" Pages.
Also Error Pages delivered by Load Balancers (for example AWS Elastic Load Balancer or CloudFlare) can be checked here.
There are two groups of unexpected Pages, the first group will cancel the test, the other group will fail the test.
"File not Found" or "Internal Server Error" should cause a test to fail, but "connection refused" should cancel the test because test server is not reachable. This is typically an environment problem, normally not a problem with the test itself.
This class is used to manage the list of UnexpectedPages.
This class is used to manage the list of UnexpectedPages.
Example:
it("should detect browsers connection refused page")
via(UrlPage("http://localhost:65534/"))
UnexpectedPagesFactory.withUnexpectedPages(EmptyUnexpectedPagesFactory()) {
at(BrowserErrorPage())
}
}
You can configure the unexpected pages using a custom DriverFactoryList:
class MyDriverFactoryList extends DefaultDriverFactoryList with UnexpectedPagesFactoryProvider {
override val unexpectedPagesFactory = UnexpectedPagesFactory(cancelTestPages = Seq(() => MyErrorPage()))
}
companion object to create UrlPage instances that are only having an URL.
If you want to use geb-like at checker, use this trait.
Example:
def at(): Unit = { assert(pageTitle == "Expected Page Title") }