test: E2E プロバイダー別テストをコンフィグレベルで制御し JSON レポートを追加
プロバイダー固有テストの skip ロジックをテストファイルから vitest.config.e2e.provider.ts に移動。 JSON レポート出力を追加し e2e/results/ を gitignore に追加。
This commit is contained in:
parent
8dcb23b147
commit
df2d4a786d
3
.gitignore
vendored
3
.gitignore
vendored
@ -23,6 +23,9 @@ npm-debug.log*
|
|||||||
# Test coverage
|
# Test coverage
|
||||||
coverage/
|
coverage/
|
||||||
|
|
||||||
|
# E2E test results
|
||||||
|
e2e/results/
|
||||||
|
|
||||||
# Environment
|
# Environment
|
||||||
.env
|
.env
|
||||||
.env.local
|
.env.local
|
||||||
|
|||||||
@ -64,7 +64,7 @@ describe('E2E: Export-cc command (takt export-cc)', () => {
|
|||||||
const pieceFiles = readdirSync(piecesDir);
|
const pieceFiles = readdirSync(piecesDir);
|
||||||
expect(pieceFiles.length).toBeGreaterThan(0);
|
expect(pieceFiles.length).toBeGreaterThan(0);
|
||||||
|
|
||||||
const personasDir = join(skillDir, 'personas');
|
const personasDir = join(skillDir, 'facets', 'personas');
|
||||||
expect(existsSync(personasDir)).toBe(true);
|
expect(existsSync(personasDir)).toBe(true);
|
||||||
const personaFiles = readdirSync(personasDir);
|
const personaFiles = readdirSync(personasDir);
|
||||||
expect(personaFiles.length).toBeGreaterThan(0);
|
expect(personaFiles.length).toBeGreaterThan(0);
|
||||||
|
|||||||
@ -5,9 +5,6 @@ import { createIsolatedEnv, type IsolatedEnv, updateIsolatedConfig } from '../he
|
|||||||
import { createLocalRepo, type LocalRepo } from '../helpers/test-repo';
|
import { createLocalRepo, type LocalRepo } from '../helpers/test-repo';
|
||||||
import { runTakt } from '../helpers/takt-runner';
|
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', () => {
|
describe('E2E: Codex permission mode readonly/full', () => {
|
||||||
let isolatedEnv: IsolatedEnv;
|
let isolatedEnv: IsolatedEnv;
|
||||||
let repo: LocalRepo;
|
let repo: LocalRepo;
|
||||||
@ -48,7 +45,7 @@ describe('E2E: Codex permission mode readonly/full', () => {
|
|||||||
try { isolatedEnv.cleanup(); } catch { /* best-effort */ }
|
try { isolatedEnv.cleanup(); } catch { /* best-effort */ }
|
||||||
});
|
});
|
||||||
|
|
||||||
codexIt('readonly で失敗し full で成功する', () => {
|
it('readonly で失敗し full で成功する', () => {
|
||||||
updateIsolatedConfig(isolatedEnv.taktDir, {
|
updateIsolatedConfig(isolatedEnv.taktDir, {
|
||||||
provider_profiles: {
|
provider_profiles: {
|
||||||
codex: { default_permission_mode: 'readonly' },
|
codex: { default_permission_mode: 'readonly' },
|
||||||
|
|||||||
@ -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 { describe, it, expect, afterAll } from 'vitest';
|
||||||
import { execSync } from 'node:child_process';
|
|
||||||
import { resetSharedServer } from '../../src/infra/opencode/client.js';
|
import { resetSharedServer } from '../../src/infra/opencode/client.js';
|
||||||
import { OpenCodeProvider } from '../../src/infra/providers/opencode.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 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(() => {
|
afterAll(() => {
|
||||||
resetSharedServer();
|
resetSharedServer();
|
||||||
});
|
});
|
||||||
|
|||||||
10
package.json
10
package.json
@ -15,13 +15,13 @@
|
|||||||
"test": "vitest run",
|
"test": "vitest run",
|
||||||
"test:watch": "vitest",
|
"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": "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: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": "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: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 --reporter=verbose",
|
"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 --reporter=verbose",
|
"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 --reporter=verbose",
|
"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:claude": "npm run test:e2e:provider:claude",
|
||||||
"test:e2e:codex": "npm run test:e2e:provider:codex",
|
"test:e2e:codex": "npm run test:e2e:provider:codex",
|
||||||
"test:e2e:opencode": "npm run test:e2e:provider:opencode",
|
"test:e2e:opencode": "npm run test:e2e:provider:opencode",
|
||||||
|
|||||||
@ -13,4 +13,5 @@ export const e2eBaseTestConfig: UserConfig['test'] = {
|
|||||||
singleThread: true,
|
singleThread: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
reporters: ['verbose', 'json'],
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,20 +1,33 @@
|
|||||||
import { defineConfig } from 'vitest/config';
|
import { defineConfig } from 'vitest/config';
|
||||||
import { e2eBaseTestConfig } from './vitest.config.e2e.base';
|
import { e2eBaseTestConfig } from './vitest.config.e2e.base';
|
||||||
|
|
||||||
export default defineConfig({
|
const provider = process.env.TAKT_E2E_PROVIDER;
|
||||||
test: {
|
if (!provider) {
|
||||||
...e2eBaseTestConfig,
|
throw new Error('TAKT_E2E_PROVIDER must be set');
|
||||||
include: [
|
}
|
||||||
|
|
||||||
|
const commonTests = [
|
||||||
'e2e/specs/add-and-run.e2e.ts',
|
'e2e/specs/add-and-run.e2e.ts',
|
||||||
'e2e/specs/worktree.e2e.ts',
|
'e2e/specs/worktree.e2e.ts',
|
||||||
'e2e/specs/pipeline.e2e.ts',
|
'e2e/specs/pipeline.e2e.ts',
|
||||||
'e2e/specs/github-issue.e2e.ts',
|
'e2e/specs/github-issue.e2e.ts',
|
||||||
'e2e/specs/structured-output.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.e2e.ts',
|
||||||
'e2e/specs/team-leader-worker-pool.e2e.ts',
|
'e2e/specs/team-leader-worker-pool.e2e.ts',
|
||||||
'e2e/specs/team-leader-refill-threshold.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: [
|
||||||
|
...commonTests,
|
||||||
|
...(providerSpecificTests[provider] ?? []),
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user