Skip to content

Commit

Permalink
Add Chrome MV3 integration test runner (#1194)
Browse files Browse the repository at this point in the history
Add an integration test runner for Chrome MV3. This is to aid the
transition between Chrome MV2 and Chrome MV3.

Also expand on the integration test helpers to properly handle
extensions with a background ServiceWorker instead of a background
page.
  • Loading branch information
kzar committed May 24, 2022
1 parent a740020 commit d740fc6
Show file tree
Hide file tree
Showing 4 changed files with 87 additions and 9 deletions.
5 changes: 5 additions & 0 deletions integration-test/config-mv3.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"spec_dir": "integration-test",
"spec_files": [
]
}
73 changes: 68 additions & 5 deletions integration-test/helpers/backgroundWait.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,52 @@
const puppeteer = require('puppeteer')

// Puppeteer does not yet (as of 14) provide a waitForTimeout method for
// WebWorkers.
function manuallyWaitForTimeout (timeout) {
return new Promise(resolve => {
setTimeout(resolve, timeout)
})
}

function forTimeout (bgPage, timeout) {
if (bgPage.waitForTimeout) {
return bgPage.waitForTimeout(timeout)
}

return manuallyWaitForTimeout(timeout)
}

// Puppeteer does not yet (as of 14) provide a waitForFunction method for
// WebWorkers. The evaluate method is available though.
function manuallyWaitForFunction (bgPage, func, { polling, timeout }, ...args) {
return new Promise((resolve, reject) => {
const startTime = Date.now()
const waitForFunction = async () => {
let result
try {
result = await bgPage.evaluate(func, ...args)
} catch (e) {
reject(e)
}
if (result) {
resolve(result)
} else {
if (Date.now() - startTime > timeout) {
reject(
new puppeteer.errors.TimeoutError(
'Manually waiting for function timed out: ' +
func.toString()
)
)
} else {
setTimeout(waitForFunction, polling)
}
}
}
waitForFunction()
})
}

// Helpers that aid in waiting for the background page's state.
// Notes:
// - Puppeteer's `waitForFunction` uses `requestAnimationFrame` by default,
Expand All @@ -7,13 +56,26 @@
// (rather than the default of 30 seconds) to improve the error output on
// timeout.
function forFunction (bgPage, func, ...args) {
return bgPage.waitForFunction(func, { polling: 10, timeout: 15000 }, ...args)
const waitForFunction = bgPage.waitForFunction
? bgPage.waitForFunction.bind(bgPage)
: manuallyWaitForFunction.bind(null, bgPage)
return waitForFunction(func, { polling: 10, timeout: 15000 }, ...args)
}

function forSetting (bgPage, key) {
return forFunction(
bgPage, key => window.dbg?.settings?.getSetting(key), key
)
async function forSetting (bgPage, key) {
try {
return await forFunction(
bgPage, key => self.dbg?.settings?.getSetting(key), key
)
} catch (e) {
if (e instanceof puppeteer.errors.TimeoutError) {
throw new puppeteer.errors.TimeoutError(
'Timed out waiting for setting: ' + key
)
} else {
throw e
}
}
}

// Note: This is likely incomplete. Please add further checks as they come up!
Expand Down Expand Up @@ -53,6 +115,7 @@ async function forAllConfiguration (bgPage) {
}

module.exports = {
forTimeout,
forFunction,
forSetting,
forAllConfiguration
Expand Down
17 changes: 13 additions & 4 deletions integration-test/helpers/harness.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,12 @@ const setup = async (ops) => {
}

if (loadExtension) {
puppeteerOps.args.push('--disable-extensions-except=build/chrome/dev')
puppeteerOps.args.push('--load-extension=build/chrome/dev')
let extensionPath = 'build/chrome/dev'
if (process.env.npm_lifecycle_event === 'test-int-mv3') {
extensionPath = extensionPath.replace('chrome', 'chrome-mv3')
}
puppeteerOps.args.push('--disable-extensions-except=' + extensionPath)
puppeteerOps.args.push('--load-extension=' + extensionPath)
}

// github actions
Expand Down Expand Up @@ -57,10 +61,15 @@ const setup = async (ops) => {
try {
const backgroundPageTarget =
await browser.waitForTarget(
target => target.type() === 'background_page',
target => (
target.type() === 'background_page' ||
target.type() === 'service_worker'
),
{ timeout: 2000 }
)
bgPage = await backgroundPageTarget.page()
bgPage = backgroundPageTarget.type() === 'background_page'
? await backgroundPageTarget.page()
: await backgroundPageTarget.worker()
} catch (e) {
throw new Error('Couldn\'t find background page.')
}
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
"test": "grunt test --browser=chrome --type=dev",
"test-debug": "grunt test --browser=chrome --type=dev --test-debug",
"test-int": "make setup-artifacts-dir && make dev browser=chrome type=dev && jasmine --config=integration-test/config.json",
"test-int-mv3": "make setup-artifacts-dir && make dev browser=chrome-mv3 type=dev && jasmine --config=integration-test/config-mv3.json",
"dev-firefox": "make dev browser=firefox type=dev watch=1",
"open-dev-firefox": "web-ext run -s build/firefox/dev/ -u https://privacy-test-pages.glitch.me/",
"release-firefox": "make browser=firefox type=release",
Expand Down

0 comments on commit d740fc6

Please sign in to comment.