Can not handle multiple frame using webdriverIO. I have tried many diff ways but does not work.
<iframe id="frame1">
<html>
<iframe id="frame2"></iframe>
</html>
</iframe>
To handle above I have written below code
async function handleFrames(){
await browser.$("frame1").waitForExist({timeout: 100000}).then(async function(present){
if (present) {
await browser.switchToFrame(null);
await browser.pause(1000);
await browser.switchToFrame($("#frame1"));
await browser.switchToFrame($("frame2"));
}
})
}
After running the code I am getting this err:
TypeError: elem[prop] is not a function
Above err mean it is returning arrays, so I have tried below also
async function handleFrames(){
await browser.switchToFrame(null);
await browser.$$("iframe").forEach(async function (ele) {
await ele.getHTML().then(async function (outerHTML) {
await browser.pause(500);
if (outerHTML.includes("iframe1")) {
console.log("Frame1 found!!!!!");
await browser.switchToFrame(ele);
}
});
});
await browser.switchToFrame(browser.$("#frame2"));
}
But did not have any luck :(
Any solution to this would be highly appreciated!!!!
Related
Summary: creating my own API that returns epoch time, and it involves using an express.js server, but it's running res.send() before the function call. I referenced this page, but it didn't help. Here's what I have:
app.get('/timestampAPI', async (req, res,) => {
try {
let finalResult = await getTimeStamp();
res.send({ something: finalResult });
} catch (error) {
console.log(error);
}
});
It'll start to run the function getTimeStamp(), and before that function finishes, it runs the res.send() function which shows up as '{}' because finalResult doesn't have a value. getTimeStamp() is an async function. I'm unsure of what I'm doing wrong.
Edit:
getTimeStamp() function:
async function getTimeStamp() {
await axios.get('https://showcase.api.linx.twenty57.net/UnixTime/tounixtimestamp?datetime=now')
.then(response => {
// also used console.log(response.data.UnixTimeStamp), which returns the timestamp
return response.data;
})
.catch(error => {
var errorMessage = error.response.statusText;
console.log(errorMessage);
});
}
Another edit: yes, the API referenced above does return the current epoch time, but CORS is blocking my other site from accessing it directly, so I can't use it on that site, which is why I'm using node.js for it so that I can allow myself to access it through my node.js program. Couldn't think of another way
returning value of the then method does not return from getTimeStamp function you should write you code in resolve pattern or using await like below
try this, make sure you write correct field name in response object
async function getTimeStamp() {
try{
const res = await axios.get('https://showcase.api.linx.twenty57.net/UnixTime/tounixtimestamp?datetime=now')
return res.data
}catch(error){
throw error
}
As an alternative to Mohammad's answer you can also use returning getTimeStamp function's result as a promise and it can solve your problem.
async function getTimeStamp() {
return new Promise((resolve, reject) => {
axios.get('https://showcase.api.linx.twenty57.net/UnixTime/tounixtimestamp?datetime=now')
.then(response => {
// also used console.log(response.data.UnixTimeStamp), which returns the timestamp
resolve(response.data);
})
.catch(error => {
var errorMessage = error.response.statusText;
console.log(errorMessage);
reject(error);
});
})
}
Or you would also replace await with return in getTimeStamp function in your code if you don't want to return promise.(Which is not I recommend.). You should also throw the error in catch block which is generated in getTimeStamp function for catching the error in try-catch block that you use to call app.get(...).
I have three API calls which should be dependent on one another. The second API call should trigger only when the first succeeds.
With my current implementation, I'm getting a CORS error when the first API call is made and was able to catch the error in the catch block. However, I'm seeing that the second and third APIs calls are made irrespective of the error that got caught in the first API call.
Could anyone please advise?
const firstApiCall = async() => {
try {
await axios.post(
process.env.FIRST_API,
payload
);
]
} catch (err) {
console.log(`err`, err);
}
};
const secondApiCall = async() => {
try {
await axios.post(
process.env.SECOND_API,
payload
}
} catch (err) {
console.log(`err`, err);
}
};
const thirdApiCall = async() => {
try {
await axiosInstance.patch(
process.env.THIRD_API,
payload
);
} catch (err) {
console.log('err', err);
}
};
firstApiCall();
secondApiCall();
thirdApiCall();
You're calling the functions synchronously when you need to do it asynchronously:
async function performTasks() {
await firstApiCall();
await secondApiCall();
await thirdApiCall();
}
performTasks();
You can use the ES6 Promise implementation approacg. Therefore you should take a look to this ressource : [Promise][1]
With the promise approach you can react at each step / each API call.
[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/then
async await functions work only in their local scope.
For example:
const myFunc = async() => {
try{
//...
await foo();
//All the code below will be blocked till
//the promise return by foo function is resolved
}
catch{
//...
}
}
const main = () => {
myFunc();
otherFunc();
//Other function calls
//Regardless of using async await in myFunc,
//the code bellow myFunc will be executed as
//async await will work only in myFunc block scope
}
main()
What you can do is, use async await inside the main function, so that the functions would be called in an order
const main = async () => {
await myFunc();
await otherFunc();
}
I found the error: setValue is not a function when I was trying to set value for an element.
But I came up with a solution like using the async function
describe("Interaction with web elements", function () {
it("Enter Value in a field", async function () {
await browser.url('/');
const Search = await $('#twotabsearchtextbox')
await Search.setValue('MacBook');
})
});
Will there be any other alternative way to fix them?
it not working because you have not added async and await
describe("interaction with web elements",()=>{
it("enter value in a field", async() => {
await browser.url('/');
const search = await browser.$('#twotabsearchtextbox');
search.setValue('mac');
await browser.pause(500);
})
})
this should work
I have an async anonymous self-invoking function. The word “async” before the function means the function will always returns a promise. If the code has return in it, then JavaScript automatically wraps it into a resolved promise with that value.
This async allows us to use "wait". The keyword await makes JavaScript wait until that promise settles and returns its result. So the function execution “pauses” and resumes when the promise settles. That doesn’t cost any CPU resources, because the engine can do other jobs meanwhile: execute other scripts, handle events etc.
(async () => {
await page.goto('test.com', { waituntil: ['load', 'domcontentloaded', 'networkidle0'] });
await page.evaluate((user, pass) => {
document.querySelector('#user').setAttribute('value', user);
}, user, pass)
await page.click('button[type=submit].btn-primary');
for(var i = 0; i < 10; i++){
try {
await page.goto('test.com/second', { waituntil: ['load', 'domcontentloaded', 'networkidle0'] });
} catch(e) {
await page.goto('test.com', { waituntil: ['load', 'domcontentloaded', 'networkidle0'] });
await page.evaluate((user, pass) => {
document.querySelector('#user').setAttribute('value', user);
}, user, pass)
await page.click('button[type=submit].btn-primary');
}
// more stuff not relevant here
}
})();
But as you can see above, I have duplicate code. I want to extract the duplicate code into a separate function. Something like this:
(async () => {
logIn()
for(var i = 0; i < 10; i++){
try {
await page.goto('test.com/second', { waituntil: ['load', 'domcontentloaded', 'networkidle0'] });
} catch(e) {
logIn()
}
// more stuff not relevant here
}
})();
function logIn(){
await page.goto('test.com', { waituntil: ['load', 'domcontentloaded', 'networkidle0'] });
await page.evaluate((user, pass) => {
document.querySelector('#user').setAttribute('value', user);
}, user, pass)
await page.click('button[type=submit].btn-primary');
}
However, this won't work because await only works inside an aysnc. Now one idea is to place await in front of the logIn call like this:
await logIn()
But here is the thing. Inside that logIn function, I purposely use await 3 times because I need one statement to be resolved before the next.
How can I achieve this? Use async/await and use my logIn function?
Make your logIn function as an async function too:
async function logIn() {...}
then, when you call it, await for it:
await logIn();
like so:
async function logIn() {
await page.goto('test.com', {
waituntil: ['load', 'domcontentloaded', 'networkidle0']
});
await page.evaluate((user, pass) => {
document.querySelector('#user').setAttribute('value', user);
}, user, pass)
await page.click('button[type=submit].btn-primary');
}
(async() => {
await logIn();
for (var i = 0; i < 10; i++) {
try {
await page.goto('test.com/second', {
waituntil: ['load', 'domcontentloaded', 'networkidle0']
});
} catch (e) {
logIn()
}
// more stuff not relevant here
}
})();
More on async functions
The solution above also means that the function that calls login will also need to be async, as well as the function that calls that function, etc. all the way to the top of your code base.
Essentially, using async anywhere means that all of your functions must be async and all of your functions must be called with await.
I wish we could just wrap the execution operator with await/async so that we wouldn't have to spread it throughout our entire applications.
I wish someone would actually correct me on this, because I have found no solution that doesn't involve making all functions async and calling them with await.
If you do, please feel free to email me at rodney.barbati#gmail.com. I would appreciate it.
I've got this very basic async await which I believe is not running correctly:
const ex = {
people: () => {console.log('people')},
places: () => {console.log('places')}
}
async function example() {
try {
const people = await ex.people()
const places = await ex.places()
} catch(err) {
console.log(err)
}
}
example().then(console.log('last'))
output:
people
last
places
Shouldn't this be outputting 'people, places, last'?
Yes, this code snippet is pretty much ok!
The only thing missing here it's that promises returns functions.
So .then should be like this:
example().then(() => console.log('last'))
Hope it works for you!
Edit:
As #gyre said, ex.people and ex.places should return promises in order to work correctly
Here's an example