How to simulate the behaviour when the user loads the app from the URL in the browser's address bar - flutter

I'm writing a Flutter web application and I want to write a test on the behavior when the user loads the app when he types the URL in the browser's address bar.
For example I would like my test to behave as if the user typed /my/path.
How can I do that?

If you look at the class PlatformDispatcher (which olds a singleton instance .instance) you can see a getter defaultRouteName.
The route or path that the embedder requested when the application was launched.
This will be the string "/" if no particular route was requested.
So when your user starts your application with the url /my/path, PlatformDispatcher.instance.defaultRouteName with be equal to '/my/path'.
How to mock it?
You can also access the PlatformDispatcher.instance from WidgetsBinding.instance.platformDispatcher and if you read the doc of the getter platformDispatcher, you'll read:
A subclass of BindingBase, such as TestWidgetsFlutterBinding, can override this accessor to return a different ui.PlatformDispatcher implementation.
In the context of a testWidgets
testWidgets('', (WidgetTester test) async {});
tester.binding gives you access to the TestWidgetsFlutterBinding which is the binding used by widgets library tests. In this test binding, the platformDispatcher is overridden and a TestPlatformDispatcher with a setter defaultRouterNameTestValue that you can use to mock the defaultRouteName getter.
TL;DR
You can use:
tester.binding.platformDispatcher.defaultRouteNameTestValue = '/my/path'
to test the behavior when the user loads the app when he types the URL /my/path in the browser's address bar.

Related

How can I reload my page to redirect to an URI Fragment in VAADIN?

In my Vaadin webapp I have a tipical architecture with login. In some cases, the user can access directly to some resources using Vaadin URI Fragments (http://example.com/#fragment).
When a user tryes to access some resource, If the user has logged in, I take from the URL the #FRAGMENT and I bring him to it.
But if the user has no logged in, when he logs in I used to bring him to the main page using
getPage().open("/", "_self");
but since if I add an URI Fragment, the getPage().open(...) does not work.
Is there any way to redirect the user to a correct URL (URL with UriFragment in my case) from code?
Note that there is a fundamental difference in how navigation is handled in traditional web applications versus single-page applications as implemented with Vaadin. In traditional web applications you navigate through the app by making full HTTP GET-Requests on some path (such as www.example.com/myapp/home). On each such request, a full page reload is performed. You can't do that with Vaadin, as a full page reload means reloading the Vaadin widget set and rebuilding the page layout from the ground up. Therefore, single-page applications typically use the URI fragment for navigation purposes. Changes to this fragment are solely handled by the client-side JavaScript code. There will be no GET-Request induced by the browser when the URI fragment is changed.
That's why the approach you described doesn't work for you. Using Page.open(...) will open a web page through a HTTP GET-Request resulting in a complete reload of your Vaadin application.
The solution for your problem is to solely handle all navigation (including state-dependent redirects) through the Page object's URI fragment handling methods (or through the [Navigator][1] component). Redirecting in Vaadin can be achieved by programmatically setting the URI fragment with Page#setUriFragment() or Navigator#navigateTo() and having your URI handling code (or Navigator) take care of the rest. Only then it is assured that your users stay on the same page even when they are redirected to a login form or to some other place after logging in.
I would like to add to Roland's answer and share how I solved this.
My UI:
#Override
protected void init(VaadinRequest request) {
setSizeFull();
setContent(masterView);
getPage().addUriFragmentChangedListener(event -> present(event.getUriFragment()));
present(getPage().getUriFragment());
}
The masterView is just a CustomComponent that has a content section. When the menu is clicked, I simply setContent to the masterView's content section. Swapping out the middle, basically.
present method:
private void present(String fragment) {
masterView.setContent(getComponentFromFragment(fragment));
}
Finally:
private Component getComponentFromFragment(String fragment) {
if (fragment.equals(someOtherView.NAME))
return someOtherView;
return null; // null clears it out as in the welcome page
}
The important part is the present in the init. When the UI renders for the first time and fires the init, it goes ahead and grabs whatever the URI fragment is in the browser and presents that as well.
Works great.
Maybe this can work:
UI.getCurrent().getPage().executeJavaScript("window.location.href = 'http://google.com'");

Starting a socket on a settings page and allowing the MainPage to access it WP8

I have class that the MainPage of my app can access, but it requires user input for the ip address so I've setup a new page rather like a settings page, if I add the same code as the MainPage the socket works as expected but I only want to send the connect command from the settings page then allow the MainPage to send the values to the socket... if I connect on settings page and then try to send data from MainPage I get "Socket not initialized" when it was as it was done from the Settings Page, can anybody explain whats happening here and possible solutions? it's like the app page is two different 'ecosystems' and the two can't combine methods and vars etc?
Am I looking into this wrong and yes you've guessed it I'm hopelessly new to all this!
Each page in a WP app is a separate class. So where is your Socket object declared? If you declared it as an instance variable of the MainPage class (for example), it would not be in scope when the Settings page is active (or vice versa).
To allow both pages to reference the same instance of Socket, you can declare it as a public member in App class. And you'll probably want to declare it static as is done with App.RootFrame in the automagically generated app templates, to make it easy to reference.

Why GWT URL doesn't change on an event or a service call?

I have two questions:
Q: 1
I'm currently developing a GWT app. The entry point for the app is: ImageViewer.java. I could well access it by http://127.0.0.1:8888/ImageViewer.html?gwt.codesvr=127.0.0.1:9997. I have a service called "Search" which has corresponding "Async" and "Impl"'s defined. Now, I call the service from client side, using RPC. I could call the service, obtain return value. Everything works fine.
However, I expect the application to show a behavioral change on URL. i.e. when a service is being accessed, I thought it would be reflected on the browser's URL something like: http://127.0.0.1:8888/search?gwt.codesvr=127.0.0.1:9997 as I've modified web.xml. However, this behavior is not realized. Any particular reason why this is not reflected??
Q:2
This one is a reverse of the previous ques. i.e. I have an application running. Let's say it has an entrypoint class(Imageviewer.java) and another composite class (searchClass.java) which would be loaded on the Imageviewer based on an event. This searchClass invokes the "search" service mentioned in the previous question.
I could load the "searchClass" in "Imageviewer", invoke the service, and the service also returns the value needed. Everything works fine... But,
I need something like this: by just typing this query string:
http://127.0.0.1:8888/search?value=John
I want the "searchClass" to be loaded on the "ImageViewer", call the service using the value(which is "john" in this case) and display the result. Is this possible at all?
what I've tried: I have tried to create a httpServletClass on the server and mapped it with the URL and could do the search. The search returns appropriate results. However, I want the results from the server to be displayed on the client. Remember, I'm directly using a servlet to read the URL and so there is no value being passed from client to server.
Thanks in advance.
A: 1. To change URL, the hash part, you need to set new history token in the History class. More about history management in this article.
A: 2. For the second part you could achieve it by changing the history token, for instance "http://127.0.0.1/search#value=John". The history service will trigger an event if the # part changes. You could also use the part with "?", as in your example, if you use Window.Location , but it will cause reload of the application, which would put the whole idea of using GWT in question.
RPC (AJAX) calls are done Via XHR and do not change the browser URL.
You can't (with the URL you presented). GWT apps normally run in one web page, i.e. the URL does not change (see how gmail changes browser url bar). What you can do is enable GWT history support. Then your url would be http://host/#search?value=queryu

User roles in GWT applications

I'm wondering if you could suggest me any way to implement "user roles" in GWT applications. I would like to implement a GWT application where users log in and are assigned "roles". Based on their role, they would be able to see and use different application areas.
Here are two possible solution I thought:
1) A possible solution could be to make an RPC call to the server during onModuleLoad. This RPC call would generate the necessary Widgets and/or place them on a panel and then return this panel to the client end.
2) Another possible solution could be to make an RPC call on login retrieving from server users roles and inspecting them to see what the user can do.
What do you think about?
Thank you very much in advance for your help!
Another way is to host your GWT app in a JSP page. Your JSP might contain a snippet of code like this
<script type="text/javascript">
var role = unescape("${role}");
</script>
Where ${role} is expression language expanded from value you computed from the associated servlet / controller and exposed to the JSP.
When your GWT app runs in the browser, the value will be filled out. Your GWT app can easily call out into JS to obtain this value from a native method call, e.g.
public native String getRole() { /*-{ return $wnd.role; }-*/;
So your module could invoke getRole(), test the value and do what it likes to hide / show elements.
Obviously your backend should also enforce the role (e.g. by storing it in the session and testing it where appropriate) since someone could run the page through a JS debugger, setting breakpoint or similar that modifies the value before it is evaluated allowing them to access things they shouldn't be accessing.
Following scenario works for me:
GWT app is behind security constraint.
On module load I make RPC call to retrieve roles from the container. I store them in main GWT module's class as static field, to make it easy for other classes to use it.
Each widget (especially menu) can use roles (e.g. call Main.getRoles()) and construct itself according to roles. I don't pass roles in constructor. Each widget knows how to behave depending on role.
If it's crucial to not only hide things but also enforce them you can use container security and check roles and rights while invoking business methods.
While using GIN you can also create singleton class to store roles retrieved during login and inject it wherever you need it.

Base page class equivalent in ASP.NET MVC2? Coming from a webforms background

Problem:
I have a webforms app where every page inherits from BasePage.cs
I also have another class AuthenticatedBasePage.cs which inherits from BasePage.cs
BasePage.cs has some code which finds out if a Forms Authentication cookie is set, and if so, sets a IsAuthenticated boolean flag and a MyAppUser object (only has properties such as name, age, gendery) which means every page on the site can see if the user viewing the page is logged in or not, and if so, read the values of MyAppUser.
AuthenticatedBasePage has an additional feature where if anyone tries to browse to a page inheriting from this class are not authenticated, they are redirected to the login page with a 'returnurl' querystring variable set.
I would to have a similar setup in my MVC2 app. I've done a fair bit of reading that says I shouldn't reference HttpContext in my BaseController.cs (which all my controllers inherit from) as that means I can't unit test it. My first question is, how can I make the IsAuthenticated and MyAppUser objects available to every page? Secondly, how do I create pages which only authenticated users can access, and if they are not authenticated, they get redirected to the login page with the returnurl querystring variable set?
Many thanks,
A.
P.S. I'm not using the MembershipSchema, I'm only using the FormsAuthentication.SetCookie method.
What you want is the Authorize attribute. This article has a great explanation of how to use it with forms authentication.