In my Rails app there is a whole lot of front-end js, and I'd like to check is a specific event is attached to a DOM element.
An example of the JS that adds the event is here:
$('.nextCard')[0].addEventListener('click',nextCard);
I'd like to write something like:
expect(page).evaluate_script('$._data( $(".nextCard")[0], "events" )').to eq('nextCard');
I know it's a bit cryptic, and I could test the JS separately ... but I would like to do all the testing with Ruby / Capybara if possible.
How to return a value when using execute_script in capybara?
Can I find events bound on an element with jQuery?
Since you state the event is added using plain DOM methods (addEventListener) there is no way (cross browser/unprivileged code) to enumerate the listeners. However, if the handlers are attached via jQuery#on then you could check for the presence of a click handler with something like
expect(page.evaluate_script('"click" in $._data( $(".nextCard")[0], "events" )')).to be true
That being said, what you're trying to do is not really a great idea, and will end up with really brittle tests. What you should be doing in your feature tests is verifying the behaviors those click handlers facilitate work.
Related
I'm studying Javascript using Visual Code and every time a similar exercise that uses 'event' (the event shows in the code with the strikethrough like e̶v̶e̶n̶t̶) appears I can't complete it because of this annoying issue. In the description pop up a warning showing the issue ("event is deprecated ts(6385)"). I look out in the forums and stack over flow but I can not find any answer for this problem, only a few places says the lib dom and #deprecated, but I don't what to do.
Please, any way to help and learn to pass this problem out will be very useful.
function sayMyFirstName(element){
alert("My First name is..." + element.value)
}
function sayMyLastName(){
console.log(event)
}
It sounds like you're getting TypeScript validation for a simple JS project. There are several things you can try:
In your settings file (settings.json):
"typescript.validate.enable": false
... OR ...
In your .js source file(s):
/*tslint:disabled*/
A separate issue is why you're getting the "deprecation" warning in the first place. This is the reason:
https://developer.mozilla.org/en-US/docs/Web/API/Window/event
The read-only Window property event returns the Event which is
currently being handled by the site's code. Outside the context of an
event handler, the value is always undefined.
You should avoid using this property in new code, and should instead
use the Event passed into the event handler function. This property is
not universally supported and even when supported introduces potential
fragility to your code.
In other words, "event" should really be passed as an argument to a JS event handler. You shouldn't be using the global object; you shouldn't NEED to use the global object.
Here are a few good tutorials:
Introduction to events (MDN.com)
JavaScript Events
Strong suggestion:
If you're learning JavaScript, please make sure your study materials are up-to-date (definitely covering ES6!). This is a good book: Secrets of the JavaScript Ninja 2nd Edition
It looks to me that the TypeScript Validator is saying the implicit passing of event is deprecated. A simple fix would be to pass the event into the function as a parameter
function sayMyLastName(event){
console.log(event)
}
I'm migrating a lot of functionality from JS to Angular and found this issue a lot
You can use "window.event" to replace the deprecated "event".
You just need to open >Preferences: Open Workspace Settings (JSON) by Ctrl + Shift + P in VSCode then add this line to JSON file "editor.showDeprecated": false to disable a show deprecated in case if you only need to some workspace.
If you want to disable all workspace then use >Preferences: Open Settings (JSON) instead.
i would like to know the intention of the "this.own()" method in dojo widgets. This method is mentioned in the Dojo Api 1.8 Documentation, for example under diijit/form/button. I did not find anything that made sense to me on google. That is how the method is mentioned:
connect(obj, event, method)
Deprecated, will be removed in 2.0, use this.own(on(...)) or
this.own(aspect.after(...)) instead.
The own function is defined in dijit/Destroyable, which is a base of dijit/_WidgetBase and thus most widgets.
dijit/Destroyable is used to track handles of an instance, and then
destroy them when the instance is destroyed. The application must call
destroy() on the instance in order to release the handles
http://dojotoolkit.org/reference-guide/1.8/dijit/Destroyable.html
http://dojotoolkit.org/reference-guide/1.8/dojo/Evented.html
The short answer is: most of the things that you define inside .own() are getting correctly removed once the widget itself is destroyed. Using .own() prevents memory leaks in your app.
To remove a widget from a page, you can either call destroy or
destroyRecursively on your widget.
When you do that, anything that you added using this.own ( dojo/on,
dojo/aspect, dojo/topic, dojo/router, the creation of a related DOM
node or widget, etc.) will be removed and/or unregistered
automatically. This is implemented via the dijit/Destroyable
interface.
Understanding-WidgetBase-own-td4002453.html
Related Tutorial
My addon is injecting some content scripts into various websites. After trying to bind onbeforeunload or calling window.location.reload I realized that the window object misses some properties.
Is there a way to binding certain events (onbeforeunload, onunload, etc) while injecting code via page-mod module?
I've created a test add-on, showing that these properties are missing: https://builder.addons.mozilla.org/addon/1037497/latest/
Solutions on how to use them anyway?
Short answer: You add an event listener using addEventListener() method, like this:
window.addEventListener("beforeunload", function(event)
{
...
}, false);
Long answer: For security reasons your content script isn't communicating with the DOM objects directly, e.g. it cannot see any script-added properties. The technical details also list some limitations:
Assigning to or reading an on* property on an XPCNativeWrapper of a
DOM node or Window object will throw an exception. (Use
addEventListener instead, and use event.preventDefault(); in your
handler if you used return false; before.)
In a content script you probably don't want to replace the web page's event handlers anyway, rather add your own - that's what addEventListener() is doing.
Additional reading
I can't get Lettuce / Splinter or JsTestDriver to run tests of user interaction with Backbone-generated DOM objects. For example, at the hello backbone tutorial, I want to simulate the user's click on the button labeled "Add list item", then verify that a <li> element of text "hello world1" has appeared.
JsTestDriver: I can get a reference to the button element and call click() on it, but then document.getElementsByTagName("li") fail (or return null?).
Johansen's excellent book says that testing event handlers isn't properly a unit testing task. So I tried my BDD (?) tools for Django:
Lettuce / Splinter / Django: The Splinter Browswer object can't see the text in the button, never mind get a reference to it or click it. (It does handle these operations for elements created via HTML.) Neither world.browser.is_text_present() nor find_by_id() work; passing a wait time to the former didn't help.
I would really prefer to avoid going straight to Selenium, and thought that these tools made that unnecessary. So now what?
While firing DOM events may technically not be "unit testing", it doesn't mean you can't use a unit testing framework to do it :) This is more of a case of definition.
Anyway, you can achieve what you want with e.g. JsTestDriver, but I would advise against doing it manually through e.g. click() (which likely does not do what you expect it to). I usually use jQuery to fire events, and this can safely be done with e.g. JsTestDriver. This should work even if you don't use jQuery in your production code.
I am a Selenium newbie ...
As a JavaScript programmer, I think I want to handle JavaScript events in my Selenium-2 tests (JUnit). I am joining a team where all of the existing tests have "waitForSomethingToBeRendered" methods. Is there some way my Selenium tests can handle/listen for DOM (or custom) events?
Also, I've read on SO where developers use FireBug to write/debug Selenium-2 tests. How does this work? I don't see FireBug in the browser launched by Selenium. Similarly, why does the following appear to have no effect? Am I trying something Selenium/JUnit does not support?
selenium().getEval("alert('hello');");
selenium().getEval("debugger;");
You don't see the firebug extension because selenium opens a stripped firefox. I'm guessing the reason is it's much faster. It's possible (and quite easy in selenium-2) to add the plugin.
The alert doesn't work because selenium-1 (I don't know how selenium-2 handles them) swallows the alerts. There's an api for handling alerts.
Plus, in selenium-1, the JS runs in a different window. So the equivalent of document.getElementById() is sel.getEval("selenium.browserbot.getCurrentWindow().document.getElementById()").
Finally, I don't know about events but you can wait for conditions: sel.wait_for_condition().
Firstly if you are getting started with Selenium I suggest using the 2.0 API which is for WebDriver. To evaluate JavaScript in 2.0 simply cast your WebDriver object to a JavascriptExecutor object and use the methods provided by it. 'waitForSomethingToBeRendered' needs to be done in a few steps. First of all you must ensure the DOM object is available on the page. For this you can do something like this:
WebElement e = null;
try {
e = driver.findElement( By.id("asdf") );
} catch {
...
}
Or:
driver.findElements( By.id("asdf") ).size() != 0
After determining whether the DOM object is available you can do:
e.isDisplayed()
Which will return to you whether the element is currently displayed.
In regards to what you have seen about FireBug and Selenium I am guessing you are confusing Selenium IDE which is a Firefox plugin with Selenium RC/WebDriver which is not a plugin.
Use Firebug for Firefox while normally browsing your site to explore your DOM to determine the correct element and class ids to select in your Selenium script. If you are using extjs you are going to have some extra fun in determining which elements to select, as extjs randomizes element ids. The best way is to add an extra css class to find the correct element, then select by that class.