diff --git a/test/integration/github.js b/test/integration/github.js index cc30666ee7..e753313b63 100644 --- a/test/integration/github.js +++ b/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` @@ -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() }) diff --git a/test/integration/google.js b/test/integration/google.js index f53c4760cf..d1b1d269f0 100644 --- a/test/integration/google.js +++ b/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` @@ -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() }) diff --git a/test/integration/twitter.js b/test/integration/twitter.js index 5235c24da7..772df3ed4a 100644 --- a/test/integration/twitter.js +++ b/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 () { @@ -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() }) diff --git a/test/lib/puppeteer.js b/test/lib/puppeteer.js new file mode 100644 index 0000000000..54debb7146 --- /dev/null +++ b/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 +} \ No newline at end of file