Skip to content

Commit

Permalink
Improve Puppeteer configuration (#658)
Browse files Browse the repository at this point in the history
* Centralises configuration for Puppeteer used in tests to make it easier to maintain.
* Adds support for running tests on ARM, so we can use Raspberry Pi test runners off the cloud to get around block lists.
* Includes improved stealth mode to avoid detection which breaks integration tests.
  • Loading branch information
iaincollins committed Sep 11, 2020
1 parent 2f0f738 commit 0adfba8
Show file tree
Hide file tree
Showing 4 changed files with 42 additions and 13 deletions.
6 changes: 2 additions & 4 deletions test/integration/github.js
@@ -1,8 +1,6 @@
require('dotenv').config()
const assert = require('assert')
const puppeteer = require('puppeteer-extra')
const StealthPlugin = require('puppeteer-extra-plugin-stealth')
puppeteer.use(StealthPlugin())
const { puppeteer, puppeteerOptions } = require('../lib/puppeteer')

const BASE_URL = 'http://localhost:3000'
const CALLBACK_URL = `${BASE_URL}/test`
Expand All @@ -18,7 +16,7 @@ describe('GitHub (OAuth 2.0 flow)', function () {
let browser,page

before(async () => {
browser = await puppeteer.launch({ headless: true })
browser = await puppeteer.launch(puppeteerOptions)
page = await browser.newPage()
return Promise.resolve()
})
Expand Down
6 changes: 2 additions & 4 deletions test/integration/google.js
@@ -1,8 +1,6 @@
require('dotenv').config()
const assert = require('assert')
const puppeteer = require('puppeteer-extra')
const StealthPlugin = require('puppeteer-extra-plugin-stealth')
puppeteer.use(StealthPlugin())
const { puppeteer, puppeteerOptions } = require('../lib/puppeteer')

const BASE_URL = 'http://localhost:3000'
const CALLBACK_URL = `${BASE_URL}/test`
Expand All @@ -20,7 +18,7 @@ describe.skip('Google (OAuth 2.0 flow)', function () {
let browser,page

before(async () => {
browser = await puppeteer.launch({ headless: true })
browser = await puppeteer.launch(puppeteerOptions)
page = await browser.newPage()
return Promise.resolve()
})
Expand Down
8 changes: 3 additions & 5 deletions test/integration/twitter.js
@@ -1,15 +1,13 @@
require('dotenv').config()
const assert = require('assert')
const puppeteer = require('puppeteer-extra')
const StealthPlugin = require('puppeteer-extra-plugin-stealth')
puppeteer.use(StealthPlugin())
const { puppeteer, puppeteerOptions } = require('../lib/puppeteer')

const BASE_URL = 'http://localhost:3000'
const CALLBACK_URL = `${BASE_URL}/test`

const {
NEXTAUTH_TWITTER_USERNAME: USERNAME,
NEXTAUTH_TWITTER_PASSWORD: PASSWORD
NEXTAUTH_TWITTER_PASSWORD: PASSWORD,
} = process.env

describe('Twitter (OAuth 1.1 flow)', async function () {
Expand All @@ -18,7 +16,7 @@ describe('Twitter (OAuth 1.1 flow)', async function () {
let browser,page

before(async () => {
browser = await puppeteer.launch({ headless: true })
browser = await puppeteer.launch(puppeteerOptions)
page = await browser.newPage()
return Promise.resolve()
})
Expand Down
35 changes: 35 additions & 0 deletions test/lib/puppeteer.js
@@ -0,0 +1,35 @@
const puppeteerExtra = require('puppeteer-extra')
const StealthPlugin = require("puppeteer-extra-plugin-stealth")
const stealthPlugin = StealthPlugin()

// Override Puppeteer user agent to set 'navigator.platform' explicitly to
// prevent detection on some providers (e.g. GitHub OAuth) as they force 2FA
// on sign in if they detect sign in from a platform they haven't seen before.
const puppeteerExtraPluginUserAgentOverride = require("puppeteer-extra-plugin-stealth/evasions/user-agent-override")
stealthPlugin.enabledEvasions.delete("user-agent-override")
puppeteerExtra.use(stealthPlugin)
const pluginUserAgentOverride = puppeteerExtraPluginUserAgentOverride({
userAgent: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.141 Safari/537.36",
platform: "MacIntel"
})
puppeteerExtra.use(pluginUserAgentOverride)

// CI is set to true by GitHub Actions to indicate is running in CD/CI
const { CI } = process.env

const puppeteerOptions = {
headless: true // Set to 'false' to debug more easily
}

// When running on remote test runner (which is ARM) the executable path
// needs to be set to 'chromium-browser' so it uses the ARM build of Chromium
// not the x86 build that Puppeteer uses by default. Supporting this allows us
// to test easily from remote locations that are outside cloud networks like
// AWS, GPC, Azure, etc. and avoids tests being thwarted by IP blocklists.
if (CI)
puppeteerOptions.executablePath = 'chromium-browser'

module.exports = {
puppeteer: puppeteerExtra,
puppeteerOptions
}

1 comment on commit 0adfba8

@vercel
Copy link

@vercel vercel bot commented on 0adfba8 Sep 11, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.