Files
zn-ai/packages/electron-chrome-extensions/spec/index.js
2025-11-15 22:41:50 +08:00

187 lines
6.1 KiB
JavaScript

// Copyright (c) 2013-2020 GitHub Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
const Module = require('module')
const path = require('path')
const { promises: fs } = require('fs')
const v8 = require('v8')
Module.globalPaths.push(path.resolve(__dirname, '../spec/node_modules'))
// We want to terminate on errors, not throw up a dialog
process.on('uncaughtException', (err) => {
console.error('Unhandled exception in main spec runner:', err)
process.exit(1)
})
// Tell ts-node which tsconfig to use
process.env.TS_NODE_PROJECT = path.resolve(__dirname, '../tsconfig.json')
process.env.ELECTRON_DISABLE_SECURITY_WARNINGS = 'true'
const { app, protocol } = require('electron')
v8.setFlagsFromString('--expose_gc')
app.commandLine.appendSwitch('js-flags', '--expose_gc')
app.commandLine.appendSwitch('enable-features', 'ElectronSerialChooser')
// Prevent the spec runner quiting when the first window closes
app.on('window-all-closed', () => null)
// Use fake device for Media Stream to replace actual camera and microphone.
app.commandLine.appendSwitch('use-fake-device-for-media-stream')
// @ts-ignore
global.standardScheme = 'app'
// @ts-ignore
global.zoomScheme = 'zoom'
protocol.registerSchemesAsPrivileged([
// @ts-ignore
{ scheme: global.standardScheme, privileges: { standard: true, secure: true, stream: false } },
// @ts-ignore
{ scheme: global.zoomScheme, privileges: { standard: true, secure: true } },
{ scheme: 'cors-blob', privileges: { corsEnabled: true, supportFetchAPI: true } },
{ scheme: 'cors', privileges: { corsEnabled: true, supportFetchAPI: true } },
{ scheme: 'no-cors', privileges: { supportFetchAPI: true } },
{ scheme: 'no-fetch', privileges: { corsEnabled: true } },
{ scheme: 'stream', privileges: { standard: true, stream: true } },
{ scheme: 'foo', privileges: { standard: true } },
{ scheme: 'bar', privileges: { standard: true } },
{ scheme: 'crx', privileges: { bypassCSP: true } },
])
const cleanupTestSessions = async () => {
const sessionsPath = path.join(app.getPath('userData'), 'Partitions')
let sessions
try {
sessions = await fs.readdir(sessionsPath)
} catch (e) {
return // dir doesn't exist
}
sessions = sessions.filter((session) => session.startsWith('crx-'))
if (sessions.length === 0) return
console.log(`Cleaning up ${sessions.length} sessions from previous test runners`)
for (const session of sessions) {
const sessionPath = path.join(sessionsPath, session)
await fs.rm(sessionPath, { recursive: true, force: true })
}
}
app
.whenReady()
.then(async () => {
require('ts-node/register')
await cleanupTestSessions()
const argv = require('yargs')
.boolean('ci')
.array('files')
.string('g')
.alias('g', 'grep')
.boolean('i')
.alias('i', 'invert').argv
const Mocha = require('mocha')
const mochaOptions = {}
if (process.env.MOCHA_REPORTER) {
mochaOptions.reporter = process.env.MOCHA_REPORTER
}
if (process.env.MOCHA_MULTI_REPORTERS) {
mochaOptions.reporterOptions = {
reporterEnabled: process.env.MOCHA_MULTI_REPORTERS,
}
}
const mocha = new Mocha(mochaOptions)
// The cleanup method is registered this way rather than through an
// `afterEach` at the top level so that it can run before other `afterEach`
// methods.
//
// The order of events is:
// 1. test completes,
// 2. `defer()`-ed methods run, in reverse order,
// 3. regular `afterEach` hooks run.
const { runCleanupFunctions, getFiles } = require('./spec-helpers')
mocha.suite.on('suite', function attach(suite) {
suite.afterEach('cleanup', runCleanupFunctions)
suite.on('suite', attach)
})
if (!process.env.MOCHA_REPORTER) {
mocha.ui('bdd').reporter('tap')
}
const mochaTimeout = process.env.MOCHA_TIMEOUT || 10000
mocha.timeout(mochaTimeout)
if (argv.grep) mocha.grep(argv.grep)
if (argv.invert) mocha.invert()
const filter = (file) => {
if (!/-spec\.[tj]s$/.test(file)) {
return false
}
// This allows you to run specific modules only:
// npm run test -match=menu
const moduleMatch = process.env.npm_config_match
? new RegExp(process.env.npm_config_match, 'g')
: null
if (moduleMatch && !moduleMatch.test(file)) {
return false
}
const baseElectronDir = path.resolve(__dirname, '..')
if (argv.files && !argv.files.includes(path.relative(baseElectronDir, file))) {
return false
}
return true
}
const testFiles = await getFiles(__dirname, { filter })
testFiles.sort().forEach((file) => {
mocha.addFile(file)
})
const cb = () => {
// Ensure the callback is called after runner is defined
process.nextTick(() => {
process.exit(runner.failures)
})
}
// Set up chai in the correct order
const chai = require('chai')
chai.use(require('chai-as-promised'))
// chai.use(require('dirty-chai'));
const runner = mocha.run(cb)
})
.catch((err) => {
console.error('An error occurred while running the spec-main spec runner')
console.error(err)
process.exit(1)
})