mirror of
https://github.com/electron/electron.git
synced 2026-05-02 03:00:22 -04:00
chore: prepare spec helpers and vitest setup for migration
This commit is contained in:
38
spec/_vitest_runner/setup.ts
Normal file
38
spec/_vitest_runner/setup.ts
Normal file
@@ -0,0 +1,38 @@
|
||||
import * as chai from 'chai';
|
||||
import { afterEach, beforeEach } from 'vitest';
|
||||
|
||||
import * as fs from 'node:fs';
|
||||
import * as path from 'node:path';
|
||||
|
||||
import { runCleanupFunctions } from '../lib/spec-helpers';
|
||||
|
||||
import chaiAsPromised = require('chai-as-promised');
|
||||
import dirtyChai = require('dirty-chai');
|
||||
|
||||
chai.use(chaiAsPromised);
|
||||
chai.use(dirtyChai as any);
|
||||
|
||||
// Show full object diff.
|
||||
// https://github.com/chaijs/chai/issues/469
|
||||
chai.config.truncateThreshold = 0;
|
||||
|
||||
// Skip any tests listed in disabled-tests.json.
|
||||
const disabledTests = new Set(JSON.parse(fs.readFileSync(path.join(__dirname, '..', 'disabled-tests.json'), 'utf8')));
|
||||
beforeEach((ctx) => {
|
||||
const parts: string[] = [ctx.task.name];
|
||||
let suite = ctx.task.suite;
|
||||
while (suite) {
|
||||
if (suite.name) parts.unshift(suite.name);
|
||||
suite = suite.suite;
|
||||
}
|
||||
if (disabledTests.has(parts.join(' '))) {
|
||||
ctx.skip();
|
||||
}
|
||||
});
|
||||
|
||||
// Run defer()-ed cleanup functions after each test, before other afterEach hooks
|
||||
// registered by the test file (vitest runs hooks in registration order, and
|
||||
// setupFiles are loaded first).
|
||||
afterEach(async () => {
|
||||
await runCleanupFunctions();
|
||||
});
|
||||
@@ -4,14 +4,21 @@ import * as path from 'node:path';
|
||||
|
||||
import electronPool from './electron-pool';
|
||||
|
||||
const electronShim = path.resolve(__dirname, 'electron-shim.cjs');
|
||||
|
||||
export default defineConfig({
|
||||
resolve: {
|
||||
alias: {
|
||||
electron: path.resolve(__dirname, 'electron-shim.cjs')
|
||||
electron: electronShim,
|
||||
'electron/main': electronShim,
|
||||
'electron/common': electronShim,
|
||||
'electron/renderer': electronShim
|
||||
}
|
||||
},
|
||||
test: {
|
||||
include: ['spec/**/*.spec.ts'],
|
||||
exclude: ['spec/fixtures/**', 'spec/node_modules/**'],
|
||||
setupFiles: ['./spec/_vitest_runner/setup.ts'],
|
||||
// Custom pool: each worker is a real Electron main process.
|
||||
pool: electronPool as any,
|
||||
// Run test *files* in parallel across workers...
|
||||
|
||||
@@ -2,15 +2,22 @@
|
||||
// It is launched via `spawn(electron, [<spec-v2 dir>])` with an IPC channel,
|
||||
// so `process.send` is available and vitest's fork-worker protocol works.
|
||||
|
||||
const { app } = require('electron');
|
||||
const { app, protocol } = require('electron');
|
||||
|
||||
const path = require('node:path');
|
||||
const v8 = require('node:v8');
|
||||
|
||||
process.on('uncaughtException', (err) => {
|
||||
console.error('Unhandled exception in vitest worker:', err);
|
||||
process.exit(1);
|
||||
});
|
||||
|
||||
process.env.ELECTRON_DISABLE_SECURITY_WARNINGS = 'true';
|
||||
|
||||
if (process.env.ELECTRON_TEST_DISABLE_HARDWARE_ACCELERATION) {
|
||||
app.disableHardwareAcceleration();
|
||||
}
|
||||
|
||||
// The pool allocates (mkdtemp) and cleans up this directory; the worker just
|
||||
// points Electron at it before app ready.
|
||||
const userDataDir = process.env.ELECTRON_VITEST_USER_DATA_DIR;
|
||||
@@ -19,8 +26,50 @@ if (!userDataDir) {
|
||||
}
|
||||
app.setPath('userData', userDataDir);
|
||||
|
||||
v8.setFlagsFromString('--expose_gc');
|
||||
app.commandLine.appendSwitch('js-flags', '--expose_gc');
|
||||
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');
|
||||
app.commandLine.appendSwitch(
|
||||
'host-resolver-rules',
|
||||
[
|
||||
'MAP localhost2 127.0.0.1',
|
||||
'MAP ipv4.localhost2 10.0.0.1',
|
||||
'MAP ipv6.localhost2 [::1]',
|
||||
'MAP notfound.localhost2 ~NOTFOUND'
|
||||
].join(', ')
|
||||
);
|
||||
|
||||
// Enable features required by tests.
|
||||
app.commandLine.appendSwitch(
|
||||
'enable-features',
|
||||
[
|
||||
// spec/api-web-frame-main-spec.ts
|
||||
'DocumentPolicyIncludeJSCallStacksInCrashReports',
|
||||
// spec/spellchecker-spec.ts
|
||||
'UnrestrictSpellingAndGrammarForTesting'
|
||||
].join(',')
|
||||
);
|
||||
|
||||
global.standardScheme = 'app';
|
||||
global.zoomScheme = 'zoom';
|
||||
global.serviceWorkerScheme = 'sw';
|
||||
protocol.registerSchemesAsPrivileged([
|
||||
{ scheme: global.standardScheme, privileges: { standard: true, secure: true, stream: false } },
|
||||
{ scheme: global.zoomScheme, privileges: { standard: true, secure: true } },
|
||||
{ scheme: global.serviceWorkerScheme, privileges: { allowServiceWorkers: true, standard: true, secure: true } },
|
||||
{ scheme: 'http-like', privileges: { standard: true, secure: true, corsEnabled: true, supportFetchAPI: 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 } }
|
||||
]);
|
||||
|
||||
app
|
||||
.whenReady()
|
||||
.then(async () => {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { BrowserWindow } from 'electron/main';
|
||||
|
||||
import { AssertionError } from 'chai';
|
||||
import { SuiteFunction, TestFunction } from 'mocha';
|
||||
import { afterAll, beforeAll, describe, it } from 'vitest';
|
||||
|
||||
import * as childProcess from 'node:child_process';
|
||||
import * as http from 'node:http';
|
||||
@@ -22,8 +22,26 @@ const addOnly = <T>(fn: Function): T => {
|
||||
return wrapped as any;
|
||||
};
|
||||
|
||||
export const ifit = (condition: boolean) => (condition ? it : addOnly<TestFunction>(it.skip));
|
||||
export const ifdescribe = (condition: boolean) => (condition ? describe : addOnly<SuiteFunction>(describe.skip));
|
||||
export const ifit = (condition: boolean) => (condition ? it : addOnly<typeof it>(it.skip));
|
||||
export const ifdescribe = (condition: boolean) => (condition ? describe : addOnly<typeof describe>(describe.skip));
|
||||
|
||||
type DoneCallback = (err?: unknown) => void;
|
||||
|
||||
/**
|
||||
* Adapts a mocha-style callback test (receiving a `done` function) into a
|
||||
* vitest-compatible test that returns a Promise. `done()` resolves,
|
||||
* `done(err)` rejects.
|
||||
*/
|
||||
export function withDone(fn: (done: DoneCallback) => void): () => Promise<void> {
|
||||
return () =>
|
||||
new Promise<void>((resolve, reject) => {
|
||||
const done: DoneCallback = (err) => {
|
||||
if (err != null) reject(err instanceof Error ? err : new Error(String(err)));
|
||||
else resolve();
|
||||
};
|
||||
fn(done);
|
||||
});
|
||||
}
|
||||
|
||||
export const isWayland =
|
||||
process.platform === 'linux' &&
|
||||
@@ -189,10 +207,10 @@ export async function getRemoteContext() {
|
||||
}
|
||||
|
||||
export function useRemoteContext(opts?: any) {
|
||||
before(async () => {
|
||||
beforeAll(async () => {
|
||||
remoteContext.unshift(await makeRemoteContext(opts));
|
||||
});
|
||||
after(() => {
|
||||
afterAll(() => {
|
||||
const w = remoteContext.shift();
|
||||
w!.close();
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user