test: lock in TypeScript 6.0.3 exact dependency (E00-S01-T09)
CI / Frozen lockfile install (pull_request) Successful in 44s
CI / Frozen lockfile install (pull_request) Successful in 44s
This commit is contained in:
@@ -0,0 +1,108 @@
|
||||
/**
|
||||
* TypeScript exact-pin test — locks in the [E00-S01-T09] TypeScript 6.0.3
|
||||
* exact dependency for the workspace.
|
||||
*
|
||||
* Acceptance criteria covered (each test fails without the committed config):
|
||||
* - "TypeScript 6.0.3 is pinned as an exact dependency" → the root
|
||||
* `package.json` declares `devDependencies.typescript` as exactly
|
||||
* `6.0.3` (a bare MAJOR.MINOR.PATCH — no `^`/`~`/`>=` range), and
|
||||
* `pnpm-lock.yaml` resolves the root importer with specifier `6.0.3` /
|
||||
* version `6.0.3` and contains exactly one resolved TypeScript entry
|
||||
* (`typescript@6.0.3`) in its packages section.
|
||||
* - "workspace packages resolve the exact TypeScript version" → running
|
||||
* `pnpm exec tsc --version` inside every workspace package — the same
|
||||
* binary the package `build`/`typecheck` scripts invoke — reports
|
||||
* `Version 6.0.3`.
|
||||
*
|
||||
* Run: `node --test tests/typescript-pin.test.mjs`
|
||||
* (node:test — built into Node >= 18; no dependencies, lockfile untouched.)
|
||||
*/
|
||||
|
||||
import test from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import { readFileSync } from 'node:fs';
|
||||
import { spawnSync } from 'node:child_process';
|
||||
import path from 'node:path';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
|
||||
const REPO_ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
|
||||
|
||||
const read = (relPath) => readFileSync(path.join(REPO_ROOT, relPath), 'utf8');
|
||||
|
||||
/** The exact TypeScript version this workspace is pinned to ([E00-S01-T09]). */
|
||||
const PINNED_TYPESCRIPT = '6.0.3';
|
||||
|
||||
/** Every workspace package that must resolve the pinned TypeScript version. */
|
||||
const WORKSPACE_PACKAGES = ['apps/server', 'packages/core', 'extensions/example'];
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Tests
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
test('root package.json pins typescript as an exact dependency (6.0.3)', () => {
|
||||
const manifest = JSON.parse(read('package.json'));
|
||||
const spec = manifest.devDependencies?.typescript;
|
||||
assert.equal(
|
||||
spec,
|
||||
PINNED_TYPESCRIPT,
|
||||
`root package.json must pin devDependencies.typescript exactly as "${PINNED_TYPESCRIPT}" (got "${spec}")`,
|
||||
);
|
||||
// The pin must be exact — a bare MAJOR.MINOR.PATCH, never a semver range
|
||||
// (^, ~, >=, <, *, x-ranges) that could resolve to a different version.
|
||||
assert.match(
|
||||
spec,
|
||||
/^\d+\.\d+\.\d+$/,
|
||||
`"${spec}" is not an exact MAJOR.MINOR.PATCH version — pin typescript exactly, without a semver range`,
|
||||
);
|
||||
});
|
||||
|
||||
test('pnpm-lock.yaml resolves the root typescript pin to exactly 6.0.3', () => {
|
||||
const lockfile = read('pnpm-lock.yaml');
|
||||
|
||||
// Root importer: devDependencies.typescript must be specifier 6.0.3 with
|
||||
// resolved version 6.0.3 (a range specifier like "^6.0.3" fails this).
|
||||
const importersSection = lockfile.slice(
|
||||
lockfile.indexOf('importers:'),
|
||||
lockfile.indexOf('packages:'),
|
||||
);
|
||||
assert.match(
|
||||
importersSection,
|
||||
/devDependencies:\s*\n\s+typescript:\s*\n\s+specifier: 6\.0\.3\s*\n\s+version: 6\.0\.3/,
|
||||
'pnpm-lock.yaml must resolve the root typescript devDependency to specifier "6.0.3" / version "6.0.3"',
|
||||
);
|
||||
|
||||
// The packages section must contain exactly one resolved TypeScript entry,
|
||||
// so no package can drift onto a different TypeScript version.
|
||||
const packagesSection = lockfile.slice(
|
||||
lockfile.indexOf('packages:'),
|
||||
lockfile.indexOf('snapshots:'),
|
||||
);
|
||||
const resolvedTypescriptEntries = [...packagesSection.matchAll(/^\s+(typescript@\S+):/gm)].map(
|
||||
(m) => m[1],
|
||||
);
|
||||
assert.deepEqual(
|
||||
resolvedTypescriptEntries,
|
||||
[`typescript@${PINNED_TYPESCRIPT}`],
|
||||
`the lockfile must contain exactly one resolved TypeScript version (typescript@${PINNED_TYPESCRIPT}); got: ${resolvedTypescriptEntries.join(', ')}`,
|
||||
);
|
||||
});
|
||||
|
||||
test('every workspace package resolves the exact TypeScript version (6.0.3)', () => {
|
||||
for (const pkg of WORKSPACE_PACKAGES) {
|
||||
const result = spawnSync('corepack', ['pnpm', 'exec', 'tsc', '--version'], {
|
||||
cwd: path.join(REPO_ROOT, pkg),
|
||||
encoding: 'utf8',
|
||||
timeout: 120_000,
|
||||
});
|
||||
assert.equal(
|
||||
result.status,
|
||||
0,
|
||||
`"corepack pnpm exec tsc --version" failed in ${pkg}: ${(result.stderr || result.stdout || '').trim()}`,
|
||||
);
|
||||
assert.equal(
|
||||
result.stdout.trim(),
|
||||
`Version ${PINNED_TYPESCRIPT}`,
|
||||
`${pkg} must resolve TypeScript ${PINNED_TYPESCRIPT} (got "${result.stdout.trim()}")`,
|
||||
);
|
||||
}
|
||||
});
|
||||
Reference in New Issue
Block a user