Fairly new to capybara and cucumber (and testing in general) here.
I am doing some black box acceptance testing and I need to test a page that can only be reached by typing in the url.
That page requires authentication so when the page is reached through a call to visit() I am redirected to the login page.
The problem is after logging in the app does not redirect me back to that page but goes to the homepage instead so I can't just fill in the login form and move on.
I have tried logging in first and then performing a call to that page but it seems the session is cleared after any call to visit().
How can I keep the session after a call to visit, or solve this problem in any other way?
Ideally I would like to log in once and visit a bunch of pages only reachable by typing the uri, without having to log in again and again. Is that possible?
I am only using the chrome selenium driver but at some point will use a headless driver.
Thanks!
As the answer by #diabolist correctly states, visit doesn't reset any session (as long as your log in actions wait long enough for the log in to actually occur and the cookies to be set (expectation on a message stating you're logged in, or have_current_path(root_path) etc). Rather the session gets reset between scenarios.
If, in one scenario, you are logging in and then finding that you're not logged in when you visit a page you expected to be logged in to then it's possible you're actually logging into the wrong domain. By default Capybara will visit a path on the host 127.0.0.1 - If that is where you're visiting but your app is redirecting to localhost (or www.example.com, etc) for logging in, then the session cookies will get set on the wrong domain and when you visit a page back on 127.0.0.1 you won't be logged in. If that is the case then you can either change Capybara.server_host or fix your app so it redirects to the correct place in the test environment.
Given I am registered
And I am logged in
When I visit the test page
...
These can be implemented as
Given "I am registered" do
# do whatever it takes to be registered
end
Given "I am logged in"
#visit log in form and fill in id|password
end
When "I visit the test page" do
visit test_page_url
end
Your idea that your session is cleared after each call to visit is wrong. Each scenario has its own session, and you can perform multiple visits in a scenario. However you have to make sure you login (and register) in one single scenario
Related
I am working on the logout part of my website and I am using JWT for authentication and using cookies to send the JWT for client side.
For logging out I am passing some dummy token value with the same token name so that it over rides the previous token. But when I log out of the portal, I am still able to access my dashboard. There is some glitch in the logout functionality. I guess it is due to the browser cache.
I have few questions regarding Express.
Are there any ways to reload the current page using Express and delete the browser cache while doing so?
I need to disable the browser forward option of chrome once the user is logged out, how can I achieve this using express?
How to redirect the user to his dashboard when he tries to hit '/login' or '/signup' route when he is already logged in? I am using the JWT authentication for login
Thanks in advance
Are there any ways to reload the current page using Express and delete the browser cache while doing so?
The server can't, on its own, tell the browser what to do. The browser has to initiate communications and then act on that communications.
You could have the web page in the browser reload its own page using Javascript with window.location.reload(true) at any time. If you want the web page Javascript to be told when to do this by the server, it could either send regular Ajax calls to the server and, based on the response, decide when to reload the page. Or, it could have a webSocket connection to the server and the server could send the web page some data that, when the web page received that data, it would see that it should reload its page.
We could help you better if you told us what the real problem was here. Web pages can use Javascript and/or webSocket connections to dynamically update themselves rather than just reload all the time. That's a more modern design.
I need to disable the browser forward option of chrome once the user is logged out, how can I achieve this using express?
There's a discussion of disabling the forward button here: HTML5 history disabling forward button. You will probably find this is a brute force approach (it involves getting rid of browser history) and there is likely a much better way to solve whatever real problem you're trying to solve. It also sounds like you may also want to manage browser cache expiration too.
How to redirect the user to his dashboard when he tries to hit '/login' or '/signup' route when he is already logged in? I am using the JWT authentication for login
When you detect a request to '/login' or '/signup' in Express from a user who is already logged in, you just respond with a res.redirect("/dashboard") from your server. FYI, there are lots of questions about whether this is the proper user experience. A user going to '/login' or '/signup' when they are already signed in could have any one of these use cases:
They don't realize they are already signed in or they don't know if they are signed in as the desired user.
They want to sign in as a different user.
They want to create a new account (different from what is currently logged in).
They are trying to figure out how to log out.
You should make sure that blind redirecting (and not taking the user to the page they asked to go to) still makes all these use cases entirely clear. If not, you will just frustrate the user by not taking them where they asked to go.
I am using the Twebbrowser in Delphi (2009) to log into cpanel on my ISP and add a new remote host IP address for a MySQL database. The user name and password are filled in by code as is clicking the submit button, using code gleaned from several places here.
Navigating directly to the hosts page causes the cpanel login page to be shown first. My program detects this and logs me in.
This uses a line like
WebBrowser1.Navigate'https://thedomain.sgcpanel.com:2083/cpsess1819495779/frontend/Crystal/sql/managehost.html');
which reaches the hosts page OK but I notice that the security token (cpsess1819495779) is changed to something else each time, presumably being supplied by the login page.
However if I try to login first as a separate operation and then navigate to the hosts page using
WebBrowser1.Navigate('https://thedomain.sgcpanel.com:2083');
followed by
WebBrowser1.Navigate'https://thedomain.sgcpanel.com:2083/cpsess1819495779/frontend/Crystal/sql/managehost.html');
I get a server message saying the url for the hosts page has an invalid security token - presumably the cpsess1819495779 bit
Question
How can I use Twebbrowser to get hold of the security token generated by the login page in order to use it to build the correct url for the hosts page so that I pass the correct security token each time.
It's probably something to do with cookies etc but I don't know how to deal with those (yet)
BTW as the Twebbrowser is not visible I did spend quite a few days trying to do the same thing using Indy's TIdHTTP but have given up with that as am getting too many errors I can't sort out.
I may as well answer this myself to close the question and maybe avoid any more down votes for posting a question after extensive research failed to produce the answer and that was framed without much of my code for brevity.
The API documentation for cpanel (the application used by many ISPs to manage MySQL, email etc) is here: https://documentation.cpanel.net/display/SDK/Guide+to+cPanel+API+2
part of that says
Security token After you log in to your server, it automatically appends a security token to the URL for your session. Security tokens
help prevent authorized use of a website through XSRF (Cross-Site
Request Forgery). Security tokens contain the string cpsess and a
10-digit number.
Logging in manually in IE / Chrome etc. does indeed show the token eg cpsess1819495779 inserted into the original url that was navigated to. So if I navigate to
https://thedomain.sgcpanel.com:2083/cpsess0000000000/frontend/Crystal/sql/managehost.html
(to logon to cpanel), the part of the url displayed in the browser after cpsess gets changed to something like this, where the number changes each time.
https://secureukm11.sgcpanel.com:2083/cpsess1819495779/frontend/Crystal/sql/managehost.html
However, using Twebbrowser to show that modified url using
memo1.Lines.Add(WebBrowser1.LocationURL);
or
ShowMessage('URL: ' + Webbrowser1.OleObject.Document.Url);
simply shows the original url with the zeros, not the real security token.
So the answer to my question seems to be it can't be done in Twebbrowser as the url is only changed at the server and and the security token is not transmitted back to the browser.
Question 1
My secure web application sets a session cookie for authenticated users which is not cleared even after I close my Chrome browser.
As a result, when a user tries to hit the dashboard page of my application after re-launching the browser (even restarting machine!), they are not asked to login again. Chrome is NOT set to "continue where I left off" which is also my next question.
I tested my bank's site under the same settings and it seems to force log out the user even when Network tab shows that same cookies are being retained (and sent with initial request header) for bank site as well. My server is Apache over SSL.
Can someone please point to some resource where I can handle this scenario because Chrome clearly is not clearing session cookie at the time of browser closing.
Question 2
Now with the setting "continue where I left off" where it basically persists your sessional cookies and practically you can remain authenticated forever, is there a way to override/work around this Chrome feature.
When I see even my supposedly secure bank site letting a browser bypass security like that, it kind of makes me unnerved. Any suggestions there?
Cheers!
What ended up fixing this issue for me was to uncheck the:
Continue running background apps when Google Chrome is closed
setting under the SYSTEM section.
Hope this helps save some headaches....
On session timeout we re-direct to the login page and if the user logs back into the portal he gets re-directed to the page he was trying to navigate in the first place.
In our case, the re-directed page tries to fetch values from the session and it fails badly with exceptions and it works just fine when there is no dependency on pages which don't have any dependency on session variables.
What is the best way to handle the situation? Can we just redirect this to the home page instead, if so how to do this?
It depends on how much information you are storing in the session, as a guideline, you should always the "shortest" scope ever.
Probably your best option is to allow redirect only on stateless pages, so that it won't give you any problem about inconsistent state.
As for your last problem, take a look at this: redirecting-on-session-timeout-in-jsf-richfaces-facelet. Just set the tag to whatever you want.
I initially designed my site to show a login box at the top of the page if the user was not authenticated (e.g. how reddit.com works).
I encountered a user who was having trouble with their browser's storage of their password because after a password change because their browser had stored their login information at different urls on the website. Even after the user typed correctly the new login information at one url, and the browser updated it, there would be other urls at which the browser had the incorrect login information.
This would also cause problems with sites that have a login box on their main page, and a special login page -- especially if the user front page login box is sent to the login page.
Is this a small enough case not to bother with, or should there only be one url at which a user can login to prevent this problem, especially for less technically-savvy audiences?
There should be one login page that every other page accessible sans login links to. It standardizes the process of logging in and reduces the kind of confusion your user experienced. It conforms to a convention that all the browsers are using with respect to saving passwords as well. Don't really see how you can go wrong that way.
Most sites use a single "sign in" button that takes you to the canonical login page.
If you want a signin box on every page that the browser can remember, consider using an iframe to hold the form.
I believe that if there is any way to use only ONE login location you should try to do it that way.
As you yourself said it's quite hard for browsers to determine what to do with stored passwords for sites with multiple login locations. There are possibly other problems and all of them are solved by having exactly one login location.
If you need to provide login from more places, just use redirection. But getting "in" your system should be done from one single place.
Just have one login page and have the other pages on your site linking to it. It keeps it simple for end users as there is only one page and easy for you to manage as you one have one login page.