Newer
Older
TelosDB / wdio.conf.js
/**
 * WebdriverIO + tauri-driver で TelosDB の E2E テストを実行する設定。
 *
 * 前提:
 * - cargo install tauri-driver --locked
 * - Windows: Edge Driver (msedgedriver) を PATH に通す。バージョンは Edge と一致させる。
 * - Linux: WebKitWebDriver (例: webkit2gtk-driver) をインストール。
 *
 * 実行: npm run test:e2e
 * 初回はビルドに時間がかかります。事前に npm run build:e2e でビルドしても可。
 */
import fs from 'fs';
import os from 'os';
import path from 'path';
import { spawn, spawnSync } from 'child_process';
import { fileURLToPath } from 'url';

const __dirname = fileURLToPath(new URL('.', import.meta.url));
const root = path.resolve(__dirname);
const isWin = process.platform === 'win32';
const binaryName = isWin ? 'app.exe' : 'app';

// Windows で tauri-driver が使う Edge Driver のパス(環境変数 or edgedriver パッケージで取得)
let nativeDriverPath = process.env.TELOS_EDGE_DRIVER || null;
// 環境変数で上書き可。未指定ならビルド出力の候補を順に試す(ルート target または src/backend/target)
const candidates = [
  process.env.TELOS_E2E_APP,
  path.join(root, 'target', 'debug', binaryName),
  path.join(root, 'src', 'backend', 'target', 'debug', binaryName),
].filter(Boolean);
const applicationPath = candidates.find((p) => fs.existsSync(p)) || candidates[candidates.length - 1];

const E2E_PORTS = [4444, 3001];

function killProcessesOnPort(port) {
  try {
    if (isWin) {
      const out = spawnSync('netstat', ['-ano'], { encoding: 'utf8', shell: true });
      const lines = (out.stdout || '').split(/\r?\n/);
      const pids = new Set();
      for (const line of lines) {
        if (!line.includes(`:${port}`)) continue;
        const parts = line.trim().split(/\s+/);
        const last = parts[parts.length - 1];
        if (/^\d+$/.test(last)) pids.add(last);
      }
      for (const pid of pids) {
        spawnSync('taskkill', ['/PID', pid, '/F'], { stdio: 'ignore', shell: true });
      }
    } else {
      spawnSync('fuser', ['-k', `${port}/tcp`], { stdio: 'ignore' });
    }
  } catch (_) {}
}

function killE2ePorts() {
  for (const port of E2E_PORTS) {
    killProcessesOnPort(port);
  }
}

let tauriDriver;
let exit = false;

export const config = {
  host: '127.0.0.1',
  port: 4444,
  specs: ['./tests/e2e/specs/**/*.spec.js'],
  maxInstances: 1,
  capabilities: [
    {
      maxInstances: 1,
      'tauri:options': {
        application: applicationPath,
      },
    },
  ],
  reporters: ['spec'],
  framework: 'mocha',
  mochaOpts: {
    ui: 'bdd',
    timeout: 60000,
  },
  onPrepare: () => {
    killE2ePorts();
    if (!process.env.TELOS_E2E_PRO) {
      spawnSync('npm', ['run', 'build:e2e'], {
        cwd: root,
        stdio: 'inherit',
        shell: true,
      });
    }
  },
  onComplete: () => {
    closeTauriDriver();
    killE2ePorts();
  },
  beforeSession: async () => {
    let edgeDriverPath = nativeDriverPath;
    if (isWin && !edgeDriverPath) {
      try {
        const { download } = await import('edgedriver');
        edgeDriverPath = await download();
      } catch (e) {
        console.error('edgedriver download/resolve failed:', e.message || e);
      }
    }
    const driverPath = path.join(os.homedir(), '.cargo', 'bin', isWin ? 'tauri-driver.exe' : 'tauri-driver');
    const usePath = fs.existsSync(driverPath) ? driverPath : 'tauri-driver';
    const args = [];
    if (edgeDriverPath) {
      args.push('--native-driver', edgeDriverPath);
    }
    tauriDriver = spawn(usePath, args, {
      stdio: [null, process.stdout, process.stderr],
      shell: true,
      env: { ...process.env, PATH: process.env.PATH || '' },
    });
    tauriDriver.on('error', (err) => {
      console.error('tauri-driver error:', err);
      process.exit(1);
    });
    tauriDriver.on('exit', (code) => {
      if (!exit) {
        console.error('tauri-driver exited with code:', code);
        process.exit(1);
      }
    });
  },
  afterSession: () => {
    closeTauriDriver();
  },
};

function closeTauriDriver() {
  exit = true;
  if (tauriDriver) {
    tauriDriver.kill();
    tauriDriver = null;
  }
}

function onShutdown(fn) {
  const cleanup = () => {
    try {
      fn();
    } finally {
      process.exit();
    }
  };
  process.on('exit', cleanup);
  process.on('SIGINT', cleanup);
  process.on('SIGTERM', cleanup);
  process.on('SIGHUP', cleanup);
  if (process.platform === 'win32') {
    process.on('SIGBREAK', cleanup);
  }
}

onShutdown(() => {
  closeTauriDriver();
  killE2ePorts();
});