Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

'[object EventConstructor]' is not a constructor #11289

Closed
davidcelis opened this issue May 3, 2013 · 66 comments
Closed

'[object EventConstructor]' is not a constructor #11289

davidcelis opened this issue May 3, 2013 · 66 comments
Assignees
Labels

Comments

@davidcelis
Copy link

@davidcelis davidcelis commented May 3, 2013

This seems like a PhantomJS bug, but feel free to educate me if otherwise.

If I put new Event(message) in a Jasmine test and run it under PhantomJS's headless browser, I get an error saying '[object EventConstructor]' is not a constructor. This is weird, considering EventConstructor is probably really a constructor. If I run the Jasmine test normally (i.e. fire up a Jasmine server and let the test run in my actual browser), it works.

To fix the test on Phantom, I have to change new Event(); to document.createEvent();, which is deprecated.

@JamesMGreene
Copy link
Collaborator

@JamesMGreene JamesMGreene commented May 4, 2013

I don't see new Event mentioned anywhere in the DOM4 spec, only derived types like new UIEvent, new MouseEvent, etc.

Even with the spec considered, I've personally never seen this used in the real world nor have I really found any practical documentation examples (i.e. on MDN, WebPlatform, etc.), so this must be a pretty new shift (which also means it likely isn't supported in PhantomJS yet as we have an older version of WebKit at the moment). If you know of any good documentation, please share it for my own edification.

@davidcelis
Copy link
Author

@davidcelis davidcelis commented May 4, 2013

The MDN says to "use event constructors instead" here: https://developer.mozilla.org/en-US/docs/DOM/document.createEvent

If this isn't official, then I can retract this, but it is perturbing. MDN is where everybody points me to for JS-related docs, so I'm taking this as true.

But that doesn't seem to be my issue, I guess. I didn't realize that there are sub-constructors for specific event types that must be used. If that's the case, I'll give that a shot, and we can close this issue.

@JamesMGreene
Copy link
Collaborator

@JamesMGreene JamesMGreene commented May 4, 2013

I did find a reference to new Event after a second look at the DOM Level 4 spec: http://www.w3.org/TR/domcore/#concept-event

However, MDN's deprecation warning seems a bit premature since the spec is still only a draft. 😕

@carlthuringer
Copy link

@carlthuringer carlthuringer commented Jul 9, 2013

I'm also having this issue when trying to test that an event listener calls the right callback when an event occurs:

✘ sets the field value to the text
        ➤ TypeError: '[object EventConstructor]' is not a constructor (evaluating 'new Event('message')') in http://localhost:56873/assets/spec.js (line 42731)

but document.createEvent('message') doesn't work for me either.

 ➤ NOT_SUPPORTED_ERR: NOT_SUPPORTED_ERR: DOM Exception 9 in http://localhost:56873/assets/spec.js (line 42708)
@JamesMGreene
Copy link
Collaborator

@JamesMGreene JamesMGreene commented Jul 9, 2013

@carlthuringer: You're getting an error because you're not using document.createEvent correctly. Check out the suggested polyfill on MDN to easily see how document.createEvent and new CustomEvent differ.

TL;DR:
You need to do some like this:

var evt = document.createEvent('CustomEvent');  // MUST be 'CustomEvent'
evt.initCustomEvent('yourCustomEventName', false, false, null);
@carlthuringer
Copy link

@carlthuringer carlthuringer commented Jul 9, 2013

Awesome, thanks for the quick explanation and response!

@ianstormtaylor
Copy link

@ianstormtaylor ianstormtaylor commented Aug 26, 2013

+1

Also getting this error, except it's in a 3rd party library I have no access to. new Event('click') doesn't throw an error in the browser, so it would be nice if it didn't throw an error in Phantom either.

@kramerc
Copy link

@kramerc kramerc commented Oct 29, 2013

I have found that this issue is caused by QtWebKit in Qt4. This problem doesn't occur in Qt5 when testing with a simple web browser application though.

@rossbruniges
Copy link

@rossbruniges rossbruniges commented Jan 16, 2014

Wondering if this bug is going to get active development?

I found that the only way I could trigger a resize event on window was by using new Event('resize') and then dispatchEvent.

@peter-mouland
Copy link

@peter-mouland peter-mouland commented Jan 16, 2014

I was just wandering if this was still an issue?

I just bumped into the following error:

'[object EventConstructor]' is not a constructor (evaluating 'new Event(e)')

when running the following code within my mocha spec:

event.emit(window,'resize');

which translates into this pretty standard cross browser event handler

function emit(el, eventName) {
        var event;
        if (document.createEvent) {
            event = new Event(eventName);
            el.dispatchEvent(event);
        } else {
            event = document.createEventObject();
            el.fireEvent('on' + eventName, event);
        }
    }
@hous
Copy link

@hous hous commented Feb 6, 2014

Having issues with this myself. No problem executing tests in all browsers except phantomjs, which does throws a TypeError.

@sukima
Copy link

@sukima sukima commented Mar 28, 2014

For others who might stumble on this from Google, this is how I managed to facilitate my own tests that used keyboard events manually. The reason I had to do this was that I couldn't use $('#foo').keyup() as jQuery's trigger would not fire the browser's events that were added via addEventListener but only events that were attached through the jQuery's API. (Pasted gist available for commenting):

// <input id="my-input-element" type="text" value="foo"/>
var evt, node = document.getElementById('my-input-element');

// Have to use dispatchEvent/fireEvent because jQuery.trigger will not
// fire an event attached via addEventListener. Each environment has an
// unusual way to trigger a keyup event.
if (node.dispatchEvent) {
  // Sane browsers
  try {
    // Chrome, Safari, Firefox
    evt = new KeyboardEvent('keyup');
  } catch (e) {
    // PhantomJS (wat!)
    evt = document.createEvent('KeyboardEvent');
    evt.initEvent('keyup', true, false);
  }
  evt.keyCode = 32;
  node.dispatchEvent(evt);
} else {
  // IE 8
  evt = document.createEventObject('KeyboardEvent');
  evt.keyCode = 32;
  node.fireEvent('onkeyup', evt);
}

The situation I had to got me there was that I was in a test runner which had jQuery available for doing fixtures and testing assertions but the code I was testing (read: module) needed to be jQuery free. That code would attach to DOM events via addEventListener but when the test script attempted to trigger the event via jQuery it was ignored. Forcing me to trigger the event manually in all the browser environments.

sukima added a commit to sukima/PasswordWidget that referenced this issue Mar 28, 2014
Seems both IE8 and PhantomJS need a lot of tender love and care to
dispatch a keyboard event. Had to open several conditionals to handle
them all.

This is the only spec that needs this help as once it works we can then
use the internal event system of PasswordWidget and never have to worry
about the keyup event again.

For reference IE8 lacks a dispatchEvent allowing a simple if/else to
detect. Phantom JS however doesn't support the standard event
constructors (yes, there is a languished [issue reported][1] about it)
but it does support dispatchEvent causing a difficulty in testing for
it. I used a try/catch to trap if it fails to create the event per
standards and fall back to the deprecated createEvent method that is
supported by PhantomJS.

[1]: ariya/phantomjs#11289
sukima added a commit to sukima/PasswordWidget that referenced this issue Mar 28, 2014
Seems both IE8 and PhantomJS need a lot of tender love and care to
dispatch a keyboard event. Had to open several conditionals to handle
them all.

This is the only spec that needs this help as once it works we can then
use the internal event system of PasswordWidget and never have to worry
about the keyup event again.

For reference IE8 lacks a dispatchEvent allowing a simple if/else to
detect. Phantom JS however doesn't support the standard event
constructors (yes, there is a languished [issue reported][1] about it)
but it does support dispatchEvent causing a difficulty in testing for
it. I used a try/catch to trap if it fails to create the event per
standards and fall back to the deprecated createEvent method that is
supported by PhantomJS.

[1]: ariya/phantomjs#11289
@mendozao
Copy link

@mendozao mendozao commented Jun 6, 2014

I just ran into this issue - not sure how to work around it. According to MDN, document.createEvent is deprecated - so using event constructors is the correct way to implement your custom events.

See:
https://developer.mozilla.org/en-US/docs/Web/Guide/Events/Creating_and_triggering_events
https://developer.mozilla.org/en-US/docs/Web/API/document.createEvent (Deprecated)

@sukima
Copy link

@sukima sukima commented Jun 8, 2014

@mendozao at the time I wrote the above comment PhantomJS did not support KeyboardEvent and still relied on the deprecated createEvent. I do not know if newer versions of PhantomJS have changed since.

@mendozao
Copy link

@mendozao mendozao commented Jun 10, 2014

@sukima the error I was getting was the following:

PhantomJS 1.9.7 (Mac OS X) player encountered a declaration exception FAILED
ReferenceError: Can't find variable: CustomEvent

In my code, I create an event using the following syntax:

var myevent  = new CustomEvent('onSomething');

Just seems wrong to have to write conditional logic in my code to support phantomJS's implementation

@sukima
Copy link

@sukima sukima commented Jun 11, 2014

Kinda sucks. The above is the best I could do.

Although if I had a choice I'd just rely on jQuery's event system or something of the like. Unfortunately the requirements I had circumvented any third party event system and forced me to come up with a cross browser / cross PhantomJS test suite as seen above.

@leeight
Copy link
Contributor

@leeight leeight commented Jul 25, 2014

+1

@vitallium
Copy link
Collaborator

@vitallium vitallium commented Jul 31, 2014

Fixed in 2.0

@vitallium vitallium closed this Jul 31, 2014
@peter-mouland
Copy link

@peter-mouland peter-mouland commented Jul 31, 2014

@vitallium when is 2.0.0 to be released, i see it's currently on 1.9.7?

@perrin4869
Copy link

@perrin4869 perrin4869 commented May 12, 2016

Same problem with phantomjs@2.1.1 (using npm's phantomjs-prebuilt):

KeyboardEventConstructor is not a constructor (evaluating 'new KeyboardEvent('keydown', {
                      key: 'a',
                      keyCode: 65,
                      which: 65
                    })')
marcandre added a commit to marcandre/chosen that referenced this issue Sep 25, 2016
marcandre added a commit to marcandre/chosen that referenced this issue Sep 27, 2016
@astrotim
Copy link

@astrotim astrotim commented Dec 1, 2016

My workaround to get tests working in both browsers and PhantomJS:

var clickEvent;
var keyupEvent;

// check if Event() is a constructor function
// usage as per the spec, if true
if (typeof(Event) === 'function') {

	clickEvent = new MouseEvent('click');
	clickEvent.initMouseEvent('click');

	keyupEvent = new Event('keyup');

// the deprecated way for PhantomJS
} else {

	clickEvent = document.createEvent('CustomEvent');
	clickEvent.initCustomEvent('click', false, false, null);

	keyupEvent = document.createEvent('CustomEvent');
	keyupEvent.initCustomEvent('keyup', false, false, null);

}

Usage:

submitButton.dispatchEvent(click);
textInput.dispatchEvent(keyup);
@dwightdegroff
Copy link

@dwightdegroff dwightdegroff commented Jan 19, 2017

Any progress here? Still running into"
TypeError: MouseEventConstructor is not a constructor (evaluating 'new MouseEvent("click")')

On PhantomJS 2.1.1

@evandavis
Copy link

@evandavis evandavis commented Jan 19, 2017

@dwightdegroff I switched to jsDOM 6 months ago and have never been happier.

@cantonic
Copy link

@cantonic cantonic commented Feb 2, 2017

we have failing tests because of TypeError: MouseEventConstructor is not a constructor (evaluating 'new MouseEvent("click")') and tried using PhantomJS 2.5.0-beta on TravisCI. Now all tests that were failing with the mentioned error are now failing with this:

Capybara::Poltergeist::DeadClient:
        PhantomJS client died while processing {"id":"9600aa3c-0be5-40f3-9010-018c39322890","name":"visit","args":["http://127.0.0.1:35752/messages/conversations",30]}
@cantonic
Copy link

@cantonic cantonic commented Feb 2, 2017

Not sure if this will help anyone else, but we were able to solve the issue by tracking it down to opal-browser gem. This commit fixes it for us: opal/opal-browser@6791db2

@runarberg
Copy link

@runarberg runarberg commented Feb 7, 2017

This short shim worked for me:

function keyboardEvent(eventType, init) {
  try {
    return new KeyboardEvent(eventType, init);
  } catch (error) {
    const modKeys = [
      init.ctrlKey ? 'Control' : '',
      init.shiftKey ? 'Shift' : '',
      init.altKey ? 'Alt' : '',
      init.altGrKey ? 'AltGr' : '',
      init.metaKey ? 'Meta' : '',
    ].join(' ');
    const keyEvent = document.createEvent('KeyboardEvent');
    keyEvent.initKeyboardEvent(
      eventType,
      false,
      false,
      window,
      init.char || '',
      init.keyCode || 0,
      modKeys,
      init.repeat || false,
    );
    keyEvent.key = init.key;

    return keyEvent;
  }
}

And using it like so:

document.body.dispatchEvent(keyboardEvent('keydown', { key: 'Escape' }));
@inf3rno
Copy link

@inf3rno inf3rno commented Feb 8, 2017

@astrotim Creating some kind of polyfill would be better and you don't have to load it in your production code, just for testing.

@bertofer
Copy link

@bertofer bertofer commented Feb 8, 2017

We have faced this problem as well. In our case, we were using angular 2 testing and doing some MouseEvent with clientX and clientY properties. All the tests were working until we changed to PhantomJS instead of Chrome for CI, then we faced this.

We could fix it for PhantomJS, instead of creating a MouseEvent, creating an Event passing clientX and clientY properties, but then the typescript compiler complained that clientX and clientY are not properties expected on the properties passed to the event.

We ended up just doing:

const evtOpts = {
      clientX: component.menuContainer.nativeElement.offsetLeft + 1,
      clientY: component.menuContainer.nativeElement.offsetTop + 1
};
window.dispatchEvent(new Event('mousedown', evtOpts));

This way, evtOpts gets an implicit any, so when passed to Event constructor, TS does not complain, and PhantomJS works.

@justingrayston
Copy link

@justingrayston justingrayston commented Feb 24, 2017

@runarberg I hope you don't mind, but I created your function into a phantomJS polyfil. As above, I wanted to test in Angular2+ in Typescript and it type checking complained about the assignment of readonly properties. Being able to load it in via yarn or npm means it is outside of the linted code. It also makes it easily available to all.

https://github.com/justingrayston/basic-keyboard-event-polyfill

@runarberg
Copy link

@runarberg runarberg commented Feb 24, 2017

@justingrayston Sure, go ahead.

FYI: I extracted the vital bits from https://github.com/termi/DOM-Keyboard-Event-Level-3-polyfill.

@ghiscoding
Copy link

@ghiscoding ghiscoding commented Feb 28, 2017

In order to fix the

MouseEventConstructor is not a constructor (evaluating 'new MouseEvent')

I used the Polyfill from the MSDN MouseEvent docs and that finally worked.

@inf3rno
Copy link

@inf3rno inf3rno commented Feb 28, 2017

Probably creating a repo including both polyfills, and publishing it on npm as phantomjs-event-polyfill would be a wise idea until this is fixed. As far as I remember the error stack has similar issues, I managed to fix it somehow in my (partially complete) error polyfill.

@vitallium
Copy link
Collaborator

@vitallium vitallium commented Feb 28, 2017

Could you try again with 2.5 binary please? Thanks!

@lechu1985
Copy link

@lechu1985 lechu1985 commented May 25, 2017

For the same reasons as @justingrayston I created a npm package for helping PhantomJS with Mouse Events. It is based on the solution provided by: @ghiscoding

https://github.com/lechu1985/basic-mouse-event-polyfill-phantomjs

@fgc29
Copy link

@fgc29 fgc29 commented Aug 21, 2017

I been experiencing a sort of similar problem. TypeError: undefined is not a constructor (evaluating 'targetElement.closest('tr')'). The arg 'targetElement' is the supposed to be the DOM target element retrieved from event.target. But event.target is only returning the href in a string. Has anyone had this happen and if so, were you able to resolve it? This is for a rails 5 system test using poltergeist to run the headless test.

@stale
Copy link

@stale stale bot commented Dec 28, 2019

Due to our very limited maintenance capacity (see #14541 for more details), we need to prioritize our development focus on other tasks. Therefore, this issue will be automatically closed. In the future, if we see the need to attend to this issue again, then it will be reopened. Thank you for your contribution!

@stale stale bot closed this Dec 28, 2019
@inf3rno
Copy link

@inf3rno inf3rno commented Dec 29, 2019

Great, so a 6 years old confirmed bug was not fixed. Is this repo even maintained?

@HolgerJeromin
Copy link
Contributor

@HolgerJeromin HolgerJeromin commented Dec 30, 2019

Cleanup is a very strong sign of restart of maintenance.
There are no recources to check every 1400 issues if they are still valid. If they are still valid and important they can be reopened.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
You can’t perform that action at this time.