test: E2E プロバイダー別テストをコンフィグレベルで制御し JSON レポートを追加

プロバイダー固有テストの skip ロジックをテストファイルから vitest.config.e2e.provider.ts に移動。
JSON レポート出力を追加し e2e/results/ を gitignore に追加。
This commit is contained in:
nrslib 2026-03-04 01:57:49 +09:00
parent 8dcb23b147
commit df2d4a786d
7 changed files with 35 additions and 42 deletions

3
.gitignore vendored
View File

@ -23,6 +23,9 @@ npm-debug.log*
# Test coverage
coverage/
# E2E test results
e2e/results/
# Environment
.env
.env.local

View File

@ -64,7 +64,7 @@ describe('E2E: Export-cc command (takt export-cc)', () => {
const pieceFiles = readdirSync(piecesDir);
expect(pieceFiles.length).toBeGreaterThan(0);
const personasDir = join(skillDir, 'personas');
const personasDir = join(skillDir, 'facets', 'personas');
expect(existsSync(personasDir)).toBe(true);
const personaFiles = readdirSync(personasDir);
expect(personaFiles.length).toBeGreaterThan(0);

View File

@ -5,9 +5,6 @@ import { createIsolatedEnv, type IsolatedEnv, updateIsolatedConfig } from '../he
import { createLocalRepo, type LocalRepo } from '../helpers/test-repo';
import { runTakt } from '../helpers/takt-runner';
const provider = process.env.TAKT_E2E_PROVIDER;
const codexIt = provider === 'codex' ? it : it.skip;
describe('E2E: Codex permission mode readonly/full', () => {
let isolatedEnv: IsolatedEnv;
let repo: LocalRepo;
@ -48,7 +45,7 @@ describe('E2E: Codex permission mode readonly/full', () => {
try { isolatedEnv.cleanup(); } catch { /* best-effort */ }
});
codexIt('readonly で失敗し full で成功する', () => {
it('readonly で失敗し full で成功する', () => {
updateIsolatedConfig(isolatedEnv.taktDir, {
provider_profiles: {
codex: { default_permission_mode: 'readonly' },

View File

@ -1,31 +1,10 @@
/**
* OpenCode real E2E conversation test.
*
* Tests the full stack with a real OpenCode server:
* OpenCodeProvider callOpenCode OpenCodeClient createOpencode (real server)
*
* Skipped automatically if the opencode binary is not found.
* Run with: npm run test:e2e:opencode
*/
import { describe, it, expect, afterAll } from 'vitest';
import { execSync } from 'node:child_process';
import { resetSharedServer } from '../../src/infra/opencode/client.js';
import { OpenCodeProvider } from '../../src/infra/providers/opencode.js';
function isOpencodeAvailable(): boolean {
try {
execSync('which opencode', { stdio: 'ignore' });
return true;
} catch {
return false;
}
}
const MODEL = process.env.OPENCODE_E2E_MODEL ?? 'minimax/MiniMax-M2.5-highspeed';
const enabled = isOpencodeAvailable() && process.env.TAKT_E2E_PROVIDER === 'opencode';
describe.skipIf(!enabled)('OpenCode real E2E conversation', () => {
describe('OpenCode real E2E conversation', () => {
afterAll(() => {
resetSharedServer();
});

View File

@ -15,13 +15,13 @@
"test": "vitest run",
"test:watch": "vitest",
"test:e2e": "tmp=\"$(mktemp -t takt-e2e.XXXXXX)\"; npm run test:e2e:mock >\"$tmp\" 2>&1; code=$?; cat \"$tmp\"; if grep -q \"error connecting to api.github.com\" \"$tmp\"; then echo \"[takt] GitHub connectivity error detected in E2E output\"; code=1; fi; rm -f \"$tmp\"; if [ \"$code\" -eq 0 ]; then msg='test:e2e passed'; else msg=\"test:e2e failed (exit=$code)\"; fi; if command -v osascript >/dev/null 2>&1; then osascript -e \"display notification \\\"$msg\\\" with title \\\"takt\\\" subtitle \\\"E2E\\\"\" >/dev/null 2>&1 || true; fi; echo \"[takt] $msg\"; exit $code",
"test:e2e:mock": "TAKT_E2E_PROVIDER=mock vitest run --config vitest.config.e2e.mock.ts --reporter=verbose",
"test:e2e:mock": "TAKT_E2E_PROVIDER=mock vitest run --config vitest.config.e2e.mock.ts --outputFile.json=e2e/results/mock.json",
"test:e2e:all": "npm run test:e2e:mock && npm run test:e2e:provider",
"test:e2e:provider": "npm run test:e2e:provider:claude && npm run test:e2e:provider:codex",
"test:e2e:provider:claude": "TAKT_E2E_PROVIDER=claude vitest run --config vitest.config.e2e.provider.ts --reporter=verbose",
"test:e2e:provider:codex": "TAKT_E2E_PROVIDER=codex vitest run --config vitest.config.e2e.provider.ts --reporter=verbose",
"test:e2e:provider:opencode": "TAKT_E2E_PROVIDER=opencode vitest run --config vitest.config.e2e.provider.ts --reporter=verbose",
"test:e2e:provider:cursor": "TAKT_AUTO_PR=false TAKT_E2E_PROVIDER=cursor vitest run --config vitest.config.e2e.cursor.ts --reporter=verbose",
"test:e2e:provider:claude": "TAKT_E2E_PROVIDER=claude vitest run --config vitest.config.e2e.provider.ts --outputFile.json=e2e/results/claude.json",
"test:e2e:provider:codex": "TAKT_E2E_PROVIDER=codex vitest run --config vitest.config.e2e.provider.ts --outputFile.json=e2e/results/codex.json",
"test:e2e:provider:opencode": "TAKT_E2E_PROVIDER=opencode vitest run --config vitest.config.e2e.provider.ts --outputFile.json=e2e/results/opencode.json",
"test:e2e:provider:cursor": "TAKT_AUTO_PR=false TAKT_E2E_PROVIDER=cursor vitest run --config vitest.config.e2e.cursor.ts --outputFile.json=e2e/results/cursor.json",
"test:e2e:claude": "npm run test:e2e:provider:claude",
"test:e2e:codex": "npm run test:e2e:provider:codex",
"test:e2e:opencode": "npm run test:e2e:provider:opencode",

View File

@ -13,4 +13,5 @@ export const e2eBaseTestConfig: UserConfig['test'] = {
singleThread: true,
},
},
reporters: ['verbose', 'json'],
};

View File

@ -1,20 +1,33 @@
import { defineConfig } from 'vitest/config';
import { e2eBaseTestConfig } from './vitest.config.e2e.base';
const provider = process.env.TAKT_E2E_PROVIDER;
if (!provider) {
throw new Error('TAKT_E2E_PROVIDER must be set');
}
const commonTests = [
'e2e/specs/add-and-run.e2e.ts',
'e2e/specs/worktree.e2e.ts',
'e2e/specs/pipeline.e2e.ts',
'e2e/specs/github-issue.e2e.ts',
'e2e/specs/structured-output.e2e.ts',
'e2e/specs/team-leader.e2e.ts',
'e2e/specs/team-leader-worker-pool.e2e.ts',
'e2e/specs/team-leader-refill-threshold.e2e.ts',
];
const providerSpecificTests: Record<string, string[]> = {
codex: ['e2e/specs/codex-permission-mode.e2e.ts'],
opencode: ['e2e/specs/opencode-conversation.e2e.ts'],
};
export default defineConfig({
test: {
...e2eBaseTestConfig,
include: [
'e2e/specs/add-and-run.e2e.ts',
'e2e/specs/worktree.e2e.ts',
'e2e/specs/pipeline.e2e.ts',
'e2e/specs/github-issue.e2e.ts',
'e2e/specs/structured-output.e2e.ts',
'e2e/specs/codex-permission-mode.e2e.ts',
'e2e/specs/opencode-conversation.e2e.ts',
'e2e/specs/team-leader.e2e.ts',
'e2e/specs/team-leader-worker-pool.e2e.ts',
'e2e/specs/team-leader-refill-threshold.e2e.ts',
...commonTests,
...(providerSpecificTests[provider] ?? []),
],
},
});