1. My Page Model for Login Page:
import {Selector,t} from "testcafe"
class LoginPage{
constructor(){
this.email= Selector("#email")
this.password= Selector("#password")
this.loginButton =Selector(".new-button")
this.link= Selector("a").withText("Welcome, System Administrator")
this.onscreenmessage = Selector("#main > div.notification.notification-error > div > p")
}
async login(username, password){
var that = this;
await t.typeText(that.email, username)
.typeText(that.password, password)
.pressKey("enter")
.expect(this.link).ok()
console.log("User is able to login successfully")
}
}
export default LoginPage
2. My Data set for login
[
{
"testcasename:": "Test for Non Existing User by username",
"loginusername": "TestUser",
"loginpassword": "I love TestCafe!",
"onscreenmessage": "Invalid Login or password."
},
{
"testcasename:": "Test for Non Existing User by email",
"loginusername": "OliviaPeyton#abc.com",
"loginpassword": "TestCafe is awesome!",
"onscreenmessage": "Invalid Login or password."
},
{
"testcasename:": "Test for Valid User and invalid password",
"loginusername": "Demopreview_admin",
"loginpassword": "TestCafe is awesome!",
"onscreenmessage": "Invalid username/email or password."
}
]
3. Here is how my Tests are written - basically iterating through json file and am expecting to see the testcase name show up in the logs. But get it as undefined.
import { Selector } from 'testcafe';
import {login} from "../helper"
import LoginPage from "../page-object/Login-Page"
const dataSet = require('../test/testdata/login.json')
fixture `Role based access control`
.page `https://demopreview-qa-test-myplace.net/users/sign_in`
const LoginPage = new LoginPage()
dataSet.forEach(userdata => {
test('Executing Tests '${data.testcasename'}', async t => {
await LoginPage.login(userdata.loginusername,userdata.loginpassword);
await t.expect(LoginPage.onscreenmessage.textContent).eql(userdata.onscreenmessage,'Match not found');
});
});
Looking for a pair of eyes to scan and see what I am doing wrong.
You have two typos in your code:
testcasename: instead of testcasename (extra colon) in your .json file.
incorrect variable name in the following code: test('Executing Tests '${data.testcasename'}'.... data instead of userdata
Related
In a Vue component controlling users subsciption to newsletters, I have the fellowing code:
async newSubscriber(event) {
// Validate email
//---------------
if (!this.isEmailValid(this.subscriber_email))
this.subscribeResult = "Email not valid";
else {
// If valid, check if email is not already recorded
//-------------------------------------------------
let alreadyRecorded = false;
let recordedEmails = await this.$apollo.query({ query: gql`query { newslettersEmails { email } }` });
console.log('length ' + recordedEmails.data.newslettersEmails.length);
console.log(recordedEmails.data.newslettersEmails);
for (let i = 0; !alreadyRecorded && i < recordedEmails.data.newslettersEmails.length; i++)
alreadyRecorded = this.subscriber_email === recordedEmails.data.newslettersEmails[i].email;
if (alreadyRecorded)
this.subscribeResult = "Email already recorded";
else {
// If not, record it and warn the user
//------------------------------------
this.$apollo.mutate({
mutation: gql`mutation ($subscriber_email: String!){
createNewslettersEmail(input: { data: { email: $subscriber_email } }) {
newslettersEmail {
email
}
}
}`,
variables: {
subscriber_email: this.subscriber_email,
}
})
.then((data) => { this.subscribeResult = "Email recorded"; })
.catch((error) => { this.subscribeResult = "Error recording the email: " + error.graphQLErrors[0].message; });
}
}
}
At the very first email subscription test, $apollo.query returns me the correct number of emails already recorded (let's say, 10) and record the new subscriber email. But if I try to record a second email without hard refreshing (F5) the browser, $apollo.query returns me the exact same result than the first time (10), EVEN IF the first test email has been correctly recorded by strapi (graphql palyground showns me the added email with the very same query!). Even if I add ten emails, apollo will always return me what it got during its first call (10 recorded emails), as if it uses a buffered result. Of course, that allows Vue to record several times the same email, which I obviously want to avoid!
Does it speaks to anyone ?
After a lot of Google digging (giving the desired results by simply changing in my requests, at the end, "buffering" by "caching" !), I understood that Apollo cache its queries by default (at least, in the configuration of the Vue project I received). To solve the problem I just added "fetchPolicy: 'network-only'" to the query I make:
let recordedEmails = await this.$apollo.query({
query: gql`query { newslettersEmails { email } }`,
});
became
let recordedEmails = await this.$apollo.query({
query: gql`query { newslettersEmails { email } }`,
fetchPolicy: 'network-only'
});
And problem solved ^^
Hi i got this error when i try to launch my test.
Please help me to see why it can't click on my submit button
geb.error.RequiredPageContentNotPresent: The required page content 'loginButton - SimplePageContent (owner: LoginPage, args: [], value: null)' is not present
Below my LoginPage
import geb.Page
import pages.IndexPage
class LoginPage extends Page {
static url = "login/auth"
static at = { title == "[Paynum] Identification" }
static content = {
loginForm { $("form") }
loginButton { $("input", type: "submit") }
}
}
Below my test page
import geb.spock.GebReportingSpec
import pages.*
import spock.lang.Stepwise
#Stepwise
class FactControllerSpec extends GebReportingSpec {
def "invalid login"() {
given: "I am at the login page"
to LoginPage
when: "I am entering invalid password"
loginForm.j_username = "bba"
loginForm.j_password = "Bocxy1990"
loginButton.click()
then: "I am being redirected to the login page, the password I entered is wrong"
at LoginPage
loginForm.j_username == "bba"
!loginButton.j_password
}
}
And here a snippet of my submit button
<div>
<button id='submit' type='submit'>
<em class='fa fa-sign-in fa-lg'></em>
<g:message code='springSecurity.login.button' />
</button>
</div>
loginButton { $("input", type: "submit") }
should be
loginButton { $("button", type: "submit") } or probably better would be
loginButton { $("button#submit") } which means find me a button with an id equal to submit.
My code is below can you help me to check it out?
This is a starter code that was given, it should be a function that signs a user up:
function signUpUser()
{
//alert("clicked button");
//creates new Parse user to be saved to database
var user = new Parse.User();
//grabs the information from our form using jQuery
var username = $("#loginInput").val();
var password = $("#password").val();
//sets the username and password for the User
user.set("username", username.toString());
user.set("password", password.toString());
//can add extra information to user, attributes do not have to be defined beforehand
user.set("favoriteColor", $("#favCol").val());
//user.set("website", "http://www.google.com");
//user.set("email", "email#example.com");
//call signup function to add user to database
user.signUp(null,
{
success: function(user)
{
// Hooray! Let them use the app now.
alert("Successful Signup, you are now logged in");
user.logIn(); //sets Parse.User.currentUser() to be the user variable
},
error: function(user, error)
{
// Show the error message somewhere and let the user try again.
alert("Error: " + error.code + " " + error.message);
}
});//close user.signup
} //closes signUpUser function
So I'm using Angularfire in an ionic app and trying to figure out how to make a user object that is associated with the auth data from an Auth $createUser call. My first try had the auth call and the user got authenticated, then a user object was made and pushed into a $firebaseArray which works fine, but I don't know how to grab the current user after they are logged in to update, destory, or do anything with that users data. I have made it work with looping through the users array and matching the uid from the user array item and the auth.uid item which was set to be the same in the user array object creation. This seems really ineffecient to loop over if there is a large user array and it needs to be done on multiple pages.
My current attempt is using a different method like so:
angular.module('haulya.main')
.controller('RegisterController', ['Auth', '$scope', 'User', '$ionicPlatform', '$cordovaCamera','CurrentUserService',
function(Auth, $scope, User, $ionicPlatform, $cordovaCamera, CurrentUserService) {
//scope variable for controller
$scope.user = {};
console.log(User);
$scope.createUser = function(isValid) {
var userModel;
$scope.submitted = true;
//messages for successful or failed user creation
$scope.user.message = null;
$scope.user.error = null;
//if form is filled out valid
if(isValid) {
//Create user with email and password firebase Auth method
Auth.$createUser({
email: $scope.user.email,
password: $scope.user.password
})
.then(function(userData) {
userModel = {
uid: userData.uid,
photo: $scope.user.photo || null,
firstName: $scope.user.firstName,
lastName: $scope.user.lastName,
email: $scope.user.email,
cell: $scope.user.cell,
dob: $scope.user.dob.toString(),
city: $scope.user.city,
state: $scope.user.state,
zip: $scope.user.zip
}
// add new user to profiles array
User.create(userModel).then(function(user) {
$scope.sharedUser = User.get(user.path.o[1]);
});
$scope.user.message = "User created for email: " + $scope.user.email;
})
.catch(function(error) {
//set error messages contextually
if(error.code == 'INVALID_EMAIL') {
$scope.user.error = "Invalid Email";
}
else if(error.code == 'EMAIL_TAKEN'){
$scope.user.error = "Email already in use, if you think this is an error contact an administrator";
}
else {
$scope.user.error = "Fill in all required fields";
}
});
}
};
//Get profile pic from camera, or photo library
$scope.getPhoto = function(type) {
$ionicPlatform.ready(function() {
//options for images quality/type/size/dimensions
var options = {
quality: 65,
destinationType: Camera.DestinationType.DATA_URL,
sourceType: Camera.PictureSourceType[type.toUpperCase()],
allowEdit: true,
encodingType: Camera.EncodingType.JPEG,
targetWidth: 100,
targetHeight: 100,
popoverOptions: CameraPopoverOptions,
saveToPhotoAlbum: false
};
//get image function using cordova-plugin-camera
$cordovaCamera.getPicture(options)
.then(function(photo) {
$scope.user.photo = photo;
}, function(err) {
console.log(err);
});
});
};
}]);
And here's the service the controller is using:
angular
.module('haulya.main')
.factory('User', function($firebaseArray) {
var ref = new Firebase('https://haulya.firebaseio.com');
var users = $firebaseArray(ref.child('profiles'));
var User = {
all: users,
create: function(user) {
return users.$add(user);
},
get: function(userId) {
return $firebaseArray(ref.child('profiles').child(userId));
},
delete: function(user) {
return users.$remove(user);
}
};
return User;
});
This also works, but again I don't have a solid reference to the currently logged in users object data from the array. The objects id is only stored on the controllers scope.
I looked through other posts, but they were all using older versions of firebase with deprecated methods.
If you're storing items that have a "natural key", it is best to store them under that key. For users this would be the uid.
So instead of storing them with $add(), store them with child().set().
create: function(user) {
var userRef = users.$ref().child(user.uid);
userRef.set(user);
return $firebaseObject(userRef);
}
You'll note that I'm using non-AngularFire methods child() and set(). AngularFire is built on top of Firebase's regular JavaScript SDK, so they interoperate nicely. The advantage of this is that you can use all the power of the Firebase JavaScript SDK and only use AngularFire for what it's best at: binding things to Angular's $scope.
Storing user data is explained in Firebase's guide for JavaScript. We store them under their uid there too instead of using push(), which is what $add() calls behind the scenes.
I am currently building an Twitter client application for campus project using Codeigniter and Elliot Haughin Twitter library. It's just a standard application like tweetdeck. After login, user will be directed to the profile page containing timline. I am using Jquery to refresh the timeline every 20 second. At the beginning, everything run smoothly until i found the following error at the random time :
![the error][1]
A PHP Error was encountered
Severity: Notice
Message: Undefined property: stdClass::$request
Filename: libraries/tweet.php
Line Number: 205
I already search the web about this error but can't find satisfied explanation. So I tried to find it myself and found that the error comes out because credentials validation error. I tried to var_dump the line $user = $this->tweet->call('get', 'account/verify_credentials'); and resulting an empty array. My question is how come this error showed up when user already login and even after updated some tweets? is there any logical error in my script or is it something wrong with the library? Could anyone explain whats happening to me? please help me...
Here's my codes:
The Constructor Login.php
<?php
class Login extends CI_Controller
{
function __construct()
{
parent::__construct();
$this->load->library('tweet');
$this->load->model('login_model');
}
function index()
{
$this->tweet->enable_debug(TRUE); //activate debug
if(! $this->tweet->logged_in())
{
$this->tweet->set_callback(site_url('login/auth'));
$this->tweet->login();
}
else
{
redirect('profile');
}
}
//authentication function
function auth()
{
$tokens = $this->tweet->get_tokens();
$user = $this->tweet->call('get', 'account/verify_credentials');
$data = array(
'user_id' => $user->id_str,
'username' => $user->screen_name,
'oauth_token' => $tokens['oauth_token'],
'oauth_token_secret' => $tokens['oauth_token_secret'],
'level' => 2,
'join_date' => date("Y-m-d H:i:s")
);
//jika user sudah autentikasi, bikinkan session
if($this->login_model->auth($data) == TRUE)
{
$session_data = array(
'user_id' => $data['user_id'],
'username' => $data['username'],
'is_logged_in' => TRUE
);
$this->session->set_userdata($session_data);
redirect('profile');
}
}
}
profile.php (Constructor)
<?php
class Profile extends CI_Controller
{
function __construct()
{
parent::__construct();
$this->load->library('tweet');
$this->load->model('user_model');
}
function index()
{
if($this->session->userdata('is_logged_in') == TRUE)
{
//jika user telah login tampilkan halaman profile
//load data dari table user
$data['biography'] = $this->user_model->get_user_by_id($this->session->userdata('user_id'));
//load data user dari twitter
$data['user'] = $this->tweet->call('get', 'users/show', array('id' => $this->session->userdata('user_id')));
$data['main_content'] = 'private_profile_view';
$this->load->view('includes/template', $data);
}
else
{
//jika belum redirect ke halaman welcome
redirect('welcome');
}
}
function get_home_timeline()
{
$timeline = $this->tweet->call('get', 'statuses/home_timeline');
echo json_encode($timeline);
}
function get_user_timeline()
{
$timeline = $this->tweet->call('get', 'statuses/user_timeline', array('screen_name' => $this->session->userdata('username')));
echo json_encode($timeline);
}
function get_mentions_timeline()
{
$timeline = $this->tweet->call('get', 'statuses/mentions');
echo json_encode($timeline);
}
function logout()
{
$this->session->sess_destroy();
redirect('welcome');
}
}
/** end of profile **/
Default.js (The javascript for updating timeline)
$(document).ready(function(){
//bikin tampilan timeline jadi tab
$(function() {
$( "#timeline" ).tabs();
});
//home diupdate setiap 20 detik
update_timeline('profile/get_home_timeline', '#home_timeline ul');
var updateInterval = setInterval(function() {
update_timeline('profile/get_home_timeline', '#home_timeline ul');
},20*1000);
//user timeline diupdate pada saat new status di submit
update_timeline('profile/get_user_timeline', '#user_timeline ul');
//mention diupdate setiap 1 menit
update_timeline('profile/get_mentions_timeline', '#mentions_timeline ul');
var updateInterval = setInterval(function() {
update_timeline('profile/get_mentions_timeline', '#mentions_timeline ul');
},60*1000);
});
function update_timeline(method_url, target)
{
//get home timeline
$.ajax({
type: 'GET',
url: method_url,
dataType: 'json',
cache: false,
success: function(result) {
$(target).empty();
for(i=0;i<10;i++){
$(target).append('<li><article><img src="'+ result[i]['user']['profile_image_url'] +'">'+ result[i]['user']['screen_name'] + ''+ linkify(result[i]['text']) +'</li></article>');
}
}
});
}
function linkify(data)
{
var param = data.replace(/(^|\s)#(\w+)/g, '$1#$2');
var param2 = param.replace(/(^|\s)#(\w+)/g, '$1#$2');
return param2;
}
That's the codes. Please help me. After all, I really appreciate all comments and explanation from you guys. Thanks
NB: sorry if i had bad English grammar :-)
You are making a call to statuses/home_timeline which is an unauthenticated call. The rate limit for unauthenticated calls is 150 requests per hour.
Unauthenticated calls are permitted 150 requests per hour.
Unauthenticated calls are measured against the public facing IP of the
server or device making the request.
This would explain why you see the problem at the peak of your testing.
With the way you have it setup you would expire your rate limit after 50 minutes or less.
I suggest changing the interval to a higher number, 30 seconds would do. That way you'll be making 120 requests per hour and under the rate limit.