ISSUE: Cannot read property 'getText' of undefined - javascript

I built this to test reports against csv files containing the data but I am running into this error "Cannot read property 'getText' of undefined" . Please advise thanks. Below is my code
testReport: async function (driver, dataFile) {
var data = await csv({ noheader: true, output: "csv" }).fromFile("./admin/data/" + dataFile);
var trs = await driver.findElements(By.css('.qa-report', 'tbody', 'tr'));
//trs.shift(); // remove first tr - it's the header row
var errors = [];
for (var i in data) {
var row = data[i];
var tds = await trs[i].findElements(By.tagName('td'));
for (var j in row) {
var csvData = data[i][j];
var siteData = await tds[j].getText();
if (siteData != csvData) {
errors.push("[" + i + "," + j + "] - expected(" + csvData + ") got(" + siteData + ")");
}
}
}
if (errors.length > 0) {
errorMessage = "Cells failed to validate:";
for (var i in errors) {
errorMessage += "\n" + errors[i];
}
throw new Error(errorMessage);
}
},

Your iterators looks a bit messed up (as already commented)
try for (var j in tds) { instead of for (var j in row) {
I guess you have more result rows than columns per row. If you still have problems, post the class definitions for findElements or Bywhich we don't know.

Related

change API data depending on if statment

I'm trying to fetch data through API , and the URL contains two object and I targeted the quizzes , "quizzes": [2 items], "warnings": []
quizzes return me two objects with their details.
what I'm trying to achieve is to add if statement to retrieve the grades (another API) depends on quiz name and it is working well , but I want to add inside it another if to retrieve grades depends on the another quiz name, please see the code below how to target posttest inside pretest they have the same key and I want the data to be changed depends on quiz name.
var get_quiz = {
"url": "MyURL"
};
$.ajax(get_quiz).done(function (get_quiz_res) {
var reslength = Object.keys(get_quiz_res).length;
for (let b = 0; b < reslength; b++) {
var get_grade = {
"url": "*******&quizid="+get_quiz_res.quizzes[b].id"
};
$.ajax(get_grade).done(function (get_grade_res) {
var posttest=''
if (get_quiz_res.quizzes[b].name === "Post Test"){
posttest = get_grade_res.grade;
}
if (get_quiz_res.quizzes[b].name === "Pre Test"){
var row = $('<tr><td>' + userincourseres[i].fullname + '</td><td>' + get_grade_res.grade + '</td><td>' + posttest + '</td><td>');
$('#myTable').append(row);
}
});
}
});
the userincourseres[i].fullname from another api and it is working.
You can use async/await with $ajax if your JQuery version is 3+.
const get_quiz = {
url: "MyURL",
};
(async function run() {
const get_quiz_res = await $.ajax(get_quiz);
const reslength = Object.keys(get_quiz_res).length;
for (let b = 0; b < reslength; b++) {
const get_grade = {
url: "*******&quizid=" + get_quiz_res.quizzes[b].id,
};
let posttest = "";
const get_grade_res = await $.ajax(get_grade);
if (get_quiz_res.quizzes[b].name === "Post Test") {
posttest = get_grade_res.grade;
}
if (get_quiz_res.quizzes[b].name === "Pre Test") {
var row = $(
"<tr><td>" +
userincourseres[i].fullname +
"</td><td>" +
get_grade_res.grade +
"</td><td>" +
posttest +
"</td><td>"
);
$("#myTable").append(row);
}
}
})();

How to access attributes of NodeList elements in Protractor

I'm trying to read values from a fairly big HTML table in Protractor (about a thousand rows and 5 columns).
Protractor's element.all().getText() method is very slow at this, so I decided to implement a solution using browser.executeScript to read the values directly, like:
async getTextFromHtmlTable(){
try{
var rows = element.all(by.css('table[id^="P"] tr'));
var numRows = await rows.count();
var arrRows = [];
for (var i = 2; i <= numRows; i++){
console.log("********Processing row: " + i);
var css = 'table[id^=\"P\"] tr:nth-child(' + i + ') td div div';
//**Slow solution: var arrRowsText = await element.all(by.css(css)).getText();
//Faster:
var arrRowsText = await browser.executeScript("return document.querySelectorAll('" + css + "')").then(function(elements){
var arrayRes = [];
for (var j=0; j<elements.length; j++){
console.log("****** Element text: " + elements[j].textContent);
arrayRes.push(elements[j].textContent);
}
return arrayRes;
});
arrRows.push(arrRowsText.join(';').replace(/;\s/gm, ";"));
}
return arrRows;
}catch(err){
console.log ('Some error: ' + err)
};
}
However, console output when executing the test is:
********Processing row: 569
****** Element text: undefined
****** Element text: undefined
****** Element text: undefined
****** Element text: undefined
****** Element text: undefined
********Processing row: 570
****** Element text: undefined
****** Element text: undefined
****** Element text: undefined
****** Element text: undefined
****** Element text: undefined
No matter what attribute I read (textContent, innerText, innerHTML...), it always returns 'undefined'. Am I doing anything wrong? Thanks for the help!
I finally found a solution to this, DublinDev pointed me in the right direction when he said that executeScript does not return NodeLists. So I thought about processing the NodeList inside the executeScript method and have it return an array of texts instead of the actual NodeList:
var arrRowsText = await browser.executeScript("return (function(){" +
"var nodes = document.querySelectorAll('" + css + "');" +
"var arrayRes = [];" +
"for (var j=0; j<nodes.length; j++){" +
" arrayRes.push(nodes[j].innerText);" +
"}" +
"return arrayRes;" +
"})();");
Now it works like a charm and element texts are read much faster with innerText than with getText().
It appears that nodelists are returned through the executeScript method as an array of webElements so getText() should work. You also don't need to use .then() when something is already awaited. Can you try the below code?
async getTextFromHtmlTable(){
try{
var rows = element.all(by.css('table[id^="P"] tr'));
var numRows = await rows.count();
var arrRows = [];
for (var i = 2; i <= numRows; i++){
console.log("********Processing row: " + i);
var css = 'table[id^=\"P\"] tr:nth-child(' + i + ') td div div';
//**Slow solution: var arrRowsText = await element.all(by.css(css)).getText();
//Faster:
var arrRowsText = await browser.executeScript("return document.querySelectorAll('" + css + "')");
let allEleText = [];
for(let j = 0; j < arrRowsText.length; j++){
allEleText.push(await arrRowsText[j].getText());
}
arrRows.push(allEleText.join(';').replace(/;\s/gm, ";"));
}
return arrRows;
}catch(err){
console.log ('Some error: ' + err)
};
}

Uncaught TypeError: Cannot read property 'setRowData' of undefined

I am using with Angular 1.x with ag-grid. first of all I am confused how I do activate enterprise feature. I am evaluating now we are planing to buy the enterprise but support is pretty weak.
Now the actual problem I am trying to feed the data from ElasticSearch to the grid. I am trying to simulate like demo of ag-grid. If change the pagesize it will retrieve the data from ES server and feed the grid with new datasets with new pagesize. For that I am using $scope.gridOptions.api.setRowData(data) on any action if I try to update the grid I mean setRowData. I am getting error "method is undefined" It works for the first time when it loads the page.
How do I resolve this issue? Am I missing anything?
Function: This is the function where I invoking the $scope.gridOptions.api.setRowData(data) and I am getting error
"Uncaught TypeError: Cannot read property 'setRowData' of undefined"
function displayGrid(fromDate, toDate, fieldNameArray, affiliate, product,consmb, region, customer, page, pageSize)
{
// Constructing Query from dashboard input
var gridQuery = globalFiltersDrillDown(fromDate, toDate, fieldNameArray, page, pageSize);
var finalGridQuery = buildQueryForDrillQuery(affiliate,product, consmb, region, customer, gridQuery, "" , false);
console.log("final Query :" + JSON.stringify(finalGridQuery));
var data =[];
setTimeout(function ()
{
esClientIndirect.search
(
{
index: esIndex1,
type: esType1,
size : pageSize,
from : page,
body: finalGridQuery
},
function (error, response, status)
{
$scope.numberOfRecords = numberCommas(response.hits.total);
if(error)
{
$scope.error = "Error : " + status ;
}
else
{
var startBrace = "{ ";
var endBrace = " }"
data.length = 0;
var k = 0;
for(var o in response.hits.hits)
{
var dataFields = response.hits.hits[o].fields;
var numberOfElements = fieldNameArray.length -1;
var row = startBrace;
for (var i in dataFields)
{
var columnName = fieldNameArray[k];
var columnValue = dataFields[columnName];
if (k == numberOfElements)
{
row += (" \"" + columnName +"\" : \"" + columnValue +"\"");
}
else
{
row += (" \"" + columnName +"\" : \"" + columnValue +"\",");
}
k = k+1;
}
row += endBrace;
k =0;
data.push(JSON.parse(row));
}
// pushing data into the ag-grid
setTimeout(function()
{
$scope.gridOptions.api.setRowData(data);
}, 200);
}
}, 100); // end of elastic search call back
}); // end of elastic search set time out call back
The error indicates that the api doesn't exist. Have you made sure that you have instantiated $scope.gridOptions before you do this call?

Query Parent and child data in one call - parse.com + javascript

I am trying to understand how to query related classes in one call from parse.com using javascript.
I have 2 classes Post and Comment. Post has a column of type relation named 'Comment' and Comment has a column 'parent' of type pointer.
I use the following following code based on parse docs, to save a post and related comment
var Post = Parse.Object.extend("Post");
var Comment = Parse.Object.extend("Comment");
//Create the post
var myPost = new Post();
myPost.set("title", "I'm Hungry");
myPost.set("content", "Where should we go for lunch?");
// Create the comment
var myComment = new Comment();
myComment.set("text", "Let's do subway.");
myComment.set("parent", myPost);
myComment.save();
I am trying to query data like this
var query = new Parse.Query("Post");
query.descending("createdAt");
query.find({
success: function(results) {
for(var i = 0; i < results.length; i++) {
var post = results[i];
var relation = post.relation('Comment');
relation.query().find({
success: function(comments) {
for(var j = 0; j < comments.length; j++) {
console.log(comments[j].get("content"));
}
}
});
}
},
error: function(error) {
alert("Error: " + error.code + " " + error.message);
}
});
Can anybody tell me what i am doing wrong here?
The problem in your code is that you're not setting up the relation between the post and the comment. Without that relation setup your query won't work. Here's the working code. Note that I have to save the comments before creating the relation, otherwise you'll get an error from parse.
function createPost() {
var Post = Parse.Object.extend("Post");
var Comment = Parse.Object.extend("Comment");
//Create the post
var myPost = new Post();
myPost.set("title", "I'm Hungry");
myPost.set("content", "Where should we go for lunch?");
// Create the comment
var comment1 = new Comment();
comment1.set("text", "Let's do subway.");
comment1.set("parent", myPost);
var comment2 = new Comment();
comment2.set("text", "Let's do Hoagies.");
comment2.set("parent", myPost);
return Parse.Object.saveAll([comment1, comment2]).then(function() {
// Set the relationship
var relation = myPost.relation('comments');
relation.add(comment1);
relation.add(comment2);
return myPost.save();
});
}
createPost().then(function() {
var query = new Parse.Query("Post");
query.descending("createdAt");
var posts = [];
return query.find().then(function(results) {
var promises = [];
for(var i = 0; i < results.length; i++) {
var post = results[i];
var relation = post.relation('comments');
var postData = { post : post, comments : [] };
posts.push(postData);
console.log("Post : " + post.get('title'));
promises.push(relation.query().find({
success: function(comments) {
for(var j = 0; j < comments.length; j++) {
console.log("Comment " + j + " : " + comments[j].get("text"));
postData.comments.push(comments[j]);
}
}
}));
}
return Parse.Promise.when(promises);
},
function(error) {
alert("Error: " + error.code + " " + error.message);
}
).then(function() {
console.log(posts);
return posts;
});
})

Javascript Syntax Error "out of range"

I've been doing web development for quite sometime and have never seen this behavior with JavaScript. This is the code I started out with:
function processLogin() {
if (loginReq.readyState == 4) {
var data = eval('(' + loginReq.responseText + ')');
data = data.userData;
var focus = data.team.focus.coordinates;
thisTeam = new Team(data.team.id, data.team.missionId, data.team.name, data.team.operatingArea.coordinates[0]);
if (data.team.zoomLevel != '') {
thisTeam.zoomLevel = data.team.zoomLevel;
}
if (focus.length > 0) {
thisTeam.focusLat = focus[1];
thisTeam.focusLon = focus[0];
}
for (var i = 0; i < data.teams.length; i++) {
var temp_team = new Team(data.teams[i].id, data.teams[i].missionId, data.teams[i].name, []);
teams.push(temp_team);
}
var teamDropDownText = [];
for (var j = 0; j < teams.length; j++) {
if (thisTeam.teamId == teams[j].teamId) {
teamDropDownText.push('<option value="' + teams[j].teamId + '" selected="selected">' + teams[j].name + '</option>');
} else {
teamDropDownText.push('<option value="' + teams[j].teamId + '">' + teams[j].name + '</option>');
}
}
$('#addIncidentTeam').html(teamDropDownText.join(''));
$('#editIncidentTeam').html(teamDropDownText.join(''));
// When all this has finished, make the
// rest of the calls to get the rest of the data
startTimer();
downloadDevices();
initializeMap();
}
}
What I have written there isn't that important, and let me explain why.
The line with the single semicolon after thisTeam.zoomLevel = data.team.zoomLevel; was giving me a syntax error in firebug. I read and re-read my code, and couldn't figure out what I did wrong, so I put the semicolon on the same line as thisTeam.zoomLevel = data.team.zoomLevel and it told me it had a syntax error on the blank line!
To do another test, I moved this whole function to it's own JavaScript file and put everything after that line on one line and even tried to condense some of the code above, so now it looks like this:
function processLogin() {
if (loginReq.readyState == 4) {
var data = eval('(' + loginReq.responseText + ')');
data = data.userData;
var focus = data.team.focus.coordinates;
thisTeam = new Team(data.team.id, data.team.missionId, data.team.name, data.team.operatingArea.coordinates[0]); if (data.team.zoomLevel.length > 0) { thisTeam.zoomLevel = data.team.zoomLevel; } if (focus.length > 0) { thisTeam.focusLat = focus[1];thisTeam.focusLon = focus[0];} for (var i = 0; i < data.teams.length; i++) { var temp_team = new Team(data.teams[i].id, data.teams[i].missionId, data.teams[i].name, []); teams.push(temp_team); } var teamDropDownText = []; for (var j = 0; j < teams.length; j++) { if (thisTeam.teamId == teams[j].teamId) { teamDropDownText.push('<option value="' + teams[j].teamId + '" selected="selected">' + teams[j].name + '</option>'); } else { teamDropDownText.push('<option value="' + teams[j].teamId + '">' + teams[j].name + '</option>'); } } $('#addIncidentTeam').html(teamDropDownText.join('')); $('#editIncidentTeam').html(teamDropDownText.join('')); /* When all this has finished, make the rest of the calls to get the rest of the data */ startTimer(); downloadDevices(); initializeMap(); var kmlLink = document.getElementById('kmlLink'); var geoserverLink = document.getElementById('geoserverLink') if (user_role.substring(0, 1) == 'M') { kmlLink.href = "https://www.intelink.gov/giatstldni/hermes/webservice/kml/download/M&" + thisTeam.missionId + "&48"; kmlLink.innerHTML = "https://www.intelink.gov/giatstldni/hermes/webservice/kml/download/M&" + thisTeam.missionId + "&48"; geoserverLink.href = "https://www.intelink.gov/giatstldni/geoserver/wms/kml?layers=hermes_all&cql_filter=mission_id+=+" + thisTeam.missionId; geoserverLink.innerHTML = "https://www.intelink.gov/giatstldni/geoserver/wms/kml?layers=hermes_all&cql_filter=mission_id+=+" + thisTeam.missionId;} else { kmlLink.href = "https://www.intelink.gov/giatstldni/hermes/webservice/kml/download/T&" + thisTeam.id + "&48"; kmlLink.innerHTML = "https://www.intelink.gov/giatstldni/hermes/webservice/kml/download/T&" + thisTeam.id + "&48"; geoserverLink.href = "https://www.intelink.gov/giatstldni/geoserver/wms/kml?layers=hermes_all&cql_filter=team_id+=+" + thisTeam.id; geoserverLink.innerHTML = "https://www.intelink.gov/giatstldni/geoserver/wms/kml?layers=hermes_all&cql_filter=team_id+=+" + thisTeam.id; } } }
I did this just to see what error I would get, I knew it wouldn't work correctly. But now it's telling me there's an error on a line that doesn't exist in the file! I get:
syntax error
[Break On This Error] (10 out of range 8)
I went and commented more code out and it just made it 10 out of range 6! I don't understand!
I found the culprit. One of the values of the JSON returned was empty (no quotes or anything). Not a very helpful error message.

Categories

Resources