()
| 249 | // ── Phase 4: Consumer smoke test ─────────────────────────────────── |
| 250 | |
| 251 | function phase4() { |
| 252 | heading('Phase 4: Consumer smoke test'); |
| 253 | |
| 254 | const distIndex = join(ROOT, 'dist', 'linter', 'index.js'); |
| 255 | const distTypes = join(ROOT, 'dist', 'linter', 'index.d.ts'); |
| 256 | |
| 257 | // 16. Import resolution (ESM) |
| 258 | const tmpDir = mkdtempSync(join(tmpdir(), 'check-pkg-')); |
| 259 | const smokeFile = join(tmpDir, 'smoke.mjs'); |
| 260 | writeFileSync( |
| 261 | smokeFile, |
| 262 | `import { lint } from '${distIndex}';\n` + |
| 263 | `if (typeof lint !== 'function') { process.exit(1); }\n` + |
| 264 | `console.log('ok');\n` |
| 265 | ); |
| 266 | const importCheck = exec(`node ${smokeFile}`); |
| 267 | if (!importCheck.ok || !importCheck.stdout.trim().endsWith('ok')) { |
| 268 | console.error('Smoke test failed!'); |
| 269 | console.error('STDOUT:', importCheck.stdout); |
| 270 | console.error('STDERR:', importCheck.stderr); |
| 271 | } |
| 272 | check('#16 Import resolution (ESM)', importCheck.ok && importCheck.stdout.trim().endsWith('ok'), |
| 273 | 'Could not import lint() from dist/index.js'); |
| 274 | |
| 275 | // 17. Type declarations exist and export lint |
| 276 | const dtsContent = existsSync(distTypes) ? readFileSync(distTypes, 'utf-8') : ''; |
| 277 | const hasLintExport = dtsContent.includes('export') && dtsContent.includes('lint'); |
| 278 | const hasLintReportType = dtsContent.includes('LintReport'); |
| 279 | check('#17 Type declarations valid', |
| 280 | hasLintExport && hasLintReportType, |
| 281 | `index.d.ts missing lint export or LintReport type`); |
| 282 | |
| 283 | // 18. Runtime sanity |
| 284 | const sanityFile = join(tmpDir, 'sanity.mjs'); |
| 285 | writeFileSync( |
| 286 | sanityFile, |
| 287 | `import { lint } from '${distIndex}';\n` + |
| 288 | `const result = lint('---\\nname: Test\\ncolors:\\n primary: "#ff0000"\\n---');\n` + |
| 289 | `const keys = Object.keys(result);\n` + |
| 290 | `const expected = ['designSystem','findings','summary','tailwindConfig'];\n` + |
| 291 | `const hasAll = expected.every(k => keys.includes(k));\n` + |
| 292 | `if (!hasAll) {\n` + |
| 293 | ` console.error('Missing keys. Actual:', keys);\n` + |
| 294 | ` process.exit(1);\n` + |
| 295 | `}\n` + |
| 296 | `if (typeof result.designSystem !== 'object') { process.exit(1); }\n` + |
| 297 | `if (!Array.isArray(result.findings)) { process.exit(1); }\n` + |
| 298 | `if (typeof result.summary.errors !== 'number') { process.exit(1); }\n` + |
| 299 | `console.log('ok');\n` |
| 300 | ); |
| 301 | const sanityCheck = exec(`node ${sanityFile}`); |
| 302 | if (!sanityCheck.ok || !sanityCheck.stdout.trim().endsWith('ok')) { |
| 303 | console.error('Sanity check failed!'); |
| 304 | console.error('STDOUT:', sanityCheck.stdout); |
| 305 | console.error('STDERR:', sanityCheck.stderr); |
| 306 | } |
| 307 | check('#18 Runtime sanity', sanityCheck.ok && sanityCheck.stdout.trim().endsWith('ok'), |
| 308 | 'lint() did not return expected shape'); |
no test coverage detected
searching dependent graphs…