chromeless icon indicating copy to clipboard operation
chromeless copied to clipboard

Evaluate function cannot run function that is received by parameter

Open ricardovsilva opened this issue 7 years ago • 6 comments

await this.browser.evaluate(function(fn){
    fn();
}, function() { alert('Hello World'); });

Try execute snipet above throws error:

(node:8052) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 2): Error: > TypeError: fn is not a function at :4:4 at :5:5 at :11:7

I tried to console.log(fn) and it appears as undefined on chrome console.

ricardovsilva avatar Aug 25 '17 18:08 ricardovsilva

@ricardovsilva Did you manage to resolve this issue? I'm facing the same problem...

herooutoftime avatar Sep 20 '17 08:09 herooutoftime

@herooutoftime unfortunately no =/

ricardovsilva avatar Sep 20 '17 16:09 ricardovsilva

Hey!

Sadly this is a shortcoming of how things get evaluated into the Chrome runtime. Deep deep down, chromeless stringifies arguments and calls evaluate with the stringified arguments. It's highly likely that your alert function is being transported properly.

Is there a particular reason you're passing a function into the evaluate call? Reason I ask is so that I can either help point you in the right direction or think of a better solution. https://github.com/graphcool/chromeless/blob/master/src/util.ts#L188 is where this all happens, FYI

joelgriffith avatar Sep 20 '17 22:09 joelgriffith

@joelgriffith , now I don't remember anymore why I needed that feature. Only thing that I can remember is that I was writing some integration tests with mocha and chai. I tried that to apply some DRY, but I really really don't remember now the details =/.

ricardovsilva avatar Sep 21 '17 10:09 ricardovsilva

@joelgriffith I just had this issue. I was trying to change the value of a select DOM element but I don't know how to do that with Chromeless. A hacky way I tried is dispatching an event in the evaluate function like so.

await browser
  .evaluate((selector, selectFn) => {
    selectFn(document, selector, 'newValue')
  }, selector, selectOption)

...
const selectOption = (document, selector, value) => {
  const element = document.querySelector(selector)
  const event = document.createEvent('HTMLEvents')
  element.value = value
  event.initEvent('change', true, true)
  element.dispatchEvent(event)
}

I am changing select DOM element values multiple times so I thought I could save some typing by making it a function.

Maybe there is a better way to do this?

paopow avatar Sep 22 '17 22:09 paopow

I'm running into this too. I need access to a SVGElement on the DOM so I can pass it to a chart generator library.

a. Passing functions to .evaluate() expresses them as null. b. Passing DOM nodes out of .evaluate() expresses those as {}.

This basically means the only way I can get a DOM element to my chart code is by wrapping all my chart code in a UMD and somehow getting it on page as a global, which feels super yucky.

aendra-rininsland avatar Mar 26 '18 13:03 aendra-rininsland