I would like to pass a value to the input fied, in the test case. however this is not working. Below is my code.
class Mypage extends Page {
static content = {
inputfield { withFrame ("myFrame") {$('input',name:'myInputField') }
}
}
}
Then tested it this way:
given:
String thevalue = "hello"
then:
to Mypage
and:
inputfield >> thevalue
With this code I get the
StaleElementReference error and the chrome driver information
I then tried the following by putting the thevalue variable in Mypage class:
class Mypage extends Page {
public String thevalue = "hello"
static content = {
inputfield { withFrame ("myFrame")
{$('input',name:'myInputField') }
}
}
}
Then tested it the same way with no given:
then:
to Mypage
and:
inputfield >> thevalue
I Still get the same error.
I then tried a third form:
class Mypage extends Page {
//public String thevalue = "hello"
static content = {
inputfield { withFrame ("myFrame")
{ thevalue -> $('input',name:'myInputField').value(thevalue ) }
}
}
}
Then tested it in 2 ways:
then:
to Mypage
and:
inputfield("hello")
and this way:
then:
to Mypage
and:
inputfield >> "hello"
The only way which is working is when I pass the value directly in the class
inputfield { withFrame ("myFrame")
{ $('input',name:'myInputField').value("hello") }
But the goal is to the pass the value in the test. How do I do that
If you really don't want to follow Rushby's suggestion and stick to the path you shown in your question then the following will work:
class Mypage extends Page {
static content = {
inputfield { thevalue ->
withFrame ("myFrame") {
$('input',name:'myInputField').value(thevalue)
}
}
}
}
and
then:
to Mypage
and:
inputfield("hello")
If you follow the Geb example from The Book of Geb you have your page and it contains an iframe. The iframe in the example has its own page object:
class PageWithFrame extends Page {
static content = {
myFrame(page: FrameDescribingPage) { $('#frame-id') }
}
}
//This is your iframe page object
class FrameDescribingPage extends Page {
static content = {
myTextField { $('input',name:'myInputField') }
}
}
Now to interact with it, you do this within your test method:
def "my test method"() {
when:
to PageWithFrame
withFrame(myFrame) {
myTextField.value("whatever")
}
//etc
}
Related
I try to click html css 'a' but I cant access to it. How can I to do?
at test
waitFor { myelement.displayed }
myelement.click()
class test extends Page {
static at = { title == "test page" }
static content = {
myelement {$("a", id: "myid")}
}
}
You should be able to access it directly using the ID. I think your syntax is incorrect, try using the ID selector instead: $("#myId")
I have the following setup:
class LoginPage extends Page {
def login() { //fill user/pass, click "login"}
}
class IndexPage extends Page {
static content = {
sideTabs { module SideTabs }
}
}
class TabAPage extends Page {
//...
}
class SideTabs extends Module {
static content = {
tabA(to: TabAPage) { $(".sidetab-label", text: "tab A") }
}
}
class TabALoginSpec extends GebReportingSpec {
def setup() {
to LoginPage
}
def "test foo"() { /* ... */ }
def "test bar"() {
when:
login()
// report "after login"
at IndexPage
sideTabs.tabA.click()
//...
then:
// ...
}
}
When I execute "test bar", I get:
geb.error.RequiredPageContentNotPresent: The required page content 'IndexPage -> sideTabs: SideTabs -> tabA: geb.navigator.EmptyNavigator' is not present
When I execute "test bar" and uncomment the report line, test passes.
So I'm guessing the problem lies in "at IndexPage" returning before the page has finished loading. I don't think login() should wait on any content, because if the login fails, then there's no content loading issue, and if login succeeds - the page transitions to Index. I've attempted adding wait:true to tabA's content definition, to no avail.
Funnily, on the screenshots geb produces in the wake of "test bar"'s failure, I can actually spot the tabA element...
Help appreciated.
Update:
adding
void onLoad(Page previousPage) {
waitFor { sideTabs.tabA }
}
to IndexPage seems to iron-out the problem so-far. I'm unclear why adding wait:true to the content definition did not yield the same result.
Adding a required:false should work but placed here:
class SideTabs extends Module {
static content = {
tabA(required:false, to: TabAPage) { $(".sidetab-label", text: "tab A") }
}
}
If you don't want to wait for all of the content to load before interacting with the page then use required: false when defining your content.
e.g.
class IndexPage extends Page {
static content = {
sideTabs(required: false) { module SideTabs }
}
}
The intended use of the required statement is for hidden content that can be made visible after page interaction. But it should help in this scenario.
Good practice is to add the at in the IndexPage class, check documentation here.
Your class should look like:
class IndexPage extends Page {
static at = {...}
static content = {
sideTabs { module SideTabs }
}
}
I think that using the report slows down the test, causing the page to render correctly.
When i try to run my test i get this Exception:
groovy.lang.MissingPropertyException: Unable to resolve code as content for pages FactIndexPage, or as a property on its Navigator context. Is code a class you forgot to import?
Here my test class
import geb.spock.GebReportingSpec
import pages.*
import spock.lang.Stepwise
#Stepwise
class FactControllerSpec extends GebReportingSpec {
def "test de la presence du code dans la page d'acceuil"() {
given: "test que le champ code de facture est bien present"
when:
to IndexFactPage
then: $("form", name: code).find("input", type: "button")
}
}
And below the class who describe my page content
import geb.Page
class IndexFactPage extends Page {
static url = "/fact/mmapay"
static at = {
$("h2").text() == "Pour régler votre facture, veuillez saisir:" }
static content = {
codeField { $("input[name = code]") }
nomField { $("input[name = nom]") }
prenomField { $("input[name = prenom]") }
montantField { $("input[name = montant]") }
chercher1 { $("input", type: "button") }
abandonner1 { $("input", type: "button") }
}
}
Please help me to resolve my class IndexFactPage as a content page..
Thank you in advance..
The part causing you problems is this $("form", name: code).
$("form", name: "code") will find you a form named code, this may not be what you're after though based on your page and spec snippets.
Without seeing the page source there's no way to provide a proper solution but here's some observations from your IndexFactPage
static content = {
codeField { $("input[name = code]") }
nomField { $("input[name = nom]") }
prenomField { $("input[name = prenom]") }
montantField { $("input[name = montant]") }
chercher1 { $("input", type: "button") }
abandonner1 { $("input", type: "button") }
}
These fields codeField, nomField, prenomField, and montantField all look like they map to individual fields but chercher1 and abandonner1 will select the same button.
Based on what your spec states for it's purpose to be then possibly your spec should look like this -
import geb.spock.GebReportingSpec
import pages.*
import spock.lang.Stepwise
#Stepwise
class FactControllerSpec extends GebReportingSpec {
def "test the presence of the code field on the home page"() {
when: "we are on the home page"
to IndexFactPage
then: "the code field is present"
codeField.present
}
}
I'm getting the following error while running groovy scripts with maven:
Signup Test Happy Path(SignUpPageSpec): The required page content
'usernamefield - SimplePageContent (owner: JiraSignupPage, args: [],
value: null') is not present.
Can anybody help me to resolve this error. Following are scripts:
JiraSignUpPage.groovy
package test.groovy.script
import geb.Page;
//import main.groovy.script.*;
class JiraSignupPage extends Page
{
static url = "/vcty-jira"
static at = { title == "System Dashboard - Velocity Jira" }
static content = {
usernamefield { $("input#login-form-username") }
passwordfield { $('input#login-form-password') }
submitButton(to: JiraSignUpResultPage) { $('button#login-form-submit') }
}
}
JiraSignUpResultPage.groovy
package test.groovy.script
import geb.Page;
public class JiraSignUpResultPage extends Page
{
static url = "/jira/secure/Dashboard.jspa"
static at = { title == "Amit - Jira Tracker" }
}
SignUpPageSpec.groovy
import spock.lang.Stepwise;
import geb.spock.GebReportingSpec;
import geb.Page;
//import main.groovy.script.*;
import test.groovy.script.*;
#Stepwise
public class SignUpPageSpec extends GebReportingSpec {
def "Signup Test Happy Path"() {
given: "I'm at the sign up form"
to JiraSignupPage
when: "I signup as a valid user"
usernamefield = "xyz"
passwordfield = "xyz"
submitButton.click()
then: "I'm at the result page"
at JiraSignUpResultPage
}
}
GebConfig.groovy
import org.openqa.selenium.firefox.FirefoxDriver
import geb.waiting.*;
driver = { new FirefoxDriver() }
baseUrl = "http://172.17.48.65:8080/"
reportsDir = new File("target/geb-reports")
reportOnTestFailureOnly = true
waiting {
timeout = 20
retryInterval = 0.5
}
I'm running mvn.test to run these test. It causes browser to open but ends up with error.
The error tells you that your usernamefield content definition returned an empty navigator - an input with id login-form-username has not been found on the page you navigated to.
Probably your page is not fully loaded.
Try adding usernamefield.displayed to 'at' block
or add 'wait' to page element
usernamefield(wait: true) { $("input#login-form-username") }
I have a page that uses a module for defining form content. It is rather generically usable but needs different resulting pages after form actions have been triggered (button click, etc.).
class CreateOrganisationPage extends Page {
static url = "#contact/organisation/create"
static at = {
form.displayed
}
static content = {
form(wait: true) {
module BusinessEntityFormModule, businessEntityName: 'organisation'
}
}
}
The module implementing the form content contains a UI control saveCommand that requires that a page ViewBusinessEntityPage is navigated to after submitting. In order to keep that module more reusable across different tests I wanted to provide that page as a parameter.
What is the best approach to do so?
class BusinessEntityFormModule extends Module {
String businessEntityName = "entity"
String idPrefix = "edit"
static content = {
self {
def id = "$idPrefix-" + StringUtils.capitalize(businessEntityName)
$("form", id: id)
}
saveCommand(to: ViewBusinessEntityPage) {
$('[data-command="save"]')
}
}
}
Simply define a property for the destination page in your module and use it in the content definition:
class BusinessEntityFormModule extends Module {
Class postSavePage
static content = {
saveCommand(to: postSavePage) {
$('[data-command="save"]')
}
}
}
And then set it when defining the module as part of the page:
class CreateOrganisationPage extends Page {
static content = {
form(wait: true) {
module BusinessEntityFormModule, businessEntityName: 'organisation', postSavePage: ViewBusinessEntityPage
}
}
}