@1aboveio/skills 1.0.8 → 1.0.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.codex-plugin/plugin.json +13 -0
- package/.codex-plugin/resources.json +1827 -0
- package/README.md +22 -0
- package/package.json +9 -2
- package/skills/app-dev/airflow/SKILL.md +1 -1
- package/skills/app-dev/airflow/release-check.mjs +3 -1
- package/skills/app-dev/android-foundation/SKILL.md +1 -1
- package/skills/app-dev/android-foundation/release-check.mjs +3 -1
- package/skills/app-dev/app-debug/SKILL.md +1 -1
- package/skills/app-dev/app-debug/release-check.mjs +3 -1
- package/skills/app-dev/better-auth/SKILL.md +1 -1
- package/skills/app-dev/better-auth/release-check.mjs +3 -1
- package/skills/app-dev/data-catalog/SKILL.md +1 -1
- package/skills/app-dev/data-catalog/release-check.mjs +3 -1
- package/skills/app-dev/data-quality/SKILL.md +1 -1
- package/skills/app-dev/data-quality/release-check.mjs +3 -1
- package/skills/app-dev/ios-foundation/SKILL.md +1 -1
- package/skills/app-dev/ios-foundation/release-check.mjs +3 -1
- package/skills/app-dev/monorepo/SKILL.md +1 -1
- package/skills/app-dev/monorepo/release-check.mjs +3 -1
- package/skills/app-dev/nextjs-fullstack/SKILL.md +1 -1
- package/skills/app-dev/nextjs-fullstack/release-check.mjs +3 -1
- package/skills/app-dev/prisma-setup/SKILL.md +1 -1
- package/skills/app-dev/prisma-setup/release-check.mjs +3 -1
- package/skills/app-dev/pyspark/SKILL.md +1 -1
- package/skills/app-dev/pyspark/release-check.mjs +3 -1
- package/skills/app-dev/python-backend/SKILL.md +1 -1
- package/skills/app-dev/python-backend/release-check.mjs +3 -1
- package/skills/app-dev/shadcn/SKILL.md +1 -1
- package/skills/app-dev/shadcn/release-check.mjs +3 -1
- package/skills/app-dev/zod-v4/SKILL.md +1 -1
- package/skills/app-dev/zod-v4/release-check.mjs +3 -1
- package/skills/cicd/cloud-build/SKILL.md +1 -1
- package/skills/cicd/cloud-build/release-check.mjs +3 -1
- package/skills/cicd/cloud-debug/SKILL.md +1 -1
- package/skills/cicd/cloud-debug/release-check.mjs +3 -1
- package/skills/cicd/cloud-deploy/SKILL.md +1 -1
- package/skills/cicd/cloud-deploy/release-check.mjs +3 -1
- package/skills/cicd/docker/SKILL.md +1 -1
- package/skills/cicd/docker/release-check.mjs +3 -1
- package/skills/cicd/github-actions/SKILL.md +1 -1
- package/skills/cicd/github-actions/release-check.mjs +3 -1
- package/skills/cicd/github-flow/SKILL.md +1 -1
- package/skills/cicd/github-flow/release-check.mjs +3 -1
- package/skills/cicd/google-cloud/SKILL.md +1 -1
- package/skills/cicd/google-cloud/release-check.mjs +3 -1
- package/skills/cicd/mergify/SKILL.md +1 -1
- package/skills/cicd/mergify/release-check.mjs +3 -1
- package/skills/cicd/podman/SKILL.md +1 -1
- package/skills/cicd/podman/release-check.mjs +3 -1
- package/skills/content/article-review/SKILL.md +1 -1
- package/skills/content/article-review/release-check.mjs +3 -1
- package/skills/content/article-to-image/SKILL.md +1 -1
- package/skills/content/article-to-image/release-check.mjs +3 -1
- package/skills/content/flowchart-svg/SKILL.md +1 -1
- package/skills/content/flowchart-svg/release-check.mjs +3 -1
- package/skills/content/image-gen/SKILL.md +1 -1
- package/skills/content/image-gen/release-check.mjs +3 -1
- package/skills/content/mermaid/SKILL.md +1 -1
- package/skills/content/mermaid/release-check.mjs +3 -1
- package/skills/content/wechat-article-writer/SKILL.md +1 -1
- package/skills/content/wechat-article-writer/release-check.mjs +3 -1
- package/skills/content/wechat-publisher/SKILL.md +1 -1
- package/skills/content/wechat-publisher/release-check.mjs +3 -1
- package/skills/content/wechat-search/SKILL.md +1 -1
- package/skills/content/wechat-search/release-check.mjs +3 -1
- package/skills/content/xai-search/SKILL.md +88 -13
- package/skills/content/xai-search/release-check.mjs +3 -1
- package/skills/content/xai-search/scripts/xai_search.sh +125 -149
- package/skills/core/distill-writing/SKILL.md +1 -1
- package/skills/core/distill-writing/release-check.mjs +3 -1
- package/skills/core/doc-to-md/SKILL.md +1 -1
- package/skills/core/doc-to-md/release-check.mjs +3 -1
- package/skills/core/editorial-review/SKILL.md +1 -1
- package/skills/core/editorial-review/release-check.mjs +3 -1
- package/skills/core/house-style/SKILL.md +1 -1
- package/skills/core/house-style/release-check.mjs +3 -1
- package/skills/core/plain-language/SKILL.md +1 -1
- package/skills/core/plain-language/release-check.mjs +3 -1
- package/skills/core/polish-cn/SKILL.md +1 -1
- package/skills/core/polish-cn/release-check.mjs +3 -1
- package/skills/core/reg-parser/SKILL.md +1 -1
- package/skills/core/reg-parser/release-check.mjs +3 -1
- package/skills/core/terminology/SKILL.md +1 -1
- package/skills/core/terminology/release-check.mjs +3 -1
- package/skills/core/write-doc/SKILL.md +1 -1
- package/skills/core/write-doc/release-check.mjs +3 -1
- package/skills/engineering/better-review/SKILL.md +1 -1
- package/skills/engineering/better-review/release-check.mjs +3 -1
- package/skills/engineering/contributing/SKILL.md +1 -1
- package/skills/engineering/contributing/release-check.mjs +3 -1
- package/skills/engineering/e2e-test/SKILL.md +1 -1
- package/skills/engineering/e2e-test/release-check.mjs +3 -1
- package/skills/engineering/engineering-runtime/SKILL.md +1 -1
- package/skills/engineering/engineering-runtime/coherence/workflow.json +13 -13
- package/skills/engineering/engineering-runtime/release-check.mjs +3 -1
- package/skills/engineering/engineering-runtime/scripts/installation-resolver.mjs +191 -0
- package/skills/engineering/engineering-runtime/scripts/workflow-coherence.mjs +51 -10
- package/skills/engineering/ensure-coverage/SKILL.md +1 -1
- package/skills/engineering/ensure-coverage/release-check.mjs +3 -1
- package/skills/engineering/golden-path/SKILL.md +1 -1
- package/skills/engineering/golden-path/release-check.mjs +3 -1
- package/skills/engineering/harness-runtime/SKILL.md +1 -1
- package/skills/engineering/harness-runtime/release-check.mjs +3 -1
- package/skills/engineering/resolve-issues/SKILL.md +1 -1
- package/skills/engineering/resolve-issues/references/preflight.md +7 -0
- package/skills/engineering/resolve-issues/references/shared-modules.md +27 -0
- package/skills/engineering/resolve-issues/references/task-plan.md +5 -1
- package/skills/engineering/resolve-issues/release-check.mjs +3 -1
- package/skills/engineering/resolve-issues/scripts/active-installation.mjs +32 -0
- package/skills/engineering/resolve-issues/scripts/install-hooks.mjs +3 -0
- package/skills/engineering/resolve-issues/scripts/rehydrate.mjs +17 -1
- package/skills/engineering/resolve-release/SKILL.md +1 -1
- package/skills/engineering/resolve-release/release-check.mjs +3 -1
- package/skills/engineering/rush-issues/SKILL.md +1 -1
- package/skills/engineering/rush-issues/release-check.mjs +3 -1
- package/skills/engineering/rush-release/SKILL.md +1 -1
- package/skills/engineering/rush-release/release-check.mjs +3 -1
- package/skills/engineering/test-quality/SKILL.md +1 -1
- package/skills/engineering/test-quality/release-check.mjs +3 -1
- package/skills/risk-compliance/compliance-audit/SKILL.md +1 -1
- package/skills/risk-compliance/compliance-audit/release-check.mjs +3 -1
- package/skills/risk-compliance/contract-compare/SKILL.md +1 -1
- package/skills/risk-compliance/contract-compare/release-check.mjs +3 -1
- package/skills/risk-compliance/contract-review/SKILL.md +1 -1
- package/skills/risk-compliance/contract-review/release-check.mjs +3 -1
- package/skills/risk-compliance/doc-authenticity/SKILL.md +1 -1
- package/skills/risk-compliance/doc-authenticity/release-check.mjs +3 -1
- package/skills/risk-compliance/fraud-analysis/SKILL.md +1 -1
- package/skills/risk-compliance/fraud-analysis/release-check.mjs +3 -1
- package/skills/risk-compliance/payment-analysis/SKILL.md +1 -1
- package/skills/risk-compliance/payment-analysis/release-check.mjs +3 -1
- package/skills/risk-compliance/similar-domain/SKILL.md +1 -1
- package/skills/risk-compliance/similar-domain/release-check.mjs +3 -1
- package/skills/risk-compliance/tld-detection/SKILL.md +1 -1
- package/skills/risk-compliance/tld-detection/release-check.mjs +3 -1
- package/skills/app-dev/android-foundation/scripts/device-run.test.mjs +0 -436
- package/skills/app-dev/data-catalog/scripts/data-catalog.test.mjs +0 -36
- package/skills/app-dev/data-quality/scripts/data-quality.test.mjs +0 -12
- package/skills/cicd/github-actions/scripts/ci-run-audit.test.mjs +0 -637
- package/skills/cicd/github-flow/scripts/flow.test.mjs +0 -114
- package/skills/cicd/github-flow/scripts/persist-conventions.test.mjs +0 -108
- package/skills/cicd/mergify/scripts/audit.test.mjs +0 -201
- package/skills/cicd/mergify/scripts/entrypoints.test.mjs +0 -106
- package/skills/cicd/mergify/scripts/pr-620-mergify-comments.fixture.json +0 -30
- package/skills/cicd/mergify/scripts/stack-push.test.mjs +0 -233
- package/skills/cicd/mergify/scripts/watch-pr-delivery.test.mjs +0 -1826
- package/skills/content/image-gen/scripts/credentials.test.mjs +0 -212
- package/skills/content/image-gen/scripts/options.test.mjs +0 -245
- package/skills/content/xai-search/tests/smoke_test.sh +0 -36
- package/skills/core/polish-cn/scripts/polish-cn.test.mjs +0 -244
- package/skills/core/reg-parser/scripts/reg-parser.test.mjs +0 -165
- package/skills/engineering/better-review/scripts/pr-context.test.mjs +0 -168
- package/skills/engineering/better-review/scripts/rereview-scope.test.mjs +0 -587
- package/skills/engineering/better-review/scripts/scan-diff.test.mjs +0 -414
- package/skills/engineering/better-review/scripts/vendor-sync.test.mjs +0 -96
- package/skills/engineering/contributing/scripts/persist-conventions.test.mjs +0 -118
- package/skills/engineering/e2e-test/scripts/presentation-checks.test.mjs +0 -106
- package/skills/engineering/e2e-test/scripts/presentation-perceivability.test.mjs +0 -117
- package/skills/engineering/e2e-test/scripts/presentation-reachability.test.mjs +0 -69
- package/skills/engineering/e2e-test/scripts/presentation-render-health.test.mjs +0 -98
- package/skills/engineering/e2e-test/scripts/presentation-sweep.test.mjs +0 -71
- package/skills/engineering/e2e-test/scripts/presentation-temporal.test.mjs +0 -59
- package/skills/engineering/e2e-test/scripts/project-route-manifest.test.mjs +0 -76
- package/skills/engineering/engineering-runtime/engineering-runtime.test.mjs +0 -68
- package/skills/engineering/engineering-runtime/scripts/invocation-policy.test.mjs +0 -95
- package/skills/engineering/engineering-runtime/scripts/main-module.test.mjs +0 -288
- package/skills/engineering/engineering-runtime/scripts/required-check-plan.test.mjs +0 -96
- package/skills/engineering/ensure-coverage/scripts/adapters/nextjs-inventory.test.mjs +0 -96
- package/skills/engineering/ensure-coverage/scripts/check-quarantine-expiry.test.mjs +0 -47
- package/skills/engineering/ensure-coverage/scripts/ci-audit.test.mjs +0 -86
- package/skills/engineering/ensure-coverage/scripts/coverage-ledger.test.mjs +0 -447
- package/skills/engineering/ensure-coverage/scripts/design-parity.test.mjs +0 -552
- package/skills/engineering/ensure-coverage/scripts/lint-tests.test.mjs +0 -289
- package/skills/engineering/ensure-coverage/scripts/mock-policy-config.test.mjs +0 -119
- package/skills/engineering/golden-path/scripts/golden-path.test.mjs +0 -1457
- package/skills/engineering/harness-runtime/discover-models.test.mjs +0 -363
- package/skills/engineering/harness-runtime/harness-runtime.test.mjs +0 -967
- package/skills/engineering/harness-runtime/model-catalog-seed.test.mjs +0 -829
- package/skills/engineering/harness-runtime/model-catalog.test.mjs +0 -366
- package/skills/engineering/resolve-issues/scripts/cleanup-runs.test.mjs +0 -280
- package/skills/engineering/resolve-issues/scripts/dropbox.test.mjs +0 -346
- package/skills/engineering/resolve-issues/scripts/findings-reuse.test.mjs +0 -88
- package/skills/engineering/resolve-issues/scripts/github-reviews.test.mjs +0 -264
- package/skills/engineering/resolve-issues/scripts/install-hooks.test.mjs +0 -79
- package/skills/engineering/resolve-issues/scripts/issue-tree.test.mjs +0 -107
- package/skills/engineering/resolve-issues/scripts/manual-invocation.test.mjs +0 -14
- package/skills/engineering/resolve-issues/scripts/next-actions-capacity.test.mjs +0 -149
- package/skills/engineering/resolve-issues/scripts/next-actions.test.mjs +0 -915
- package/skills/engineering/resolve-issues/scripts/plan-sync.test.mjs +0 -156
- package/skills/engineering/resolve-issues/scripts/preflight-models.test.mjs +0 -448
- package/skills/engineering/resolve-issues/scripts/ready-check.test.mjs +0 -217
- package/skills/engineering/resolve-issues/scripts/rehydrate.test.mjs +0 -91
- package/skills/engineering/resolve-issues/scripts/review-verdict.test.mjs +0 -1060
- package/skills/engineering/resolve-issues/scripts/size-check.test.mjs +0 -458
- package/skills/engineering/resolve-release/scripts/apply.test.mjs +0 -99
- package/skills/engineering/resolve-release/scripts/dark-flags.test.mjs +0 -100
- package/skills/engineering/resolve-release/scripts/flow.test.mjs +0 -340
- package/skills/engineering/resolve-release/scripts/green-head.test.mjs +0 -101
- package/skills/engineering/resolve-release/scripts/npm-version-absence.test.mjs +0 -426
- package/skills/engineering/resolve-release/scripts/plan-npm.test.mjs +0 -659
- package/skills/engineering/resolve-release/scripts/plan-toml-boundary.test.mjs +0 -317
- package/skills/engineering/resolve-release/scripts/plan-uv.test.mjs +0 -291
- package/skills/engineering/resolve-release/scripts/plan.test.mjs +0 -428
- package/skills/engineering/test-quality/scripts/lint-tests.test.mjs +0 -591
- package/skills/engineering/test-quality/scripts/mock-policy-config.test.mjs +0 -119
- package/skills/engineering/test-quality/scripts/persist-conventions.test.mjs +0 -104
- package/skills/risk-compliance/compliance-audit/scripts/compliance-audit.test.mjs +0 -14
- package/skills/risk-compliance/doc-authenticity/manual-invocation.test.mjs +0 -12
- package/skills/risk-compliance/doc-authenticity/scripts/validate_verdict.test.mjs +0 -212
- package/skills/risk-compliance/tld-detection/scripts/detect_ladders.test.mjs +0 -14
- package/skills/risk-compliance/tld-detection/scripts/detect_streams.test.mjs +0 -14
- package/skills/risk-compliance/tld-detection/tests/test_detect_ladders.py +0 -134
- package/skills/risk-compliance/tld-detection/tests/test_detect_streams.py +0 -520
|
@@ -1,426 +0,0 @@
|
|
|
1
|
-
import { test } from 'node:test'
|
|
2
|
-
import assert from 'node:assert/strict'
|
|
3
|
-
import { spawnSync } from 'node:child_process'
|
|
4
|
-
import { mkdtempSync, mkdirSync, readFileSync, readdirSync, realpathSync, rmSync, symlinkSync, writeFileSync } from 'node:fs'
|
|
5
|
-
import { tmpdir } from 'node:os'
|
|
6
|
-
import { join } from 'node:path'
|
|
7
|
-
import { fileURLToPath } from 'node:url'
|
|
8
|
-
import { probeNpmVersionAbsence } from './npm-version-absence.mjs'
|
|
9
|
-
|
|
10
|
-
const script = fileURLToPath(new URL('./npm-version-absence.mjs', import.meta.url))
|
|
11
|
-
const request = { packageName: '@example/widget', version: '1.2.3', registry: 'https://registry.example.test/custom/npm/' }
|
|
12
|
-
const leakMarker = 'PRIVATE_CREDENTIAL_PAYLOAD_DO_NOT_FORWARD'
|
|
13
|
-
|
|
14
|
-
function fixture(t) {
|
|
15
|
-
const root = realpathSync(mkdtempSync(join(tmpdir(), 'npm-version-absence-')))
|
|
16
|
-
const bin = join(root, 'bin')
|
|
17
|
-
const cwd = join(root, 'work')
|
|
18
|
-
const calls = join(root, 'calls.jsonl')
|
|
19
|
-
mkdirSync(bin)
|
|
20
|
-
mkdirSync(cwd)
|
|
21
|
-
const savedEnv = { ...process.env }
|
|
22
|
-
t.after(() => {
|
|
23
|
-
process.env = savedEnv
|
|
24
|
-
rmSync(root, { recursive: true, force: true })
|
|
25
|
-
})
|
|
26
|
-
process.env.PATH = bin
|
|
27
|
-
process.env.FAKE_NPM_CALLS = calls
|
|
28
|
-
process.env.FAKE_NPM_REPLY = JSON.stringify({ stderr: 'npm error code E404', exitCode: 1 })
|
|
29
|
-
process.env.npm_config_registry = 'https://ambient-registry.example.test/ignored/'
|
|
30
|
-
const executable = `#!${process.execPath}
|
|
31
|
-
const fs = require('node:fs')
|
|
32
|
-
fs.appendFileSync(process.env.FAKE_NPM_CALLS, JSON.stringify({ argv: process.argv.slice(2), cwd: process.cwd() }) + '\\n')
|
|
33
|
-
const reply = JSON.parse(process.env.FAKE_NPM_REPLY)
|
|
34
|
-
fs.writeSync(1, reply.stdout || '')
|
|
35
|
-
fs.writeSync(2, reply.stderr || '')
|
|
36
|
-
if (reply.stdoutHex) fs.writeSync(1, Buffer.from(reply.stdoutHex, 'hex'))
|
|
37
|
-
if (reply.stderrHex) fs.writeSync(2, Buffer.from(reply.stderrHex, 'hex'))
|
|
38
|
-
for (const [fd, size] of [[1, reply.stdoutBytes], [2, reply.stderrBytes]]) {
|
|
39
|
-
let remaining = size || 0
|
|
40
|
-
while (remaining > 0) {
|
|
41
|
-
const chunk = Buffer.alloc(Math.min(8192, remaining), ' ')
|
|
42
|
-
remaining -= fs.writeSync(fd, chunk)
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
if (reply.signal) process.kill(process.pid, reply.signal)
|
|
46
|
-
process.exit(reply.exitCode ?? 0)
|
|
47
|
-
`
|
|
48
|
-
writeFileSync(join(bin, 'npm'), executable, { mode: 0o755 })
|
|
49
|
-
for (const command of ['git', 'gh', 'gcloud', 'curl', 'wget', 'touch']) {
|
|
50
|
-
writeFileSync(join(bin, command), `#!${process.execPath}
|
|
51
|
-
require('node:fs').appendFileSync(process.env.FAKE_NPM_CALLS, JSON.stringify({ forbiddenCommand: ${JSON.stringify(command)}, argv: process.argv.slice(2) }) + '\\n')
|
|
52
|
-
process.exit(91)
|
|
53
|
-
`, { mode: 0o755 })
|
|
54
|
-
}
|
|
55
|
-
t.mock.timers.enable({ apis: ['Date'], now: Date.UTC(2030, 0, 2) })
|
|
56
|
-
return {
|
|
57
|
-
root, bin, cwd,
|
|
58
|
-
reply(value) { process.env.FAKE_NPM_REPLY = JSON.stringify(value) },
|
|
59
|
-
calls() {
|
|
60
|
-
try { return readFileSync(calls, 'utf8').trim().split('\n').map((line) => JSON.parse(line)) }
|
|
61
|
-
catch (error) { if (error.code === 'ENOENT') return []; throw error }
|
|
62
|
-
},
|
|
63
|
-
probe(overrides = {}) { return probeNpmVersionAbsence({ ...request, cwd, ...overrides }) },
|
|
64
|
-
cli(args = ['--package', request.packageName, '--version', request.version, '--registry', request.registry]) {
|
|
65
|
-
return spawnSync(process.execPath, [script, ...args], { cwd, env: process.env, encoding: 'utf8', timeout: 40_000 })
|
|
66
|
-
},
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
function checkResult(result, status, reason, input = request) {
|
|
71
|
-
assert.deepEqual(Object.keys(result).sort(), ['status', 'packageName', 'version', 'registry', 'observedAt', 'reason'].sort())
|
|
72
|
-
assert.equal(result.status, status)
|
|
73
|
-
assert.equal(result.reason, reason)
|
|
74
|
-
assert.equal(result.packageName, input.packageName)
|
|
75
|
-
assert.equal(result.version, input.version)
|
|
76
|
-
assert.equal(result.registry, input.registry)
|
|
77
|
-
assert.equal(new Date(result.observedAt).toISOString(), result.observedAt)
|
|
78
|
-
assert.equal(JSON.stringify(result).includes(leakMarker), false)
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
test('clean E404 observes absence through one read-only npm argv with explicit scoped registry', (t) => {
|
|
82
|
-
const f = fixture(t)
|
|
83
|
-
checkResult(f.probe(), 'absent', 'version-absent')
|
|
84
|
-
assert.deepEqual(f.calls(), [{
|
|
85
|
-
argv: ['view', '@example/widget@1.2.3', 'version', '--registry=https://registry.example.test/custom/npm/', '--json'],
|
|
86
|
-
cwd: f.cwd,
|
|
87
|
-
}])
|
|
88
|
-
assert.deepEqual(readdirSync(f.cwd), [])
|
|
89
|
-
})
|
|
90
|
-
|
|
91
|
-
const responses = [
|
|
92
|
-
['plain E404 on stdout', { stdout: 'npm ERR! code E404\n', exitCode: 1 }, 'absent', 'version-absent'],
|
|
93
|
-
['JSON E404', { stdout: '{"error":{"code":"E404","summary":"Not found","detail":""}}', exitCode: 1 }, 'absent', 'version-absent'],
|
|
94
|
-
['JSON E404 with matching stderr', { stdout: '{"error":{"code":"E404"}}', stderr: 'npm error code E404', exitCode: 1 }, 'absent', 'version-absent'],
|
|
95
|
-
['bare E404 on stderr', { stderr: 'E404', exitCode: 1 }, 'absent', 'version-absent'],
|
|
96
|
-
['JSON E404 on stderr', { stderr: '{"error":{"code":"E404"}}', exitCode: 1 }, 'absent', 'version-absent'],
|
|
97
|
-
['escaped JSON E404 code', { stdout: '{"error":{"co\\u0064e":"E\\u0034\\u0030\\u0034"}}', exitCode: 1 }, 'absent', 'version-absent'],
|
|
98
|
-
['E404 with exit 2', { stderr: 'npm error code E404', exitCode: 2 }, 'inconclusive', 'npm-error'],
|
|
99
|
-
['E404 with exit 7', { stderr: 'npm error code E404', exitCode: 7 }, 'inconclusive', 'npm-error'],
|
|
100
|
-
['empty nonzero', { exitCode: 1 }, 'inconclusive', 'npm-error'],
|
|
101
|
-
['unknown nonzero', { stderr: 'Something failed', exitCode: 42 }, 'inconclusive', 'npm-error'],
|
|
102
|
-
['non-code E404 substring', { stderr: 'NOT_E404 or E404suffix', exitCode: 1 }, 'inconclusive', 'npm-error'],
|
|
103
|
-
['E404 with unknown named code', { stderr: 'npm error code E404\nnpm error code UNKNOWN', exitCode: 1 }, 'inconclusive', 'npm-error'],
|
|
104
|
-
['E404 mixed within JSON', { stdout: '{"error":{"code":"E404","detail":"E403"}}', exitCode: 1 }, 'inconclusive', 'npm-error'],
|
|
105
|
-
['escaped mixed JSON code', { stdout: '{"error":{"code":"E404","detail":"E\\u0034\\u0030\\u0033"}}', exitCode: 1 }, 'inconclusive', 'npm-error'],
|
|
106
|
-
['duplicate JSON keys cannot hide mixed codes', { stdout: '{"error":{"code":"E403","code":"E404"}}', exitCode: 1 }, 'inconclusive', 'npm-error'],
|
|
107
|
-
['malformed UTF-8 stdout cannot clear absence', { stdout: 'E404 ', stdoutHex: 'ff', exitCode: 1 }, 'inconclusive', 'unexpected-response'],
|
|
108
|
-
['malformed UTF-8 stderr cannot clear absence', { stdout: 'E404 ', stderrHex: 'ff', exitCode: 1 }, 'inconclusive', 'unexpected-response'],
|
|
109
|
-
['malformed JSON error', { stdout: '{"error":{"code":"E404"', exitCode: 1 }, 'inconclusive', 'unexpected-response'],
|
|
110
|
-
['malformed JSON stderr', { stderr: '["E404",', exitCode: 1 }, 'inconclusive', 'unexpected-response'],
|
|
111
|
-
['successful JSON version', { stdout: '"1.2.3"\n' }, 'present', 'version-present'],
|
|
112
|
-
['successful bare version', { stdout: ' \n1.2.3\t\n' }, 'present', 'version-present'],
|
|
113
|
-
['successful version with warning', { stdout: '"1.2.3"', stderr: 'npm warn using cached metadata' }, 'present', 'version-present'],
|
|
114
|
-
['successful empty output', {}, 'inconclusive', 'unexpected-response'],
|
|
115
|
-
['successful wrong version', { stdout: '"1.2.4"' }, 'inconclusive', 'unexpected-response'],
|
|
116
|
-
['successful bare wrong version', { stdout: '2.0.0' }, 'inconclusive', 'unexpected-response'],
|
|
117
|
-
['successful malformed JSON', { stdout: '"1.2.3' }, 'inconclusive', 'unexpected-response'],
|
|
118
|
-
['successful version object', { stdout: '{"version":"1.2.3"}' }, 'inconclusive', 'unexpected-response'],
|
|
119
|
-
['successful version array', { stdout: '["1.2.3"]' }, 'inconclusive', 'unexpected-response'],
|
|
120
|
-
['successful extra output', { stdout: '1.2.3\n1.2.3' }, 'inconclusive', 'unexpected-response'],
|
|
121
|
-
['successful E404', { stdout: 'E404' }, 'inconclusive', 'unexpected-response'],
|
|
122
|
-
['successful version with error', { stdout: '"1.2.3"', stderr: 'npm error code E404' }, 'inconclusive', 'unexpected-response'],
|
|
123
|
-
['process killed after E404', { stdout: 'E404', signal: 'SIGKILL' }, 'inconclusive', 'process-error'],
|
|
124
|
-
]
|
|
125
|
-
for (const code of ['E403', 'ENOTFOUND', 'E500', 'ETARGET', 'ENEEDAUTH', 'ECONNRESET']) {
|
|
126
|
-
responses.push(
|
|
127
|
-
[code, { stderr: `npm error code ${code}`, exitCode: 1 }, 'inconclusive', 'npm-error'],
|
|
128
|
-
[`E404 mixed with ${code}`, { stdout: '{"error":{"code":"E404"}}', stderr: `npm error code ${code}`, exitCode: 1 }, 'inconclusive', 'npm-error'],
|
|
129
|
-
)
|
|
130
|
-
}
|
|
131
|
-
for (const [name, reply, status, reason] of responses) {
|
|
132
|
-
test(name, (t) => {
|
|
133
|
-
const f = fixture(t)
|
|
134
|
-
f.reply(reply)
|
|
135
|
-
checkResult(f.probe(), status, reason)
|
|
136
|
-
assert.equal(f.calls().length, 1)
|
|
137
|
-
})
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
const incidentalJsonRefusals = [
|
|
141
|
-
'{"note":"E404"}',
|
|
142
|
-
'{"E404":"diagnostic only"}',
|
|
143
|
-
'{"error":{"detail":"previous E404; request failed"}}',
|
|
144
|
-
'{"note":"E\\u0034\\u0030\\u0034"}',
|
|
145
|
-
'"E404"',
|
|
146
|
-
'["E404"]',
|
|
147
|
-
'{"code":"E404"}',
|
|
148
|
-
'{"causes":[{"code":"E404"}]}',
|
|
149
|
-
]
|
|
150
|
-
for (const output of incidentalJsonRefusals) {
|
|
151
|
-
for (const channel of ['stdout', 'stderr']) {
|
|
152
|
-
for (const otherError of [false, true]) {
|
|
153
|
-
test(`incidental JSON cannot prove absence on ${channel}: ${output}; other error ${otherError}`, (t) => {
|
|
154
|
-
const f = fixture(t)
|
|
155
|
-
f.reply({
|
|
156
|
-
[channel]: output,
|
|
157
|
-
...(otherError ? { [channel === 'stdout' ? 'stderr' : 'stdout']: 'npm error code E404' } : {}),
|
|
158
|
-
exitCode: 1,
|
|
159
|
-
})
|
|
160
|
-
const result = f.cli()
|
|
161
|
-
assert.equal(result.status, 2)
|
|
162
|
-
checkResult(JSON.parse(result.stdout), 'inconclusive', 'npm-error')
|
|
163
|
-
})
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
const structuredRefusals = [
|
|
169
|
-
['unknown code with E404 detail', '{"error":{"code":"UNKNOWN","detail":"upstream E404"}}'],
|
|
170
|
-
['numeric code', '{"error":{"code":404}}'],
|
|
171
|
-
['null code', '{"error":{"code":null}}'],
|
|
172
|
-
['boolean code', '{"error":{"code":false}}'],
|
|
173
|
-
['array code', '{"error":{"code":["E404"]}}'],
|
|
174
|
-
['object code', '{"error":{"code":{"value":"E404"}}}'],
|
|
175
|
-
['empty code', '{"error":{"code":""}}'],
|
|
176
|
-
['mixed code value', '{"error":{"code":"E404 UNKNOWN"}}'],
|
|
177
|
-
['nested unknown code', '{"error":{"code":"E404","causes":[{"code":"UNKNOWN"}]}}'],
|
|
178
|
-
['escaped unknown code key', '{"error":{"co\\u0064e":"UNKNOWN","detail":"E404"}}'],
|
|
179
|
-
['duplicate unknown then E404', '{"error":{"code":"UNKNOWN","code":"E404"}}'],
|
|
180
|
-
['duplicate E404 then unknown', '{"error":{"code":"E404","code":"UNKNOWN"}}'],
|
|
181
|
-
['escaped duplicate code key', '{"error":{"code":"UNKNOWN","co\\u0064e":"E404"}}'],
|
|
182
|
-
['duplicate error object', '{"error":{"code":"UNKNOWN"},"error":{"code":"E404"}}'],
|
|
183
|
-
['duplicate nested unrelated key', '{"error":{"code":"E404","causes":[{"note":"first","note":"second"}]}}'],
|
|
184
|
-
]
|
|
185
|
-
for (const [name, output] of structuredRefusals) {
|
|
186
|
-
for (const channel of ['stdout', 'stderr']) {
|
|
187
|
-
test(`CLI refuses ${name} on ${channel}`, (t) => {
|
|
188
|
-
const f = fixture(t)
|
|
189
|
-
f.reply({
|
|
190
|
-
[channel]: output,
|
|
191
|
-
[channel === 'stdout' ? 'stderr' : 'stdout']: `npm error code E404\n${leakMarker}`,
|
|
192
|
-
exitCode: 1,
|
|
193
|
-
})
|
|
194
|
-
const result = f.cli()
|
|
195
|
-
assert.equal(result.error, undefined)
|
|
196
|
-
assert.equal(result.status, 2)
|
|
197
|
-
assert.equal(result.stderr, '')
|
|
198
|
-
checkResult(JSON.parse(result.stdout), 'inconclusive', 'npm-error')
|
|
199
|
-
assert.equal(f.calls().length, 1)
|
|
200
|
-
assert.deepEqual(readdirSync(f.cwd), [])
|
|
201
|
-
})
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
test('CLI refuses an exact successful version with an unknown structured stderr code', (t) => {
|
|
206
|
-
const f = fixture(t)
|
|
207
|
-
f.reply({ stdout: '"1.2.3"', stderr: JSON.stringify({ error: { code: 'UNKNOWN', detail: leakMarker } }) })
|
|
208
|
-
const result = f.cli()
|
|
209
|
-
assert.equal(result.error, undefined)
|
|
210
|
-
assert.equal(result.status, 2)
|
|
211
|
-
assert.equal(result.stderr, '')
|
|
212
|
-
checkResult(JSON.parse(result.stdout), 'inconclusive', 'unexpected-response')
|
|
213
|
-
assert.equal(f.calls().length, 1)
|
|
214
|
-
})
|
|
215
|
-
|
|
216
|
-
const framingRefusals = [
|
|
217
|
-
['warning then malformed JSON', 'npm warn diagnostic\n{"error":{"code":"E404"', 'unexpected-response'],
|
|
218
|
-
['warning then one JSON object', 'npm warn diagnostic\n{"error":{"code":"E404"}}', 'unexpected-response'],
|
|
219
|
-
['warning then two JSON documents', 'npm warn diagnostic\n{"error":{"code":"E404"}}\n{"error":{"code":"UNKNOWN"}}', 'unexpected-response'],
|
|
220
|
-
['two JSON documents', '{"error":{"code":"E404"}}\n{"error":{"code":"UNKNOWN"}}', 'unexpected-response'],
|
|
221
|
-
['plain E404 then truncated JSON', 'npm error code E404\n{"error":', 'unexpected-response'],
|
|
222
|
-
['warning then JSON string', 'npm warn diagnostic\n"E404"', 'unexpected-response'],
|
|
223
|
-
['warning then JSON array', 'npm warn diagnostic\n[{"code":"E404"},{"code":"UNKNOWN"}]', 'unexpected-response'],
|
|
224
|
-
['YAML instead of JSON syntax', '{error: {code: E404}}', 'unexpected-response'],
|
|
225
|
-
['missing plain code value', 'npm error code', 'npm-error'],
|
|
226
|
-
['mixed plain code value', 'npm ERR! code E404 UNKNOWN', 'npm-error'],
|
|
227
|
-
]
|
|
228
|
-
for (const [name, output, reason] of framingRefusals) {
|
|
229
|
-
for (const channel of ['stdout', 'stderr']) {
|
|
230
|
-
test(`CLI refuses ${name} on ${channel}`, (t) => {
|
|
231
|
-
const f = fixture(t)
|
|
232
|
-
f.reply({
|
|
233
|
-
[channel]: output,
|
|
234
|
-
[channel === 'stdout' ? 'stderr' : 'stdout']: `npm error code E404\n${leakMarker}`,
|
|
235
|
-
exitCode: 1,
|
|
236
|
-
})
|
|
237
|
-
const result = f.cli()
|
|
238
|
-
assert.equal(result.error, undefined)
|
|
239
|
-
assert.equal(result.status, 2)
|
|
240
|
-
assert.equal(result.stderr, '')
|
|
241
|
-
checkResult(JSON.parse(result.stdout), 'inconclusive', reason)
|
|
242
|
-
assert.equal(f.calls().length, 1)
|
|
243
|
-
assert.deepEqual(readdirSync(f.cwd), [])
|
|
244
|
-
})
|
|
245
|
-
}
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
const invalidNames = [
|
|
249
|
-
'', '@scope', '@scope/', '@/widget', '@scope/widget/extra', 'one/two', '@scope/@widget',
|
|
250
|
-
'Widget', '@Scope/widget', '@scope/Widget', '.widget', '_widget', '-widget', '@.scope/widget',
|
|
251
|
-
' widget', 'widget ', 'widget\n', 'widget\r', 'wid\tget', 'wid\0get',
|
|
252
|
-
'widget@1.2.3', 'widget;touch injected', 'widget$(touch injected)', 'widget%2fother',
|
|
253
|
-
'https://example.test/widget.tgz', '../widget', 'caf\u00e9', 'node_modules', 'favicon.ico',
|
|
254
|
-
'a'.repeat(215), `@a/${'b'.repeat(212)}`, null, 3, {}, ['widget'],
|
|
255
|
-
]
|
|
256
|
-
const invalidVersions = [
|
|
257
|
-
'', 'v1.2.3', 'V1.2.3', '01.2.3', '1.02.3', '1.2.03', '1.2', '1.2.3.4',
|
|
258
|
-
'1.2.3-rc.1', '1.2.3+build', '^1.2.3', 'latest', '*', ' 1.2.3', '1.2.3\n',
|
|
259
|
-
'1.2.3;touch injected', '9007199254740992.0.0', null, 123, {},
|
|
260
|
-
]
|
|
261
|
-
const invalidRegistries = [
|
|
262
|
-
'', 'http://registry.example.test', 'ftp://registry.example.test', '//registry.example.test',
|
|
263
|
-
'https:', 'https://', 'https://user:password@registry.example.test', 'https://user@registry.example.test',
|
|
264
|
-
'https://@registry.example.test', 'https://registry.example.test?token=private',
|
|
265
|
-
'https://registry.example.test/#fragment', 'https://registry.example.test/?', 'https://registry.example.test/#',
|
|
266
|
-
' https://registry.example.test', 'https://registry.example.test ',
|
|
267
|
-
'https://registry.example.test/\npath', 'https://registry.example.test/\rpath',
|
|
268
|
-
'https://registry.example.test/\u2028path', 'https://registry.example.test/\u2029path',
|
|
269
|
-
'https://registry.example.test/\tpath', 'https://registry.example.test/\0path',
|
|
270
|
-
'https://registry.example.test\\@other.test', 'https://registry.example.test:bad',
|
|
271
|
-
null, 42, {},
|
|
272
|
-
]
|
|
273
|
-
|
|
274
|
-
test('bad API parameters fail with a fixed message before spawning any process', (t) => {
|
|
275
|
-
const f = fixture(t)
|
|
276
|
-
for (const [field, values] of [['packageName', invalidNames], ['version', invalidVersions], ['registry', invalidRegistries], ['cwd', ['', 2, null, 'bad\0directory']]]) {
|
|
277
|
-
for (const value of field === 'cwd' ? values : [...values, undefined]) {
|
|
278
|
-
assert.throws(() => f.probe({ [field]: value }), { message: 'npm-version-absence: invalid arguments' })
|
|
279
|
-
}
|
|
280
|
-
}
|
|
281
|
-
for (const value of [undefined, null, 'bad', [], 1, {}]) {
|
|
282
|
-
assert.throws(() => probeNpmVersionAbsence(value), { message: 'npm-version-absence: invalid arguments' })
|
|
283
|
-
}
|
|
284
|
-
assert.deepEqual(f.calls(), [])
|
|
285
|
-
assert.deepEqual(readdirSync(f.cwd), [])
|
|
286
|
-
})
|
|
287
|
-
|
|
288
|
-
test('canonical safe names up to 214 characters and stable versions are accepted', (t) => {
|
|
289
|
-
const f = fixture(t)
|
|
290
|
-
for (const packageName of ['widget', 'widget.js_v2-extra', '@scope-name/widget.js_v2', 'a'.repeat(214), `@a/${'b'.repeat(211)}`]) {
|
|
291
|
-
for (const version of ['0.0.0', '10.20.30']) {
|
|
292
|
-
checkResult(f.probe({ packageName, version }), 'absent', 'version-absent', { ...request, packageName, version })
|
|
293
|
-
}
|
|
294
|
-
}
|
|
295
|
-
})
|
|
296
|
-
|
|
297
|
-
test('explicit HTTPS registries support custom paths, ports and case-insensitive schemes', (t) => {
|
|
298
|
-
const f = fixture(t)
|
|
299
|
-
for (const registry of ['https://registry.example.test', 'HTTPS://REGISTRY.EXAMPLE.TEST/npm/', 'https://registry.example.test:8443/custom/npm/', 'https://[::1]:8443/custom/']) {
|
|
300
|
-
checkResult(f.probe({ registry }), 'absent', 'version-absent', { ...request, registry })
|
|
301
|
-
assert.equal(f.calls().at(-1).argv[3], `--registry=${registry}`)
|
|
302
|
-
}
|
|
303
|
-
})
|
|
304
|
-
|
|
305
|
-
test('the API defaults cwd to the calling directory', (t) => {
|
|
306
|
-
const f = fixture(t)
|
|
307
|
-
const previous = process.cwd()
|
|
308
|
-
try {
|
|
309
|
-
process.chdir(f.cwd)
|
|
310
|
-
checkResult(probeNpmVersionAbsence(request), 'absent', 'version-absent')
|
|
311
|
-
} finally {
|
|
312
|
-
process.chdir(previous)
|
|
313
|
-
}
|
|
314
|
-
assert.equal(f.calls()[0].cwd, f.cwd)
|
|
315
|
-
})
|
|
316
|
-
|
|
317
|
-
for (const failure of ['missing executable', 'missing cwd']) {
|
|
318
|
-
test(`real spawn failure: ${failure}`, (t) => {
|
|
319
|
-
const f = fixture(t)
|
|
320
|
-
if (failure === 'missing executable') rmSync(join(f.bin, 'npm'))
|
|
321
|
-
const cwd = failure === 'missing cwd' ? join(f.root, leakMarker) : f.cwd
|
|
322
|
-
checkResult(f.probe({ cwd }), 'inconclusive', 'process-error')
|
|
323
|
-
assert.deepEqual(f.calls(), [])
|
|
324
|
-
})
|
|
325
|
-
}
|
|
326
|
-
|
|
327
|
-
for (const [name, reply, status, reason] of [
|
|
328
|
-
['exact 1 MiB', { stdout: 'E404\n', stdoutBytes: 1024 * 1024 - 5, exitCode: 1 }, 'absent', 'version-absent'],
|
|
329
|
-
['over 1 MiB stdout', { stdout: 'E404\n', stdoutBytes: 1024 * 1024, exitCode: 1 }, 'inconclusive', 'process-error'],
|
|
330
|
-
['over 1 MiB stderr', { stderr: 'E404\n', stderrBytes: 1024 * 1024, exitCode: 1 }, 'inconclusive', 'process-error'],
|
|
331
|
-
['over 1 MiB combined', { stdout: 'E404\n', stdoutBytes: 600 * 1024, stderrBytes: 600 * 1024, exitCode: 1 }, 'inconclusive', 'process-error'],
|
|
332
|
-
]) {
|
|
333
|
-
test(`bounded output: ${name}`, (t) => {
|
|
334
|
-
const f = fixture(t)
|
|
335
|
-
f.reply(reply)
|
|
336
|
-
checkResult(f.probe(), status, reason)
|
|
337
|
-
})
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
for (const [name, reply, status, reason, exitCode] of [
|
|
341
|
-
['absence', { stdout: '{"error":{"code":"E404"}}', stderr: leakMarker, exitCode: 1 }, 'absent', 'version-absent', 0],
|
|
342
|
-
['presence', { stdout: '"1.2.3"', stderr: leakMarker }, 'present', 'version-present', 1],
|
|
343
|
-
['inconclusive', { stdout: leakMarker, stderr: 'npm error code E403', exitCode: 1 }, 'inconclusive', 'npm-error', 2],
|
|
344
|
-
['signal death', { stdout: `E404 ${leakMarker}`, signal: 'SIGKILL' }, 'inconclusive', 'process-error', 2],
|
|
345
|
-
]) {
|
|
346
|
-
test(`CLI maps ${name} to exit ${exitCode} without forwarding child output`, (t) => {
|
|
347
|
-
const f = fixture(t)
|
|
348
|
-
f.reply(reply)
|
|
349
|
-
const result = f.cli()
|
|
350
|
-
assert.equal(result.error, undefined)
|
|
351
|
-
assert.equal(result.status, exitCode)
|
|
352
|
-
assert.equal(result.stderr, '')
|
|
353
|
-
checkResult(JSON.parse(result.stdout), status, reason)
|
|
354
|
-
assert.equal(result.stdout.includes(leakMarker), false)
|
|
355
|
-
assert.deepEqual(f.calls(), [{
|
|
356
|
-
argv: ['view', '@example/widget@1.2.3', 'version', `--registry=${request.registry}`, '--json'], cwd: f.cwd,
|
|
357
|
-
}])
|
|
358
|
-
assert.deepEqual(readdirSync(f.cwd), [])
|
|
359
|
-
})
|
|
360
|
-
}
|
|
361
|
-
|
|
362
|
-
test('CLI rejects missing, duplicate, unknown and unsafe arguments without registry discovery or raw errors', (t) => {
|
|
363
|
-
const f = fixture(t)
|
|
364
|
-
const valid = ['--package', request.packageName, '--version', request.version, '--registry', request.registry]
|
|
365
|
-
const invalidArgs = [
|
|
366
|
-
[], valid.slice(0, 4), valid.slice(2), [...valid.slice(0, 2), ...valid.slice(4)],
|
|
367
|
-
[...valid, '--registry', request.registry], [...valid, '--package', request.packageName],
|
|
368
|
-
[...valid, '--version', request.version], [...valid, '--timeout', '1'],
|
|
369
|
-
[...valid, '--help'], [...valid, `--unknown-${leakMarker}`],
|
|
370
|
-
[...valid, '--registry'], ['--package', leakMarker, ...valid.slice(2)],
|
|
371
|
-
['--package', request.packageName, '--version', '1.2.3', '--registry', `https://user:${leakMarker}@registry.example.test`],
|
|
372
|
-
]
|
|
373
|
-
for (const args of invalidArgs) {
|
|
374
|
-
const result = f.cli(args)
|
|
375
|
-
assert.equal(result.error, undefined)
|
|
376
|
-
assert.equal(result.status, 2)
|
|
377
|
-
assert.equal(result.stdout, '')
|
|
378
|
-
assert.equal(result.stderr, 'npm-version-absence: invalid arguments\n')
|
|
379
|
-
}
|
|
380
|
-
assert.deepEqual(f.calls(), [])
|
|
381
|
-
assert.deepEqual(readdirSync(f.cwd), [])
|
|
382
|
-
})
|
|
383
|
-
|
|
384
|
-
test('probing preserves files and tags and invokes no publisher or provider even with shell metacharacters', (t) => {
|
|
385
|
-
const f = fixture(t)
|
|
386
|
-
mkdirSync(join(f.cwd, '.git', 'refs', 'tags'), { recursive: true })
|
|
387
|
-
writeFileSync(join(f.cwd, '.git', 'refs', 'tags', 'existing'), 'historical-tag-sha\n')
|
|
388
|
-
writeFileSync(join(f.cwd, 'unchanged'), leakMarker)
|
|
389
|
-
const registry = 'https://registry.example.test/custom/npm/;git'
|
|
390
|
-
f.reply({ stdout: JSON.stringify({ error: { code: 'E404', detail: leakMarker } }), exitCode: 1 })
|
|
391
|
-
checkResult(f.probe({ registry }), 'absent', 'version-absent', { ...request, registry })
|
|
392
|
-
assert.deepEqual(f.calls(), [{
|
|
393
|
-
argv: ['view', '@example/widget@1.2.3', 'version', `--registry=${registry}`, '--json'], cwd: f.cwd,
|
|
394
|
-
}])
|
|
395
|
-
assert.deepEqual(readdirSync(f.cwd).sort(), ['.git', 'unchanged'])
|
|
396
|
-
assert.deepEqual(readdirSync(join(f.cwd, '.git'), { recursive: true }).sort(), ['refs', 'refs/tags', 'refs/tags/existing'])
|
|
397
|
-
assert.equal(readFileSync(join(f.cwd, '.git', 'refs', 'tags', 'existing'), 'utf8'), 'historical-tag-sha\n')
|
|
398
|
-
assert.equal(readFileSync(join(f.cwd, 'unchanged'), 'utf8'), leakMarker)
|
|
399
|
-
})
|
|
400
|
-
|
|
401
|
-
test('importing the module does not run npm or the CLI', (t) => {
|
|
402
|
-
const f = fixture(t)
|
|
403
|
-
const result = spawnSync(process.execPath, ['--input-type=module', '-e', `await import(${JSON.stringify(new URL('./npm-version-absence.mjs', import.meta.url).href)})`], {
|
|
404
|
-
cwd: f.cwd, env: process.env, encoding: 'utf8', timeout: 10_000,
|
|
405
|
-
})
|
|
406
|
-
assert.equal(result.error, undefined)
|
|
407
|
-
assert.equal(result.status, 0)
|
|
408
|
-
assert.equal(result.stdout, '')
|
|
409
|
-
assert.equal(result.stderr, '')
|
|
410
|
-
assert.deepEqual(f.calls(), [])
|
|
411
|
-
})
|
|
412
|
-
|
|
413
|
-
test('the CLI still blocks a present version when launched through a symlink', (t) => {
|
|
414
|
-
const f = fixture(t)
|
|
415
|
-
const link = join(f.root, 'installed-helper.mjs')
|
|
416
|
-
symlinkSync(script, link)
|
|
417
|
-
f.reply({ stdout: '"1.2.3"' })
|
|
418
|
-
const result = spawnSync(process.execPath, [link, '--package', request.packageName, '--version', request.version, '--registry', request.registry], {
|
|
419
|
-
cwd: f.cwd, env: process.env, encoding: 'utf8', timeout: 10_000,
|
|
420
|
-
})
|
|
421
|
-
assert.equal(result.error, undefined)
|
|
422
|
-
assert.equal(result.status, 1)
|
|
423
|
-
assert.equal(result.stderr, '')
|
|
424
|
-
checkResult(JSON.parse(result.stdout), 'present', 'version-present')
|
|
425
|
-
assert.equal(f.calls().length, 1)
|
|
426
|
-
})
|