We are trying to test a page which at one point redirects the execution to another page for login credentials. After this we need to go back to initial page and continue from where it stopped before redirection.
How can I achieve this?
I tried with roles but this wouldn't keep the data on the initial page and instead reloads the page which then is empty. Also with roles you always go back to same page.
Any suggestions?
Using the roles mechanism is the only built-in way to save and restore cookies/storages. Each role has its role constructor with the initialization function. Cookies and storages are saved only after a role is initialized. It means that you can try to use a role for the first part of your test and save the page state:
const role1 = Role(basePage, {
// do smth
});
const role2 = Role(loginPage, {
// login
});
test('test', async t => {
await t.useRole(role1); // state is saved
await t.useRole(role2); //
await t.useRole(role1); // state is restored
})
If this approach does not meet your needs, you can try writing some custom logic to save/restore the state. Please follow this link https://github.com/DevExpress/testcafe/issues/2142 to see an example of a custom solution of how to save/restore localStorage via CustomFunctions.
There may be some design considerations worth making in the app itself, perhaps some usage of local or session storage is in order. Testing aside, wouldn't the user also experience this disappearing data if they manually reloaded, for whatever reason?
In my experience with TestCafe, there were instances where I had to do more in each test than I cared to, to workaround similar issues, including times I couldn't use roles and simply cooked up my own reusable login function that I called here and there.
That seems to be one of the limitations with TestCafe in conjunction with testing such functionality (the SPA paradigm, which perhaps this is). It's going to reload pages, but if I remember correctly there was a discussion about it in their issue tracker, so it may be worth browsing there as well if you haven't already.
Related
I have a Layout page which sets up the list of Projects in the application using Telerik's ComboBox as shown. The combobox allows user to select a project he/she wants to work on.
Once a selection is made, I want all subsequent actions in the application should correspond to the selected Project. I can preserve the Project information in a Session but then if user chooses to open this in a new tab and in 2nd tab users switches to a different Project and comes back to the first tab and refreshes the page then the session information (Project) would have changed which will create issues in my application.
So, what is the best way for me to persist Project information of the Layout.cshtml controls so that I can use it in my application such that every page that is rendered uses the currently/correctly selected values.
Tempdata / QueryStrings came to my mind but i don't know whether they will be reasonable solution to my problem. If yes, then how should I use them generically (specially querystrings) without complicating my solution?
localStroage and sessionStorage also seems like relevant solutions but then how do I use them in scenario where user opens a new tab from existing page? How will the Project # will persist on the newly opened page/window/tab?
something like this is achievable, if you make sure the url changes when a selection is made.
So let's say you select project C-1379 in your dropdown box, at that point your url could become http://localhost:58692/pid=C-1379.
from now onwards, your page can load the desired data, retrieving its required information from the query string. Do not use session or localstorage or anything like that as it won't work.
This way, you can still load your list of projects in your layout page, and you can select one based on the query string value and then load some default values via api calls to the back end.
If all your work from now on is done based on api calls, for example, you have some properties that you change and then you issue a POST to update said details then this is very easily done as well.
telerik controls usually have some events associated with them. the one you are using should have an onChange or something like that. This where where you would update the query string with the value of the project selected and then you can proceed to do what you need
I can preserve the Project information in a Session but then if user
chooses to open this in a new tab and in 2nd tab users switches to a
different Project and comes back to the first tab and refreshes the
page then the session information (Project) would have changed which
will create issues in my application.
I would have thought this is the desired behavior... take stackoverflow.com as an example, if I change my username in one browser-tab, I would expect my username to be updated in other browser-tabs as well... and that's what happens if I refresh my other tab.
There is no built in solution for maintaining user info in different browser tabs separately... the only way to achieve this, is by sending project name back and forth in the URL... but then you would loose this info if user changes the URL... In my opinion, this is an ad hoc solution and does not worth the effort of development, because it's a very uncommon scenario.
Getting to your options:
Storing user info is a very typical use case for session variable.
TempData is stored in Session by default. Though you can write
your own custom TempDataProvider and store it somewhere else (e.g.
database, cookie, etc). See Brok Allen's Cookie TempDataProvider
as an example. One advantage of using Cookie is that you send your
session variable back and forth with the request so you don't need to
worry about Sticky Sessions.
You can of course use a permanent storage, such as DB/Disk.
If the project name is not a sensitive info then I don't see any issue in passing it in Query String.
I have been trying for a while to find a method to prevent the the browser from using cached data while the user is logged out. I am trying to force the browser to use the information from the database once the user is logged out instead. This will prevent the back button from exposing information on previously visited pages from being shown. I have used the PHP destroy session. I do not have a clue how to work with REST API.
Well, the REST API doesn't have anything to do with the frontend, but there are ways you can force the frontend page to reload on the back button being pressed.
Here is a similar question.
Essentially, you need to store some local storage data that get's checks on page load and force the page to refresh.
Page One
<script>
if (sessionStorage.getItem("Page2Visited")) {
sessionStorage.removeItem("Page2Visited");
window.location.reload(true); // force refresh page1
}
</script>
Page Two
<script>
sessionStorage.setItem("Page2Visited", "True");
</script>
Now, this isn't full-proof. If a user has javascript turned off or has some other block or something in there, it won't work. Companies do not allow sites to control a users browser. And for very good reason. But something like this can be a partial solution for the majority of users.
I am using ASP.NET MVC with AngularJs framework. In my home controller I'm checking if there is a valid license and if not, I'm re-directing to a page to import license with this code:
public ActionResult Index()
{
var retVal = _licenseProvider.ValidateExistingLicense();
if (!retVal.Item1)
{
Response.Redirect("DataMaintenance/ImportLicenses", true);
return View("DataMaintenance/ImportLicenses");
}
So, in my ImportLicenses controller I want to detect that I was re-directed vs. called from the menu. I found an older thread about redirecting to a different action, but that solution doesn't apply. What are my options here?
You have a couple of options here:
Add a query string parameter in the ImportLicenses action that
determines whether the user got here via a redirect or the menu
Set a TempData variable before redirecting your user to the
ImportLicenses action.
Use a Session variable
Read this for more information about passing data between Action methods.
It really depends on your constraints, there are a number of options. Without knowing much about your project. My first suggestion would be to drop a cookie before redirecting, then when the request comes in to the ImportLicenses action you can check for the check, and delete it, but include whether or not the cookie was found in your view model so you can reflect this in the UI.
There are other options like using session state, or a query string parameter. A querystring parameter could be just as effective as the cookie idea i mentioned above, and it would be a bit cleaner.
If you can provide more information about your use case, I may be able to expand my answer.
Hope this helps.
In the meanwhile I decided to do a little bit of cheating, but it worked. In the menu I changed the original call to this
dataMaintNodes.SubNodes.Add(new MenuMapNode() { LabelKey = "importLicense", Action = "ImportLicenses", Controller = "ImportLicenses", Area = "DataMaintenance", Icon = "", Roles = "IMPORTLIC" });
In other words, instead of normal Index action I introduced a different action. I added that new action to my controller and just set the ViewBag property to false when called from the menu and to true in the Index action that is called by Redirect. So, it's a cheating, but it works. I only wanted to display Cancel button on that modal dialog when I am calling from the regular menu and no Cancel button when called from the home controller. Now, my second problem is that Modal Dialog doesn't really prevent from escaping from it and continuing working with the application. So, we may want to introduce more logic.
I am trying to implement Login/Logout functionality in my website without using inbuilt functionality of Login controls in ASP.NET. In some pages, which require the user to be logged in, I have written this in Page_Load
if (Session["cod"] == null && Session["admin"] == null)
{
Response.Redirect("You need to Login.aspx");
}
if (Session["cod"] != null || Session["admin"] != null)
{
LinkButton1.Text = "Logout";
}
if (Page.IsPostBack == false)
{
log_bind();
grid1_bind();
grid2_bind();
}
But while I was testing this, I noticed that when I press the Back/Forward button on the browser, these pages are viewable without being logged in. How do I prevent this?
This has nothing to do with the login controls, but as others state, the caching of the page.
The trick is to tell the browser that it can't cache the page.
Look at this post, and its solution:
Disable browser cache for entire ASP.NET website
I think that even if you do not use ASP.NET login controls you should still use the Principal/Identity classes and verify if a user is Authenticated or not. That is surely the safest way.
I don't know of any reliable way to do this. Once a page has been viewed, it's on the user's computer. If they hit the back button, they are looking at a cached version anyway so I can't imagine why this would be an issue.
As long as they can't refresh the page to get the latest content, what does it matter if they're able to look at a page they already accessed?
Have you tried wrapping the whole function in
if (!IsPostBack)
{
}
The browser may simply be showing you a cached version of the page, try to attach a debugger to the page load event and check to see if:
It is actually hitting the server when you hit back and forward
The values in the session state, whether they are consistent with a logged out user.
If the values in the session are consistent with a logged in user then you have to check your session clearing logic.
It is however best to use the asp.net controls or the system.web.security.FormsAuthentication class to perform functions like logging in and logging out based on custom logic.
I am using VS 2005, C# 2, ASP.Net 2.0
I am unable to find out how to track that user pressed F5/Ctrl+F5/ Open a new Window(Ctrl + N) in ASP.Net.
I know that there is a Page.IsPostBack property, which tells that a page is loaded in response to an action taken by user.
I am just curious to know, that why isn't there a property as IsRefresh or Page.IsRefresh in ASP.Net, which will return true,
whenever user takes any of the above actions.
Is there a way to know this?
Actually my problem is that i have a DLL using which all of my aspx pages are inherited, I have to
insert some values in a table whenever the page is opened for the first time that's it, if user just opens the page or do not take any action,
an entry should be inserted into the database, but as far as I have tried, I controlled it anyhow using the Page.IsPostBack property, but I got stuck
in the refresh case, as it is inserting records unconditionally.
Similar to using a function in Global.asax (as others have suggested) you could use a session variable "flag". When the page first loads set a session variable and then just check against it in your page load function:
if (Session("visited") != "true"
//page has not been visited, log visit to DB
Just make sure you set the session flag sometime after the above check during the page load.
It won't be exact (sessions can timeout while a page is active, users can completely leave the site and come back in the same browser and the session stays alive, etc) but for your tracking it is much better than counting every page hit in the DB.
Perhaps you want the Session_Start method in the Global.asax file, which will be triggered once at the start of each user session?
In your Global.asax file, add or edit the method:
void Session_Start(object sender, EventArgs e)
{
}
why isn't there a property as IsRefresh or Page.IsRefresh in ASP.Net
Because ASP.NET cannot possibly know. The browser does not send any information that could allow it to determine whether the page is being requested due to a refresh or normal load. You will need to reconsider your requirements: what is the actual purpose of the database logging?
Session_Start method in Global.asax file is fired every time when a browser session is started. You can use this method to count number of unique users on your website.
Session_End method in Global.asax is fired when a session ends (explicitly or timedout). So you can decrement the count here.
Hope the above to example uses of these methods helps you understand how you can use them.
Because of the stateless nature of HTTP protocol there is no way to tell apart the initial load from the refresh
As has already been said. This isn't possible. A request issued due to a refresh is no different to a request issued the first time the page is loaded.
It sounds to me like you are trying to track page views somehow. This is certainly possible though it will require some work on your part. Your best bet is probably to log the URL of the page. You may also want to include the query string in order to differentiate between page loads for different pieces of data (if this happens in your application). You will also want to log the ID of the current user, and the ID of their session.
You can then make sure that you don't insert two page views for the same user for the same page in the same session, effectively filtering out any reloads of a page.
You do need to be aware that this isn't the same as detecting a refresh, what you are detecting is two page views in the same session, this could be a refresh, or it could be use of the back button, or just reloading from the address bar.
My suggestion would be to create a cookie on very first load, then on Page_Load check to see if the cookie exists. If it does, don't insert the record. You can use Session_End to destroy or create the cookie as someone suggested if that works with your application's architecture.