Files
ArtPlayer/test/ecosystem-types.test.js

75 lines
4.3 KiB
JavaScript

import assert from 'node:assert/strict'
import fs from 'node:fs'
import path from 'node:path'
import process from 'node:process'
// eslint-disable-next-line test/no-import-node-test -- Tests repository consumer orchestration with real child processes.
import { test } from 'node:test'
import { ecosystemChecks, runConsumerCommand, verifyEcosystemScope } from '../scripts/consumers/ecosystem.ts'
import { consumerDirectory, removeConsumer, workspace } from '../scripts/package-consumer.mjs'
test('Installed type roster covers every library once and rejects omissions, duplicates and missing scripts', () => {
assert.equal(verifyEcosystemScope(workspace).length, 21)
assert.throws(() => verifyEcosystemScope(workspace, ecosystemChecks.slice(1)), /Every library package/)
assert.throws(() => verifyEcosystemScope(workspace, [...ecosystemChecks, ecosystemChecks[0]]), /Every library package/)
const missing = ecosystemChecks.map(check => ({ ...check }))
missing[0].script = 'test:missing-consumer'
assert.throws(() => verifyEcosystemScope(workspace, missing), /Missing consumer command/)
})
test('Consumer child failures retain both output streams and actual exit status', async () => {
const dir = consumerDirectory()
try {
const log = path.join(dir, 'failed.log')
const failed = await runConsumerCommand(process.execPath, ['-e', 'console.log("before failure"); console.error("type mismatch"); process.exitCode=23'], dir, log)
assert.equal(failed.code, 23)
assert.equal(failed.signal, null)
assert.match(fs.readFileSync(log, 'utf8'), /before failure[\s\S]*type mismatch/)
const passed = await runConsumerCommand(process.execPath, ['-e', 'console.log("next package")'], dir, path.join(dir, 'next.log'))
assert.equal(passed.code, 0)
assert.match(fs.readFileSync(passed.log, 'utf8'), /next package/)
const missing = await runConsumerCommand(path.join(dir, 'missing-executable'), [], dir, path.join(dir, 'missing.log'))
assert.equal(missing.code, null)
assert.match(missing.error, /ENOENT/)
}
finally { removeConsumer(dir) }
})
for (const failure of ['build', 'test:package']) {
test(`Ecosystem command propagates ${failure} failure with the correct remaining scope`, async () => {
const dir = consumerDirectory()
try {
const scripts = Object.fromEntries(ecosystemChecks.map(check => [check.script, 'controlled child']))
fs.writeFileSync(path.join(dir, 'package.json'), JSON.stringify({ scripts }))
for (const name of ecosystemChecks.flatMap(check => check.packages)) {
const folder = path.join(dir, 'packages', name)
fs.mkdirSync(folder, { recursive: true })
fs.writeFileSync(path.join(folder, 'package.json'), JSON.stringify({ name }))
}
const yarn = path.join(dir, 'controlled-yarn.cjs')
fs.writeFileSync(yarn, `console.log(process.argv.slice(2)); if (process.argv[2] === ${JSON.stringify(failure)}) process.exitCode = 29`)
const launcher = path.join(dir, 'launch.mjs')
fs.writeFileSync(launcher, `import { checkEcosystem } from ${JSON.stringify(new URL('../scripts/consumers/ecosystem.ts', import.meta.url).href)};
process.env.npm_config_user_agent = 'yarn/1.22.22';
process.env.npm_execpath = ${JSON.stringify(yarn)};
try { await checkEcosystem(${JSON.stringify(dir)}) } catch (error) { console.error(error); process.exitCode = 1 }
`)
const result = await runConsumerCommand(process.execPath, [launcher], dir, path.join(dir, 'aggregate.log'))
assert.equal(result.code, 1)
const parent = path.join(dir, 'refactor/.cache/ecosystem-types')
const [run] = fs.readdirSync(parent)
const report = JSON.parse(fs.readFileSync(path.join(parent, run, 'report.json'), 'utf8'))
if (failure === 'build') {
assert.deepEqual(report.results.map(item => item.command), [['build:types'], ['build', 'all']])
assert.deepEqual(report.results.map(item => item.outcome.code), [0, 29])
}
else {
assert.equal(report.results.length, ecosystemChecks.length + 3)
assert.deepEqual(report.results.slice(3).map(item => item.command[0]), ecosystemChecks.map(check => check.script))
assert.equal(report.results.filter(item => item.outcome.code === 29).length, 1)
assert(report.results.slice(4).every(item => item.outcome.code === 0))
}
}
finally { removeConsumer(dir) }
})
}