Brief introduction to the problem. So my project is using BDD Framework (Cucumber) automated with help of Protractor/Selenium using Typescript as scripting language. I passed a table with multiple rows to the step definition and want to run the function in iteration mode using typescript/javascript. I pass the expected dropdowns values and verify it against the application. I came with the below solution with help of one topic on stack overflow. (Using protractor with loops)
But the problem is that it does not work all the time. Many times i have got function time out error.(Error: function timed out after 30000 milliseconds)
Can anyone please let me know what am i missing here? Any help would be greatly appreciated.
Please find below Cucumber and Typescript code.
Cucumber Step Definition_Screenshot
#then(/^.*verify the country data in both the citizenship drop downs$/, 'extratime', 30000)
public VerifyCountryData(table, callback: CallbackStepDefinition): void {
let promises = []
let dropcheck
let dropcheck1
let promise
let noOfRows
var i,j;
var i1,j1;
var k,l;
var funcs = [];
for (i = 0; i < 2; i++) {
let index = i;
funcs[i] = function(index) {
promises.push(element(by.model('vm.citizenships['+index+'].citizenshipCd')).all(by.tagName('option')).getText().then((CitizenValueList) => {
var dropdown = table.rows()[index][1].split(";")
for (i1 = 0; i1 < dropdown.length; i1++) {
dropcheck = false;
for (j1 = 0; j1 < CitizenValueList.length; j1++) {
if (dropdown[i1] === CitizenValueList[j1]) {
dropcheck = true;
break;
}
}
if (!dropcheck) {
callback("Passed value: '" + dropdown[i1] + "' not found")
}
}
for (k = 0; k < CitizenValueList.length; k++) {
dropcheck1 = false;
for (l = 0; l < dropdown.length; l++) {
if (CitizenValueList[k] === dropdown[l]) {
dropcheck1 = true;
break;
}
}
if (!dropcheck1) {
callback("Application value: '" + CitizenValueList[k] + "' not found in expected")
}
}
}))
}.bind(null, i);
}
for (j = 0; j < 2; j++) {
funcs[j]();
}
Promise.all(promises).then(() => {
callback();
}, (error) => {
callback(error);
});
}
}
as far as I can see in your code you loops will take more then 30 seconds, that's the timeout you gave in the #then(/^.*verify the country data in both the citizenship drop downs$/, 'extratime', 30000). If you change it to for example 60000 you have more time for this method.
Upgrading the time is a temporary solution in my opinion, you also need to find the root-cause of exceeding the 30 seconds time limit. One of the problems can be a slow connection which results in not retrieving the webdriver-calls fast enough. Are you testing it locally or against a cloud solution? The experience I have with cloud solutions is that 1 webdriver-call can take up to 1 second. If you compare it to local testing than local webdriver-calls just take a few milliseconds.
About the code. Depending on the version of Typescript you have (I think you need at least version 2.1) you can use async/await. This will remove all the promises.push(..), Promise.all(promises) hell and introduce a more clean code like this
#then(/^.*verify the country data in both the citizenship drop downs$/, 'extratime', 30000)
public async VerifyCountryData(table): Promise < void > {
const citizenValueListOne = await element(by.model('vm.citizenships[1].citizenshipCd')).all(by.tagName('option')).getText();
const dropdownOne = table.rows()[1][1].split(';');
const citizenValueListTwo = await element(by.model('vm.citizenships[2].citizenshipCd')).all(by.tagName('option')).getText();
const dropdownTwo = table.rows()[2][2].split(';');
for (let i1 = 0; i1 < dropdownOne.length; i1++) {
let dropdownOnecheck = false;
for (let j1 = 0; j1 < citizenValueListOne.length; j1++) {
if (dropdownOne[i1] === citizenValueListOne[j1]) {
dropdownOnecheck = true;
break;
}
}
if (!dropdownOnecheck) {
Promise.reject(`Passed value: '${dropdownOne[i1]}' not found`);
}
}
for (let k = 0; k < citizenValueListTwo.length; k++) {
let dropdownTwocheck = false;
for (let l = 0; l < dropdownTwo.length; l++) {
if (citizenValueListTwo[k] === dropdownTwo[l]) {
dropdownTwocheck = true;
break;
}
}
if (!dropdownTwocheck) {
Promise.reject(`Application value: '${citizenValueListTwo[k]}' not found in expected`);
}
}
return Promise.resolve();
}
This can also have an impact on the execution time.
Hope this helps
Related
I have a little code to traite and sort some data get by api, my probleme but actually is that's applying on first array, could you please help me to resolve my problem ?
downlinks = [];
for (var i = 0; i < msg.payload.length; i++) {
downlink = {};
downlink.eui = msg.payload[i].valve_EUI;
if (msg.payload[i].System_Activated === null ) {
downlink.payload = new Buffer("00", "hex");
} else {
downlink.payload = new Buffer( "01", "hex");
}
downlink.port = 1;
downlink.ack = true;
downlink.RxWnd = 1;
downlinks.push(downlink);
}
return downlinks;
verifyActiveInterfacesViaConnectionStatus() {
var sum = 0
var i;
for (i = 1; i <= 5; i++) {
cy.xpath(`(//*[name()='g' and #class ='highcharts-label highcharts-data-label highcharts-data-label-color-undefined']//*[name()='text']//*[#class='highcharts-text-outline'])[${i}]`).invoke("text").then(($text1) => {
var textValue1 = $text1 + "\n"
cy.log(textValue1)
var total = parseInt(textValue1)
sum += total
})
}
cy.log("Total of all connected OS= " + sum)
}
In the cypress automation, when I'm running this block of code it is returning the sum=0 but I don't know why it is displaying 0. Please help me out.
Cypress commands are asynchronous.
cy.log captures the sum value before the first xpath command gets really executed.
To synchronize access to the sum you can use a then callback:
verifyActiveInterfacesViaConnectionStatus() {
var sum = 0
var i;
for (i = 1; i <= 5; i++) {
cy.xpath(`(//*[name()='g' and #class ='highcharts-label highcharts-data-label highcharts-data-label-color-undefined']//*[name()='text']//*[#class='highcharts-text-outline'])[${i}]`).invoke("text").then(($text1) => {
var textValue1 = $text1 + "\n"
cy.log(textValue1)
var total = parseInt(textValue1)
sum += total
})
}
cy.then(() => {
cy.log("Total of all connected OS= " + sum)
})
}
Look at this article for details on how to handle variables at Cypress.
I am trying to scan ECC Data Matrix code with binary content, but if there is a NULL byte I can only get the string up to there.
Unfortunately, I have no control over these matrix codes, as I have to scan the codes provided.
Does somebody has any idea?
Is it possibly to convert the rawData?
It would be enough if I received the content as a hex value.
The rawData is allready hex, but not as expected, maybe it is also corrupt or in an unknown coding.
Does somebody know encoding of rawdata?
see https://developers.google.com/ml-kit/reference/ios/mlkitbarcodescanning/api/reference/Classes/MLKBarcode#rawdata
I found a solution for me:
Here my Code for React-Native:
import {DataMatrixDecodedBitStreamParser, ZXingStringEncoding} from "#zxing/library";
const bin2hex = (s)=> {
// discuss at: https://locutus.io/php/bin2hex/
// original by: Kevin van Zonneveld (https://kvz.io)
// bugfixed by: Onno Marsman (https://twitter.com/onnomarsman)
// bugfixed by: Linuxworld
// improved by: ntoniazzi (https://locutus.io/php/bin2hex:361#comment_177616)
// example 1: bin2hex('Kev')
// returns 1: '4b6576'
// example 2: bin2hex(String.fromCharCode(0x00))
// returns 2: '00'
let i;
let l;
let o = '';
let n;
s += '';
for (i = 0, l = s.length; i < l; i++) {
n = s.charCodeAt(i)
.toString(16);
o += n.length < 2 ? '0' + n : n;
}
return o;
}
const hex2bin = (s)=> {
// discuss at: https://locutus.io/php/hex2bin/
// original by: Dumitru Uzun (https://duzun.me)
// example 1: hex2bin('44696d61')
// returns 1: 'Dima'
// example 2: hex2bin('00')
// returns 2: '\x00'
// example 3: hex2bin('2f1q')
// returns 3: false
const ret = []
let i = 0
let l
s += ''
for (l = s.length; i < l; i += 2) {
const c = parseInt(s.substr(i, 1), 16);
const k = parseInt(s.substr(i + 1, 1), 16);
if (isNaN(c) || isNaN(k)) return false;
ret.push((c << 4) | k);
}
return String.fromCharCode.apply(String, ret);
}
const fromHexString = hexString => new Uint8Array(hexString.match(/.{1,2}/g).map(byte => parseInt(byte, 16)));
const matrixcodeRAW2HEX = raw_hex => {
let data = fromHexString(raw_hex);
try {
global.Buffer = global.Buffer || require('buffer').Buffer;
ZXingStringEncoding.customDecoder = (stringContent, encodingName) => {
let encodingName2 = encodingName;
if(encodingName.toLowerCase()=="iso-8859-1"){
encodingName2="latin1";
}
return new Buffer(stringContent).toString(encodingName2);
}
ZXingStringEncoding.customEncoder = (stringContent, encodingName) => {
let encodingName2 = encodingName;
if(encodingName.toLowerCase()=="iso-8859-1"){
encodingName2="latin1";
}
return new Buffer(stringContent).toString(encodingName2);
};
let newData = DataMatrixDecodedBitStreamParser.decode(data);
return bin2hex(newData.getText());
}catch (e) {
console.log(e);
}
}
My function will return the original data as hex, so there is no problem with NUL, but you can also use hex2bin to get it as a Text if necessary.
I´m using the zxing polyfill for JS => https://github.com/zxing-js/library, cause JS does not Cut String like Objective C do.
I found out in Objective C NUL always will cut a string, so there is no solution yet.
I’m new to both Ionic and Vue.js. I’m taking advantage of this summer break to start learning both.
I’m building a mobile app for this purpose and so far, so good. However, I have found and issue that I hope you could help me with. Namely, how to fetch or “call” data from one file to another (Is it called routing?).
In my app, I am trying to start/open a function named myFunction() from one of the pages (quiz.vue) when I call it using v-on:click="myFunction3".
This function is located in a JS file called quizz.js, and it is located in the assets folder. This is its path: (“./assets/js/quizz.js”).
I have tried many things to make it work and finally it is working as it should. However, I think my solution is not optimal as it keeps throwing “Uncaught TypeErrors” in the console of the Developer’s Tool…even though it works.
My solution was to push the function inside methods: this.$router.push(myFunction3())
Also, when running the app, it says that myFunction() , and other functions in the same quizz.js file, “is define but never used”.
If you could advise me with anything, I would be most grateful. I am still a beginner so please explain it to me in as simple a manner as possible.
methods:{
openMenu(){
menuController.open("app-menu")
},
myFunction3(){
this.$router.push(myFunction3())
},
Below, the quizz.js file:
var mlhttp = new XMLHttpRequest();
mlhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
var myObj = JSON.parse(this.responseText);
const quiz = myObj.results[0]['question'];
const correctAnswer = myObj.results[0]['correct_answer'];
const incorrect = myObj.results[0]['incorrect_answers'];
incorrect.push(correctAnswer);
shuffle(incorrect);
document.getElementById("ans").innerHTML = quiz;
var text = "";
var val = 0;
var i;
for (i = 0; i < incorrect.length; i++) {
if(incorrect[i] == correctAnswer){
text += "<ion-button fill='outline' id='right' onClick='increment();myFunc();'/><b>" + incorrect[i] + "</b></ion-button></br>";
val = val + 1;
}else{
text += "<ion-button fill='outline' class='wrong' onClick='myFunc2();'/><b>" + incorrect[i] + "</b></ion-button></br>";
}
}
document.getElementById("ans5").innerHTML = text;
}
};
var j=0;
function myFunction3() {
document.getElementById("ans6").innerHTML = "";
mlhttp.open("GET", "https://opentdb.com/api.php?amount=1", true);
mlhttp.send();
j++;
document.getElementById('ans11').innerHTML=j;
}
function shuffle(array) {
for (let i = array.length - 1; i > 0; i--) {
let j = Math.floor(Math.random() * (i + 1));
[array[i], array[j]] = [array[j], array[i]];
}
}
function myFunc(){
document.getElementById("ans6").innerHTML = "<h1 style='color:green'><i class='fa fa-check'></i> That is correct!</h1>";
document.getElementById("right").style.color = "white";
document.getElementById("right").style.backgroundColor = "green";
var audio = new Audio('./assets/sound/win.mp3');
audio.play();
}
function myFunc2(){
document.getElementById("ans6").innerHTML = "<h1 style='color:red'><i class='fa fa-thumbs-down' ></i>Wrong Answer! </h1>";
document.getElementById("right").style.color = "white";
document.getElementById("right").style.backgroundColor = "green";
var x = document.getElementsByClassName("wrong");
var i;
for (i = 0; i < x.length; i++) {
x[i].style.backgroundColor = "rgba(255, 0, 0, 0.8)";
x[i].style.color = "white";
}
//document.getElementById("wrong").style.color = "red";
var audio = new Audio('./assets/sound/wrong.mp3');
audio.play();
}
var i=0;
function increment() {
i++;
document.getElementById('ans10').innerHTML=i;
}
I'm trying to print qz tray from javascript.
I have barcode with number in ascending order 1,2,3,4, 5 and so on.
I looping the seq correctly . but when printed out, it was not in order.
setTimeout("directPrint2()",1000);
function sleep(milliseconds) {
var start = new Date().getTime();
for (var i = 0; i < 1e7; i++) {
if ((new Date().getTime() - start) > milliseconds){
break;
}
}
}
function directPrint2(){
var data;
var xhttp;
var v_carton = "' || x_str_carton ||'";
var carton_arr = v_carton.split('','');
var v1 = "' ||
replace(x_zebra_printer_id, '\', '|') ||
'".replace(/\|/g,"\\");
if(v1 == ""){
alert("Please setup ZPL Printer");
}
else{
xhttp=new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
data = [ toNative(this.responseText) ];
printZPL(data, v1);
}
};
for (var j = 0; j < carton_arr.length; j++){
var url = "' || x_wms_url ||
'WWW_URL.direct_print_label?in_carton_no="+toValidStr(carton_arr[j]);
xhttp.open("GET", url, false);
xhttp.send();
sleep(5000);
}
}
};
',
'javascript'
What's missing from your example:
I do not see any looping logic in the example calling the printZPL function,
printZPL isn't a QZ Tray function and you're missing the code snippet which it calls. Usually this would be qz.print(config, data);.
Regardless of the missing information, the qz.print(...) API is ES6/Promise/A+ based meaning if you want to call qz.print multiple times in a row you need to use a Promise-compatible technique. (e.g. .then(...) syntax) between your print calls as explained in the Chaining Requests guide.
To avoid this, you can concatenate all ZPL data into one large data array. Be careful not to spool too much data at once.
If you know exactly how many jobs you'll be appending, you can hard-code the promise chain:
qz.websocket.connect()
.then(function() {
return qz.printers.find("zebra"); // Pass the printer name into the next Promise
})
.then(function(printer) {
var config = qz.configs.create(printer); // Create a default config for the found printer
var data = ['^XA^FO50,50^ADN,36,20^FDRAW ZPL EXAMPLE^FS^XZ']; // Raw ZPL
return qz.print(config, data);
})
.catch(function(e) { console.error(e); });
Finally, if you do NOT know in advanced how many calls to qz.print(...) you can use a Promise loop as explained in the Promise Loop guide.
function promiseLoop() {
var data = [
"^XA\n^FO50,50^ADN,36,20^FDPRINT 1 ^FS\n^XZ\n",
"^XA\n^FO50,50^ADN,36,20^FDPRINT 2 ^FS\n^XZ\n",
"^XA\n^FO50,50^ADN,36,20^FDPRINT 3 ^FS\n^XZ\n",
"^XA\n^FO50,50^ADN,36,20^FDPRINT 4 ^FS\n^XZ\n"
];
var configs = [
{ "printer": "ZDesigner LP2844-Z" },
{ "printer": "ZDesigner LP2844-Z" },
{ "printer": "ZDesigner LP2844-Z" },
{ "printer": "ZDesigner LP2844-Z" }
];
var chain = [];
for(var i = 0; i < data.length; i++) {
(function(i_) {
//setup this chain link
var link = function() {
return qz.printers.find(configs[i_].printer).then(function(found) {
return qz.print(qz.configs.create(found), [data[i_]]);
});
};
chain.push(link);
})(i);
//closure ensures this promise's concept of `i` doesn't change
}
//can be .connect or `Promise.resolve()`, etc
var firstLink = new RSVP.Promise(function(r, e) { r(); });
var lastLink = null;
chain.reduce(function(sequence, link) {
lastLink = sequence.then(link);
return lastLink;
}, firstLink);
//this will be the very last link in the chain
lastLink.catch(function(err) {
console.error(err);
});
}
Note: The Promise Loop is no longer needed in QZ Tray 2.1. Instead, since 2.1, an array of config objects and data arrays can be provided instead.