Testing third party authentication flows with Espresso - android

I am writing an Espresso test for an Activity which contains a button used for authenticating using a Google account and a button used for authenticating using a Facebook account. In my test I would like to simulate clicks on each of these buttons and ensure that it launches the correct component provided by these third parties.
It seems that there are two possible options:
Simulate a click on the appropriate button and ensure the UI contains the expected views.
Simulate a click on the appropriate button and ensure the correct Intent was fired.
I've initially opted for option #2, as I have found that it is difficult to test the UI with components outside of the Activity under test.
To start, I created a test for the Google button. The code is below:
#Test
public void testGoogleAuthButton() {
// Start the Activity under test.
activityRule.launchActivity(new Intent());
// Click the Google button.
onView(withId(R.id.googleSignUpButton)).perform(click());
// Ensure the `SignInHubActivity`, an `Activity` provided by the Google APIs, was launched.
intended(hasComponent(SignInHubActivity.class.getName()), times(1));
// Simulate a press on the back button to close the account chooser.
UiDevice.getInstance(getInstrumentation()).pressBack();
}
This test passes, however I am unsure as to whether or not this is the correct way to perform this test. Next, I tried a similar technique for the Facebook button:
#Test
public void testFacebookAuthButton() {
// Start the Activity under test.
activityRule.launchActivity(intent);
// Simulate a click on the Facebook button.
onView(withId(R.id.facebookSignUpButton)).perform(click());
// Ensure the `FacebookActivity`, an `Activity` provided by the Facebook APIs, was launched.
intended(hasComponent(FacebookActivity.class.getName()), times(1));
// Simulate a press on the back button to close the current Activity.
UiDevice.getInstance(getInstrumentation()).pressBack();
}
Strangely, this test fails, and notes that no Intents were matched and that none were recorded.
My questions:
Does the code shown above represent the correct way to test these flows?
Why does the Facebook version of the test shown above fail, while the Google version does not?

Related

Starting Google Assistant / What's on my screen from onClick of button?

I want to start Google Assistant with a query (or without any) when the user clicks a button, could not find any reference to doing this task.
I tried calling the following function, as I found in the documentation of Google Assistant but I do not understand how to use it for my Application:
#Override
public void onProvideAssistContent(AssistContent assistContent) {
super.onProvideAssistContent(assistContent);
String structuredJson = new JSONObject()
.put("#type", "MusicRecording")
.put("#id", "https://example.com/music/recording")
.put("name", "Album Title")
.toString();
assistContent.setStructuredData(structuredJson);
}
It does nothing, even when I long press home screen button to open Google Assistant, and select option what's on my screen it shows nothing.
If this is not possible, can I add the same action as Long Press Home does, i.e. open Google Assistant; to my button?
This method is for the on-screen reading feature "What's on my screen?" It can help to parse content by giving additional context.
As of now there is no programmable way to activate the Assistant in the normal manner. It doesn't have to be as the process is straightforward for users.
You can implement an Assistant-like intent receiver for your app, so it'll be called when users long press. However, it would override that for all apps, which would not be a great experience.
There is a Google Assistant SDK for embedding it into apps and devices. You can use the gRPC calls to send audio or text requests to the Google Assistant and get back a response. It is just a network API, so there's no UI included.

Messing with Twitter login using both Fabric and Parse.com

I'm so confused. I started using parse.com, noted they had useful APIs for logging in with Twitter, and was doing:
Button login = (Button) findViewById(R.id.twitter_login);
login.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
ParseTwitterUtils.logIn(this, ...)
}
});
So when clicking on login (a simple button of mine) I was being shown a floating dialog, and asked to give permissions to the app I registered on the Twitter Application Management.
Then I wanted to have the twitter-designed log-in button, of course, and so subscribed to io.fabric, installed Twitter APIs, and put a <com.twitter.sdk.android.core.identity.TwitterLoginButton/> element in my layout.
This button needs no click listener, because clicking on it brings up a new window where I am asked to give permissions to a fabric registered app which I wasn't even aware of, and that I can manage through the official Fabric website.
So
if I have a TwitterLoginButton and also set my parse.com click listener on it, I will be asked giving permission to two different apps (but these are the same app I'm working on!)
How to get elegantly out of this mess?
Is there something I can do to merge the two applications in these two different websites?
Should I stick to one approach or the other? I really need the user to sign on my parse.com database. But if only use ParseTwitterUtils, I won't have the login button (right?).
What is really happening when calling ParseTwitterUtils.logIn? Is it logging in the user into Twitter (and so I'll be able to use "share" functions and such), or just fetching user data into the parse.com database?
Wrote four questions, but what I'm really asking is what is the most used approach to this.

Google Play Game Services - not signed in on next activity

In my application, i have in game helper(i want log in on button click):
// Whether to automatically try to sign in on onStart(). We only set this
// to true when the sign-in process fails or the user explicitly signs out.
// We set it back to false when the user initiates the sign in process.
boolean mConnectOnStart = false;
In my MainActivity (extends BaseGameActivity), after login button click i call:
beginUserInitiatedSignIn();
Of course now isSignedIn() returns true.
But when I go to next Activity (aslo extends BaseGameActivity):
isSignedIn() return false.
I can of course call beginUserInitiatedSignIn() on my next Activity, but i don' t want it.
In my app user can be logged in, but not have to. So if user not logged in at my mainActivity i don' t want show login form on next activity.
Edit: For this moment my solution is to create static variable and set it when i leave my main activity for ture if isSignedIn() and call beginUserInitiatedSignIn() on next activity only when this variable is true. Is it any better, automatic solution ?
There's two types of sign in:
The user initiated sign in which shows the Google Play Games logo and requires the user to approve access, etc.
Silent sign in (which BaseGameActivity does in its onStart call) - this automatically attempts to sign in and, if the user has already signed in, does the same callback as if you had gone through the user initiated sign in flow.
Therefore you do need to wait for the sign in callback before attempting any Google Play Games related calls in each and every activity.
Note that recently (4 days ago on Feb 18, 2014), the BaseGameUtils library for Android was updated to use the new Google Api Client model, which allows you to do read calls before being signed in (where they will automatically wait until sign in before attempting to process). As the Google Api Client gives a number of other benefits (such as improved sign in reliability), you should update to the latest BaseGameUtils if you haven't already.

Running Facebook Login / Publish as Seperate Class

I have followed : https://developers.facebook.com/docs/howtos/androidsdk/3.0/login-with-facebook/
I have created a separate page as in the example and works perfectly fine.
My issue is now I want to add the Login button to my home page and the publish button on a different page. Is it possible to convert this into a separate class that I can call from anywhere?
Has anyone done this and can point my in the right direction.
Sorry if this has been asked before. I am very new to Facebook SDK
Thanks for your time
Yes, if you use the Active Session, you should be able to call Session.getActiveSession() from any activity, and it should return you the right thing. So the page with the login button would create the active session, and the page with the publish button would get the active session, and call requestNewPublishPermission and do the publish.
There are 2 outstanding issues:
You need to ensure that the page with the login button appears in your app before the page with the publish button (at least the first time, when the user initially logs in).
In subsequent restarts of your app (after the user has already logged in), you can use the UiLifecycleHelper to manage, restore, and auto-open the active session for you.

Android - Facebook API - How to authenticate two times?

I have a problem while trying to log in on Facebook for the second time. The first time the user enter its credentials, I start to upload some pictures in the background into its Facebook account.
However, in that period, another user can come and hit the Facebook button again. I expect that the previous request is still being processed, which is the case. However, I can't get the second user to log in WHILE THE FIRST PROCESSING (that is, the upload of the pictures of the first user) HAS NOT FINISHED YET.
What happens with the current version is that, when the second user hits my Facebook button, the Facebook API just assume that it refers to the previous user (because it is still running in the background). However, I want to start ANOTHER section with this new user, while the old one is still running in the background. How can I achieve that?
Here is my simple code (when the user hits my Facebook button on the screen, I call the following method):
private void uploadPictures(View target) {
mFacebook = new Facebook(getString(R.string.facebookappid));
mAsyncRunner = new AsyncFacebookRunner(mFacebook);
mFacebook.authorize(this, Settings.FACEBOOK_PERMISSIONS, Facebook.FORCE_DIALOG_AUTH, new LoginDialogListener());
}
PS: I have also tried to instantiate more than one Facebook and AsyncFacebookRunner objects, but it did not work (I get the same behaviour, that is, even though the objects are different, the login screen simply does not show up the second time (if the previous request is still being processed))!!!
Thank you so much in advance!
You're able to do something similar to this with the new 3.0 beta SDK. You can get it here and check out the SwitchUserSample.
You won't be able to use single sign-on (SSO) with the different users (they'll need to sign in via a webview dialog), but you'll get a different Session object that use can use for different users.

Categories

Resources