we are working with Page objects in nightwatch to check the login functionality of a js page.And using '#'annotation for accessing elements but these elements are not accessible inside a perform function. Below is the code for reference:
'use strict';
var paths = require('../../../e2e/paths/paths.js');
var loginData = require('../../../e2e/data/loginData.js');
module.exports = {
url: paths.launchPath,
elements: {
username: {
selector: 'input[name^="username"]'
},
},
commands: [{
signIn: function() {
return this
.waitForElementPresent('#headerTitle', 10000)
.api.perform(function() {
var nodeLength = loginData.login.length;
console.log(nodeLength);
this.api.waitForElementPresent('input[name^="username"]', 10000)
for(var i=0; i<nodeLength; i++) {
console.log('Going for iteration # ' + i + loginData.login[i].criteria);
if(loginData.login[i].criteria=='success'){
console.log('success ' + loginData.login[i].criteria + i);
this.api.waitForElementPresent('input[name^="username"]', 10000)
this.api.pause(6000)
this.api.clearValue('input[name^="username"]')
this.api.setValue('input[name^="username"]', loginData.login[i].usernam)
}
}
}
})
}
}]
};
Can anyone help in accessing these elements inside perform function?
Thanks in advance !
Related
I am using the following code to sort the rows of a table based on Ids. I am using Dragula for drag and drop functionality. The Sorted Ids is presented in the variable sortedIDs. The alert present within if(sortedIDs) is showing an alert, but no request is being sent using AJAX.
var container = document.getElementById('tb');
var rows = container.children;
var nodeListForEach = function (array, callback, scope) {
for (var i = 0; i < array.length; i++) {
callback.call(scope, i, array[i]);
}
};
var sortableTable = dragula([container]);
var pingu='';
sortableTable.on('dragend', function() {
nodeListForEach(rows, function (index, row) {
//alert(row.id);
pingu=pingu+','+row.id;
//alert(pingu);
// row.lastElementChild.textContent = index + 1;
// row.dataset.rowPosition = index + 1;
});
var sortedIDs=pingu;
pingu='';
// alert (sortedIDs);
if (sortedIDs) {
alert(sortedIDs);
$.ajax({
type: 'GET',
url: '<?php echo $site_url . 'index.php/API/p2376ghDSPOLWYBdhBT'?>',
data: 'lmqSPOEhyVt87H6tBYSfdreg=' + sortedIDs + '&hjhqweuty87685gh87GCfsc6HF=' + sbds98JWUDGHKJ98yujg,
success: function (tata) {
alert (tata);
if (tata == '1') {
$("#success").show();
$('#success').delay(2000).fadeOut('slow');
} else {
$("#failure").show();
$('#failure').delay(5000).fadeOut('slow');
}
}
});
} else {
//$('#ms').html('<option value="">Select Q level first</option>');
}
});
And when i am adding
error : function(jqXHR, textStatus, errorThrown){
}
for showing AJAX error, it starts throwing the alert too.
Any sort of help would be deeply appreciated.
Thanks
I solved the problem. I forgot to retrieve the value of an attribute and send it to the API.
var sbds98JWUDGHKJ98yujg = $('#p2JMopns3hfBubNNHJeer').val();
A Backbonejs collection has a function to reset a collection for bulk updates. I would like to use this feature in Titanium Alloy when I sync with JSON data from a server but it appears as if this is not being committed/saved to SQLite - I am using an sql adapter.
config: {
columns: {
// stuff
name: "TEXT"
},
adapter: {
type: "sql",
collection_name: "pony",
db_name: Alloy.CFG.db_name
}
}
I have some jasmine tests which keep failing. FYI I have migration script for development that adds 7 items to the collection so that I have something to work with.
describe("pony model", function () {
var Alloy = require("alloy")
data = {name: "My little pony"},
collection,
item;
beforeEach(function(){
collection = Alloy.createCollection('pony');
item = Alloy.createModel('pony');
});
// PASSES
it('can reset all data', function () {
collection.fetch();
expect(collection.length).toEqual(7);
collection.reset(data)
expect(collection.length).toEqual(1);
})
// FAILS
it('saves reset data', function () {
collection.fetch();
expect(collection.length).toEqual(7);
collection.reset(data)
collection.fetch()
expect(collection.length).toEqual(1);
})
afterEach(function () {
item.destroy();
});
})
The way this bug shows in the UI is that when I save that when I sync data with the server the TableView shows the new records then when I go to another view and come back to the same TableView the synced data is gone and replaced with the default data.
The best approach I found (and I shamefully can't remember where I copied the code from) was to do the reset manually. I posted the code to do this: https://gist.github.com/sukima/8321859
Basically I do my own SQL DELETE then a Backbone reset(), then looped INSERT INTO, finally finishing with a backbone trigger("fetch") event. Doing this via backbone's sync was way to slow. And the normal reset() doesn't run sync anyways.
exports.definition = {
config: {
columns: {
// ...
},
adapter: {
type: "sql",
collection_name: "MyModels"
}
},
extendCollection: function(Collection) {
Collection.prototype.destroyAll = function(opt) {
var db = Ti.Database.open(this.config.adapter.db_name);
db.execute("DELETE FROM " + this.config.adapter.collection_name);
db.close();
this.models = [];
if (!opt || !opt.silent) { this.trigger("reset"); }
return this;
};
Collection.prototype.saveAll = function(opt) {
var util = require("alloy/sync/util");
var dbName = this.config.adapter.db_name;
var table = this.config.adapter.collection_name;
var columns = this.config.columns;
var db = Ti.Database.open(dbName);
db.execute("BEGIN;");
this.forEach(function (model) {
if (!model.id) {
model.id = util.guid();
model.attributes[model.idAttribute ] = model.id;
}
var names = [], values = [], q = [];
for (var k in columns) {
names.push(k);
values.push(model.get(k));
q.push("?");
}
var sqlInsert = "INSERT INTO " + table + " (" + names.join(",") + ") VALUES (" + q.join(",") + ");";
db.execute(sqlInsert, values);
});
db.execute("COMMIT;");
db.close();
if (!opt || !opt.silent) { this.trigger("reset"); }
return this;
};
Collection.prototype.refreshFromData = function refreshFromData(data) {
this.destroyAll({silent:true});
this.reset(data, {silent:true});
this.saveAll({silent: true});
this.trigger("fetch");
};
}
};
I wrote my first scriptaculous script to create a slideshow between some div element :
var SlideShow = Class.create({
initialize:function(element, delayStart){
this.element = element;
this.delayStart = delayStart;
this.slides = this.element.childElements();
this.numberOfSlides = this.slides.size();
this.numberActiveSlide = 1;
this.start_slideshow();
},
start_slideshow: function()
{
this.switch_slides.delay(this.delayStart);
},
switch_slides: function()
{
this.slides[this.numberActiveSlide].fade();
if (this.numberActiveSlide == this.numberOfSlides) { this.numberActiveSlide = 1; } else { this.numberActiveSlide = this.numberActiveSlide + 1; }
Effect.Appear.delay(this.slides[this.numberActiveSlide], 850);
this.switch_slides.delay(this.delay + 850);
}
});
document.observe("dom:loaded", function(){
var slideshows = $$('div.slideshow');
slideshows.each(
function(slideshow) {
s = new SlideShow(slideshow, 2);
});
});
But I always get this error and It's been hours I can't figure it out where my problem is!
Undefined is not an object (evaluating this.slides[this.numberActiveSlide]);
Thanks you !
Nick
99% sure it's a context issue. Make sure you bind your function calls so that this is retained throughout your code.
Debug what this is in switch_slides: it should be the same thing as this in start_slideshow. If it's not, bind your call to switch_slides to your instance:
start_slideshow: function()
{
this.switch_slides.bind(this).delay(this.delayStart);
},
You'll probably have to do the same in switch_slides where it calls itself.
I cannot seem to find out why IE does not read my success on get after the post. I have tried cache: false, with no luck. This works in all other browsers, just not IE.
$.ajaxSetup({ cache: false });
num = $('#num').val();
phone = $('#phone').val();
$.post("post.php?"+$("#MYFORM").serialize(), {
}, function(response){
if(response==1 && codeVal == 1 && telVal == 1)
{
$("#after_submit").html('');
$("#Send").after('<label class="success" id="after_submit">Η αποστολή πραγματοποιήθηκε</label>');
change_captcha();
clear_form();
$.ajax({
type:'get',
cache: false,
url: "http://web.somesite/submit_code.php",
dataType: 'html',
data:{ user: "one", pass: "mtwo", source: "WEB", receipt: num, msisdn: phone},
success: function(data) {
var qsFull = "http://web.somesite.gr/submit_code.php?" + data;
var qs = URI(qsFull).query(true);
TINY.box.show({html:qs.message,animate:false,boxid:'error',top:5});
}
});
}
else
{
$("#after_submit").html('');
$("#Send").after('<label class="error" id="after_submit">Error! in CAPTCHA .</label>');
}
});
OK, I tried adding an error after the success and I see that I get my pop up as I should be, but the value of qs.message is 0. Why would I get error and not success, when it is successful in other browsers.
I found the answer, It has to do with IE not being flexible with cross domains and such, so I added a XDomainRequest like so
if (jQuery.browser.msie && window.XDomainRequest) {
var xdr = new XDomainRequest();
var my_request_data = { user: "M1web", pass: "m!", source: "WEB", receipt: num, msisdn: phone};
my_request_data = $.param(my_request_data);
if (xdr) {
xdr.onerror = function () {
alert('xdr onerror');
};
xdr.ontimeout = function () {
alert('xdr ontimeout');
};
xdr.onprogress = function () {
alert("XDR onprogress");
alert("Got: " + xdr.responseText);
};
xdr.onload = function() {
//alert('onload ' + xdr.responseText);
var qsFull = "http://web.web.gr/submit_code.php?" + xdr.responseText;
var qs = URI(qsFull).query(true);
TINY.box.show({html:qs.message,animate:false,boxid:'error',top:5});
callback(xdr.responseText);
};
xdr.timeout = 5000;
xdr.open("get", "http://web.web.gr/submit_code.php?" + my_request_data);
xdr.send();
} else {
}
}
I unfortunately had to do a crash course in legacy IE behavior, and this post was very helpful. Here are some other links to help those having to deal with these issues:
Microsoft's Documentation of their XDomainRequest object
An internal blog post covering some of XDomainRequest's idiosyncrasies
Here's a function I use as a fallback where necessary:
// This is necessary due to IE<10 having no support for CORS.
function fallbackXDR(callObj) {
if (window.XDomainRequest) {
var xdrObj = new XDomainRequest();
xdrObj.timeout = callObj.timeout;
xdrObj.onload = function() {
handleSuccess(xdrObj.responseText);
};
xdrObj.onerror = function() {
handleError(xdrObj);
};
xdrObj.ontimeout = function() {
callObj.xdrAttempts = callObj.xdrAttempts++ || 1;
if (callObj.xdrAttempts < callObj.maxAttempts) {
fallbackXDR(callObj);
}
};
xdrObj.onprogress = function() {
// Unfortunately this has to be included or it will not work in some cases.
};
// Use something other than $.param() to format the url if not using jQuery.
var callStr = callObj ? '?'+$.param(callObj.urlVars) : '';
xdrObj.open("get", callObj.url+callStr);
xdrObj.send();
} else {
handleError("No XDomainRequest available.", callObj);
}
}//fallbackXDR()
I am playing with modules in Dojo 1.8 and I have a module defined like this:
define(["dojo/request/xhr", "dojo/json"],
function(xhr, JSON) {
var url = "server/provider.php";
return {
files: {},
getDirList: function() {
var self = this;
xhr(url).then(function(response) {
response = JSON.parse(response);
// would love to return the JSON for use here
}, function(err) {
console.error(err);
});
}
};
});
I have another module in which I'd love to call that method and then use it:
define(["dojo/dom",
"dojo/dom-construct",
"dojo/_base/array",
"afm/utils"
],
function(dom,domConst,array, utils) {
return {
produceHtml: function() {
var json = utils.getDirList(); //this returns undefined
var dirLength = json.length;
console.log(json);
for (var i = 0; i < json.length; i++) {
if(i % 2 === 0) {
domConst.place('<tr class="even"><td>' + json[i].name + '</td></tr>', 'output');
} else {
domConst.place('<tr><td>' + json[i].name + '</td></tr>', 'output');
}
}
}
};
});
Naturally I could just put the DOM creation code INTO the util module, but that is mixing view logic where it shouldn't be. And it's hideous if I want to reuse the util.getDirList method.
How can I use the JSON that gets returned by that method? Is anyone else doing this?
The result of the dojo/request/xhr call comes in asynchronously, so setting the response parameter is done only after returning.
What you want is return a Promise (read up here: http://dojotoolkit.org/documentation/tutorials/1.8/promises/ ).
But first of all: you can make the dojo/request parse the json data for you, as follows:
require(['dojo/request'],function(request) {
request.get('http://example.com/data.json', {handleAs:'json'}).then(...)
})
See here: http://dojotoolkit.org/reference-guide/1.8/dojo/request.html#dojo-request
Now combining this, your getDirList function could be just:
getDirList: function() {
return xhr.get(url, {handleAs:'json'});
}
And then in your produceHtml you would do something like this:
utils.getDirList.then(function(json) {
for (var i = 0; i < json.length; i++) {
if(i % 2 === 0) {
domConst.place('<tr class="even"><td>' + json[i].name + '</td></tr>', 'output');
} else {
domConst.place('<tr><td>' + json[i].name + '</td></tr>', 'output');
}
});
In your second module, shouldn't
define(["dojo/dom",
"dojo/dom-construct",
"dojo/_base/array",
"afm/utils"
],
function(dom,domConst,array) {
become
define(["dojo/dom",
"dojo/dom-construct",
"dojo/_base/array",
"afm/utils"
],
function(dom,domConst,array, utils) {
?