import { execSync } from 'node:child_process' import { cpSync, mkdirSync, rmSync } from 'node:fs' import { dirname, resolve } from 'node:path' import { fileURLToPath } from 'node:url' import { defineConfig } from 'cypress' import createBundler from '@bahmutov/cypress-esbuild-preprocessor' import { Client } from 'pg' const configDirectory = dirname(fileURLToPath(import.meta.url)) const backendDirectory = resolve(configDirectory, '../../backend') const seedAssetDirectory = resolve(backendDirectory, 'database/seeders/assets') const socketDirectory = resolve(configDirectory, '../../.postgres') const storagePublicDirectory = resolve(backendDirectory, 'storage/app/public') const appDatabase = 'postgres' const templateDatabase = 'postgres_cypress_template' function controlClient(): Client { return new Client({ host: socketDirectory, database: 'template1', user: 'postgres', }) } async function buildTemplate(): Promise { const setupClient = controlClient() await setupClient.connect() await setupClient.query( `UPDATE pg_database SET datistemplate = false WHERE datname = $1`, [templateDatabase], ) await setupClient.query( `SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE datname = $1 AND pid <> pg_backend_pid()`, [templateDatabase], ) await setupClient.query(`DROP DATABASE IF EXISTS ${templateDatabase}`) await setupClient.query(`CREATE DATABASE ${templateDatabase}`) await setupClient.end() const seedEnvironment = { ...process.env, DB_DATABASE: templateDatabase } execSync('php artisan migrate:fresh --force', { cwd: backendDirectory, stdio: 'pipe', env: seedEnvironment, }) execSync('php artisan db:seed --force', { cwd: backendDirectory, stdio: 'pipe', env: seedEnvironment, }) resetSeedStorage() const markClient = controlClient() await markClient.connect() await markClient.query( `UPDATE pg_database SET datistemplate = true WHERE datname = $1`, [templateDatabase], ) await markClient.end() } async function resetFromTemplate(): Promise { const client = controlClient() await client.connect() await client.query( `SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE datname IN ($1, $2) AND pid <> pg_backend_pid()`, [appDatabase, templateDatabase], ) await client.query(`DROP DATABASE IF EXISTS ${appDatabase}`) await client.query( `CREATE DATABASE ${appDatabase} TEMPLATE ${templateDatabase}`, ) await client.end() resetSeedStorage() return null } function resetSeedStorage(): void { rmSync(resolve(storagePublicDirectory, 'element-icons'), { recursive: true, force: true, }) rmSync(resolve(storagePublicDirectory, 'element-pdfs'), { recursive: true, force: true, }) mkdirSync(storagePublicDirectory, { recursive: true }) cpSync(seedAssetDirectory, storagePublicDirectory, { recursive: true }) } export default defineConfig({ e2e: { baseUrl: 'http://localhost:5173', specPattern: 'cypress/e2e/**/*.cy.ts', supportFile: 'cypress/support/e2e.ts', fixturesFolder: false, video: false, screenshotOnRunFailure: false, setupNodeEvents(onEvent) { onEvent('before:run', async function () { await buildTemplate() }) onEvent('file:preprocessor', createBundler()) onEvent('task', { 'db:reset': resetFromTemplate, }) }, }, })