How to navigate to same page before running any test script in GEB SPOCK - selenium

I am creating one automation script using geb spock and groovy. In my test class I have multiple tests and I want to navigate to home page before running any of the test meaning
login to application and navigate to home page (default page after login is home page).
Click on Link1. Check Page.navigate to home page
Click on Link2. Check Page . navigate to home page
Click on Link3. Check Page. navigate to home page...
I created a method and try to reuse it in my geb test but getting the following error:
geb.error.PageInstanceNotInitializedException: Instance of page class pages.Test_HomePage has not been initialized. Please pass it to Browser.to(), Browser.via(), Browser.page() or Browser.at() before using it.
at geb.Page.uninitializedException(Page.groovy:521)
at geb.content.UninitializedPageContentSupport.getContent(UninitializedPageContentSupport.groovy:30)
at geb.content.PageContentSupport.propertyMissing(PageContentSupport.groovy:39)
at geb.Page.propertyMissing(Page.groovy:99)
at pages.Test_HomePage.clickOnHomePage(Test_HomePage.groovy:46)
at com.abc.vcctest.TestNavigationInitialTestSpec.Navigate to Home page of test portal(TestNavigationInitialTestSpec.groovy:44)
Here is my sample geb test:
#TestMixin(GrailsUnitTestMixin)
class TestNavigationInitialTestSpec extends LoginBaseTestSpec {
#Shared
Test_HomePage test_HomePage = new Test_HomePage()
def cleanupSpec() {
browser.close()
}
def setup() {
}
def cleanup() {
}
def navigateToHomePage() {
Test_HomePage test_HomePage = at Test_HomePage
test_HomePage.clickOnHomePage()
at Test_HomePage
}
def "Navigate to Home page of test portal"() {
given:
HomePage homePage = at HomePage
when: "Click on Home tab/link"
navigateToHomePage()
test_HomePage.clickOnHomePage()
def crashDisplayed = test_HomePage.crashPageDisplayed()
then: "You are on Home Page"
!crashDisplayed || { at Test_HomePage }
}
def "Navigate to Change Password page of testportal"() {
given:
at Test_HomePage
when: "Click on Change Password"
test_HomePage.clickOnChangePassword()
Test_ChangePassword test_ChangePassword = at Test_ChangePassword
def crashDisplayed1 = test_ChangePassword.crashPageDisplayed()
then: "You are on Change Password Page"
!crashDisplayed1 || { at Test_ChangePassword }
at Test_ChangePassword
}
This is my Test_HomePage class:
class Test_HomePage extends HomePage2{
static url = '/home'
static at = {
waitFor(message:"The Test Portal title is missing."){driver.title == "Test Portal"}
}
static content = {
pageCrash(required: false, cache: false) { $("h1") }
homePageLink {
$("a[href = '/Link1']")
}
changePasswordLink{
$("a[href='/Link2']")
}
updateEmailLink{
$ ("a[href = '/Link3']")
}
}
void crashPageDisplayed() {
if (pageCrash.isDisplayed()) {
driver.navigate().back()
}
}
void clickOnHomePage() {
homePageLink.click()
}
void clickOnChangePassword(){
changePasswordLink.click()
}
void clickUpdateEmail(){
updateEmailLink.click()
}
}
I am new to geb and spock and I might be doing a very silly mistake but any help would be really appreciated or suggestion to implement this in an effective way.

You should make you feature methods independent of each other, so they can be called in any order. Why don't you put something like to Test_HomePage into your setup() method? Then it will be called at the beginning of each feature method. Even if you do it in the given: block for each single feature method, you still need to before you can check at. I think you should study the Book of Geb a little bit. This is what the error message is trying to explain to you, by the way:
geb.error.PageInstanceNotInitializedException:
Instance of page class pages.Test_HomePage has not been initialized.
Please pass it to Browser.to(), Browser.via(), Browser.page() or Browser.at() before using it.
In navigateToHomePage(), your first command should therefore be:
Test_HomePage test_HomePage = to Test_HomePage

Related

How to check if a href element find in geb

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")

geb: RequiredPageContentNotPresent after login request

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.

Grails 3.0.x Interceptor matchAll().excludes for multiple controllers

Following Grails 3.0.11 Interceptors document, I code my own Interceptors as below:
class AuthInterceptor {
int order = HIGHEST_PRECEDENCE;
AuthInterceptor() {
println("AuthInterceptor.AuthInterceptor(): Enter..............");
// ApiController.index() and HomeController.index() don't need authentication.
// Other controllers need to check authentication
matchAll().excludes {
match(controller:'api', action:'index);
match(controller:'home', action:'index');
}
}
boolean before() {
println "AuthInterceptor.before():Enter----------------->>>>>>";
log.debug("AuthInterceptor.before(): params:${params}");
log.debug("AuthInterceptor.before(): session.id:${session.id}");
log.debug("AuthInterceptor.before(): session.user:${session.user?.englishDisplayName}");
if (!session.user) {
log.debug("AuthInterceptor.before(): display warning msg");
render "Hi, I am gonna check authentication"
return false;
} else {
return true;
}
}
boolean after() {
log.debug("AuthInterceptor.after(): Enter ...........");
true
}
void afterView() {
// no-op
}
}
class P2mController {
def index() {
log.debug("p2m():Enter p2m()..............")
render "Hi, I am P2M";
}
}
When I test http://localhost:8080/p2m/index, from log console, I saw that P2mController.index() is executed without been checked authentication.
However, when I test http://localhost:8080/api/index or http://localhost:8080/home/index, AuthInterceptor.check() is executed and the browser displays
Hi, I am gonna check authentication
I wish P2mController been checked authentication, and HomeController.index() and ApiController.index() don't need to be checked authentication. But from the log and response, the result is opposite.
Where is wrong in my AuthInterceptor ?
You want to do this instead:
matchAll().excludes(controller:'api', action:'index')
.excludes(controller:'home', action:'index')
And don't forget the single-quote after the first 'index'.

Geb cannot see my class as content page

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
}
}

Getting error while running Geb test using spock and maven

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") }