dify/cli/vitest.e2e.config.ts
2026-06-09 10:06:55 +00:00

108 lines
4.3 KiB
TypeScript

import { readFileSync } from 'node:fs'
import { resolve } from 'node:path'
import { defineConfig } from 'vite-plus'
import { resolveBuildInfo } from './scripts/lib/resolve-buildinfo.js'
const buildInfo = resolveBuildInfo()
// Load .env.e2e into process.env (only if the file exists; in CI vars are
// injected directly via GitHub Actions secrets).
const envFilePath = resolve(process.cwd(), '.env.e2e')
try {
const raw = readFileSync(envFilePath, 'utf8')
for (const line of raw.split('\n')) {
const trimmed = line.trim()
if (!trimmed || trimmed.startsWith('#'))
continue
const eqIdx = trimmed.indexOf('=')
if (eqIdx === -1)
continue
const key = trimmed.slice(0, eqIdx).trim()
const val = trimmed.slice(eqIdx + 1).trim()
if (key && !(key in process.env))
process.env[key] = val
}
}
catch {
// .env.e2e not found — rely on environment variables already set in the shell
}
/**
* Vitest configuration for E2E tests.
*
* E2E tests run against a real staging Dify server and require
* DIFY_E2E_* environment variables to be set (see test/e2e/setup/env.ts).
*
* Run: bun vitest --config vitest.e2e.config.ts
*/
export default defineConfig({
pack: {
entry: ['src/index.ts'],
format: ['esm'],
outDir: 'dist',
target: 'node22',
define: {
__DIFYCTL_VERSION__: JSON.stringify(buildInfo.version),
__DIFYCTL_COMMIT__: JSON.stringify(buildInfo.commit),
__DIFYCTL_BUILD_DATE__: JSON.stringify(buildInfo.buildDate),
__DIFYCTL_CHANNEL__: JSON.stringify(buildInfo.channel),
__DIFYCTL_MIN_DIFY__: JSON.stringify(buildInfo.minDify),
__DIFYCTL_MAX_DIFY__: JSON.stringify(buildInfo.maxDify),
},
},
test: {
environment: 'node',
globalSetup: ['test/e2e/setup/global-setup.ts'],
// E2E tests do NOT use the unit-test setup.ts (no globalThis stubs needed —
// the real binary sets its own globals at startup).
setupFiles: [],
// DIFY_E2E_INCLUDE: comma-separated glob patterns, e.g.
// DIFY_E2E_INCLUDE="test/e2e/suites/run/run-app-basic.e2e.ts"
// DIFY_E2E_INCLUDE="test/e2e/suites/run/**/*.e2e.ts"
// DIFY_E2E_INCLUDE="test/e2e/suites/discovery/**/*.e2e.ts,test/e2e/suites/run/run-app-basic.e2e.ts"
// Deprecated alias: DIFY_E2E_SINGLE_FILE (single path only, kept for back-compat)
include: (() => {
const raw = process.env.DIFY_E2E_INCLUDE ?? process.env.DIFY_E2E_SINGLE_FILE
if (raw)
return raw.split(',').map(s => s.trim()).filter(Boolean)
return undefined
})()
?? (process.env.DIFY_E2E_MODE === 'local'
? ['test/e2e/suites/framework/help.e2e.ts', 'test/e2e/suites/agent/**/*.e2e.ts']
: [
// auth tests first (most others depend on a valid session)
'test/e2e/suites/auth/login.e2e.ts',
'test/e2e/suites/auth/status.e2e.ts',
'test/e2e/suites/auth/use.e2e.ts',
'test/e2e/suites/auth/whoami.e2e.ts',
// help (no network, no auth — runs first)
'test/e2e/suites/framework/help.e2e.ts',
// output format (table / cross-cutting)
'test/e2e/suites/output/**/*.e2e.ts',
// error handling (cross-cutting error message spec)
'test/e2e/suites/error-handling/**/*.e2e.ts',
// framework (global flags, non-interactive, debug)
'test/e2e/suites/framework/**/*.e2e.ts',
// discovery (get app / describe app)
'test/e2e/suites/discovery/**/*.e2e.ts',
// run tests (require valid token)
'test/e2e/suites/run/**/*.e2e.ts',
'test/e2e/suites/agent/**/*.e2e.ts',
// devices + logout LAST — both can revoke tokens
'test/e2e/suites/auth/devices.e2e.ts',
'test/e2e/suites/auth/logout.e2e.ts',
]),
// E2E calls a real staging server — allow plenty of time per test.
testTimeout: 120_000,
hookTimeout: 30_000,
// Retry up to 2 times on staging flakiness.
// VITEST_RETRY env var lets CI opt-in to automatic retries for flaky server 500s.
// Local default is 0 — per-test withRetry() handles known flaky paths more precisely.
retry: Number(process.env.VITEST_RETRY ?? 0),
// Run suites sequentially to avoid workspace-level conflicts on staging.
pool: 'forks',
fileParallelism: false,
reporters: ['verbose'],
},
})