We're developing several widgets, and have a requirement that we must support keyboard navigation (accessibility).
We've added keyboard navigation as to the spec, and all is well, but we also want to test that it works using unit tests.
What we have tried is testing it with
selenium, but selenium does not seem to record arrow keys
busterJS, using the solution given in thread Simulate left and right arrow key event with javascript. But here we get different exceptions indicating that we are doing something illegal.
Triggering the event using jQuery trigger(), with the same results as the previous attempt.
I can understand that fireing keyboard events with key codes can be viewed as dangerous by browser manufacturers, and thus prohibited (If thats the core problem here). If this is actually the case, is there some option to set in IE10, Chrome or Firefox to enable the possibility to fire the events?
Any comments are welcomed, I might also be looking in the completely wrong direction here, so if you have some thoughts on how to unit test keyboard navigation in javascript, please feel free to enlighten me :)
Well some solutions turned up,
The old saying "when the user says nothing has changed, asume he is lying" turned out to be truthy once again. I retested the solution in the "Simulate left and right arrow key event with javascript" thread, and doing it exactly as the solution there described worked (except IE10).
To make it work in IE10, I needed to switch the order of the if tests in the solution, because IE10 obviously only supports document.createEvent(), even though document.createEventObject evaluates to true.
I also found a solution for Selenium.
Even though selenium does not record the arrow key navigation, you can specify a keyDown command, set an element locator as your target and the escaped keyCode as your value (\37 = left, \38 = up, \39 = right, \40 = down)
How to specify selenium element locators is described in the Selenium documentation
For both solutions to work, you need to attach the elements you want to use for your test to the DOM.
Related
Background:
I often find myself in the position of debugging a piece of Java script on a web page in an unfamiliar codebase, and often one that has seen many developers and coding approaches. Sometimes I do not even what technologies might be in use, eg. angular etc.
The first time I need to address the Java script is when a specific behaviour is unexpected (ie. it has gone wrong.)
Question:
What tool provides the fastest route to identifying the entry point of the code that is causing the problem?
Example:
I have an html element on a page lets say a button. When that button is clicked I expect to see an http request at the server. There are many ways the element can be associated with its Java script listener. eg JQuery, thrid party plugins such as knockout etc, in house scripts, and so on.
Using developer tools I can start debugging this in the browser but only if I already know the entry point to put a breakpoint on.
Is there a faster method to find the entry point than doing regular expressions searches on the pages code based on intuition and guess work to find what might be attached to that particular element?
For me, the best starting point is in Chrome developer tools. You can:
Choose an element in the elements tab
On the right-hand side of the elements tree, click the "Event Listeners" tab.
Find the event you want to debug (like click)
Click the hyperlink to bring up the code for event listeners, and set breakpoints. Sometimes you have to click the "format code" button (looks like { }) to get the code on multiple lines so that the breakpoint is manageable.
Do the click, and you'll hit your breakpoint, allowing you to step through the code, add watch variables, etc.
I have a webapp which will be viewed using certain popular browsers and I am required to support the handling of certain keypress events. Our users will be using Windows and the keypress events always use the Alt key as a modifier.
There is no specific requirement for keyUp/keyDown event handling, the user just has to feel like something happens when he/she presses, for example, Alt-F.
How do we accomplish this in the Firefox browser, which we are required to support?
The problem:
All of our implementation attempts are interfered-with by the fact that when the FireFox menu bar is visible (File, Edit...), pressing an Alt key combination which is already claimed by the menu bar (example: Alt-f) will cause the appropriate menu to expand. We don't want this to happen. I have been shown examples of web apps (using tens of thousands of lines of javascript....) that do NOT experience this issue, so I know it is possible, but I don't know how this was done in the example I've seen with my own eyes.
I can find dozens of examples on the web of how to write an alt-key handler in JS, but I haven't found a single article on this issue or a single code example that works under the circumstances I've described. We are using Spring-MVC and a recent version of jQuery, if that matters.
I'm happy to update the question with any other information that proves relevant.
Side note about work-around suggestions:
The requestor has specifically demanded that I use the Alt key as the modifier, on the grounds that they use other webapps in FireFox where both the menu-bar is visible AND alt key combinations work. (Example: Alt-s). So, feel free to post well-intentioned work-arounds in the comment section if you wish - I promise that my own personal curiosity will drive me to read them all - but also keep in mind this is not the subject of my question.
Be aware that some browsers will not allow you to capture certain shortcuts! A working example in native Javascript for the Alt+s shortcut in Mozilla Firefox (version: 51.0.1, Linux):
window.onkeydown = function(e){
if(e.altKey && e.keyCode == 83){
e.preventDefault();
alert("Shotcut Pressed")
}
}
Hotkeys have been done well by various projects, such as jquery.hotkeys. You can see a working example on their demo page for most hotkeys. It's very small, only about 200 lines.
Here is a small example with the Alt+S hotkey that works for me (without triggering the history menu) in Firefox 40.0.2 (when the page is in focus of course, not the codepen editor).
$(document).bind('keydown', 'Alt+s', function() {
$('body').append('Alt+s was pressed; ');
// alert('alert will cause the menu to activate, do not use');
return false;
});
I'll pick Chrome for this example, but I'm open to a solution from any browser.
Use Case:
I have an update button on my website that is used to update item quantities in a shopping cart. I'd like to allow a user to enter a 0 and click update in order to remove the item. Trouble is, there is some listener in some js function that is denying the ability to enter a 0 and click update (after clicking update the old quantity remains).
My question is, what developer tool can I use to find which js function is running during that event? I don't think that Chrome's inspector does this, and I'm not very familiar with Firebug, but I couldn't find the functionality there either.
I feel that I should be able to inspect js firings just like I do css stylings. Is anyone aware of a tool I may use?
I've had to debug some particularly nasty unseen-cause Javascript issues at my job. Knowing the full depth of developer tools like Chrome's is definitely helpful. It undeniably takes some creativity to find places that might be causing the issue, but a few tips:
Tracking down event listeners
Under Chrome's Elements view, try Inspect-ing an element (right-click, Inspect); then, on the right side of the developer view, scroll down to Event Listeners. Here you can view what code files have hooked up an event. Often, this will just point you to a middle-framework from the really devious code you're looking for, but sometimes it will point you in the right direction.
Trapping a DOM modification
Many of the unwanted effects I see are because of something changing some value or attribute on the page that I don't want. Anytime this happens, you can right-click on the element (under the Elements view) and say "Break on..." and the specific scenario you're looking for. When Chrome then hits a breakpoint, you can then look downward in the Stack Trace until you find something recognizable that shouldn't be called.
EDIT after reaching ten votes!
Trapping a JS object modification
If the change you're interested in is code-internal, not in the UI, things get trickier. What's meant by this scenario is that you know somewhere in the code, something incredibly annoying like the following is happening.
company.data.myObject.parameter = undefined;
In this situation, you know myObject is still the same object, but it's being modified, perhaps unintentionally. For that, I often insert the following bit of code, sometimes just through the developer console at some point before said modification happens.
Object.defineProperty(company.data.myObject, 'parameter', {
set: (val) => {
debugger;
}
});
This includes an arrow function - you're only using this for debugging and Chrome supports it, so might as well save keystrokes. What this will do is freeze your debugger as soon as some line of code attempts to modify myObject's "parameter" property. You don't necessarily have to have a global reference to the variable if you can run this line of code from a previous breakpoint that will have the given object in the locals.
Otherwise, if all I'm starting out with is the HTML code, and I want to tie that to Javascript code, I'll often just look for identifying features like "id" elements, and search all JS files in my development directory for it. Normally, I can reach it pretty fast.
Open your page in Firefox with Firebug enabled.
Go to console tab in firebug and click profiling
enter 0 in the textbox and click the button.
Stop profiling.
You will be able to see all the javascript functions which have executed due to your actions. You can view them one by one to figure out which method has caused the mischief.
Go to you code. If you are using jQuery there is going to be a function that will be called with the class or id of that particular update button. Or, if you are using Javascript, there is going to be a function called inside the
<input type="button" name="update" onclick="update()">
These are the two ways to look for the function that is being called; there is no software that I know
Download Firebug for Mozilla Firefox, open it, click on Net and refresh your website. Than, you can see which files are loaded on the page.
If you want to check on errors and what goes wrong with an explanation, than click on console and refresh the page once again. You will see the errors and on which line it goes wrong.
Note: in your console, you can say hold or stop, so that the js file stops loading. And you can edit the script by clicking on script in Firebug. Debugging is simple, as it says on their official page https://getfirebug.com/javascript
This is a rather complicated question that may simply be impossible with what's currently available, but if there was an easy way of doing it it would be huge.
I'm debugging some JavaScript in Chrome, and because it's very event-driven, I prefer to get trace reports of the code (what got called, etc.) instead of breakpoints. So wherever I leave a breakpoint, I'd like to see the local function name and arguments.
The closest I can get is to drop a conditional breakpoint in, like the following:
There are two big problems with this approach:
Pasting this into each breakpoint is too cumbersome. People would be far more likely to use it if it could be chosen as the default action for each breakpoint.
In Google Chrome, the log calls get fired twice.
Any ideas on a way to surmount either of these problems? I think it might be possible in IE with VS, but the UI there seems equally cumbersome.
IE11 now has "tracepoints", independent of Visual Studio. They do exactly what you asked for three years ago. I don't see them in Chrome or any other browsers yet, but hopefully they will catch on soon!
The best option I found was to edit the javascript code in Chrome's Javascript panel, adding a console.log.
It would only work after the page has been loaded (unless you can afford to put a break point after refresh and then add the logging lines) and (to be worse) you would have to do it each time you reload the page.
Good luck with your search!
I couldn't find something to do this, so I wrote my own.
Now, instead of constantly inserting and removing console.log calls, I leave the logging in and only watch it when necessary.
Warning: specific code below is untested.
var debug = TraceJS.GetLogger("debug", "mousemove");
$('div').mousemove(function(evt) {
debug(this.id, evt);
});
Every time the mouse is moved over a DIV, it generates a logevent tagged ["mousemove", {id of that element}]
The fun part is being able to selectively watch events. When you want to only see mousemove events for element #a, call the following in the console:
TraceJS('a');
When I want to see all mousemove events, you can call:
TraceJS('mousemove');
Only events that match your filter are shown. If you call TraceJS(no argument), the log calls stop being shown.
I'm a little distraught at the current state of key capturing for web applications. It works great as long as you know your user is going to be typing in a specific place (e.g. an input field), but as soon as you want to do global shortcuts for an entire "application", it seems to fall apart.
I'm trying to find out if there is a better way to capture all the key events for a web page than the method I am currently using.
My current method is to use the JQuery Hotkeys plugin, bound to the document element, i.e.:
$(document).bind("keyup", "delete", function() {});
That works great for most purposes, but for example on Firefox, if the user happens to absentmindedly move their mouse over the navigation bar, the delete key will sometimes result in the user going "back", and the key is never received by the handler so that I can stop propagation.
Is there a different element I should be binding to? Is there a better plugin out there for this? Should I just avoid using any keys that are bound to things in common web browsers?
As more and more web applications look to mimic their desktop counterparts, it seems like this is a basic feature that web developers will increasingly require.
EDIT: I should point out that I am already using e.stopPropagation() and e.preventDefault(). The main problem seems to be that sometimes the event is never even passed to the bound function. I am basically wondering if anyone has figured out a "higher" element to bind to other than document. Or is there an alternative I have never even thought of? Embedding an invisible Flash element on the page and then passing all keys from that to JavaScript, for example (I don't think this would work).
I think, at this point, I am doing things the "standard, well-known way." I am trying to see if there is an outside-the-box way that isn't widely known that maybe someone on Stack Overflow knows about :-).
If you are making a sophisticated web-app with customized keyboard controls, the first thing you should do is alert the user that you are making a sophisticated web-app with customized keyboard controls. After that, tell them what the controls are and what they do.
Binding the keypress and keydown listeners to the document is the correct way to do it, but you have to remember to preventDefault and/or stopPropogation for keypresses that you want to override. Even if there is no default behavior, you will need to prevent them from cascading in case the user has rebound their default keyboard shortcuts.
Also, you will only be able to receive keyboard input when the page has focus.
When you say Delete I assume you mean the Backspace key as Delete generally referrs to the key next to Insert, Home, End, Page Up and Page Down.
Edit to add:
Be very careful about which keys you choose to override. If you're making an app to be used by people other than yourself, you have to worry about usability and accessibility. Overriding the Tab, Space and Enter keys is risky, especially for people using screen-readers. Make sure to test the site blind and fix any issues that may arise with traversing the page via the keyboard.
maybe you can use html-attribute ACCESSKEY and react onfocus.
i.e.:
<input type="text" size="40" value="somefield" accesskey="F">
i think u might need to add a tabindex to tags like <div>
<div id="foo" tabindex="1" accesskey="F">
You can't bind to events that happen where you have no control - e.g. the window chrome. The way most webapps deal with this is asking the user to confirm their decision to leave the page, using the onbeforeunload event:
window.onbeforeunload = function (e) {
var str = 'Are you sure you want to leave this page?';
e = e || window.event;
if (userHasSomeUnsavedWork) {
e.returnValue = str;
return str;
}
}
onbeforeunload - MDC
Absolutly non-tested but... try it on 'window' element.