Automating / Passing a MSAL Login

Hi everyone! I’m new here.

I’m trying to automate a login test on Microsoft Authentication Library (MSAL).

I’m new to appium and I’m trying to understand why this test is flakey.

I get this error from the server:

Send a sequence of keystrokes to the active element.[“[email protected]”]
An element could not be located on the page using the given search parameters

when trying to perform:

// Tapping E-mail …
t.tap(PointOption.point(263, 607)).perform(); // tapping the email/password field: a desperate move …
Thread.sleep(10000);
System.out.println(“Typing E-mail …”);
driver.getKeyboard().pressKey(account); // not working, why?
Thread.sleep(10000);

The code of the test is below:

public static boolean loginTest(AndroidDriver driver, String account, String password) throws InterruptedException {
Thread.sleep(10000);

    // Attempting to Login ...
    TouchAction t = new TouchAction((PerformsTouchActions) driver);

    // Tapping Sign-In Button ...
    System.out.println("Tapping the Sign-In Button ...");
    By signInButton = By.id("signIn");
    driver.findElement(signInButton).click(); // this works ...

// t.tap(PointOption.point(539, 2064)).perform(); // Tapping the sign-in button: a desperate move … this is flakey! why?

    Thread.sleep(10000);

    // Tapping E-mail ...
    t.tap(PointOption.point(263, 607)).perform();  // tapping the email/password field: a desperate move ...
    Thread.sleep(10000);
    System.out.println("Typing E-mail ...");
    driver.getKeyboard().pressKey(account); // not working, why?
    Thread.sleep(10000);

    // Tapping Next ...
    t.tap(PointOption.point(837, 1006)).perform();  // Tapping next: a desperate move ...
    Thread.sleep(10000);

    // Tapping Password ...
    System.out.println("Tapping Password ...");
    driver.getKeyboard().pressKey(password); // not working, why?
    Thread.sleep(10000);

    // ...
    driver.getKeyboard().pressKey(Keys.ENTER);
    Thread.sleep(10000);

    String syncActivity = ".Sync";
    // Return true if login was performed successfully ...
    return (Objects.equals(driver.currentActivity(), syncActivity));
}

Thank you.

Welcome to the forums.

Not sure how to say this.

  1. automating secure logins using an automation engine is something we really should warn people about in school. It generally works, but when it does not, there is a very good reason for that.
    It’s secure for a reason. Just don’t. Are those 10 second sleeps, you get paid to wait for that long?
  2. Did you try typing in each character of the secure login form with a tiny delay in between each key of the username and password, instead of stuffing the keyboard buffer, that’s normally a sure sign to the app, that a robot is trying to hack.
  3. You are not describing the error you get, you say it’s “flakey”, so you mean to does sometimes work? What is different about when it works, and when it does not work, and what have you tried (not using long sleeps) so far and learned so far.

Addressing your points:

1. automating secure logins not working for a good reason: that is a possibility. however, this is the first step on the mobile app I’m testing. if this step is not automated, automation of subsequent tests may not be possible - this is the reason why it’s being done. In case you have any alternative suggestions, I’d be happy to learn about em.

2. Yes, I have tried, extensively, 10 seconds delays in between each key. Also, I’ve tried the following and it works, unless for the NUMPAD_DOT. Any idea why this happens?

System.out.println(“Typing E-mail …”);

    // working ...
    driver.pressKeyCode(AndroidKeyCode.KEYCODE_U);
    driver.pressKeyCode(AndroidKeyCode.KEYCODE_S);
    driver.pressKeyCode(AndroidKeyCode.KEYCODE_E);
    driver.pressKeyCode(AndroidKeyCode.KEYCODE_R);
    driver.pressKeyCode(AndroidKeyCode.KEYCODE_AT);
    driver.pressKeyCode(AndroidKeyCode.KEYCODE_E);
    driver.pressKeyCode(AndroidKeyCode.KEYCODE_M);
    driver.pressKeyCode(AndroidKeyCode.KEYCODE_A);
    driver.pressKeyCode(AndroidKeyCode.KEYCODE_I);
    driver.pressKeyCode(AndroidKeyCode.KEYCODE_L);
 
    // note: all above fail to type/tap the dot character '.'
    //driver.pressKey(new KeyEvent(AndroidKey.NUMPAD_DOT));
    //((AndroidDriver) driver).pressKey(new KeyEvent(AndroidKey.NUMPAD_DOT));
    //driver.getKeyboard().pressKey(".");
    //driver.pressKeyCode(AndroidKeyCode.KEYCODE_NUMPAD_DOT);
    //driver.pressKeyCode(158);
    
    // working ...
    driver.pressKeyCode(AndroidKeyCode.KEYCODE_O);
    driver.pressKeyCode(AndroidKeyCode.KEYCODE_R);
    driver.pressKeyCode(AndroidKeyCode.KEYCODE_G);

3. Flakey: I’m tapping the coordinates and sometimes it works, sometimes it doesn’t.

// t.tap(PointOption.point(539, 2064)).perform(); // Tapping the sign-in button: a desperate move … this is flakey! why?

Note: I have found an alternative functional locator strategy to do this, however, I’d like to learn how reliable is coordinates tapping.

From my experience, and it is short, appium gets flakey often when you don’t use sleeps long enough.
So my strategy is to make sure it works first, reducing the testing time later.
I’m learning as I go and building up.
Again, suggestions are welcome.

1 Like

You could also use https://github.com/appium/appium-uiautomator2-driver#mobile-type to emulate sending of keystrokes.

In general, it is usually not the best idea to automate login flows unless the purpose of an automated test is to test exactly this particular flow. In all other cases it would only slow down tests and make them more flaky. Check https://appiumpro.com/editions/23-making-your-appium-tests-fast-and-reliable-part-5-setting-up-app-state and https://appiumpro.com/editions/26-making-your-appium-tests-fast-and-reliable-part-8-mocking-external-services for more details

I’m already using the uiautomator2: none of the below is working to tap the dot “.” character, however, it works for other characters.

// note: fails to type/tap the dot character ‘.’
driver.pressKey(new KeyEvent(AndroidKey.NUMPAD_DOT));
((AndroidDriver) driver).pressKey(new KeyEvent(AndroidKey.NUMPAD_DOT));
driver.getKeyboard().pressKey(".");
driver.pressKeyCode(AndroidKeyCode.KEYCODE_NUMPAD_DOT);
driver.pressKeyCode(158);

@Conrad_Braam:

By “flakey” I mean that sometimes the test works, sometimes it doesn’t, and I don’t know why.

@mykola-mokhnach:

According to the Dev Team, setting up an app version with a logged-in state may not be possible. They claim they don’t know how to bypass the Microsoft Authentication Library by code. In case someone has a hint or workaround, please share.

I have automated the log in. However, does this mean I’ll always have to run a login automated test to get the app to the state where I can automate tests for other features (I’m afraid of the answer)? Thanks for your expertise.

Note: tapping “.” can be done using the following line of code.

    `driver.pressKey(new KeyEvent(AndroidKey.PERIOD));`

https://developer.android.com/reference/android/view/KeyEvent#KEYCODE_PERIOD

According to the Dev Team, setting up an app version with a logged-in state may not be possible. They claim they don’t know how to bypass the Microsoft Authentication Library by code. In case someone has a hint or workaround, please share.

I have automated the log in. However, does this mean I’ll always have to run a login automated test to get the app to the state where I can automate tests for other features (I’m afraid of the answer)? Thanks for your expertise.

You could try to ask devs about creating a backdoor for the build used in automated testing. It worths the time you could save on performing login for each test.

2 Likes