Xamarin.Forms UI Automation Testing WaitForElement WebView always times out - xamarin

My Xamarin.Forms app uses Azure AD B2C for authentication. It works great. I'm trying to build UI automation tests now and I ran into my first blocker. I have been trying to wait for the WebView to come on the screen so I can enter the email and password of a test user into my ui test automation script however the WaitForElement method always times out!
[Test]
public void RegistrationStarts()
{
app.Screenshot("Welcome screen.");
app.WaitForElement(c => c.WebView());
app.Tap(c => c.WebView().Css("input#logonIdentifier"));
app.EnterText("sample#example.com");
}
I'm not sure why. I'm only testing in Android. I notice that the Azure AD B2C login web view appears to be inside my app. I can tell this because when I open the Android task switcher I can see Chrome and my app.

Is there a reason you used input before the id? If logonIdentifier is your ID of whatever you want to type, it should just be
app.Tap(c => c.WebView().Css("#logonIdentifier"));
Also, if logonIdentifier is the TextBox in which you want to type, enter text should be
_app.EnterText(c => c.WebView().Css("#logonIdentifier"), "sample#example.com");

you can try wait for element with timeout - time in milisecond, second, and min.
app.WaitForElement(x => x.Marked("AutomationID"), timeout:TimeSpan.FromSeconds(90));
or
https://learn.microsoft.com/en-us/dotnet/api/xamarin.uitest.iapp.waitforelement?view=xamarin-uitest-sdk

It seems you are using systembrowser instead of WebView.
Change your method of acquiring token with WebView.
AuthenticationResult authResult = await _pca.AcquireTokenInteractive(B2CConstants.Scopes)
.WithUseEmbeddedWebView(true)
.ExecuteAsync();
https://github.com/microsoft/appcenter/issues/287#issuecomment-484151924

Related

How to read and set cookies from Browser/WebView in NativeScript?

I'm building an app which mainly displays public data from a website. A few items require authentication to read. I don't want to recreate the entire website in the app so I'd like to have the user log in via a web view or browser popup and grab the cookie containing the token from this session. I would then use it to authenticate my in-app rest calls in order to fetch the data. This should work on iOS and Android but I couldn't come up with a functioning solution yet. How would one read and write cookies from the phone browser / webview? I'm using the latest Angular (9) and NativeScript.
For android
The webview UI
<WebView height="1200px" src="https://www.nativescript.org"
(loadFinished)="onLoadFinished($event)"></WebView>
The typescript code
import * as application from 'application';
declare const android;
....
....
....
onLoadFinished(args: LoadEventData) {
android.webkit.CookieManager.getInstance().getCookie(<cookie name>)
android.webkit.CookieManager.getInstance().setCookie(<cookie name>, <cookie value>)
}
For IOS seems it is little bit complicated
Refer StackOverflow set cookie in IOS nativescript

How do I deal with a possible exception in a Xamarin Forms application deployed to iOS or Android?

I have a finished application which I would like to make available to run on the iOS and Android platforms.  I have tested the application as much as possible and it works without problem.  But I know there is always the chance that something might go wrong and I could get an exception.
My question is how can I deal with this or what should I do. What happens on the phone, if a Forms application is deployed and there is an exception.
Would appreciate any advice or even links as to how this is handled.
If an exception is thrown and not handled by your code, the app will stop working (i.e. crash).
In order to handle these crashes we are using MS AppCenter (the successor to HockeyApp/Xamarin AppInsights).
You'll have to create a project there (one for each platform), and add the NuGet package to your projects. Afterwards you can initialize it with
AppCenter.Start("ios={Your App Secret};android={Your App Secret}",
typeof(Crashes)); // you'll get the app secrets from appcenter.ms
Crashes will be logged to AppCenter now and you'll be informed whenever there is a new crash.
Please note that it's best practice (if not required by law), that you ask the user for consent before sending the crash report (see here). You are using the delegate Crashes.ShouldAwaitUserConfirmation for that matter. You could for example show an action sheet with Acr.UserDialogs
private bool AwaitUserConfirmation()
{
// you should of course use your own strings
UserDialogs.Instance.ActionSheet(
new ActionSheetConfig
{
Title = "Oopsie",
Message = "The app crashed. Send crash to developers.",
Options = new List<ActionSheetOption>
{
new ActionSheetOption("Sure", () => Crashes.NotifyUserConfirmation(UserConfirmation.Send)),
new ActionSheetOption("Yepp, and don't bug be again.", () => Crashes.NotifyUserConfirmation(UserConfirmation.AlwaysSend)),
new ActionSheetOption("Nope", () => Crashes.NotifyUserConfirmation(UserConfirmation.DontSend))
}
});
return true;
}

How to Close/Exit current instance of Xamarin.Forms app while loading a new one

We are facing a strange issue. Not sure if it is design flaw of the existing application. Your help/suggestion is appreciated.
We have a Xamarin.forms app. Targeted both for iOS and Android.
Problem is coming mainly in Android app.
Application flow:
once we logout from the application, app opens an logout activity and delete user info and other data.
opens a new activity for login which contains client SSO implementation
on successful login, app is setting user info and fetch data from web service.
then it calls LoadApplication method so that flow comes back in main application
Now if user perform logout/login several times, its opening a new application instance by calling LoadApplication method and then displaying home screen
So when user is tapping back button in home page, app is not closing and displays previous instance of same application.
User need to press back button several times (depending how many time user perform logout-login).
Is there any goodway to stop this?
Can we close current instance of the application before LoadApplication being called?
Stuck for a long time.
I'd try to avoid to call LoadApplication more then once. You should control the navigation stack.
Given you are on the LogoutPage
remove all views via PopToRootAsync
show the LoginPage
await Navigation.PopToRootAsync(false);
await Navigation.PushAsync(new LoginPage(), true);
This blog post may be worth a reading: https://jfarrell.net/2015/01/22/understanding-xamarin-forms-navigation/
Kindly try this.
https://stackoverflow.com/a/36885388/1941942
[Activity (NoHistory = true)]
public class LoginActivity : Activity { }
The saving instance error has gone a while after I implement it on MainActivity.

Opening the uri from background tasks in Universal windows apps

I know this sounds weird. Is there any way we can open a URI from background tasks in Windows 10 Apps?
I have 2 requirements,
Talk to cortana and it will show you results based on the speech recognition, when user clicks on it, we cannot open the links in browser directly. Instead I am passing the Launch Context to the Foreground app and then using LauchUri I am opening the url in default browser.
Send toast notifications from the App, when user clicks on it, I have requirement to open a url instead opening an app. So, did the same, by passing the launch context to foreground app and then opening the url.
Both scenarios, it just opening url in browser. Here user experience is very poor that user seeing the app open for each action and then opening browser. Please throw some ideas if any possibilities.
thanks in advance.
For your second requirement, you can make Toast Notifications launch a URL!
If you're using the Notifications library (the NuGet package that we suggest you use), just set the Launch property to be a URL, and change the ActivationType to Protocol. You can also do this with raw XML, but that's error-prone.
You can also make buttons on the toast launch a URL too, since they also support ActivationType of Protocol.
Show(new ToastContent()
{
Visual = new ToastVisual()
{
BindingGeneric = new ToastBindingGeneric()
{
Children =
{
new AdaptiveText() { Text = "See the news" },
new AdaptiveText() { Text = "Lots of great stories" }
}
}
},
Launch = "http://msn.com",
ActivationType = ToastActivationType.Protocol
});

Closing Android Activity opened from Forms.Context.StartActivity

I am working on facebook authentication in a Xamarin forms app and want to use "native" login on each device.
The Facebook SDK (by Xamarin) is not designed for forms since it requires passing in an Android activity that implements some specific interfaces.
However; I was able to get the UI to display using a custom page renderer and then in that renderer calling StartActitivty with an activity that uses the exact implementation described in the Facebook SDK getting started. https://components.xamarin.com/view/facebookandroid
So far everything works perfect. The android app starts, xamarin forms kicks in, the custom page renderer is loaded the login android activity starts and the user logs in with facebook and we get to the console.writeline below.
So, how do I dismiss this intent or otherwise get back to xamarin forms?
Do I:
Dismiss this intent? - if so then what?
Inject something to "reset" the main page?
Other?
public void OnCompleted (Xamarin.Facebook.Model.IGraphUser user, Response response)
{
//TODO: show user details with welcome and button that takes them to main app.
//TODO: switch back to xam forms from here on out.
//TODO: figure out how to change the `main` activity to xam forms.
// 'Me' request callback
if (user != null) {
//How do I get back to Xamarin forms from here?
Console.WriteLine ("GOT USER: " + user.Name);
} else {
Console.WriteLine ("Failed to get 'me'!");
}
}
You should call Finish();
Anyway, if you want to see exactly how I did it, you can check it here:
https://github.com/IdoTene/XamarinFormsNativeFacebook

Resources