Skip to content

Commit

Permalink
feat($browser): add screen-capture on error (#86)
Browse files Browse the repository at this point in the history
  • Loading branch information
RABrown1986 committed Feb 22, 2021
1 parent bb45cf6 commit a1a7443
Show file tree
Hide file tree
Showing 2 changed files with 151 additions and 54 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ Options passed to the task include:
| usernameSubmitBtn | Optional for CustomizedLogin: string, a selector for the username button | |
| passwordField | Required for CustomizedLogin: string, a selector for the password field | |
| passwordSubmitBtn | Optional for CustomizedLogin: string, a selector for password submit button | |
| screenshotOnError | Optional: will grab a screen shot if an error occurs on the username, password, or post-login page and saves in the Cypress screenshots folder. | false |
| additionalSteps | Optional: function, to define any additional steps which may be required after executing functions for username and password, such as answering security questions, PIN, or anything which may be required to fill out after username and password process. The function and this property must be defined or referenced from index.js for Cypress Plugins directory. | `async function moreSteps({page, options} = {}) { await page.waitForSelector('#pin_Field') await page.click('#pin_Field') }` |

## Install
Expand Down
204 changes: 150 additions & 54 deletions src/Plugins.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

const puppeteer = require('puppeteer')
const authenticator = require('otplib').authenticator
const fs = require('fs')

/**
*
Expand All @@ -29,6 +30,7 @@ const authenticator = require('otplib').authenticator
* @param {options.passwordField} string selector for the password field
* @param {options.passwordSubmitBtn} string selector password submit button
* @param {options.additionalSteps} function any additional func which may be required for signin step after username and password
* @param {options.screenshotOnError} boolean grab a screenshot if an error occurs during username, password, or post-login page
*
*/

Expand All @@ -44,6 +46,15 @@ function validateOptions(options) {
}
}

function takeScreenshot(options) {
if (options.screenshotOnError) {
if (!fs.existsSync('./cypress/screenshots/cypresssociallogin/')) {
fs.mkdirSync('./cypress/screenshots/cypresssociallogin/', {recursive: true})
}
page.screenshot({path: `'./cypress/screenshots/cypresssociallogin/SocialLoginError.png`})
}
}

async function login({page, options} = {}) {
if (options.preLoginSelector && !options.preLoginSelectorIframe) {
await page.waitForSelector(options.preLoginSelector)
Expand Down Expand Up @@ -252,39 +263,64 @@ module.exports.baseLoginConnect = baseLoginConnect

module.exports.GoogleSocialLogin = async function GoogleSocialLogin(options = {}) {
const typeUsername = async function({page, options} = {}) {
await page.waitForSelector('input#identifierId[type="email"]')
await page.type('input#identifierId[type="email"]', options.username)
await page.click('#identifierNext')
try {
await page.waitForSelector('input#identifierId[type="email"]')
await page.type('input#identifierId[type="email"]', options.username)
await page.click('#identifierNext')
} catch (err) {
takeScreenshot(options)
throw err
}
}

const typePassword = async function({page, options} = {}) {
let buttonSelectors = ['#signIn', '#passwordNext', '#submit']
try {
let buttonSelectors = ['#signIn', '#passwordNext', '#submit']

await page.waitForSelector('input[type="password"]', {visible: true})
await page.type('input[type="password"]', options.password)
await page.waitForSelector('input[type="password"]', {visible: true})
await page.type('input[type="password"]', options.password)

const buttonSelector = await waitForMultipleSelectors(buttonSelectors, {visible: true}, page)
await page.click(buttonSelector)
const buttonSelector = await waitForMultipleSelectors(buttonSelectors, {visible: true}, page)
await page.click(buttonSelector)
} catch (err) {
takeScreenshot(options)
throw err
}
}

const postLogin = async function({page, options} = {}) {
await page.waitForSelector(options.postLoginClick)
await page.click(options.postLoginClick)
try {
await page.waitForSelector(options.postLoginClick)
await page.click(options.postLoginClick)
} catch (err) {
takeScreenshot(options)
throw err
}
}

return baseLoginConnect(typeUsername, typePassword, null, null, postLogin, options)
}

module.exports.GitHubSocialLogin = async function GitHubSocialLogin(options = {}) {
const typeUsername = async function({page, options} = {}) {
await page.waitForSelector('input#login_field')
await page.type('input#login_field', options.username)
try {
await page.waitForSelector('input#login_field')
await page.type('input#login_field', options.username)
} catch (err) {
takeScreenshot(options)
throw err
}
}

const typePassword = async function({page, options} = {}) {
await page.waitForSelector('input#password', {visible: true})
await page.type('input#password', options.password)
await page.click('input[type="submit"]')
try {
await page.waitForSelector('input#password', {visible: true})
await page.type('input#password', options.password)
await page.click('input[type="submit"]')
} catch (err) {
takeScreenshot(options)
throw err
}
}

const authorizeApp = async function({page, options} = {}) {
Expand All @@ -293,26 +329,41 @@ module.exports.GitHubSocialLogin = async function GitHubSocialLogin(options = {}
}

const postLogin = async function({page, options} = {}) {
await page.waitForSelector(options.postLoginClick)
await page.click(options.postLoginClick)
try {
await page.waitForSelector(options.postLoginClick)
await page.click(options.postLoginClick)
} catch (err) {
takeScreenshot(options)
throw err
}
}

return baseLoginConnect(typeUsername, typePassword, null, authorizeApp, postLogin, options)
}

module.exports.MicrosoftSocialLogin = async function MicrosoftSocialLogin(options = {}) {
const typeUsername = async function({page, options} = {}) {
await page.waitForSelector('input[type="email"]')
await page.type('input[type="email"]', options.username)
await page.click('input[type="submit"]')
try {
await page.waitForSelector('input[type="email"]')
await page.type('input[type="email"]', options.username)
await page.click('input[type="submit"]')
} catch (err) {
takeScreenshot(options)
throw err
}
}

const typePassword = async function({page, options} = {}) {
await delay(5000)

await page.waitForSelector('input[type="password"]', {visible: true})
await page.type('input[type="password"]', options.password)
await page.click('input[type="submit"]')
try {
await delay(5000)

await page.waitForSelector('input[type="password"]', {visible: true})
await page.type('input[type="password"]', options.password)
await page.click('input[type="submit"]')
} catch (err) {
takeScreenshot(options)
throw err
}
}

const authorizeApp = async function({page, options} = {}) {
Expand All @@ -321,27 +372,42 @@ module.exports.MicrosoftSocialLogin = async function MicrosoftSocialLogin(option
}

const postLogin = async function({page, options} = {}) {
await page.waitForSelector(options.postLoginClick)
await page.click(options.postLoginClick)
try {
await page.waitForSelector(options.postLoginClick)
await page.click(options.postLoginClick)
} catch (err) {
takeScreenshot(options)
throw err
}
}

return baseLoginConnect(typeUsername, typePassword, null, authorizeApp, postLogin, options)
}

module.exports.AmazonSocialLogin = async function AmazonSocialLogin(options = {}) {
const typeUsername = async function({page, options} = {}) {
await page.waitForSelector('#ap_email', {visible: true})
await page.type('#ap_email', options.username)
try {
await page.waitForSelector('#ap_email', {visible: true})
await page.type('#ap_email', options.username)
} catch (err) {
takeScreenshot(options)
throw err
}
}

const typePassword = async function({page, options} = {}) {
let buttonSelectors = ['#signInSubmit']

await page.waitForSelector('input[type="password"]', {visible: true})
await page.type('input[type="password"]', options.password)

const buttonSelector = await waitForMultipleSelectors(buttonSelectors, {visible: true}, page)
await page.click(buttonSelector)
try {
await page.waitForSelector('input[type="password"]', {visible: true})
await page.type('input[type="password"]', options.password)

const buttonSelector = await waitForMultipleSelectors(buttonSelectors, {visible: true}, page)
await page.click(buttonSelector)
} catch (err) {
takeScreenshot(options)
throw err
}
}

const otpApp = async function({page, options} = {}) {
Expand All @@ -359,17 +425,27 @@ module.exports.AmazonSocialLogin = async function AmazonSocialLogin(options = {}

module.exports.FacebookSocialLogin = async function FacebookSocialLogin(options = {}) {
const typeUsername = async function({page, options} = {}) {
const emailSelector = '#email'
await page.waitForSelector(emailSelector)
await page.type(emailSelector, options.username)
try {
const emailSelector = '#email'
await page.waitForSelector(emailSelector)
await page.type(emailSelector, options.username)
} catch (err) {
takeScreenshot(options)
throw err
}
}

const typePassword = async function({page, options} = {}) {
await page.waitForSelector('input[type="password"]', {visible: true})
await page.type('input[type="password"]', options.password)

// Submit first form
await page.click('#loginbutton')
try {
await page.waitForSelector('input[type="password"]', {visible: true})
await page.type('input[type="password"]', options.password)

// Submit first form
await page.click('#loginbutton')
} catch (err) {
takeScreenshot(options)
throw err
}

try {
// Submit next form
Expand All @@ -382,8 +458,13 @@ module.exports.FacebookSocialLogin = async function FacebookSocialLogin(options
}

const postLogin = async function({page, options} = {}) {
await page.waitForSelector(options.postLoginClick)
await page.click(options.postLoginClick)
try {
await page.waitForSelector(options.postLoginClick)
await page.click(options.postLoginClick)
} catch (err) {
takeScreenshot(options)
throw err
}
}

return baseLoginConnect(typeUsername, typePassword, null, null, postLogin, options)
Expand All @@ -392,22 +473,37 @@ module.exports.FacebookSocialLogin = async function FacebookSocialLogin(options
module.exports.CustomizedLogin = async function CustomizedLogin(options = {}) {
if (options.usernameField && options.passwordField) {
const typeUsername = async function({page, options} = {}) {
await page.waitForSelector(options.usernameField, {visible: true})
await page.type(options.usernameField, options.username)
if (options.usernameSubmitBtn) {
await page.click(options.usernameSubmitBtn)
try {
await page.waitForSelector(options.usernameField, {visible: true})
await page.type(options.usernameField, options.username)
if (options.usernameSubmitBtn) {
await page.click(options.usernameSubmitBtn)
}
} catch (err) {
takeScreenshot(options)
throw err
}
}
const typePassword = async function({page, options} = {}) {
await page.waitForSelector(options.passwordField, {visible: true})
await page.type(options.passwordField, options.password)
if (options.passwordSubmitBtn) {
await page.click(options.passwordSubmitBtn)
try {
await page.waitForSelector(options.passwordField, {visible: true})
await page.type(options.passwordField, options.password)
if (options.passwordSubmitBtn) {
await page.click(options.passwordSubmitBtn)
}
} catch (err) {
takeScreenshot(options)
throw err
}
}
const postLogin = async function({page, options} = {}) {
await page.waitForSelector(options.postLoginClick)
await page.click(options.postLoginClick)
try {
await page.waitForSelector(options.postLoginClick)
await page.click(options.postLoginClick)
} catch (err) {
takeScreenshot(options)
throw err
}
}
return baseLoginConnect(typeUsername, typePassword, null, null, postLogin, options)
} else {
Expand Down

0 comments on commit a1a7443

Please sign in to comment.