import fs from 'node:fs' import os from 'node:os' import path from 'node:path' import { spawn, spawnSync } from 'node:child_process' import http from 'node:http' import { fileURLToPath } from 'node:url' import { describe, expect, it } from 'vitest' const currentFile = fileURLToPath(import.meta.url) const websiteRoot = path.resolve(path.dirname(currentFile), '..') const frontendProductionEnv = path.join(websiteRoot, '.env.production.example') const frontendPreviewEnv = path.join(websiteRoot, '.env.preview.example') const serverProductionEnv = path.join(websiteRoot, 'server', '.env.production.example') const serverPreviewEnv = path.join(websiteRoot, 'server', '.env.preview.example') const runtimeReadinessScript = path.join(websiteRoot, 'scripts', 'check-runtime-readiness.mjs') function runCli(args, options = {}) { return new Promise((resolve, reject) => { const child = spawn(process.execPath, args, { cwd: websiteRoot, stdio: ['ignore', 'pipe', 'pipe'], ...options, }) let stdout = '' let stderr = '' child.stdout.on('data', (chunk) => { stdout += chunk }) child.stderr.on('data', (chunk) => { stderr += chunk }) child.on('error', reject) child.on('close', (status) => { resolve({ status, stdout, stderr, }) }) }) } describe('check-runtime-readiness CLI', () => { it('fails the real production example env files until placeholder launch values are replaced', () => { const result = spawnSync( process.execPath, [ runtimeReadinessScript, '--frontend-env', frontendProductionEnv, '--server-env', serverProductionEnv, '--skip-live-health', '--json', ], { cwd: websiteRoot, encoding: 'utf8', }, ) expect(result.status).toBe(1) expect(result.stderr).toBe('') const report = JSON.parse(result.stdout) expect(report.ok).toBe(false) expect(report.failures).toContain('VITE_WINDOWS_DOWNLOAD_URL still contains a placeholder value.') expect(report.failures).toContain('VITE_PADDLE_CHECKOUT_URL_OPERATOR still contains a placeholder value.') expect(report.failures).toContain('VITE_MPL_SOURCE_URL still contains a placeholder value.') expect(report.failures).toContain('PADDLE_WEBHOOK_SECRET still contains a placeholder value.') expect(report.failures).toContain('PADDLE_PRODUCT_PLAN_MAP still contains a placeholder value.') expect(report.failures).toContain('PADDLE_PRICE_PLAN_MAP still contains a placeholder value.') }) it('passes the real preview example env files while preserving honest preview warnings', () => { const result = spawnSync( process.execPath, [ runtimeReadinessScript, '--frontend-env', frontendPreviewEnv, '--server-env', serverPreviewEnv, '--skip-live-health', '--json', ], { cwd: websiteRoot, encoding: 'utf8', }, ) expect(result.status).toBe(0) expect(result.stderr).toBe('') const report = JSON.parse(result.stdout) expect(report.ok).toBe(true) expect(report.failures).toEqual([]) expect(report.deploymentTier).toBe('preview') expect(report.warnings).toContain('VITE_WINDOWS_DOWNLOAD_URL or WINDOWS_DOWNLOAD_URL is not set; Windows download will remain in preview posture until the release lane is configured.') expect(report.warnings).toContain('VITE_PADDLE_CHECKOUT_URL_OPERATOR is not set; Operator pricing will stay on the support fallback until checkout is configured.') expect(report.warnings).toContain('PADDLE_WEBHOOK_SECRET is not set; billing webhook handling will remain in preview posture until the live secret is configured.') }) it('fails a live deployment probe when the public origin still serves the placeholder page instead of JSON routes', async () => { const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'hypertwist-runtime-readiness-')) const frontendEnv = path.join(tempDir, 'frontend.env') const serverEnv = path.join(tempDir, 'server.env') fs.writeFileSync(frontendEnv, ` VITE_SUPERTOKENS_API_DOMAIN=https://hypertwist.app VITE_SUPERTOKENS_WEBSITE_DOMAIN=https://hypertwist.app VITE_AUTH_API_BASE_URL=https://hypertwist.app VITE_WINDOWS_DOWNLOAD_URL=https://downloads.hypertwist.app/windows.exe VITE_PADDLE_CHECKOUT_URL_OPERATOR=https://buy.paddle.com/operator VITE_PADDLE_CHECKOUT_URL_STUDIO=https://buy.paddle.com/studio VITE_MPL_SOURCE_URL=https://hypertwist.app/open-source/source VITE_OPEN_SOURCE_REPO_URL=https://git.scriptoriumai.io/scriptoriumadmin/hypertwist `) fs.writeFileSync(serverEnv, ` API_DOMAIN=https://hypertwist.app WEBSITE_DOMAIN=https://hypertwist.app SUPERTOKENS_CORE_URI=https://auth-core.internal COOKIE_SECURE=true SERVE_STATIC_WEBSITE=true PADDLE_WEBHOOK_SECRET=secret PADDLE_PRICE_PLAN_MAP={"pri_operator":"operator"} `) const placeholderHtml = ` HyperTwist

HyperTwist

Deployment target is live on the new VPS. Application rollout is pending.

` const server = http.createServer((req, res) => { res.writeHead(200, { 'content-type': 'text/html; charset=utf-8' }) res.end(placeholderHtml) }) await new Promise((resolve) => server.listen(0, '127.0.0.1', resolve)) const address = server.address() if (!address || typeof address === 'string') { throw new Error('Expected an IPv4 test listener address.') } const healthUrl = `http://127.0.0.1:${address.port}` try { const result = await runCli( [ runtimeReadinessScript, '--frontend-env', frontendEnv, '--server-env', serverEnv, '--health-url', healthUrl, '--json', ], ) expect(result.status).toBe(1) expect(result.stderr).toBe('') const report = JSON.parse(result.stdout) expect(report.ok).toBe(false) expect(report.failures.some((item) => item.includes('Live auth health check failed: Live auth health endpoint returned HTML instead of JSON.'))).toBe(true) expect(report.failures.some((item) => item.includes('placeholder rollout page'))).toBe(true) expect(report.failures.some((item) => item.includes('Live release manifest check failed: Live release manifest endpoint returned HTML instead of JSON.'))).toBe(true) expect(report.failures.some((item) => item.includes('Live website root still serves the placeholder rollout page'))).toBe(true) } finally { await new Promise((resolve, reject) => { server.close((error) => { if (error) { reject(error) return } resolve() }) }) fs.rmSync(tempDir, { recursive: true, force: true }) } }) })