Files
dify/e2e/features/support/hooks.ts
2026-03-29 13:40:24 +00:00

91 lines
2.8 KiB
TypeScript

import { After, AfterAll, Before, BeforeAll, Status, setDefaultTimeout } from '@cucumber/cucumber'
import { chromium, type Browser } from '@playwright/test'
import { mkdir, writeFile } from 'node:fs/promises'
import path from 'node:path'
import { fileURLToPath } from 'node:url'
import { ensureAuthenticatedState } from '../../fixtures/auth'
import { baseURL, cucumberHeadless, cucumberSlowMo } from '../../test-env'
import type { DifyWorld } from './world'
const e2eRoot = fileURLToPath(new URL('../..', import.meta.url))
const artifactsDir = path.join(e2eRoot, 'cucumber-report', 'artifacts')
let browser: Browser | undefined
setDefaultTimeout(60_000)
const sanitizeForPath = (value: string) =>
value.replaceAll(/[^a-zA-Z0-9_-]+/g, '-').replaceAll(/^-+|-+$/g, '')
const writeArtifact = async (
scenarioName: string,
extension: 'html' | 'png',
contents: Buffer | string,
) => {
const artifactPath = path.join(
artifactsDir,
`${Date.now()}-${sanitizeForPath(scenarioName || 'scenario')}.${extension}`,
)
await writeFile(artifactPath, contents)
return artifactPath
}
BeforeAll(async () => {
await mkdir(artifactsDir, { recursive: true })
browser = await chromium.launch({
headless: cucumberHeadless,
slowMo: cucumberSlowMo,
})
console.log(`[e2e] session cache bootstrap against ${baseURL}`)
await ensureAuthenticatedState(browser, baseURL)
})
Before(async function (this: DifyWorld, { pickle }) {
if (!browser) throw new Error('Shared Playwright browser is not available.')
await this.startAuthenticatedSession(browser)
this.scenarioStartedAt = Date.now()
const tags = pickle.tags.map((tag) => tag.name).join(' ')
console.log(`[e2e] start ${pickle.name}${tags ? ` ${tags}` : ''}`)
})
After(async function (this: DifyWorld, { pickle, result }) {
const elapsedMs = this.scenarioStartedAt ? Date.now() - this.scenarioStartedAt : undefined
if (result?.status !== Status.PASSED && this.page) {
const screenshot = await this.page.screenshot({
fullPage: true,
})
const screenshotPath = await writeArtifact(pickle.name, 'png', screenshot)
this.attach(screenshot, 'image/png')
const html = await this.page.content()
const htmlPath = await writeArtifact(pickle.name, 'html', html)
this.attach(html, 'text/html')
if (this.consoleErrors.length > 0)
this.attach(`Console Errors:\n${this.consoleErrors.join('\n')}`, 'text/plain')
if (this.pageErrors.length > 0)
this.attach(`Page Errors:\n${this.pageErrors.join('\n')}`, 'text/plain')
this.attach(`Artifacts:\n${[screenshotPath, htmlPath].join('\n')}`, 'text/plain')
}
const status = result?.status || 'UNKNOWN'
console.log(
`[e2e] end ${pickle.name} status=${status}${elapsedMs ? ` durationMs=${elapsedMs}` : ''}`,
)
await this.closeSession()
})
AfterAll(async () => {
await browser?.close()
browser = undefined
})