I have a page which consists of some disabled inputs, spans and divs.
In the background I wait for pressed keys. Background of this is some memory game.
My problem is, that it turned out to be pretty hard to test.
I know two functions to simulate input: type() and keys(). When I use keys("#someElement", "34"), I get "element not interactable". Similar happens with type() (well that's not surprising as type suggests filling some input).
How can I properly simulate a pressed key without using an active input element?
Use the underlying driver:
$browser->driver->getKeyboard()->sendKeys('a');
$browser->driver->getKeyboard()->sendKeys(\Facebook\WebDriver\WebDriverKeys::ENTER);
Related
I know that both of them can be used to validate if an element appears on the page but I was wondering about the performance impact and readability implications of each. So my question is, suppose you have 20 elements to check in the page,
Is it better to use Wait Until Element Is Visible for all 20 elements?
OR
Use Wait Until Element Is Visible for one element (for example, a header text) to let my automation script know that the page has loaded AND then use Element Should Be Visible for the rest (e.g. form fields)?
Yes, factually both of them can be used to validate if an element appears on the page but ofcoarse you can design your tests for a much better performance.
Ideally, the Waits should be implemented strictly as per your Usecase and Test Steps.
Using Wait Until Element Is Visible: If your usecase involves visibility of all the 20 elements, albeit Wait Until Element Is Visible is the best fit.
Using Wait Until Element Is Visible for header text AND then use Element Should Be Visible: If your usecase involves visibility of any element, inducing Wait Until Element Is Visible for header text would be a complete overhead. As you have no validation with the header text, this step isn't necessary. Rather you should directly induce Wait for the visibility of the desired element(s).
In a strict performance comparison the execution speed of Wait Until Element Is Visible vs Element Should Be Visible, on element(s) that is already present in the DOM, is virtually the same.
They both do the same thing - find the element in the DOM, and call selenium's is_visible() method. The difference is the Wait Until loops and repeats if any of the two steps fail.
Thus for your (or similar) case, when the presence of one element (the header) should guarantee the other 19 are also already loaded, which one to use shouldn't matter.
If you use Wait Until ... on the header and Element Should Be Visible on the others, you'll be also testing that assumption in your case. Naturally, if all but the 19th elements are loaded together with the header, the case will fail.
If you use Wait Until ... on all elements the chance of passing will be higher - if any of the elements is added and visualized slower than the rest, the kw will wait for it. Obviously this situation will lead to slower runtime - because of the waiting on the condition to be fulfilled.
As for the readability aspect of using one vs the other, I won't comment on that. This is a question of implementation and code structure; you can always make something simple look dreadful, or present a complex solution in a beautiful way :). The same as python allowing you to write code like poetry, or ugly mess (the same goes for some SO answers :D); yours truly is guilty of doing all of this :)
I'm using Robot Framework and Selenium to test a website that has a language selector. I need to be able to select a language and then verify the page has actually changed to that language.
Since after choosing a new language the value in the lang attribute of the <html> tag changes, I decided I would use that to validate the language has been successfully changed. But I'm getting flaky results, as my test sometimes passes and sometimes doesn't.
This is the definition of the keyword I'm using:
CHANGE LANGUAGE
[Arguments] ${lang}
Select From List By Value ${LANGUAGE SWITCH} ?hl=${lang}
Wait Until Page Contains Element css=html
${doc lang} Get Element Attribute css=html#lang
Should Be True '${doc lang}'=='${lang}' timeout=15s
Since I have to execute this keyword quite a few times (one per each available language), I keep getting pretty often the dreaded "stale element" error: | FAIL | stale element reference: element is not attached to the page document.
I read through this article and a few other questions in here and understand this could happen if an element reference is updated after obtaining it. However, I'm not sure how exactly I should modify my keyword to avoid getting this error.
Using the information that everyone has so kindly provided, I may have found a potential fix (not sure if it's robust enough not to throw the exception anymore, but after a few test runs they have all passed): I added a "Wait Until Keyword Succeeds" and moved the language validation to a new keyword:
VALIDATE PAGE LANGUAGE
[Arguments] ${lang}
${doc lang} Get Element Attribute css=html#lang
Should Be True '${doc lang}'=='${lang}'
CHANGE LANGUAGE
[Arguments] ${lang}
Select From List By Value ${LANGUAGE SWITCH} ?hl=${lang}
Wait For Condition return document.readyState=="complete"
Wait Until Keyword Succeeds 5 5s VALIDATE PAGE LANGUAGE ${lang}
Then I call this "CHANGE LANGUAGE" keyword as many times as languages I need to test.
I added this as an answer instead of a comment so I could show the code in a more readable way.
In order to wait for a page to be ready to test after a user action (clicking a link or button, for example), the algorithm I've found that seems to be almost bulletproof is this:
get a reference to the html element
perform the action that will cause the page to change (eg: click a link or button)
wait for the html element to go stale - this signals that the refresh has started
wait for document.readyState to be "complete"
Step 4 may not be necessary, but it doesn't hurt.
This has worked extremely well for my team. This can still fail since you might have some async javascript that runs after document.readyState has been set, but there's simply no generic solution to that.
If your pages have a bunch of async javascript, you'll have to come up with your own scheme to know when the page is finally ready to be tested. For example, the last job to complete could set a flag, or you could wait until there are no pending async jobs, etc.
I'm not sure if you can do the above with robot keywords since it relies on the selenium staleness_of condition. It's pretty easy to implement in python, though.
The inspiration for this solution came from this blog post: How to get Selenium to wait for page load after a click
If you use my page object library for robot, this is built-in as a context manager.
As highlighted, a Stale Element error typically means that between the element retrieval and the corresponding action the element changed. Often this is due to a page refresh.
For this reason it is important to invest in a robust waiting approach. Not guessing that your page/application has completed loading, but instead knowing it has completed. This will not only prevent Stale Element errors but also speed up your tests as you're not unnecessarily waiting.
As the Get Element Attribute ${DOCUMENT}#lang is causing the stale element error and the Select From List By Value ${LANGUAGE SWITCH} ?hl=${lang} is causing the page refresh, then that leaves the Wait Until Page Contains Element html as your waiting approach.
As the <html> tag is always present and the first to be loaded in the DOM, this is not the best tag to wait for. I'd advise something unique for the loaded page or the last element of that page. Though I have to stress that this still constitutes to guessing the page has loaded.
It is better to invest in a robust waiting approach. Especially if your application is using a framework like Angular, React or jQuery then you have several Javascript markers to help you with this. For some frameworks there are even custom Robot Framework Libraries that support their specific markers.
Should your application not use a framework, then talk to your developers and have them develop this for you. Simplest would be a visible spinner, but a Javascript function that returns True will work just as well.
I have created a custom keyword when ever i want to click an element or perform and action i would call this custom keyword . This custom keyword uses the built-in keyword 'Wait Until Keyword Succeeds' which runs the specified keyword and retries if it fails. through this built-in keyword the number of retry's and the time to wait before trying to run the keyword again after the previous run has failed can be configured.
This custom keyword would call another custom keyword where three SeleniumLibrary keywords would be called. The first one would Waits until element locator is enabled keyword, which would wait until the element is not disabled nor read-only. Once the element is enabled then focus would be taken to the element where we are going to perform action. Finally perform the action. All these precautions has prevented me from Stale Element error.
HighLevelKeyword_Identify And Click Element
[Arguments] ${locator}
Wait Until Keyword Succeeds ${RETRY_ATTEMPTS} ${RETRY_AFTER} Identify And Click Element ${locator}
Identify And Click Element
[Arguments] ${locator}
Wait Until Element Is Enabled ${locator}
Set Focus To Element ${locator}
Click Element ${locator}
I'm trying to get voiceover to work on safari however, it seems when I tab through elements it doesnt read out the aria-label of the new input box in a certain scenario.
Scenario:
When tabbing onto the next element and the on blur of the current element does something to the dom then it will not read out the aria-label of the next element.
Here is an example
http://plnkr.co/edit/x0c67oIl0wlQEguBIQVZ?p=preview
Notice if you take out the onblur function below then it works fine.
<input id="test" onblur="blurer()" onfocus="focuser()"/>
In this case, the issue isn't the presence of a blurer, but rather the contents of your blurer and corresponding focuser functions. Together these two functions are toggling the hidden state of a nearbye element. This is interupting the announcement. There's a role announcement that also occurs. The full annoucement (when text is populated in the edit text control) should be:
"The edited text" contents selected/unselected, "your aria label", edit text.
The quoted portions are parts you control, the other portions are parts controlled by the OS/VoiceOver's interaction with it, calculated automatically by the state of the control and other aria values.
The announcement we're getting is simply
"The edited text"
So, it's not an issue with the aria-label specifically. But rather, you are causing the entire announcement of the element to be interrupted.
When your blur and focus functions trigger you muck with the VoiceOver's response (or the OS's communication of) these events. Not sure what about your functions is causing this. Regardless, a trick that helps in these circumstances is to add a setTimeout to your code. By separating your function and the actual focus/blur event, you can allow the accessibility APIs to do their thing, before mucking with styles and such on the page. Here is an example that makes your little code snippet work. Just replace the contents of your javascript file with this:
function blurer(){
window.setTimeout(function() {
document.getElementById('myDiv').style.display = 'none';//
}, 0);
}
function focuser(){
window.setTimeout(function() {
document.getElementById('myDiv').style.display = 'block';//
}, 0);
}
In general I like to avoid setTimeouts because they create race conditions. However, setTimeouts of 0 are acceptable, because there is no race condition. You're just decoupling the firing event and the execution of your code by pushing your code to the end of the queue. When hacking around VoiceOver, setTimeout(someFunction, 0) works quite well for a lot of cases.
As far as I'm aware there are two ways of typing with Selenium:
new Actions(webDriver).sendKeys("text to send").perform();
webElement.sendKeys("text to send");
The Actions method seems like the most natural way of replicating a user typing as the keys are sent wherever the browser wants (I believe a method called sendKeysToActiveElement is being used under the covers). However, many tutorials instruct testers to use the WebElement method (this is in fact the only option when using SafariDriver), I assume as it is simpler.
Is the Actions method actually a better simulation of user interaction, or should I use the WebElement method for convenience?
public Actions sendKeys(java.lang.CharSequence... keys)
Sends keys to the active element. This differs from calling WebElement.sendKeys(CharSequence...) on the active element in two ways:
The modifier keys included in this call are not released.
There is no attempt to re-focus the element - so sendKeys(Keys.TAB) for switching elements should work.
for more you can refer this link : https://seleniumhq.github.io/selenium/docs/api/java/org/openqa/selenium/interactions/Actions.html#sendKeys-java.lang.CharSequence...-
This doesn't answert the question directly but I would have thought using SendKeys in the WebElement class would have been better, since you already have the WebElement object in memory, why do you need to create an Actions object?
I have always used the WebElement.SendKeys() method and I have not found any uses to switch over to using the Actions class for sending over a regular string.
I would use the Actions class when I require more complex scenarios e.g. Need to hold down a button or drag something.
Two things:
If you want to recreate exactly the interactions of a user, it is better to use Actions, otherwise it is better to use webElement.sendkeys() because it is more practical and simple.
If you need to execute a complex action like drag and drop it is also better to use Actions.
Currently most of the SVG framework provides drag and dropping. I have used RaphaelJs , Extjs Drawing , and SVG.js(http://www.svgjs.com/). All of the framework provides the event handling method by binding it with the element itself. For example:
dragStart: function(event){
//'this' refers to the element itself
this.doSomething();
this.moveTo(event.x,event.y);
};
However the consequences of this is that browser performance is greatly degraded, when there are more than hundred of elements and some logic processing aside. My elements will be composite elements, meaning maybe some text or path in a rect but the rect should be the target (or this) of the event when dragged. The elements will have other event to listen to , for example onclick, onDblClick, onHover & etc.
My question is, is there any way to optimize this ? The user experience is bad after the application is showing a lot of the composite elements I mentioned above.
UPDATE:
I have built an application using the mean that i spoke of above. Binding the event handler to each of the objects. The result is not very user friendly when the element is listening to onhover and onmousedown events. I am thinking to optimize the application but not sure how. The effect is more obvious in FF, chrome is better.
Are you sure you need SVG? Fabric.js is an awesome API for scaling, rotating, drag-drop, and grouping, based on the Canvas element.