I am trying to write a simple test with GEB and Spock. Following is the Page and Spec test:
Page
import geb.Page
class DashboardPage extends Page {
static url = "?root=dashboard"
static at = { pageTitle.text() == "Dashboard Content Area" }
static content = {
pageTitle(wait: 25) { $("div#content-view-title>h1") }
leaderBoardPeriodCombo { $("#leaderboardPeriod") }
//manualsMenu { module(ManualsMenuModule) }
}
def selectLeaderBoardPeriod(periodValue) {
leaderBoardPeriodCombo.value(periodValue)
}
}
Spec Test:
import geb.spock.GebSpec
import pages.DashboardPage
class LeaderboardSpec extends GebSpec {
def "change LeaderBoard type value"() {
when: to DashboardPage
then: at DashboardPage
when: DashboardPage.selectLeaderBoardPeriod("monthly")
then: at DashboardPage
}
}
But i am getting the following error:
groovy.lang.MissingMethodException:
No signature of method: static pages.DashboardPage.selectLeaderBoardPeriod() is applicable for argument types: (java.lang.String) values: [monthly]
Possible solutions: selectLeaderBoardPeriod(java.lang.String)
at specs.LeaderboardSpec.change LeaderBoard type value(LeaderboardSpec.groovy:13)
Results :
Tests in error:
LeaderboardSpec.change LeaderBoard type value:13 MissingMethod No signature of...
Tests run: 1, Failures: 0, Errors: 1, Skipped: 0
The signature of the selectLeaderBoardPeriod it have a parameter. I tried to define explicitly the type as String but i am getting the same error.
Can someone spot what i am doing wrong?
Thank you in advance.
Best Regards
Your spec needs to be something like:
class LeaderboardSpec extends GebSpec {
def "change LeaderBoard type value"() {
when:
def page = to DashboardPage
and:
page.selectLeaderBoardPeriod("monthly")
then:
at DashboardPage
}
}
Related
I am new to writing geb specs for funcational testing and appreciate your help with this issue. I am also new to Groovy, and the "Not Initialized" error might be to do with basic inexperience in that. I am trying to build a module to log me in automatically, at which point I can proceed with further tests, but I receive a geb.error.ModuleInstanceNotInitializedException. Previously, not using a module, I was able to log in to my page using only a spec. I was refactoring this to a module approach based on the answer on rcgeorge23's response here:
How to refactor common Geb test sequences.
The spec:
import spock.lang.Unroll
class FlowSpecs extends GebReportingSpec {
#Unroll
def "setup Spec"() {
given:
to QUserPage
when:
authModule.signIn("mwalle","password")
then:
assert { $("span", "class":"login-text z-label")[3].text() == "mwalle" }
}
the page:
package pages.app
import geb.Page
import AuthModule
class QUserPage extends Page {
static url = "/qsystem/quser"
static at = { title == "QSystem" }
static content = {
authModule { module AuthModule }
}
}
and the module:
import geb.Module
class AuthModule extends Module {
def idUser = js."zk.Widget.\$('\$usr').uuid" + "-real"
def idPass = js."zk.Widget.\$('\$pwd').uuid"
static content = {
loginUser { $("input", id:idUser) }
loginPass { $("input", id:idPass) }
loginButton { $("button",class:"login-button z-button")[0] }
}
void signIn(String username = "mwalle", String password = "password") {
loginUser.value(user)
loginPass.value(pass)
loginButton.click()
}
}
The full error is:
geb.error.ModuleInstanceNotInitializedException: Instance of module class AuthModule has not been initialized. Please pass it to Navigable.module() or Navigator.module() before using it.
at geb.Module.uninitializedException(Module.groovy:757)
at geb.Module.getJs(Module.groovy:96)
at AuthModule.<init>(AuthModule.groovy:5)
at geb.navigator.AbstractNavigator.module(AbstractNavigator.groovy:356)
at geb.content.NavigableSupport.module(NavigableSupport.groovy:207)
at geb.content.PageContentTemplateFactoryDelegate.module(PageContentTemplateFactoryDelegate.groovy:31)
at pages.app.QUserPage._clinit__closure2$_closure3(QUserPage.groovy:12)
at pages.app.QUserPage._clinit__closure2$_closure3(QUserPage.groovy)
at geb.content.PageContentTemplate.invokeFactory(PageContentTemplate.groovy:97)
at geb.content.PageContentTemplate.create_closure1(PageContentTemplate.groovy:59)
at geb.content.PageContentTemplate.create_closure1(PageContentTemplate.groovy)
at geb.content.PageContentTemplate.create(PageContentTemplate.groovy:82)
at geb.content.PageContentTemplate.get(PageContentTemplate.groovy:54)
at geb.content.DefaultPageContentSupport.getContent(DefaultPageContentSupport.groovy:42)
at geb.content.PageContentSupport.propertyMissing(PageContentSupport.groovy:39)
at geb.Page.propertyMissing(Page.groovy:112)
at geb.Browser.propertyMissing(Browser.groovy:216)
at geb.spock.GebSpec.propertyMissing(GebSpec.groovy:60)
at FlowSpecs.setup Spec(FlowSpecs.groovy:23)
The problem are these lines
def idUser = js."zk.Widget.\$('\$usr').uuid" + "-real"
def idPass = js."zk.Widget.\$('\$pwd').uuid"
js needs an initialized navigator, as you can see with at geb.Module.getJs(Module.groovy:96)
I would strongly advise to use another selector (css or otherwise) if you can instead of using javascript to lookup the id. If you cannot then move the lookup code into the content block.
static content = {
loginUser { $("input", id: js."zk.Widget.\$('\$usr').uuid" + "-real") }
loginPass { $("input", id: js."zk.Widget.\$('\$pwd').uuid") }
loginButton { $("button",class:"login-button z-button")[0] }
}
I'm writing a Geb test and I want to use a parameterized module, but I can't seem to get it working.
This is my page object:
class CreateNewOrganizationPage extends Page {
static url = "/organization/create"
static content = {
organizationTypes { module MultiSelect, id: "orgTypeIds" }
}
}
And this is my module:
class MultiSelect extends Module {
def id
static content = {
caret { $("#" + id + "-caret") }
}
}
And this is how I use it in a test:
when:
to CreateNewOrganizationPage
organizationTypes.caret.click()
It seems to be the same as the situation on this site:
http://swalsh.org/blog/2014/06/25/groovy-browser-automation-with-geb/
What am I doing wrong here? Because I get the following exception in the stacktrace:
groovy.lang.MissingMethodException: No signature of method: geb.content.PageContentTemplateFactoryDelegate.module() is applicable for argument types: (java.util.LinkedHashMap, java.lang.Class) values: [[id:orgTypeIds], class pages.management.MultiSelect]
Possible solutions: module(java.lang.Class), module(java.util.Map, java.lang.Class), module(geb.Module), module(java.lang.Class, java.lang.Object), module(java.util.Map, java.lang.Class, geb.navigator.Navigator), dump()
at geb.content.PageContentTemplateFactoryDelegate.module(PageContentTemplateFactoryDelegate.groovy:49)
at pages.management.CreateNewOrganizationPage._clinit__closure1$_closure3(CreateNewOrganizationPage.groovy:43)
at pages.management.CreateNewOrganizationPage._clinit__closure1$_closure3(CreateNewOrganizationPage.groovy)
at geb.content.PageContentTemplate.invokeFactory(PageContentTemplate.groovy:97)
at geb.content.PageContentTemplate.create_closure1(PageContentTemplate.groovy:59)
at geb.content.PageContentTemplate.create_closure1(PageContentTemplate.groovy)
at geb.content.PageContentTemplate.create(PageContentTemplate.groovy:82)
at geb.content.PageContentTemplate.get(PageContentTemplate.groovy:54)
at geb.content.DefaultPageContentSupport.getContent(DefaultPageContentSupport.groovy:42)
at geb.content.PageContentSupport.propertyMissing(PageContentSupport.groovy:39)
at geb.Page.propertyMissing(Page.groovy:112)
at geb.Browser.propertyMissing(Browser.groovy:216)
at geb.spock.GebSpec.propertyMissing(GebSpec.groovy:60)
at ManagementSpec.create new organization(ManagementSpec.groovy:21)
EDIT:
Problem solved:
specialDatePicker { module(new DatePicker(id: "someId")) }
Now it works!
I am trying to re-use a Geb Spec test I wrote in another Geb Spec so I won't need to re-write code. I always need the product number in different pages so I would like to do something similar to the following;
class BasePageGebSpec extends GebReportingSpec {
def firstProductOnBrowsePage(){
when:
to BrowsePage
then:
waitFor { BrowsePage }
productId { $("meta", 0, itemprop: "mpn").#content }
return productID // ???
}
}
And in another GebSpec I wish to use the above firstProductOnBrowsePage like below:
class ProductDetailsPageGebSpec extends BasePageGebSpec {
def "See first products details page"(){
when:
to ProductDetailsPage, productId: firstProductOnBrowsePage()
then:
waitFor { $("h2", class:"title").size() != 0 }
assert true
}
}
Any help would be appreciated,
Thank you!
With traits you can almost get what you want (tests don't work within a trait however). You might also consider creating a spec class that tests the product number for every page you have, and then not worrying about testing this functionality within each individual page's spec class.
trait BasePageGebSpec extends GebReportingSpec {
def testingFirstBrowse() {
waitFor { BrowsePage }
productId { $("meta", 0, itemprop: "mpn").#content }
return productID
}
}
class ProductDetailsPageGebSpec implements BasePageGebSpec {
def firstProductOnBrowsePage(){
when:
to BrowsePage
then:
testingFirstBrowse()
}
}
Add productId as content on the BrowsePage:
class BrowsePage extends Page {
static content = {
productId { $("meta", 0, itemprop: "mpn").#content }
}
}
and then use it in your spec:
class ProductDetailsPageGebSpec extends BasePageGebSpec {
def "See first products details page"(){
when:
to ProductDetailsPage, productId: to(BrowsePage).productId
then:
waitFor { $("h2", class:"title").size() != 0 }
}
}
I work with tests on geb and I have problem. I need to save/print the address of the current page (function SaveUrl()).
Spock Test:
class TestSpec extends GebReportingSpec {
def "Google"() {
given: "go to google.com"
to GooglePage
when: "we at Google home page"
at GooglePage
then: "Search Yahoo"
Search("Yahoo")
SaveUrl()
}
}
GooglePage:
class GooglePage extends Page {
static url = "http://www.google.by"
static at = { $("title").text() == "Google"}
static content = {
theModule { module SearchModule }
}
def Search(String arg0) {
theModule.field.value(arg0)
theModule.search.click()
}
def SaveUrl() {
// need implement
}
}
Modile:
class SearchModule extends Module {
static content = {
field { $("input", name: "q") }
search { $("input", name: "btnK") }
}
}
Please help save/print current URL.
Thank You!
You can use the current url getter on WebDriver class. A WebDriver instance is stored as driver property on Browser. So in a Geb Spock test it is as simple as saying:
driver.currentUrl
EDIT
Since Geb 0.9.3 there is also a current url getter available on Browser.
I created a java interface for my annotation. I am now writing a geb spock test and I would like to print the annotation values so it shows in the gradle report. Is this possible? Here is my test case and let me know if I am doing this wrong
class Checkout extends GebReportingSpec {
#TestCase(someID="12345")
def "A checkout 3-D script"() {
// My test steps.....
}
}
Use StackTraceUtils.sanitize to get the current method and use reflection to iterate through the annotations:
import java.lang.annotation.*
import org.codehaus.groovy.runtime.StackTraceUtils
class Checkout {
#TestCase(someID="12345")
def "yeah a"() {
printTestCaseId()
// My test steps.....
}
def printTestCaseId() {
def stack = StackTraceUtils.sanitize(new Throwable()).stackTrace[1]
def method = getClass().declaredMethods.find { it.name == stack.methodName }
println method
def someID = method.annotations[0].someID()
println someID
assert someID == "12345"
}
}
#Retention (RetentionPolicy.RUNTIME)
#interface TestCase { String someID() }
co = new Checkout()
co."${'yeah a'}"()
The StackTraceUtils is not needed if you are the one iterating through the methods.
spockframework (version "spock-core-1.1-groovy-2.4") is provides way of accessing annotation:
package com.test.integration.spec
import com.test.integration.annotation.Scenario
import com.test.integration.annotation.TestCase
import spock.lang.Specification
#Scenario("AnnotationSpec")
class AnnotationSpec extends Specification {
String scenario
String test_case
def setup() {
scenario = specificationContext.currentSpec.getAnnotation(Scenario).value()
test_case = specificationContext.currentFeature.featureMethod.getAnnotation(TestCase).value()
}
#TestCase("case-001")
def 'spock provides way of accessing annotation'(){
expect:
"AnnotationSpec" == scenario
"case-001" == test_case
}
}