Imagine you want to click a button on a web site. How would you do it? Intuitively everyone knows how to do this. But what if you want the button to be clicked programatically so that for example it tests that the app is working correctly. In that case, a more rigorous set of steps for clicking a button is needed. Here is a simple algorithm (in pseudo-code) to accomplish this task:
Although this algorithm seems to work for most straightforward cases it is nowhere near robust enough for real world use. Let us look at some of the situations where this algorithm fails.
1. Button is outside of the viewport
This is a very common scenario, but is easy to overlook. Often, at the start of testing/development there is very little data so that when showing a list view or a template grid it all fits neatly on one screen. But as more data is added elements start to flow out of the viewport. In that case a user needs to scroll to the button before clicking it. Scrolling can be emulated with selenium, but it is often the responsibility of the developer to ensure elements are scrolled into view.
2. Button is not rendered yet
3. Button is rendered but disabled
When a button is clicked in a Mendix app, usually other buttons are disabled for the duration of the action. When a button is disabled it is still possible to move the mouse over it and press the mouse button, but the actual click event is not triggered. For the click function to work properly it needs to detect if a button is disabled and if yes then wait until it is enabled before clicking.
4. Button is obscured by other elements
So far, it was not important where the mouse was moved to, so long as it is inside the button. By default selenium moves to the middle of the button, except when it doesn't. This creates a problem because sometimes, e.g. in navigation menus, part of the button is overlaid behind other elements. In that case it is important to click the part of the button that is visible, as clicking a part that is overlaid might actually trigger a click for a completely different button (see screenshot).
This is a quite tricky issue. For the navigation menu one approach would be to target the icon instead of the entire button. One has to be careful since not all buttons have icons.
A similar problem is with check boxes and radio buttons where the center of the div (marked with a red
x in the screenshot) happens to be between the clickable parts. (very interesting bug to troubleshoot as it only occurs for labels with a certain width)
5. Button HTML structure changes
When building an app with Mendix, developers do not have to worry about HTML. The Mendix platform takes care of this. However, what many developers oversee, is that this HTML often changes when new Mendix versions are released. This has implications for testing, especially for the selector that is used to identify elements.
To give only one very recent example, for some time all widgets had the following attribute
data-button-id="10.Testpp.Page.actionButton2" - notice the last part which matches the widget name in Studio. Unfortunately, after the Mx8.8 release that attribute was changed and now only shows
data-button-id="10_191" which is not as useful anymore when it comes to identifying widgets.
Such changes happen constantly so if you ever decide to upgrade the Mendix version of the app it will happen that many of your tests are no longer working correctly. This is especially troublesome since when upgrading to a new Mendix version you want to test that the app remains functionally the same, and that might be hard to do if your tests are not working.
Based on all the above points the algorithm can be updated as follows:
This version of the algorithm although much better is still far from perfect and there are other edge case cases that need to be addressed. To name but one, what if the button is outside the viewport, but scrolling to it leaves it hidden behind a sticky header/footer. Intuitively a user would scroll a bit more until the button is visible. However, selenium tries to minimize scrolling so it will never scroll more than necessary. The outcome is that the click does not register or even worse, some other element from the header/footer is clicked by mistake (another fun bug to troubleshoot).
It turns out that the simple task of clicking a button is not as simple. At CLEVR we struggled with many of the above issues on a daily basis. This led us to develop the Application Test Suite, a testing tool that abstracts away the complexities of selenium and lets you focus on actual functional testing for your Mendix application.
How can ATS help you to click a button?
One of the built/in functions in ATS is Click Widget and it implements the algorithm above, but also includes special handling for many other edge-cases and browser and selenium inconsistencies. Moreover, all ATS functions include a so called Magic wait routine. This intelligent wait understands the Mendix runtime and makes sure that no clicks are attempted if Mendix is busy with opening a page, running a button action, refreshing with conditional visibility and many other scenarios.
In addition to click widget, ATS has over 200 other functions available out of the box and built specifically for Mendix widgets. For every function we guarantee compatibility between Mendix, Selenium and browser versions. If you are testing Mendix applications, value your sanity and would rather spend your time creating test cases than fighting with the inner workings and version inconsistencies in Selenium and Mendix HTML structure, then give ATS a try.
Thank you for reading this blog and happy testing!