import assert from 'node:assert/strict'; import fs from 'node:fs'; import os from 'node:os'; import path from 'node:path'; import { spawnSync } from 'node:child_process'; const repoRoot = process.cwd(); const scriptPath = path.join(repoRoot, 'scripts', 'taro-visual-guardrails.js'); function run(args = []) { return spawnSync(process.execPath, [scriptPath, '--json', ...args], { cwd: repoRoot, encoding: 'utf8', env: { PATH: process.env.PATH || '', Path: process.env.Path || '', SystemRoot: process.env.SystemRoot || '', ComSpec: process.env.ComSpec || '', TEMP: process.env.TEMP || os.tmpdir(), TMP: process.env.TMP || os.tmpdir(), }, }); } function parseJson(result) { return JSON.parse(result.stdout || '{}'); } const current = run(); assert.equal(current.status, 0, current.stderr || current.stdout); const currentPayload = parseJson(current); assert.equal(currentPayload.summary.fail, 0); assert.ok(currentPayload.summary.scannedFiles >= 6, 'current Taro CSS files should be scanned'); assert.ok(currentPayload.checks.some(item => item.id === 'css.border_radius' && item.status === 'pass')); assert.ok(currentPayload.checks.some(item => item.id === 'css.decorative_effects' && item.status === 'pass')); const fixtureRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'taro-visual-guardrails-')); fs.writeFileSync(path.join(fixtureRoot, 'bad.css'), ` .hero-card { border-radius: 44px; font-size: 6vw; letter-spacing: -0.04em; background: radial-gradient(circle, #fff, #dbeafe); filter: blur(20px); } .random-shape { border-radius: 999px; } `, 'utf8'); const bad = run(['--root', fixtureRoot]); fs.rmSync(fixtureRoot, { recursive: true, force: true }); assert.notEqual(bad.status, 0, 'fixture with visual violations should fail'); const badPayload = parseJson(bad); assert.ok(badPayload.checks.some(item => item.id === 'css.border_radius' && item.status === 'fail')); assert.ok(badPayload.checks.some(item => item.id === 'css.viewport_font_size' && item.status === 'fail')); assert.ok(badPayload.checks.some(item => item.id === 'css.letter_spacing' && item.status === 'fail')); assert.ok(badPayload.checks.some(item => item.id === 'css.decorative_effects' && item.status === 'fail')); assert.ok(badPayload.checks.some(item => item.id === 'css.pill_radius_scope' && item.status === 'fail')); console.log('[PASS] Taro visual guardrails');