Skip to content

Instantly share code, notes, and snippets.

@arthurtsang
Created August 30, 2019 16:59
Show Gist options
  • Save arthurtsang/82d91a3f770df45842b310ec75f2318b to your computer and use it in GitHub Desktop.
Save arthurtsang/82d91a3f770df45842b310ec75f2318b to your computer and use it in GitHub Desktop.
authorize and get token from gmail api using protractor
import gmailCred from '../resources/gmail.credentials.json';
import { gmail_v1, google } from 'googleapis';
import * as fs from 'fs';
import { OAuth2Client } from 'google-auth-library';
import { browser, by, ElementFinder } from 'protractor';
// If modifying these scopes, delete token.json.
const SCOPES = ['https://www.googleapis.com/auth/gmail.readonly'];
// The file token.json stores the user's access and refresh tokens, and is
// created automatically when the authorization flow completes for the first
// time.
const TOKEN_PATH = 'token.json';
const gmailAccount = '[email protected]';
const gmailPassword = 'somepassword';
export class GmailUtils {
/**
* Create an OAuth2 client with the given credentials
*/
async authorize() {
const { client_secret, client_id, redirect_uris } = gmailCred.installed;
const oAuth2Client = new google.auth.OAuth2(
client_id,
client_secret,
redirect_uris[0]
);
// Check if we have previously stored a token.
const token = !fs.existsSync(TOKEN_PATH)
? await this.getNewToken(oAuth2Client)
: JSON.parse(fs.readFileSync(TOKEN_PATH).toString());
oAuth2Client.setCredentials(token);
return oAuth2Client;
}
/**
* Get and store new token after prompting for user authorization, and then
* execute the given callback with the authorized OAuth2 client.
* @param {google.auth.OAuth2} oAuth2Client The OAuth2 client to get token for.
*/
private async getNewToken(oAuth2Client: OAuth2Client) {
const authUrl = oAuth2Client.generateAuthUrl({
access_type: 'offline',
scope: SCOPES
});
const code = await this.getOAuth2Code(authUrl);
const tokenResponse = await oAuth2Client.getToken(code);
fs.writeFileSync(TOKEN_PATH, JSON.stringify(tokenResponse.tokens));
return tokenResponse.tokens;
}
/**
* the function is only use when token.json does not exists
* it will open a new window, grant permission to the app and return the code
* @param authUrl
*/
async getOAuth2Code(authUrl: string) {
const googleBrowser = await browser.forkNewDriverInstance().ready;
await googleBrowser.waitForAngularEnabled(false);
await googleBrowser.manage().window().maximize();
await googleBrowser.driver.get(authUrl);
const appPo = new AppPo(googleBrowser);
const email = googleBrowser.element(by.id('identifierId'));
await appPo.sendKeys(email, gmailAccount, false);
const emailNext = googleBrowser.element(by.id('identifierNext'));
await appPo.click(emailNext);
const password = googleBrowser.element(by.id('password')).element(by.tagName('input'));
await appPo.sendKeys(password, gmailPassword);
const passwordNext = googleBrowser.element(by.id('passwordNext'));
await appPo.click(passwordNext);
await googleBrowser.wait(
async () => {
try {
const links: ElementFinder[] = await googleBrowser.element.all(
by.tagName('a')
);
for (const link of links) {
if ((await link.getText()) === 'Advanced') {
await appPo.click(link);
return true;
}
}
} catch (e) {}
return false;
},
defaultTimeout,
'Timeout waiting for Advanced link'
);
await googleBrowser.wait(
async () => {
try {
const links: ElementFinder[] = await googleBrowser.element.all(
by.tagName('a')
);
for (const link of links) {
if ((await link.getText()) === 'Go to Quickstart (unsafe)') {
await appPo.click(link);
return true;
}
}
} catch (e) {}
return false;
},
defaultTimeout,
'Timeout waiting for Go to Quickstart link'
);
await googleBrowser.wait(
async () => {
try {
const divs: ElementFinder[] = await googleBrowser.element.all(
by.tagName('div')
);
for (const div of divs) {
if ((await div.getAttribute('role')) === 'button') {
if ((await div.getText()) === 'Allow') {
await appPo.click(div);
return true;
}
}
}
} catch (e) {}
return false;
},
defaultTimeout,
'Timeout waiting for the Allow button'
);
const approveAccess = googleBrowser.element(by.id('submit_approve_access'));
await appPo.click(approveAccess);
const textarea = googleBrowser.element(by.tagName('textarea'));
await appPo.waitForElementToBePresent(textarea);
await appPo.waitForElementToBeVisible(textarea);
const code = await textarea.getAttribute('value');
googleBrowser.close();
return code;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment