mirror of
https://github.com/tinyhumansai/openhuman.git
synced 2026-07-30 23:14:37 +00:00
122 lines
4.0 KiB
TypeScript
122 lines
4.0 KiB
TypeScript
import type { Options } from '@wdio/types';
|
|
import fs from 'fs';
|
|
import path from 'path';
|
|
import { fileURLToPath } from 'url';
|
|
|
|
import { captureFailureArtifacts } from './e2e/helpers/artifacts';
|
|
|
|
const configDir = path.dirname(fileURLToPath(import.meta.url));
|
|
const projectRoot = path.resolve(configDir, '..');
|
|
const repoRoot = path.resolve(projectRoot, '..');
|
|
const tsconfigE2ePath = path.join(projectRoot, 'test', 'tsconfig.e2e.json');
|
|
const testSpecsPath = path.join(projectRoot, 'test', 'e2e', 'specs', '**', '*.spec.ts');
|
|
|
|
/**
|
|
* Resolve the path to the built Tauri application.
|
|
*
|
|
* - macOS: .app bundle for Appium Mac2
|
|
* - Linux: debug binary for tauri-driver
|
|
* - Windows: .exe for tauri-driver
|
|
*/
|
|
function getAppPath(): string {
|
|
const bundleBases = [
|
|
path.join(projectRoot, 'src-tauri', 'target', 'debug', 'bundle'),
|
|
path.join(repoRoot, 'target', 'debug', 'bundle'),
|
|
];
|
|
|
|
switch (process.platform) {
|
|
case 'darwin': {
|
|
for (const base of bundleBases) {
|
|
const appPath = path.join(base, 'macos', 'OpenHuman.app');
|
|
if (fs.existsSync(appPath)) {
|
|
return appPath;
|
|
}
|
|
}
|
|
return path.join(bundleBases[0], 'macos', 'OpenHuman.app');
|
|
}
|
|
case 'win32':
|
|
return path.join(projectRoot, 'src-tauri', 'target', 'debug', 'OpenHuman.exe');
|
|
case 'linux': {
|
|
// tauri-driver launches the binary directly (not a bundle).
|
|
// Prefer the Tauri build output (src-tauri/target) over the repo-root
|
|
// target/ which may contain a stale core-only binary.
|
|
const candidates = [
|
|
path.join(projectRoot, 'src-tauri', 'target', 'debug', 'OpenHuman'),
|
|
path.join(repoRoot, 'target', 'debug', 'OpenHuman'),
|
|
];
|
|
for (const candidate of candidates) {
|
|
if (fs.existsSync(candidate)) return candidate;
|
|
}
|
|
return candidates[0];
|
|
}
|
|
default:
|
|
throw new Error(`Unsupported platform: ${process.platform}`);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Build capabilities for the current platform.
|
|
*
|
|
* - Linux: tauri-driver (W3C WebDriver, port 4444)
|
|
* - macOS: Appium Mac2 (XCUITest, port 4723)
|
|
*/
|
|
function getPlatformCapabilities(): Record<string, unknown>[] {
|
|
if (process.platform === 'linux') {
|
|
return [{ 'tauri:options': { application: getAppPath() } }];
|
|
}
|
|
|
|
// macOS: Appium Mac2
|
|
return [
|
|
{
|
|
platformName: 'mac',
|
|
'appium:automationName': 'Mac2',
|
|
'appium:app': getAppPath(),
|
|
'appium:showServerLogs': true,
|
|
},
|
|
];
|
|
}
|
|
|
|
/** Port for the automation driver: tauri-driver (4444) or Appium (4723). */
|
|
const isLinuxDriver = process.platform === 'linux';
|
|
const driverPort = isLinuxDriver
|
|
? parseInt(process.env.TAURI_DRIVER_PORT || '4444', 10)
|
|
: parseInt(process.env.APPIUM_PORT || '4723', 10);
|
|
|
|
export const config: Options.Testrunner & Record<string, unknown> = {
|
|
runner: 'local',
|
|
hostname: '127.0.0.1',
|
|
port: driverPort,
|
|
specs: [testSpecsPath],
|
|
rootDir: projectRoot,
|
|
maxInstances: 1, // Tauri apps are single-instance
|
|
capabilities: getPlatformCapabilities(),
|
|
logLevel: 'warn',
|
|
bail: 0,
|
|
waitforTimeout: 10_000,
|
|
// Linux tauri-driver can take longer to establish the initial session on
|
|
// loaded CI runners; keep macOS defaults while giving Linux more headroom.
|
|
connectionRetryTimeout: isLinuxDriver ? 240_000 : 120_000,
|
|
connectionRetryCount: isLinuxDriver ? 5 : 3,
|
|
// No appium/tauri-driver service — driver is started externally via scripts.
|
|
framework: 'mocha',
|
|
reporters: ['spec'],
|
|
mochaOpts: {
|
|
ui: 'bdd',
|
|
timeout: 120_000, // Billing/settings tests need extra time for API polling
|
|
},
|
|
autoCompileOpts: { tsNodeOpts: { project: tsconfigE2ePath } },
|
|
/**
|
|
* Always capture screenshot + page source on failure so agents can
|
|
* inspect what the app looked like the moment the assertion failed.
|
|
*/
|
|
afterTest: async function (
|
|
test: { title: string; parent?: string },
|
|
_context: unknown,
|
|
result: { passed: boolean; error?: Error }
|
|
) {
|
|
if (result.passed) return;
|
|
const name = [test.parent, test.title].filter(Boolean).join(' ').trim() || test.title;
|
|
await captureFailureArtifacts(name);
|
|
},
|
|
};
|