Promise resolver [object Array] is not a function - puppeteer

I have a script that asks for the user input to download (or not) a file. It's fairly straight forward, but I have a problem with the following piece of code. If the user chooses "NO", then the else if condition works fine and the code finishes its expected execuetion. But if the user chooses Yes, the file gets downloaded but I get the following error:
UnhandledPromiseRejectionWarning: TypeError: Promise resolver [object Array] is not a function
I problably need to learn more about Promises, but I share the section of the code that fails in case I am making an obvious mistake that I fail to see.
async function download_fallo(page) {
if (download == "Y") {
await new Promise([
page.click('div > div.col-xs-12.col-sm-11 > div.row > div.col-sm-4.col-lg-3 > a'),
//page.wait({ waitUntil: 'networkidle0' }) // does not work either
//page.wait(2000) // UnhandledPromiseRejectionWarning page.wait is not a function...
]);
return console.log("Perfect")
} else if (download == "N") {
console.log("Just the information then!") }
}

Thanks guys --- I was making obvious mistakes and you clarified them. I was not using Promise.all and made a mistake with page.await, both were pointed out. With that corrected, the code works. I post below in case someone finds it useful, it's a simple if condition tied to a readLine user input to download (or not) a PDF file from a website.
async function download_fallo(page) {
if (download == "Y") {
await Promise.all([
page.click('div > div.col-xs-12.col-sm-11 > div.row > div.col-sm-4.col-lg-3 > a'),
page.waitFor(2000)
]);
return console.log("Perfect")
} else if (download == "N") {
console.log("Just the information then!") }
}

I dont really know what you need because i need more context, but if you want to execute an array of promises you could try
Promise.all([ promise1, promise2 ])
This method takes an array of promises as an input, and returns a single Promise as an output. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all

I am not a 100% sure if your script does what you expect to do, but ‘page.wait’ is a non-existent puppeteer method. You need ‘page.waitFor’ if you want to wait for / pause the script for certain ms-s.

Related

React - When user search an API in form, how to handle no matches in API?

I'm trying to build an weatherapplication for a schoolproject in React. I've gotten so far that when i search for London, it will show me the current temprature and other useful information i've chosen to display. I simply want a message to appear that the city could not be found, i guess this somehow should done in a variable and with help of If statements?
However im not sure how i handle if the user types something that that isnt there, for example "new jorc" instead of New York. My current code looks like this.
getWeather = async (e) => {
e.preventDefault();
const city= e.target.elements.city.value;
if(city){
const api_call = await fetch(
`http://api.openweathermap.org/data/2.5/weather?q=${city}&units=metric&appid=${API_KEY}`
);
const response = await api_call.json();
this.setState({
city: `${response.name}`,
celsius: this.evenDeagree(response.main.temp),
wind: this.evenDeagree(response.wind.speed),
feelsLike: this.evenDeagree(response.main.feels_like)
});
} else{
this.setState({error: true})
}
Any aid is appreciated.
A try/ catch block could work.
Wrap the call in the try block and put any error handling code you want in the catch block.
This way if the user types in "New Jork", the call will fail and enter the catch block. (You could also use .then/.catch instead as fetch returns a promise, up to you)
You should also check the response before setting it to the state, put something like this after response;
if (!response.ok) {
return "INPUT ERROR";
}
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/try...catch

Assert that element cannot respond to mouseover

I am trying to assert that, when I mouseover a covered element, the element on top is activated and not the hidden one.
However, when using .trigger('mouseover') on the hidden object, an error occurs because I cannot mouseover that object, and the test stops.
Is there a way to try to mouseover and assert that a failure occurs?
Your best bet for now is probably to use this .shouldNotBeClickable() command, because if the element cannot be clicked then it also cannot be hovered. Use this command with caution, as it skips all remaining commands in your it() block when used due to a bug in Cypress.
As of right now (Cypress 3.1.0), this is not possible. It should be as per this answer, but cy.once() has some code-breaking bugs that I've run into trying to adapt the command in that answer.
The following custom command does not work as of Cypress 3.1.0. It should work, but it causes Cypress to hang.
index.js:
Cypress.Commands.add("shouldNotBeHoverable", {
prevSubject: true
}, function(subject) {
let errorMessage = "shouldNotBeHoverable: element hover succeeded, but it souldn't have";
let done = false;
cy.wrap(subject[0]).trigger('mouseover', { force: true });
cy.once('fail', (err) => {
if (err == errorMessage)
throw errorMessage;
expect(err.message).to.include('cy.trigger() failed because this element');
expect(err.message).to.include('is being covered by another element');
done = true;
});
cy.wrap(subject[0]).trigger('mouseover', {timeout: 1000});
cy.get('html').then(() => {
if (!done)
throw errorMessage;
});
});
Cypress test:
cy.get("#selector").shouldNotBeHoverable();
The related Github issues are linked below. This specific issue isn't reported, but both issues are similar enough that I suspect the underlying cause is the same.
Mixing cy.on()/cy.once() with a one-argument it() function causes test to hang
Queued commands silently skipped when using cy.once() in a custom command

ResizeObserver - loop limit exceeded

About two months ago we started using Rollbar to notify us of various errors in our Web App. Ever since then we have been getting the occasional error:
ResizeObserver loop limit exceeded
The thing that confuses me about this is that we are not using ResizeObserver and I have investigated the only plugin which I thought could possibly be the culprit, namely:
Aurelia Resize
But it doesn't appear to be using ResizeObserver either.
What is also confusing is that these error messages have been occuring since January but ResizeObserver support has only recently been added to Chrome 65.
The browser versions that have been giving us this error are:
Chrome: 63.0.3239 (ResizeObserver loop limit exceeded)
Chrome: 64.0.3282 (ResizeObserver loop limit exceeded)
Edge: 14.14393 (SecurityError)
Edge: 15.15063 (SecurityError)
So I was wondering if this could possibly be a browser bug? Or perhaps an error that actually has nothing to do with ResizeObserver?
You can safely ignore this error.
One of the specification authors wrote in a comment to your question but it is not an answer and it is not clear in the comment that the answer is really the most important one in this thread, and the one that made me comfortable to ignore it in our Sentry logs.
This error means that ResizeObserver was not able to deliver all observations within a single animation frame. It is benign (your site will not break). – Aleksandar Totic Apr 15 at 3:14
There are also some related issues to this in the specification repository.
It's an old question but it still might be helpful to someone. You can avoid this error by wrapping the callback in requestAnimationFrame.
For example:
const resizeObserver = new ResizeObserver(entries => {
// We wrap it in requestAnimationFrame to avoid this error - ResizeObserver loop limit exceeded
window.requestAnimationFrame(() => {
if (!Array.isArray(entries) || !entries.length) {
return;
}
// your code
});
});
If you're using Cypress and this issue bumps in, you can safely ignore it in Cypress with the following code in support/index.js or commands.ts
const resizeObserverLoopErrRe = /^[^(ResizeObserver loop limit exceeded)]/
Cypress.on('uncaught:exception', (err) => {
/* returning false here prevents Cypress from failing the test */
if (resizeObserverLoopErrRe.test(err.message)) {
return false
}
})
You can follow the discussion about it here.
As Cypress maintainer themselves proposed this solution, so I believe it'd be safe to do so.
We had this same issue. We found that a chrome extension was the culprit. Specifically, the loom chrome extension was causing the error (or some interaction of our code with loom extension). When we disabled the extension, our app worked.
I would recommend disabling certain extensions/addons to see if one of them might be contributing to the error.
For Mocha users:
The snippet below overrides the window.onerror hook mocha installs and turns the errors into a warning.
https://github.com/mochajs/mocha/blob/667e9a21c10649185e92b319006cea5eb8d61f31/browser-entry.js#L74
// ignore ResizeObserver loop limit exceeded
// this is ok in several scenarios according to
// https://github.com/WICG/resize-observer/issues/38
before(() => {
// called before any tests are run
const e = window.onerror;
window.onerror = function(err) {
if(err === 'ResizeObserver loop limit exceeded') {
console.warn('Ignored: ResizeObserver loop limit exceeded');
return false;
} else {
return e(...arguments);
}
}
});
not sure there is a better way..
add debounce like
new ResizeObserver(_.debounce(entries => {}, 200);
fixed this error for me
The error might be worth investigating. It can indicate a problem in your code that can be fixed.
In our case an observed resize of an element triggered a change on the page, which caused a resize of the first element again, which again triggered a change on the page, which again caused a resize of the first element, … You know how this ends.
Essentially we created an infinite loop that could not be fitted into a single animation frame, obviously. We broke it by holding up the change on the page using setTimeout() (although this is not perfect since it may cause some flickering to the users).
So every time ResizeObserver loop limit exceeded emerges in our Sentry now, we look at it as a useful hint and try to find the cause of the problem.
In my case, the issue "ResizeObserver - loop limit exceeded" was triggered because of window.addEventListener("resize" and React's React.useState.
In details, I was working on the hook called useWindowResize where the use case was like this const [windowWidth, windowHeight] = useWindowResize();.
The code reacts on the windowWidth/windowHeight change via the useEffect.
React.useEffect(() => {
ViewportService.dynamicDimensionControlledBy(
"height",
{ windowWidth, windowHeight },
widgetModalRef.current,
{ bottom: chartTitleHeight },
false,
({ h }) => setWidgetHeight(h),
);
}, [windowWidth, windowHeight, widgetModalRef, chartTitleHeight]);
So any browser window resize caused that issue.
I've found that many similar issues caused because of the connection old-javascript-world (DOM manipulation, browser's events) and the new-javascript-world (React) may be solved by the setTimeout, but I would to avoid it and call it anti-pattern when possible.
So my fix is to wrap the setter method into the setTimeout function.
React.useEffect(() => {
ViewportService.dynamicDimensionControlledBy(
"height",
{ windowWidth, windowHeight },
widgetModalRef.current,
{ bottom: chartTitleHeight },
false,
({ h }) => setTimeout(() => setWidgetHeight(h), 0),
);
}, [windowWidth, windowHeight, widgetModalRef, chartTitleHeight]);
One line solution for Cypress. Edit the file support/commands.js with:
Cypress.on(
'uncaught:exception',
(err) => !err.message.includes('ResizeObserver loop limit exceeded')
);
https://github1s.com/chromium/chromium/blob/master/third_party/blink/renderer/core/resize_observer/resize_observer_controller.cc#L44-L45
https://github1s.com/chromium/chromium/blob/master/third_party/blink/renderer/core/frame/local_frame_view.cc#L2211-L2212
After looking at the source code, it seems in my case the issue surfaced when the NotifyResizeObservers function was called, and there were no registered observers.
The GatherObservations function will return a min_depth of 4096, in case there are no observers, and in that case, we will get the "ResizeObserver loop limit exceeded" error.
The way I resolved it is to have an observer living throughout the lifecycle of the page.
Managed to solve this in React for our error logger setup.
The Observer error propagates to the window.onerror error handler, so by storing the original window.onerror in a ref, you can then replace it with a custom method that doesn't throw for this particular error. Other errors are allowed to propagate as normal.
Make sure you reconnect the original onerror in the useEffect cleanup.
const defaultOnErrorFn = useRef(window.onerror);
useEffect(() => {
window.onerror = (...args) => {
if (args[0] === 'ResizeObserver loop limit exceeded') {
return true;
} else {
defaultOnErrorFn.current && defaultOnErrorFn.current(...args);
}
};
return () => {
window.onerror = defaultOnErrorFn.current;
};
}, []);
I had this issue with cypress tests not being able to run.
I found that instead of handling the exception the proper way was to edit the tsconfig.json in a way to target the new es6 version like so:
{
"extends": "../tsconfig.json",
"compilerOptions": {
"baseUrl": "../node_modules",
"target": "es5", --> old
"target": "es6", --> new
"types": ["cypress", "#testing-library/cypress"],
"sourceMap": true
},
"include": [
"**/*.ts"
]
}

ES6 - Confused about processing order of Promise

I've got this code:
let p1 = new Promise(function (resolve, reject) {
setTimeout(function () {
resolve({dogs: ['Fido', 'Spot']});
}, 2000);
});
p1.then(function (val) {
console.log('first then');
console.dir(val);
return _.extend(val, {cats: ['Fluffy', 'Whiskers']});
}).then(function (val) {
console.log('second then');
console.dir(val);
});
The unexpected console output shows:
I don't understand how cats could possibly be part of the value before it's actually appended into the object. The results printed in the second then make sense to me though. Am I missing something?
You're adding the cats property to the same object you already logged.
As the i icon tells you, the console only reads the properties of the object when you actually expand it.
As far as I know there is a bug in console.log by ES6 Promises. It waits for a few seconds before it logs the value of your object, that's why it contains the cats. If I remember well, this bug happens in firefox. I don't know how it behaves by the other browsers.

Code execution step by step (synchronous)

I just have two (see below) lines of code in my index.html. I want to execute the first line BEFORE the second line will be executed. How can I do/ensure that? Currently, "undefined" will be apprear in the console for dataDB, because the function getDataFunction() takes some time.
var dataDB = getDataFunction(afterDate, toDate, afterTime, toTime);
console.log("Content of dataDB: " + dataDB);
Probably an easy question for you :-) I appreciate your help!
UPDATE: getDataFunction()
This function just get some data (collection+json) from a server with d3 (data driven document)...The parameters are used to identify the data of interest (time frame).
function getDataFunction(afterDate, toDate, afterTime, toTime){
d3.json("http://server...", function(error, data){
if(error) {
console.log(error);
} else {
console.log(data);
dataDB = data.collection.items;
console.log(dataDB);
}
});
}
D3 api reference
It says in the api reference the post is indeed done asychronously, thus the execution of the rest of the code proceeds (in this case console.log) there are no decent ways to make javascript wait. The best thing to do is to redesign it that your callback function takes care of whatever needs to come next.