How to Skip Authentication in test automation using Playwright

How to Skip Authentication in test automation using Playwright

Every software application identifies, recognizes, and authenticates the user trying to access the system using some type of credentials (i.e Username and password). And once the user is verified/authenticated, that user is granted permission to access authorized resources.

So, while testing the software application for every test case, the first step we perform is the login step.

If the test suite consists of 100+ test cases, then the step of logging in to the application will be performed for each test case. You can imagine the unnecessary time that will consume for logging in to the application each time for all those 100+ test cases.

Can we find a way to reduce the time required for logging in to the application for every test case? or can we skip logging in to the software application altogether?

This is where Playwright comes into the picture.

The playwright is an open-source test automation tool created by Microsoft. It is a cross-platform tool and has a set of features like Test Generator (codegen), Trace viewer, Inspector, etc, and the most important feature of Playwright which will help us to skip authentication in test automation is full isolation with browser context.

In addition, you can refer to the official document on playwright basic authentication.

First Off, we will have to login into the application via UI and reuse the authentication state in different and multiple scenarios using the browser context.

Let’s see how we can do it.

First, we are going to create a GenerateSession.java class where all of our own logical and automated login steps will be implemented,

Code:

import com.microsoft.playwright.*;
import java.nio.file.Paths;
public class GenerateSession {

        Playwright playwright = Playwright.create();
        Browser browser = playwright.chromium().launch(new      BrowserType.LaunchOptions().setHeadless(false));
        BrowserContext browserContext = browser.newContext();

        Page page = browserContext.newPage();
        page.navigate(BASE URL);
        page.fill("//*[@id=\"username\"]",USERNAME);
        page.fill("//*[@id=\"password\"]",PASSWORD);
        page.click("//*[@id=\"Login\"]");

So, what we did here is, launched the browser and created a new page.

In BrowserContext browserContext = browser.newContext();
we have created a browser context. This browserContext will store our authentication state i.e it will store the session, cookies, local storage, etc.

As you can see, we created the browser context browserContext, but the question here is, where will this authentication state (browserContex) will be stored?

The best way to store this browser context in a .json file.

The playwright provides a method called storageState() which will help us store the authentication state.

browserContext.storageState(new BrowserContext.StorageStateOptions().setPath(Paths.get("appLoginInfo.json")));

The above code snippet will store the authentication state, cookies, local storage, etc in json format in appLoginInfo.json file.

If the appLoginInfo.json file is not created then the playwright will create a new file with the provided name appLoginInfo.json at the provided location in setPath(Paths.get(“appLoginInfo.json”)));

If you have the appLoginInfo.json file already created, each time you execute the above snippet, a new authentication state with cookies and local storage will be overwritten in the appLoginInfo.json file.

Now, we are all set up with our authentication state, cookies, and local storage. Our next question is

How do we use that authentication state and skip login for each scenario?

We can use a Playwright to skip authentication scenarios. As we all know, Web applications use cookies and token-based authentications. These authentications are stored in the form of cookies or local storage. The playwright provides us with methods that can store these authentication state and then create a new browser context with the previously restored session, which in turn help us skip login/authentication for the scenarios.

Here, we will set the stored authentication state using the methods above to the new browser context created for each scenario we run.

The playwright provides us with a method newContext()  which will create a new browser context.

And by using NewContextOptions(), we can add/set the stored authentication state in the appLoginInfo.json file.

Let’s look at how we can do it in the code snippet below.

BrowserContext brContext = browser.newContext(new Browser.NewContextOptions().

setStorageStatePath(Paths.get("appLoginInfo.json")));

Here, setStorageStatePath(Paths.get(“appLoginInfo.json”))will set the authentication state stored in appLoginInfo.json to the new browser context created in the previous step.

So, every time we execute the above code snippet, the browser context that is stored in appLoginInfo.json file will be set to the new browser context and the previous session will be restored.

Please refer to the methods listed below. I used these methods to skip authentication scenarios for one of the Salesforce apps.

        @Test
        public void generateSessionCookies() throws InterruptedException {
        Playwright playwright = Playwright.create();
        Browser browser = playwright.chromium().launch(new BrowserType.LaunchOptions().setHeadless(false));
        BrowserContext browserContext = browser.newContext();
        Page page = browserContext.newPage();
        page.navigate("BASE URL");
        page.fill("//*[@id=\"username\"]", "USERNAME");
        page.fill("//*[@id=\"password\"]", "PASSWORD");
        page.click("//*[@id=\"Login\"]");
        page.click("//*[@id=\"save\"]");
        browserContext.storageState(new BrowserContext.StorageStateOptions().setPath(Paths.get("appLoginInfo.json")));
        page.close();
}
         @Test
         public void useSavedSessionCookies() throws InterruptedException {
         Playwright playwright = Playwright.create();
         Browser browser = playwright.chromium().launch(new BrowserType.LaunchOptions().setHeadless(false));
         BrowserContext browserContext = browser.newContext();
         Page page = browserContext.newPage();
         browserContext.storageState(new BrowserContext.StorageStateOptions().setPath(Paths.get("appLoginInfo.json")));
         page.close();
}

Conclusion:

In this way, Playwright helps us to store the authentication state, cookies, local storage, etc. And we can use this authentication state and set it to our new browser context and restore the previous session, which will in turn help us skip the login step for the n number of scenarios for a software application.

I hope this article has served you well. 

Read more blogs here

Inspecting Webview App Element using Chrome Extension

Inspecting Webview App Element using Chrome Extension

Inspecting the WebView element using the Chrome browser is the easiest and most efficient way. So in this blog, I am going to explain how to inspect the WebView element using the chrome browser. Let’s first understand what WebView is and why to use it.

What Is A WebView?

It is widely used to display web pages in an application. The web pages and web apps can reuse in an Android application. The content used to display inside a WebView is responsive and mobile-friendly and because of this, it works better towards providing a better user experience.

Now let’s see how to inspect elements on Android WebView

1) The first step is you need to connect your mobile device to your system.

2) The second step is you need to go to your chrome browser and go to chrome://chrome-urls/ then you will see the result like the below screenshot:

3) You need to select “chrome://inspect/” from that list.

4) Click on it and it will open a window like this. There is an option to discover USB devices in it. It will display information about the devices that are currently attached to the system.

5) Now launch the app on your mobile device, and for inspecting the element just click on inspect.

This will open a new chrome window containing all the UI details of that screen.

Now you can inspect the elements for the webview app like you inspect for the website. By following these steps you will get a better understanding of how you can inspect a webview using a chrome browser and how you can locate your desired elements.

Below is the link for your reference to inspect webViews and get locators.

http://www.qaautomationsimplified.com/android/android-automation-how-to-inspect-webviews-and-get-locators/

Conclusion:

According to my experience, this is the most effective and easier way to inspect WebView elements using the chrome browser.

Read more blogs here

How to set an automatic backup of your source code repository?

How to set an automatic backup of your source code repository?

One day my colleague David was working on a task to migrate a repository from one platform to another while he was doing that the server crashed, the platform went down and all the data, code, and documentation available on the repository was lost. Have you ever imagined yourself in David’s Situation, What if this happens to you? Wondering what solution you can use instead of manual efforts?

You’re not alone.

We faced the same problem and found one of the best automation solutions that will work on all the platforms.

Problem:

We want to protect our source code repositories at any cost. It contains all of our code, documentation, and work history.

The real nightmare comes when you don’t have a backup. We all know that taking frequent backups manually is a tedious process.

So how can we do that through automation?

Solution:

There are many solutions to that. We have used this solution because it is based on bash script and works on all the platforms like Azure DevOps, Gitlab, and Bitbucket.

We are copying the Azure DevOps repository to GitHub. But as we said we can use this solution on every platform.

  1. First, log in to your GitHub account and create a GitHub repository. (If you don’t have it already)
  2. You have to generate a Personal access token at GitHub.

Settings -> Developer Settings -> Personal Access tokens

Generate and copy the token value. (refer to the following screenshot)

C:\Users\Uddhav\Desktop\Blogs\A2G\Untitled.png

3. Navigate to your Azure repository. And create a pipeline there.


4. Add the following bash script task to the pipeline.

What will this script do?

This script will override the branch code of GitHub. In simple words, if you want to copy code from the feature branch of Azure to GitHub then:

  1. In GitHub – If the feature branch is present, it will override the code.
  2. In GitHub – if the feature branch is not present, then the branch will be created.
bash: |
git push -- \
Prune //ghp_iYwH9mwvmWVAFCD@github.com/SpurQLabs/SpurQLabsProject \
+refs/remotes/origin/master:refs/heads/master +refs/tags/:refs/tags/
displayName: 'Copy to GitHub'
condition: eq(variables['Build.SourceBranch'], 'refs/heads/master')
Note:

If your branch (in Azure) is master then no need to change but if your branch is main then you should replace the “master” with “main”.

Be Careful:

If you already have a repository (With Code)  in GitHub, then instead of main or master use the feature branch in Azure.  And then raised PR to the main branch.

And if you want to update code from the main branch from Azure to the main branch from GitHub then no worries. You are good to go. (It will override main branch code, if not there then will create a new one.).

  • You can trigger your pipeline according to your requirements.
  • If you want to schedule it on a daily, weekly, or monthly basis then you can use the “schedule”&”cron” options in the pipeline.
  • Below is the link for your reference to schedule the pipeline

https://docs.microsoft.com/en-us/azure/devops/pipelines/process/scheduled-triggers?view=azure-devops&tabs=yaml

Run your pipeline.

  And Done and Dusted..!

#Azure-pipeline.yml for reference

#Azure-pipeline.yml for reference
trigger:
- DemoSync #your feature Branch, Run this pipeline from your feature branch.
pool:
  vmImage: ubuntu-latest
steps:
- checkout: self
- bash: |
    git push --prune https://ghp_cbvnn@github.com/SpurQLabs/SpurQLabsProject \
    +refs/remotes/origin/DemoSync:refs/heads/DemoSync +refs/tags/*:refs/tags/*
  displayName: 'Copy to GitHub'
  condition: eq(variables['Build.SourceBranch'], 'refs/heads/DemoSync')

Conclusion

This is how the source code is migrated from azure repositories to GitHub repositories automatically after every check-in/PR merge.

As mentioned above, you can schedule it daily, Weekly, or monthly.

Read more blogs here

Automating biometric authentication on iOS using BrowserStack

Automating biometric authentication on iOS using BrowserStack

Introduction:-

Today, almost all mobile devices support biometric authentication, such as Touch ID/Fingerprint Sensors and Face ID. Using the Browser Stack Android/iOS testing platform, developers can test their mobile applications using biometric authentication. In Automating biometric authentication on iOS using BrowserStack users can be authenticated using biometrics.

Note This feature is currently not available for Android devices.

My application uses biometric authentication when it relaunches (relaunching means that the user is logged in and the app is closed from the background). Let’s look at a practical example.

How to check biometric authentication:

You can check Biometric authentication in an App Automate session by following these steps:

  1. A browser Stack Appium session can be enabled with Biometrics by using the following Browserstack Appium capability: BrowserStack.enable biometric:”true”
  2. As shown below, this capability ensures that your app passes through Sensor Instrumentation.
def before_scenario(context,scenario):
	if context.config.userdata["executionMode"]=="Browserstack":
	context.driver =webdriver.Remote(
	command_executor='https://'+context.config.userdata["userName"]+':'+context.config.u
	serdata["accessKey"]+'@hub-cloud.browserstack.com/wd/hub',
	desired_capabilities={
		"platformName": "iOS",
		"build": context.config.userdata["browserstack_build"],
		"device": context.config.userdata["browserstack_device"],
		"os_version": context.config.userdata["device_os_version"],
		"app":context.config.userdata["browserstack_appUrl"],
		"nativeWebTap":True,
		"browserstack.enableBiometric": True    #desired Capability
		}
		)
	elif context.config.userdata["executionMode"]=="Emulator":
	context.driver = webdriver.Remote(
	.
	.
	.					 

By using the ‘before scenario’ context in the ‘environment.py’ file, this Python code creates the desired capability. As a result of using this capability, we get the following screen when it is executed.

How to interact with the Biometric authentication dialog:

Using the custom executor, you can manipulate the Automating biometric authentication on iOS using BrowserStack dialog box.

Following are the complete scenario and required steps with the page file code.

Scenario: User Login by biometric after app relaunch
Given User is on "Welcome" page		
And User does Login with "Username" and "Password"
When User creates security pin for "Username"  
# creates security step depends on application
And User closes app and relaunch the app
Then User clicks "Pass" on biometric alert screen
#Then User clicks "Fail" on biometric alert screen						 

Step definition file –

@then('I click "{option}" on biometric alert screen')
def step_impl(context,option):
	context.signIn.clickon_pass(option) 

Page file –

def clickon_pass(self,option):
	self.driver.find_element_by_accessibility_id(option).click()
	sleep(5)

Note: – There are two options here ‘Pass’ or ‘Fail’

The application opens when the user clicks ‘Pass’ on the authentication alert screen.

If you click “Fail” on the authentication alert screen, the application will request that you re-login with your forgotten pin or security pin instead of biometric information.

This feature supports native apps & apps built with cross-platform frameworks such as React Native, Flutter, etc. The BrowserStack Biometric feature supports Biometric APIs. only if the app uses one of the supported Biometric APIs. A biometric API can be used with the approval of the app development team on Android and iOS.

Conclusion:

The BrowserStack platform with Appium capabilities allows developers and testers to test mobile applications with Biometric Authentication.

Read more blogs here

How to automate office 365 login in cypress using Nightwatch.js

How to automate office 365 login in cypress using Nightwatch.js

This blog will explore how to automate office 365 login in cypress using Nightwatch.js. Currently, I’m working on Cypress automation for testing web applications.

First, let’s understand the problem area.

We needed to automate the login flow in an application using office 365’s IDP. When we launched the application through cypress, we landed on the office 365 login screen which was not possible to automate. We were not able to have control over the page through cypress. Cypress has some other techniques to automate this like SSO(single-sign-on) However, our clients were not able to share some secrets and also the Azure DevOps environment.

So far nothing worked for us, So now let’s come to the point.

In order to automate office 365 login in cypress using Nightwatch.js. I thought we could use other tools to get the JWT token that we can use to log into an application through Cypress.

Now, the question was which tools to be selected

I selected Nightwach.js tools because it was easy to use with little configuration. We successfully automated office 365 login. Get the JWT token from local storage and write it in common utility files.

Again the question was how to trigger the Nightwatch.js script through cypress.

Cypress supports cy. exec command runs the Nightwatch.js script and then control comes back to cypress and the rest execution is done.

  • Now let us try the recipe, First install nightwatch.js with the following command, Copy
npm install nightwatch						 
  • And also need to install the chrome driver with the following command, Copy
npm install chromedriver --detect_chromedriver_version

And also created a script for nightwatch.js

In the below code, we are reading JWT Token from local storage and storing it into jwtToken.txt

module.exports =
{
  '@tags': ['adm'],
  "test": function (browser) {
    let ch
    browser.url("Application url")
    browser.click('#details-button')
    browser.click('#proceed-link')
    browser.click('span[class="microsoft-logo"]')
    browser.setValue('#i0116', 'email')
    browser.click('#idSIButton9')
    browser.setValue('#i0118', 'password')
    browser.click('#idSIButton9')
    browser.click('#idBtn_Back')
    browser.execute(function () {
      ch = window.localStorage.getItem('jwtToken');
      return ch
    }, [], function (result) {
      this.assert.equal(result.value, result.value
      const fs = require('fs'
      const path = require('path');
      const dirPath = path.join(__dirname, '../cypress/fixtures/jwtToken.txt')
      var path2 = dirPath.replace(/\\/g, "/");
      console.log(path2)
      fs.writeFile(path2, result.value, err => {
        if (err) {
          console.error(err)
          return
        }
      })
    })
  }
}				
  • Add the following command in support/command.js
Cypress.Commands.add("User", () => {
  cy.exec("npx nightwatch -e chrome ")
})
  • Add the following code in the hooks file to use the JWT token in your tests reading the jwtToken.txt
Before({ tags: "@user" }, () => {
  cy.readFile('cypress/fixtures/jwtToken.txt').then((jwtToken) => {
    cy.log("JWT Token before : " + jwtToken)
  })
  cy.log('start')
  cy.User()
  cy.log('end')
  cy.readFile('cypress/fixtures/jwtToken.txt').then((jwtToken) => {
    cy.log("JWT Token After : " + jwtToken)
    cy.window().then(
      window => window.localStorage.setItem('jwtToken',jwtToken), { flag: 'w' })
      cy.visit(Cypress.config('apiLoginURL'))
  })
})

The output is that a new JWT token is generated and that the JWT token is used to run cypress test cases.

JWT Token in Cypress Test

Conclusion :

 Different automation tools can be integrated with Cypress where Cypress lacks the ability to do so. In the previous version of Cypress, multi-domain origins were not supported, so we automated this scenario through Nightwatch.js.

Read more blogs here