service auth | Cell 5 | Automatically fill any type of login form using various algorithms | Search

This code automates the Google sign-in process using Selenium, handling both username and password entry, and includes logic to select an account from multiple options if necessary.

Run example

npm run import -- "log in to Google using webdriver"

log in to Google using webdriver

var matchUsername = 'input[name="Email"], input[autocomplete="username"]';
function enterGoogleUsername(email) {
    console.log('Google: Sign in required');
    return client
        .pause(1000)
        .then(() => client.$(matchUsername))
        .then(el => el.addValue(email))
        .then(() => client.$('#identifierNext'))
        .then(el => el.click())
        .catch((e) => console.log(e));
}

var matchPassword = 'input[name="Passwd"], input[autocomplete="password"], input[name="password"]';
function enterGooglePassword(pass) {
    console.log('Google: Require password');
    return client
        .pause(2000)
        .then(() => client.$(matchPassword))
        .then(el => el.addValue(pass))
        .then(() => client.$('#passwordNext'))
        .then(el => el.click());
}

function enterCredentials(is) {
    var credentials = getCredentials('accounts.google.com');
    if (is) {
        return client.$('#passwordNext')
            .then(el => el.isDisplayed())
            .then(is => is
                ? enterGooglePassword(credentials.Passwd)
                : enterGoogleUsername(credentials.Email)
                    .then(() => enterGooglePassword(credentials.Passwd)))
    } else {
        return client
            .findElements('xpath', '//h1[contains(., "Choose an account")]')
            .then(is => {
                if (is.length > 0) {
                    return client
                        .findElements('xpath', '//*[@data-authuser][contains(., "@")]')
                        .then(is => {
                            console.log(is);
                            return is.length > 0
                              ? client.$('//*[@data-authuser][contains(., "@")]').then(el => el.click())
                              : []
                        })
                        .then(() => client.$('#passwordNext'))
                        .then(el => el.isDisplayed())
                        .then(is => is
                            ? enterGooglePassword(credentials.Passwd)
                            : [])
                } else {
                    return client.findElements('xpath', '//h1[contains(., "Sign in")]')
                        .then(is => is
                            ? enterGoogleUsername(credentials.Email)
                                .then(() => enterGooglePassword(credentials.Passwd))
                            : null)
                }
            })
            .catch((e) => console.log(e));
    }
}

function loginGoogle() {
    return client
        .findElements('css selector', 'a[href*="ServiceLogin"]')
        .then(is => is.length > 0 ? client.click('a[href*="ServiceLogin"]') : null)
        .then(() => client.pause(1000))
        .then(() => client.findElements('css selector', 'form[action*="signin"]'))
        .then(is => enterCredentials(is.length > 0))
        .catch((e) => {
            console.log(e);
            console.log('Google: Could not log in');
        });
}

module.exports = loginGoogle;

What the code could have been:

// Constants for matching elements on the page
const MATCH_USERNAME = 'input[name="Email"], input[autocomplete="username"]';
const MATCH_PASSWORD = 'input[name="Passwd"], input[autocomplete="password"], input[name="password"]';

class GoogleLogin {
  constructor(client) {
    this.client = client;
  }

  /**
   * Enters the username in the Google sign-in form
   * @param {string} email - The email to enter in the sign-in form
   * @returns {Promise} A promise that resolves when the operation is complete
   */
  enterGoogleUsername(email) {
    console.log('Google: Sign in required');
    return this.client
     .pause(1000)
     .then(() => this.client.$(MATCH_USERNAME))
     .then(el => el.addValue(email))
     .then(() => this.client.$('#identifierNext'))
     .then(el => el.click())
     .catch((e) => console.log(e));
  }

  /**
   * Enters the password in the Google sign-in form
   * @param {string} pass - The password to enter in the sign-in form
   * @returns {Promise} A promise that resolves when the operation is complete
   */
  enterGooglePassword(pass) {
    console.log('Google: Require password');
    return this.client
     .pause(2000)
     .then(() => this.client.$(MATCH_PASSWORD))
     .then(el => el.addValue(pass))
     .then(() => this.client.$('#passwordNext'))
     .then(el => el.click());
  }

  /**
   * Determines whether to enter a username or password in the Google sign-in form
   * @param {boolean} isPassword - Whether to enter a password
   * @param {Object} credentials - The credentials to use
   * @returns {Promise} A promise that resolves when the operation is complete
   */
  enterCredentials(isPassword, credentials) {
    return this.client
     .$('#passwordNext')
     .then(el => el.isDisplayed())
     .then(isDisplayed => {
        if (isDisplayed) {
          return this.enterGooglePassword(credentials.Passwd);
        } else if (isPassword) {
          // This is redundant, as isPassword is already true
          // return this.enterGooglePassword(credentials.Passwd);
          return this.enterGooglePassword(credentials.Passwd);
        } else {
          return this.enterGoogleUsername(credentials.Email).then(() => this.enterGooglePassword(credentials.Passwd));
        }
      })
     .catch((e) => console.log(e));
  }

  /**
   * Logs in to Google
   * @returns {Promise} A promise that resolves when the operation is complete
   */
  loginGoogle() {
    return this.client
     .findElements('css selector', 'a[href*="ServiceLogin"]')
     .then(is => is.length > 0? this.client.click('a[href*="ServiceLogin"]') : null)
     .then(() => this.client.pause(1000))
     .then(() => this.client.findElements('css selector', 'form[action*="signin"]'))
     .then(is => is.length > 0 && this.enterCredentials(true, getCredentials('accounts.google.com')))
     .catch((e) => {
        console.log(e);
        console.log('Google: Could not log in');
      });
  }
}

module.exports = (client) => new GoogleLogin(client).loginGoogle();

This code snippet defines functions for automating the Google sign-in process using a Selenium WebDriver client.

Here's a breakdown:

  1. Selectors:

  2. enterGoogleUsername Function:

  3. enterGooglePassword Function:

  4. enterCredentials Function: