I'm new to Robot Framework and stuck with quite simple login web page test using SeleniumLibrary:
*** Test Cases ***
Valid Login
Open Browser To Login Page
Input Username admin
Input Password test
Submit Credentials
Dashboard Page Should Be Open
[Teardown] Close Browser
Most of the keywords are irrelevant to the question, except
Submit Credentials
Click Button login-button
Dashboard Page Should Be Open
Location Should Be ${DASHBOARD URL}
Title Should Be Dashboard
If I run this test, it will fail, because Location Should Be check is executed too early, while browser is still on the original login page. I found two solutions that work, but both seems to be conceptually wrong:
Use sleep
Submit Credentials
sleep ${DELAY}
Dashboard Page Should Be Open
In this case ${DELAY} should be quite big (e.g. 10s) to be sure that page is definitely loaded or it may fail anyway. Also, I've read that best practice is to avoid sleeps. And I can't use some Wait Until Page Contains, because I don't know, whether login page will be loaded again with some error message or Dashboard page loaded in success.
Use Form Submit instead of Click Button:
Submit Credentials
Submit Form login-form
The Form Submit works fine, but it's different from actually clicking a button, because button may have some onclick handler that would prevent submitting a form.
Using Wait Until Keyword Succeeds as suggested in some other threads doesn't seem to help, as Click Button succeeds right away.
You definitely should not use sleep since it introduces artificial delays that may make your whole suite slower than it needs to be. I personally also thing Wait until keyword succeeds should almost never be used. It litters the log with messages as it retries. Plus, I think it masks problems instead of fixing them.
The answer is to use one of the wait keywords. You say you can't use Wait Until Page Contains ""because I don't know, whether login page will be loaded again with some error message or Dashboard page loaded in success". I don't understand that reasoning.
Your application should be deterministic. That is, if you enter correct login credentials than you should be guaranteed that it will go to the dashboard page, and if you enter the wrong conditions you should see an error and/or be redirected back to the login page.
The point of the test is to verify those conditions. So, for a test that verifies whether you get the dashboard page or not, you should find an element on the dashboard page and wait for it to be visible after submitting the form. If it doesn't appear in the proper amount of time, your test should throw an error.
Personally I recommend using page objects. The library I wrote [1], for example, has a mechanism to wait for a page refresh, and assertions to verify you are on the page you think you should be on. You don't need to use my library though -- the core of the code is only a couple hundred lines of code, so it's easy to write your own.
[1] https://github.com/boakley/robotframework-pageobjectlibrary
Related
I have the following code I execute in Chrome with Tampermonkey, which I use to login to digitalocean.com.
setTimeout (function() {
document.querySelector("input[type=submit]").click();
}, 3000);
For some reason, this code sometimes work and sometimes it doesn't: That is, sometimes I'm logged in and sometimes (most cases) I get DigitalOcean's 404 webpage.
My login details are already saved in local storage and appear on the form.
By principle, this problem can be reproduced by registering to DigitalOcean, installing Tampermonkey, and executing the code with it, with the match:
https://cloud.digitalocean.com/login*
Might something be missing to ensure human-like behavior in the eyes of the machine?
OK, it took some digging, but I see what's going on.
There is an authentication token in the form.
If the token is not what the server expects, it kicks you to a 404 error at https://cloud.digitalocean.com/sessions.
If your browser loads the login page from cache (usually because you got to it by clicking the "back" button in your browser) you'll be submitting an invalid token (the one you got back when the page was put in the cache).
Sometimes it's wrong for some other reason I haven't figured out.
To deal with the cache-loaded page issue
I'd edit your script check if the page was loaded from cache, and refresh the page instead of triggering the click event:
if (window.performance.navigation.type === 2)
{
location.reload();
} else {
document.querySelector("input[type=submit]").click();
}
The other issue is probably an issue with DigitalOcean's back-end
I'd recommend that you report the fact that their login page seems to occasionally get a bad authentication token, as the issue can intermittently be reproduced by clicking (with the mouse) on the "Log In" button of a freshly loaded copy of the page.
(I wouldn't mention the script or they'll blame it and then you'll be out of luck.)
In the mean-time
As a stop-gap until they fix their issue, you could make a new script matching https://cloud.digitalocean.com/sessions (it sends me to that page exactly, but add a * if it's needed) that sends you back if you came from the login page, and got a 404 error:
if (document.referrer.startsWith("https://cloud.digitalocean.com/login") && document.title.endsWith(" (404)"))
{
history.back();
}
Note that document.title.endsWith(" (404)") only works because the contents of their 404 page's <title> tag ends with (404).
It seems to be a bug in Tampermonkey as the reported behavior doesn't happen in Greasemonkey.
Anyway, 3D1T0R's answer provides an interesting workaround with the current situation (would thumb up if I could).
I've been working on replacing alert() pop-ups in our Angular code with Angular overlay modals. I'm almost done with the exception of one problem.
I have a modal that opens when the user login has timed out. Some pages will load, fire the script properly and the overlay will be in focus, waiting for the user to click "ok" which sends them to the login page - which is what I want.
On other pages, content will partially load, then fire the overlay modal and for a split second I will see it, then the page continues to load, the modal goes away and even though they get logged out the page doesn't go to the login page.
I need some direction determining what code I should add after the overlay fires to prevent any other code from executing so the user has to interact with the overlay.
I'm sorry I can't share any code - it's proprietary - I just need some direction to go in.
This is very difficult to answer without having access to any code or fully understanding how you are managing various states/views.
A simple solution would be adding a function to the $rootScope which constantly checks if a user is authenticated (aka not timed out). And then have it perform some action if the user is no longer authenticated.
How you store the authentication indicator is completely up to you. Without knowing more about the app it would be difficult to say where the best place would be.
Example code:
$rootScope.checkAuth(){
if (!$sessionStorage.auth){
$state.go(login)
}
}
setTimeout($rootScope.checkAuth,10000)
You could also handle this by not resolving each view/state until a user has been confirmed as authenticated. Once again, how you set that up would be dependent on the structure of your app.
I'm using browser-like approach for adding a bug to Bugzilla.
I'm making a successful login. When I add the bug, I don't get error. I get status code OK. But, the response html contains this:
Bugzilla – Suspicious Action
"It looks like you didn't come from the right page (you have no valid token for the create_bug action while processing the 'post_bug.cgi' script). The reason could be one of:
You clicked the "Back" button of your web browser after having successfully submitted changes, which is generally not a good idea (but harmless).
You entered the URL in the address bar of your web browser directly, which should be safe.
You clicked on a URL which redirected you here without your consent, in which case this action is much more critical.
Are you sure you want to commit these changes anyway? This may result in unexpected and undesired results."
There is a confirm button.
When I do this by hand (not by code), I don't get the error page. Instead, I get response that everything went fine and I can get my bug's id. So, ahead in my code I'm using the id. However, because of the error I get, the id is an empty string. How to resolve this?
Can it be resolved by clicking on the confirm button by code?
You can use Bugzilla's REST API from your script.
Creation of a bug is documented here
I have a login page which is shown on first launch. After the user puts in his credentials he is taken to the main page of the application. At this point, if the user presses the back key I want it to skip the login page and exit. I tried what was suggested here: Remove a page from Navigation Stack (in OnNavigatedTo, use NavigationService.GoBack()) but it throws an exception because there is nothing else in the back stack. I read some other places that not handling exceptions is basically the only way to close the app...
The problem with this method of closing the app is, well other than being a hack, it doesn't hit Application_Closing() so my state isn't saved.
Anyone know how I can skip the login page when hitting the back key, save state, and exit the application?
Thanks in advance!
Yeah, this is becoming a huge problem with Navigation in WP7 - many folks are complaining about this same type of issue. The key to remember is that Navigation mimics navigation of a website - it acts a lot less like UserForms and more like web pages and their static history.
The easiest way around this which is both transparent to your users and easy for you is to make that first login page you are reference as User Control that sits on top of your actual main page (i.e. don't use a phone:PhoneApplicationPage for your login page - just a control that is part of your main page phone:PhoneApplicationPage). Use a boolean in your OnNavigatedTo on the main page that says "if user is not logged in, display login control, otherwise, just show main page."
On saving state (i.e. tombstoning), ask another question as that's another topic.
The general best practice is to not use a page for anything you dont want in the navigation stack.
In my case i chose to use a Popup to host my Login Control. I pop it from my mainpage if they are not logged in. If they are i dont show it. This way if they are not logged in and hit back, they exit the app. However if they are logged in and also on teh main page, they see their data, and if they hit back they also exit the app (not see the login page).
For the login / home page scenario one thing you can do is on successful login rather than navigating to the home page you call "GoBack", this will take them back to the home page, but pop the login page off the navigation stack and allow the user to exit the app on the next press of the back button.
i have just had an app denied in the windows phone market place because i didn't adhere to the "close application on back button" rule.
currently i am doing the following:
open app
if you've never entered your details, navigate to the save details page
on arriving at this "first entry" page i cancel the use of the back button
because as you can see the first view that the user sees is my "first entry" page although i'm trying to be smart and lock the user from going back to an empty main page (because they havent entered their details) i'm really stopping them from exiting on the first screen.
as there is no way to exit using code in silverlight as per
http://blogs.msdn.com/b/ptorr/archive/2010/08/01/exiting-a-windows-phone-application.aspx
what am i supposed to do?
should i let the user navigate back and then try and capture that they have just hit back and navigate back again? (this seems like and odd way of doing it)
or is there a way for me to capture the first navigation instance and simply not store the first page actually loading into the history, so that when they hit back, it exits anyway?
I'm going to assume you mean "close app on back button rule"
I think the approach that will work for you and stick within cert reqs is to redirect the intial navigation... this will cause your initial page to not enter the backstack. Peter offers two implementations for this here.
Redirecting an initial navigation - Peter Torr's Blog