I have an application developed in ggts with grails/groovy and there are users with different roles. I want to test if a user can access some parts of the application by directly inserting link into address bar. So, where is my problem? When I test my application on localhost, everything is OK. But when I want to test through http://shopapp then it isn't OK. The application is the same.
Here is my code:
LoginSpec.groovy
import geb.spock.GebReportingSpec
import spock.lang.*
import pages.*
#Stepwise
class LoginSpec extends GebReportingSpec {
def "opage"() {
when:
to LoginPage
loginUser()
acceptButton.click()
then:
to ProductPage
}
}
ProductPage.groovy
package pages
import geb.Browser
import grails.util.Holders
class ProductPage extends ScaffoldPage {
def config = org.codehaus.groovy.grails.commons.ConfigurationHolder.config
static url = {config.grails.serverURL + "/shop/catalog/show/123"}
static at = {
waitFor { title ==~ /Products/ }
title ==~ /Products/
}
static content = {
}
}
config.grails.serverURL should be http://shopapp.
When I start the test, it opens http://shopapp/login, the user logs in and the home page opens. But then it stays on home page. It should go to http://shopapp/shop/catalog/show/123 because I want to test if a user can access a product by directly inserting a link into address bar.
Please help, I don't have any more ideas.
Thanks.
The static url property should be a string, not a closure:
static url = config.grails.serverURL + "/shop/catalog/show/123"
Related
This is the page object.
package myapp.pages
import geb.Page
class LoginPage extends Page {
static url = "http://localhost:8080/login/auth"
//static at = {title.contains("Login")}
static at = {
waitFor {title.contains("Login")} // Add waitFor here to verify on page
}
static content = {
loginForm { $( 'form') }
usernameField { $('form').userName }
passwordField { $('form').password }
submitButton { $('input#submit' )}
}
void loginSubmit(String email, String password) {
usernameField = "email#something.com"
assert $('form').username == "email#something.com"
passwordField = "secret"
assert $('form').password == "secret"
submitButton.click()
}
}
And this is the LoginSpec test file
package myapp.login
import geb.spock.GebSpec
import grails.testing.mixin.integration.Integration
import grails.transaction.*
import myapp.pages.LoginPage
#Integration
#Rollback
class LoginSpec extends GebSpec {
def setup() {
}
def cleanup() {
}
void "user successfully logs in, is redirected to homepage"() {
given:
to LoginPage
when:
LoginPage.loginSubmit("email#something.com", "secret")
then:
title.contains("Dashboard")
}
}
When i run this test, I get the following error:
groovy.lang.MissingMethodException: No signature of method: static myapp.pages.LoginPage.loginSubmit() is applicable for argument types: (java.lang.String, java.lang.String) values: [email#something.com.com, secret]
I basically get the same error when I hardcode the username and password into the login page loginsubmit function. The selectors are fine, when I use the same selectors directly in the LoginSpec test to set the username and password, the test passes. The issue only occurs when I try to use the page object.
Instead of this:
when:
LoginPage.loginSubmit("email#something.com", "secret")
Use this:
when:
loginSubmit("email#something.com", "secret")
The issue isn't really a Geb one. The JVM doesn't allow you to invoke an instance method on a class reference as the context necessary to carry out that invocation wouldn't exist. loginSubmit is an instance method, not a static method.
I hope that helps.
Geb remembers the current page and automatically dispatches method calls to the page, so you do not need to include the page class name: loginSubmit("email#something.com", "secret") in the test will call the method on the page.
This question already has answers here:
Angular2 Beta dependency injection
(3 answers)
Closed 7 years ago.
I am using angular2 Beta. and getting error when using the #Inject annotation to DI my one service to another, not able to figure out where I am wrong. Everything seem to be as per Angular2 documentation.
I am using a cloud based data-services - CloudDB - for my application's data needs.
CloudDB gives me a javascript based client library that I can include in my js app and use to do CRUD operations in my cloudDB database or call other custom API I have stored in my CloudDB account, like UserAuth API (API to authenticate user's credentials).
Before using cloudDB js client lib API , I need to supply my cloudDB account's URL and authKey by calling CloudDB js object's getClient method.
In my angualar2 app, I created a injectable service class - CloudDBProvider - the would store my CloudDB account URL and authKey and call CloudDB.getClient to set the provider's js client object for my CloudDB account.
import {Injectable} from 'angular2/angular2';
///<reference path="../typeDefs/CloudDB.d.ts" /> //typedef of CloudDB js library
#Injectable()
export class CloudDBProvider {
private cloudDBClient: CloudDB.JSClient;
public get cloudDBClient(): CloudDB.JSClient {
return this.cloudDBClient;
}
constructor() {
this.cloudDBClient = new CloudDB.getClient(
"https://myaccount.CloudDB.com/",
"AcfdsfmyDdCMHeadfsdsdfHdsf68" // account authKey
);
}
}
Now, I want to create a UserUtils service in this angular2 app, to which I want to inject above class to get cloudDBClient object. I coded UserUtils service class like below, as learnt from your tutorial
import {Injectable, Inject} from 'angular2/angular2';
import {CloudDBProvider} from './CloudDBProvider';
#Injectable()
export class UserUtils {
private _userDetails: Object = {};
private _cloudDBProvider: CloudDBProvider;
private _cloudDBClient: Microsoft.WindowsAzure.MobileServiceClient;;
constructor( #Inject(CloudDBProvider) cloudDBPrvdr: CloudDBProvider) {
this._cloudDBProvider = cloudDBPrvdr;
this._cloudDBClient = this._cloudDBProvider.cloudDBClient; //the public getter property in the class CloudDBProvider
}
public authenicateUser(p_strUserName: string, p_strUserPassword: string) {
var p: Promise<any> = new Promise(
(resolve: (result: any) => void, reject: (err: any) => void) =>
this._cloudDBClient.userlogin(p_strUserName, p_strUserPassword).done( //using API 'userlogin' of cloudDB to authenticate user against my cloudDB's users table.
(loginResult) => {
alert("from Userutils - You are now logged in as: " + loginResult.user.basicProfile.firstName);
resolve(loginResult);
},
(loginErr: any) => {
alert("Error: " + loginErr.request.responseText);
reject(loginErr);
}
)
);
return p;
}
}
then I am trying to use UserUtils in my LoginPage component like below:
import {Component} from 'angular2/core';
import {WelcomePage} from "../views/welcome/welcome";
import {UserUtils} from "../services/UserUtils";
#Component({
templateUrl: 'app/login/login.html',
providers: [UserUtils]
})
export class LoginPage {
private _userUtils: UserUtils;
constructor( userUtils: UserUtils) {
this._userUtils = userUtils;
}
public loginButtonClicked(event, userName, password) { //called when Login Button is clicked by user
//...
//... to-do field value verification
//...
this._userUtils.authenicateUser(userName, password).then(
(result) => {
//navigate to WelcomePage
},
(err) => { alert(err); }
);
}
}
the component LoginPage doesn't work when I use UserUtils. The browser console throws error - No provider for CloudDBProvider! (LoginPage -> UserUtils -> CloudDBProvider)
Note that, if I move the 'authenicateUser' method from UserUtils to CloudDBProvider directly and use CloudDBProvider in LoginPage component for user authentication, then everything works just fine, user gets authenticated and navigated to welcome page after login. Also, no error is thrown and app working if I remove #Inject(CloudDBProvider) cloudDBPrvdr from UserUtils's constructor obviously I cannot use CloudDBProvider then in UserUtils, but point is app doesn't throw any error, which means something is wrong with #Inject.
any clue where I am going wrong?
Upto my Understanding your mistake is in the imports change the import of Injectablewith this
import {Component, Inject, Injectable} from 'angular2/core';
also accoriding to me when we have used #injectable annotation no need to use #inject in the constructor you simply put your service with the public identifier and can use that service into any another method of the same class.
Perhaps you could add the CloudDBProvider provider in the list of providers of your component:
#Component({
templateUrl: 'app/login/login.html',
providers: [UserUtils, CloudDBProvider]
})
export class LoginPage {
(...)
}
Or at application level within the second parameter of the bootstrap function:
bootstrap(MainComponent, [CloudDBProvider]);
This answer could give you some additional hints: Angular2 Beta dependency injection.
Hope it helps you,
Thierry
My web-app utilizes Geb for functional testing.
It is a non-english application, all page messages being received from i18n message bundle.
How to make Geb work with internationalized messages?
The Grails RemoteControl plugin allows remote access to a running Grails application. In a functional test setting it can be used to read and change configuration settings, access the application context including the message source, … .
The code below is added to a common base class for all our Geb specifications/tests that can be used in an individual test to retrieve an internationalized message:
class BaseTest/Spec {
RemoteControl remoteControl = new RemoteControl()
String msg(String msgKey, args = null, locale = defaultLocale) {
if (args != null) {
args = args as Object[]
}
return remoteControl.exec {
ctx.messageSource.getMessage(msgKey, args, locale)
}
}
}
All my page classes extend from base class: ScaffoldPage
import java.util.ResourceBundle;
import geb.Page
class ScaffoldPage extends Page {
static content = {
resourceBundle {
ResourceBundle bundle = new PropertyResourceBundle(new InputStreamReader(new FileInputStream('./grails-app/i18n/messages_ru.properties'), "UTF-8"))
bundle
}
}
}
Then, at a certain page, I use a construction like this:
class CreatePayeePage extends ScaffoldPage {
static at = {
title == resourceBundle.getString('payee.title.create.label')
}
}
I have a secured grails application with the spring security plugin and right now I am trying to do some tests with the login process with no success till now. Has anybody an idea of what is the problem?
This is my LoginPage.groovy
package pages.login
import geb.Page
class LoginPage extends Page {
static url = "login/auth"
static at = {
title ==~ /Login/
}
static content = {
loginForm { $("form") }
username { $("input", type:"text", name:"j_username") }
password { $("input", type:"password", name:"j_password") }
loginButton{ $("input", type:"submit", value:"Login") }
}
}
And this is the test using junit4:
import geb.junit4.GebReportingTest
import pages.copyright.*
import pages.login.LoginPage
import org.junit.Test
class CopyrightCRUDTests extends GebReportingTest {
#Test
void doSomeCrud() {
to LoginPage
at LoginPage
$("form").j_username() << "admin"
$("form").j_password() << "XXXXX"
loginButton.click()
to AuthenticatedPage
at AuthenticatedPage
}
}
The AuthenticatedPage is a page which needs authentication, but in this moment it is imposible to be authenticated using geb. Does anybody know anything about this issue?
Thanks in advance!
Try rewriting doSomeCrud() as follows:
to LoginPage
loginForm.j_username = 'admin'
loginForm.j_password = 'XXXXX'
loginButton.click()
waitFor { at AuthenticatedPage }
I don't know if this will help you since you are not using Spock, but I had a few issues with login as well (can't remember exactly what though)
I eventually found this code that I put in a spec extending GebSpec.
This gets called before each of the tests requiring a login:
def setupSpec() {
Browser.drive {
go baseUrl
$("form.login").with {
username = System.getenv("APP_USERNAME")
password = System.getenv("APP_PASSWORD")
}
$("input[name='submit']").click()
}
}
It doesn't seem like much, but the use of 'with' on the form worked for me.
Hi i have looked up a lot of answers but havnt been able to fix my problem. I am using external actionscript and i have used the following code:
package
{
import flash.display.MovieClip;
import flash.net.*;
import flash.events.*;
import flash.display.Loader;
import fl.motion.MotionEvent;
import flash.ui.Mouse;
public class submenu1 extends MovieClip
{
private var movieLoader:Loader;
//everything in this function is exicuted when you start the application
public function submenu1()
{
movieLoader = new Loader();
image3_btn.addEventListener(MouseEvent.MOUSE_DOWN,addMovie);
image4_btn.addEventListener(MouseEvent.MOUSE_DOWN,addMovie);
exit_btn.addEventListener(MouseEvent.MOUSE_DOWN,closeTheMovie);
}
private function addMovie(e:MouseEvent)
{
if(e.target.name=="image3_btn")
{
loadTheMovie("image3");
}
else if(e.target.name=="image4_btn")
{
loadTheMovie("image4");
}
}
private function loadTheMovie(m:String)
{
var movieRequest:URLRequest = new URLRequest("../swf/" + m + ".swf");
movieLoader.load(movieRequest);
addChild(movieLoader);
}
private function closeTheMovie (e:MouseEvent)
{
removeChild(movieLoader);
exit_btn.addEventListener(MouseEvent.MOUSE_DOWN,closeTheMovie);
}
}
}
I can get the sub movie to open but i cant get the exit_btn to close the sub movie and return to the original. I am wanting the exit_btn when clicked to remove the child and take you back to the texture page. The flash itself doesn't bring up any errors just the button wont work. Any suggestions?
Did you export to actions script your exit buttons? Right click on the exit button then choose properties and then click on the box called export for actionScript.