Merge pull request '[E00-S01-T09] TypeScript 6.0.3 exact dependency' (#376) from feature/162 into main
CI / Frozen lockfile install (push) Successful in 48s
CI / Frozen lockfile install (push) Successful in 48s
This commit was merged in pull request #376.
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