diff --git a/src/test/configuration/resolution.spec.ts b/src/test/configuration/resolution.spec.ts new file mode 100644 index 000000000..5a36e623a --- /dev/null +++ b/src/test/configuration/resolution.spec.ts @@ -0,0 +1,56 @@ +import { lstatSync } from 'fs'; +import { join } from 'path'; +import { BIN_CWD_PATH, BIN_PATH, BIN_SCRIPT_PATH, createExec, ctxTsNode, TEST_DIR } from '../helpers'; +import { context, expect } from '../testlib'; + +const exec = createExec({ + cwd: TEST_DIR, +}); + +const test = context(ctxTsNode); + +test('should locate tsconfig relative to entry-point by default', async () => { + const r = await exec(`${BIN_PATH} ../a/index`, { + cwd: join(TEST_DIR, 'cwd-and-script-mode/b'), + }); + expect(r.err).toBe(null); + expect(r.stdout).toMatch(/plugin-a/); +}); +test('should locate tsconfig relative to entry-point via ts-node-script', async () => { + const r = await exec(`${BIN_SCRIPT_PATH} ../a/index`, { + cwd: join(TEST_DIR, 'cwd-and-script-mode/b'), + }); + expect(r.err).toBe(null); + expect(r.stdout).toMatch(/plugin-a/); +}); +test('should locate tsconfig relative to entry-point with --script-mode', async () => { + const r = await exec(`${BIN_PATH} --script-mode ../a/index`, { + cwd: join(TEST_DIR, 'cwd-and-script-mode/b'), + }); + expect(r.err).toBe(null); + expect(r.stdout).toMatch(/plugin-a/); +}); +test('should locate tsconfig relative to cwd via ts-node-cwd', async () => { + const r = await exec(`${BIN_CWD_PATH} ../a/index`, { + cwd: join(TEST_DIR, 'cwd-and-script-mode/b'), + }); + expect(r.err).toBe(null); + expect(r.stdout).toMatch(/plugin-b/); +}); +test('should locate tsconfig relative to cwd in --cwd-mode', async () => { + const r = await exec(`${BIN_PATH} --cwd-mode ../a/index`, { + cwd: join(TEST_DIR, 'cwd-and-script-mode/b'), + }); + expect(r.err).toBe(null); + expect(r.stdout).toMatch(/plugin-b/); +}); +test('should locate tsconfig relative to realpath, not symlink, when entrypoint is a symlink', async (t) => { + if (lstatSync(join(TEST_DIR, 'main-realpath/symlink/symlink.tsx')).isSymbolicLink()) { + const r = await exec(`${BIN_PATH} main-realpath/symlink/symlink.tsx`); + expect(r.err).toBe(null); + expect(r.stdout).toBe(''); + } else { + t.log('Skipping'); + return; + } +}); diff --git a/src/test/configuration/tsnode-opts-from-tsconfig.spec.ts b/src/test/configuration/tsnode-opts-from-tsconfig.spec.ts index 8e3054d06..2164f41f1 100644 --- a/src/test/configuration/tsnode-opts-from-tsconfig.spec.ts +++ b/src/test/configuration/tsnode-opts-from-tsconfig.spec.ts @@ -1,5 +1,5 @@ import { BIN_PATH } from '../helpers/paths'; -import { createExec } from '../exec-helpers'; +import { createExec } from '../helpers/exec'; import { TEST_DIR } from '../helpers/paths'; import { context, expect } from '../testlib'; import { join, resolve } from 'path'; diff --git a/src/test/create.spec.ts b/src/test/create.spec.ts new file mode 100644 index 000000000..41792ee6c --- /dev/null +++ b/src/test/create.spec.ts @@ -0,0 +1,35 @@ +import { ctxTsNode } from './helpers'; +import { context, expect } from './testlib'; + +const test = context(ctxTsNode); + +test.suite('create', ({ contextEach }) => { + const test = contextEach(async (t) => { + return { + service: t.context.tsNodeUnderTest.create({ + compilerOptions: { target: 'es5' }, + skipProject: true, + }), + }; + }); + + test('should create generic compiler instances', (t) => { + const output = t.context.service.compile('const x = 10', 'test.ts'); + expect(output).toMatch('var x = 10;'); + }); + + test.suite('should get type information', (test) => { + test('given position of identifier', (t) => { + expect(t.context.service.getTypeInfo('/**jsdoc here*/const x = 10', 'test.ts', 21)).toEqual({ + comment: 'jsdoc here', + name: 'const x: 10', + }); + }); + test('given position that does not point to an identifier', (t) => { + expect(t.context.service.getTypeInfo('/**jsdoc here*/const x = 10', 'test.ts', 0)).toEqual({ + comment: '', + name: '', + }); + }); + }); +}); diff --git a/src/test/esm-loader.spec.ts b/src/test/esm-loader.spec.ts index 4a7084665..942533e67 100644 --- a/src/test/esm-loader.spec.ts +++ b/src/test/esm-loader.spec.ts @@ -11,16 +11,16 @@ import { CMD_ESM_LOADER_WITHOUT_PROJECT, CMD_TS_NODE_WITHOUT_PROJECT_FLAG, ctxTsNode, - delay, nodeSupportsImportAssertions, nodeSupportsUnflaggedJsonImports, nodeUsesNewHooksApi, resetNodeEnvironment, TEST_DIR, tsSupportsImportAssertions, - tsSupportsStableNodeNextNode16, + createExec, + createSpawn, + ExecReturn, } from './helpers'; -import { createExec, createSpawn, ExecReturn } from './exec-helpers'; import { join, resolve } from 'path'; import * as expect from 'expect'; import type { NodeLoaderHooksAPI2 } from '../'; diff --git a/src/test/exec-helpers.ts b/src/test/helpers/exec.ts similarity index 99% rename from src/test/exec-helpers.ts rename to src/test/helpers/exec.ts index 5cb2365e3..5f5a223dd 100644 --- a/src/test/exec-helpers.ts +++ b/src/test/helpers/exec.ts @@ -1,7 +1,7 @@ import type { ChildProcess, ExecException, ExecOptions, SpawnOptions } from 'child_process'; import { exec as childProcessExec, spawn as childProcessSpawn } from 'child_process'; import { ExpectStream, expectStream } from '@cspotcode/expect-stream'; -import { expect } from './testlib'; +import { expect } from '../testlib'; export type ExecReturn = Promise & { child: ChildProcess }; export interface ExecResult { diff --git a/src/test/helpers/index.ts b/src/test/helpers/index.ts index fbb64d072..c34a5cf63 100644 --- a/src/test/helpers/index.ts +++ b/src/test/helpers/index.ts @@ -5,3 +5,4 @@ export * from './paths'; export * from './command-lines'; export * from './reset-node-environment'; export * from './version-checks'; +export * from './exec'; diff --git a/src/test/index.spec.ts b/src/test/index.spec.ts index 66e144991..884808a77 100644 --- a/src/test/index.spec.ts +++ b/src/test/index.spec.ts @@ -1,20 +1,11 @@ -import { context, ExecutionContext } from './testlib'; +import { context } from './testlib'; import * as expect from 'expect'; import { join, resolve, sep as pathSep } from 'path'; import { BIN_PATH_JS, CMD_TS_NODE_WITH_PROJECT_TRANSPILE_ONLY_FLAG, - ts, tsSupportsMtsCtsExtensions, - tsSupportsStableNodeNextNode16, -} from './helpers'; -import { lstatSync } from 'fs'; -import { createExec } from './exec-helpers'; -import { - BIN_CWD_PATH, BIN_PATH, - BIN_SCRIPT_PATH, - DIST_DIR, ROOT_DIR, TEST_DIR, testsDirRequire, @@ -22,8 +13,8 @@ import { CMD_TS_NODE_WITH_PROJECT_FLAG, CMD_TS_NODE_WITHOUT_PROJECT_FLAG, CMD_ESM_LOADER_WITHOUT_PROJECT, + createExec, } from './helpers'; -import type { CreateOptions } from '..'; const exec = createExec({ cwd: TEST_DIR, @@ -32,49 +23,6 @@ const exec = createExec({ const test = context(ctxTsNode); test.suite('ts-node', (test) => { - test('should export the correct version', (t) => { - expect(t.context.tsNodeUnderTest.VERSION).toBe(require('../../package.json').version); - }); - test('should export all CJS entrypoints', () => { - // Ensure our package.json "exports" declaration allows `require()`ing all our entrypoints - // https://github.com/TypeStrong/ts-node/pull/1026 - - testsDirRequire.resolve('ts-node'); - - // only reliably way to ask node for the root path of a dependency is Path.resolve(require.resolve('ts-node/package'), '..') - testsDirRequire.resolve('ts-node/package'); - testsDirRequire.resolve('ts-node/package.json'); - - // All bin entrypoints for people who need to augment our CLI: `node -r otherstuff ./node_modules/ts-node/dist/bin` - testsDirRequire.resolve('ts-node/dist/bin'); - testsDirRequire.resolve('ts-node/dist/bin.js'); - testsDirRequire.resolve('ts-node/dist/bin-transpile'); - testsDirRequire.resolve('ts-node/dist/bin-transpile.js'); - testsDirRequire.resolve('ts-node/dist/bin-script'); - testsDirRequire.resolve('ts-node/dist/bin-script.js'); - testsDirRequire.resolve('ts-node/dist/bin-cwd'); - testsDirRequire.resolve('ts-node/dist/bin-cwd.js'); - - // Must be `require()`able obviously - testsDirRequire.resolve('ts-node/register'); - testsDirRequire.resolve('ts-node/register/files'); - testsDirRequire.resolve('ts-node/register/transpile-only'); - testsDirRequire.resolve('ts-node/register/type-check'); - - // `node --loader ts-node/esm` - testsDirRequire.resolve('ts-node/esm'); - testsDirRequire.resolve('ts-node/esm.mjs'); - testsDirRequire.resolve('ts-node/esm/transpile-only'); - testsDirRequire.resolve('ts-node/esm/transpile-only.mjs'); - - testsDirRequire.resolve('ts-node/transpilers/swc'); - testsDirRequire.resolve('ts-node/transpilers/swc-experimental'); - - testsDirRequire.resolve('ts-node/node14/tsconfig.json'); - testsDirRequire.resolve('ts-node/node16/tsconfig.json'); - testsDirRequire.resolve('ts-node/node18/tsconfig.json'); - }); - test('should not load typescript outside of loadConfig', async () => { const r = await exec( `node -e "require('ts-node'); console.dir(Object.keys(require.cache).filter(k => k.includes('node_modules/typescript')).length)"` @@ -439,52 +387,6 @@ test.suite('ts-node', (test) => { }); }); - test('should locate tsconfig relative to entry-point by default', async () => { - const r = await exec(`${BIN_PATH} ../a/index`, { - cwd: join(TEST_DIR, 'cwd-and-script-mode/b'), - }); - expect(r.err).toBe(null); - expect(r.stdout).toMatch(/plugin-a/); - }); - test('should locate tsconfig relative to entry-point via ts-node-script', async () => { - const r = await exec(`${BIN_SCRIPT_PATH} ../a/index`, { - cwd: join(TEST_DIR, 'cwd-and-script-mode/b'), - }); - expect(r.err).toBe(null); - expect(r.stdout).toMatch(/plugin-a/); - }); - test('should locate tsconfig relative to entry-point with --script-mode', async () => { - const r = await exec(`${BIN_PATH} --script-mode ../a/index`, { - cwd: join(TEST_DIR, 'cwd-and-script-mode/b'), - }); - expect(r.err).toBe(null); - expect(r.stdout).toMatch(/plugin-a/); - }); - test('should locate tsconfig relative to cwd via ts-node-cwd', async () => { - const r = await exec(`${BIN_CWD_PATH} ../a/index`, { - cwd: join(TEST_DIR, 'cwd-and-script-mode/b'), - }); - expect(r.err).toBe(null); - expect(r.stdout).toMatch(/plugin-b/); - }); - test('should locate tsconfig relative to cwd in --cwd-mode', async () => { - const r = await exec(`${BIN_PATH} --cwd-mode ../a/index`, { - cwd: join(TEST_DIR, 'cwd-and-script-mode/b'), - }); - expect(r.err).toBe(null); - expect(r.stdout).toMatch(/plugin-b/); - }); - test('should locate tsconfig relative to realpath, not symlink, when entrypoint is a symlink', async (t) => { - if (lstatSync(join(TEST_DIR, 'main-realpath/symlink/symlink.tsx')).isSymbolicLink()) { - const r = await exec(`${BIN_PATH} main-realpath/symlink/symlink.tsx`); - expect(r.err).toBe(null); - expect(r.stdout).toBe(''); - } else { - t.log('Skipping'); - return; - } - }); - test('should have the correct working directory in the user entry-point', async () => { const r = await exec(`${BIN_PATH} --cwd ./cjs index.ts`, { cwd: resolve(TEST_DIR, 'working-dir'), @@ -600,98 +502,6 @@ test.suite('ts-node', (test) => { expect(r.stdout).toBe(`value\nFailures: 0\n`); }); }); - - test.suite('create', ({ contextEach }) => { - const test = contextEach(async (t) => { - return { - service: t.context.tsNodeUnderTest.create({ - compilerOptions: { target: 'es5' }, - skipProject: true, - }), - }; - }); - - test('should create generic compiler instances', (t) => { - const output = t.context.service.compile('const x = 10', 'test.ts'); - expect(output).toMatch('var x = 10;'); - }); - - test.suite('should get type information', (test) => { - test('given position of identifier', (t) => { - expect(t.context.service.getTypeInfo('/**jsdoc here*/const x = 10', 'test.ts', 21)).toEqual({ - comment: 'jsdoc here', - name: 'const x: 10', - }); - }); - test('given position that does not point to an identifier', (t) => { - expect(t.context.service.getTypeInfo('/**jsdoc here*/const x = 10', 'test.ts', 0)).toEqual({ - comment: '', - name: '', - }); - }); - }); - }); - - test.suite('issue #1098', (test) => { - function testAllowedExtensions( - t: ExecutionContext, - compilerOptions: CreateOptions['compilerOptions'], - allowed: string[] - ) { - const disallowed = allExtensions.filter((ext) => !allowed.includes(ext)); - const { ignored } = t.context.tsNodeUnderTest.create({ - compilerOptions, - skipProject: true, - }); - for (const ext of allowed) { - t.log(`Testing that ${ext} files are allowed`); - expect(ignored(join(DIST_DIR, `index${ext}`))).toBe(false); - } - for (const ext of disallowed) { - t.log(`Testing that ${ext} files are ignored`); - expect(ignored(join(DIST_DIR, `index${ext}`))).toBe(true); - } - } - - const allExtensions = [ - '.ts', - '.js', - '.d.ts', - '.mts', - '.cts', - '.d.mts', - '.d.cts', - '.mjs', - '.cjs', - '.tsx', - '.jsx', - '.xyz', - '', - ]; - const mtsCts = tsSupportsMtsCtsExtensions ? ['.mts', '.cts', '.d.mts', '.d.cts'] : []; - const mjsCjs = tsSupportsMtsCtsExtensions ? ['.mjs', '.cjs'] : []; - - test('correctly filters file extensions from the compiler when allowJs=false and jsx=false', (t) => { - testAllowedExtensions(t, {}, ['.ts', '.d.ts', ...mtsCts]); - }); - test('correctly filters file extensions from the compiler when allowJs=true and jsx=false', (t) => { - testAllowedExtensions(t, { allowJs: true }, ['.ts', '.js', '.d.ts', ...mtsCts, ...mjsCjs]); - }); - test('correctly filters file extensions from the compiler when allowJs=false and jsx=true', (t) => { - testAllowedExtensions(t, { allowJs: false, jsx: 'preserve' }, ['.ts', '.tsx', '.d.ts', ...mtsCts]); - }); - test('correctly filters file extensions from the compiler when allowJs=true and jsx=true', (t) => { - testAllowedExtensions(t, { allowJs: true, jsx: 'preserve' }, [ - '.ts', - '.tsx', - '.js', - '.jsx', - '.d.ts', - ...mtsCts, - ...mjsCjs, - ]); - }); - }); }); test('Falls back to transpileOnly when ts compiler returns emitSkipped', async () => { @@ -730,42 +540,3 @@ test.suite('node environment', (test) => { } }); }); - -test('Detect when typescript adds new ModuleKind values; flag as a failure so we can update our code flagged [MUST_UPDATE_FOR_NEW_MODULEKIND]', async () => { - // We have marked a few places in our code with MUST_UPDATE_FOR_NEW_MODULEKIND to make it easier to update them when TS adds new ModuleKinds - const foundKeys: string[] = []; - function check(value: number, name: string, required: boolean) { - if (required) expect(ts.ModuleKind[name as any]).toBe(value); - if (ts.ModuleKind[value] === undefined) { - expect(ts.ModuleKind[name as any]).toBeUndefined(); - } else { - expect(ts.ModuleKind[value]).toBe(name); - foundKeys.push(name, `${value}`); - } - } - check(0, 'None', true); - check(1, 'CommonJS', true); - check(2, 'AMD', true); - check(3, 'UMD', true); - check(4, 'System', true); - check(5, 'ES2015', true); - try { - check(6, 'ES2020', false); - check(99, 'ESNext', true); - } catch { - // the value changed: is `99` now, but was `6` in TS 2.7 - check(6, 'ESNext', true); - expect(ts.ModuleKind[99]).toBeUndefined(); - } - check(7, 'ES2022', false); - if (tsSupportsStableNodeNextNode16) { - check(100, 'Node16', true); - } else { - check(100, 'Node12', false); - } - check(199, 'NodeNext', false); - const actualKeys = Object.keys(ts.ModuleKind); - actualKeys.sort(); - foundKeys.sort(); - expect(actualKeys).toEqual(foundKeys); -}); diff --git a/src/test/module-node/1778.spec.ts b/src/test/module-node/1778.spec.ts index 89e6dec04..57909e61e 100644 --- a/src/test/module-node/1778.spec.ts +++ b/src/test/module-node/1778.spec.ts @@ -1,4 +1,4 @@ -import { createExec } from '../exec-helpers'; +import { createExec } from '../helpers/exec'; import { ctxTsNode, TEST_DIR, tsSupportsStableNodeNextNode16, CMD_TS_NODE_WITHOUT_PROJECT_FLAG } from '../helpers'; import { context, expect } from '../testlib'; import { join } from 'path'; diff --git a/src/test/module-node/module-node.spec.ts b/src/test/module-node/module-node.spec.ts index 9dc833181..b10e13ba1 100644 --- a/src/test/module-node/module-node.spec.ts +++ b/src/test/module-node/module-node.spec.ts @@ -8,7 +8,7 @@ import { } from '../helpers'; import * as Path from 'path'; import { ctxTsNode } from '../helpers'; -import { exec } from '../exec-helpers'; +import { exec } from '../helpers/exec'; import { file, project, ProjectAPI as ProjectAPI, StringFile } from '@TypeStrong/fs-fixture-builder'; const test = context(ctxTsNode); diff --git a/src/test/package.spec.ts b/src/test/package.spec.ts new file mode 100644 index 000000000..5b1835e17 --- /dev/null +++ b/src/test/package.spec.ts @@ -0,0 +1,52 @@ +// Verify the shape of the published tarball: +// valid import specifiers +// CLI commands on PATH +// named exports + +import { ctxTsNode, testsDirRequire } from './helpers'; +import { context, expect } from './testlib'; + +const test = context(ctxTsNode); + +test('should export the correct version', (t) => { + expect(t.context.tsNodeUnderTest.VERSION).toBe(require('../../package.json').version); +}); +test('should export all CJS entrypoints', () => { + // Ensure our package.json "exports" declaration allows `require()`ing all our entrypoints + // https://github.com/TypeStrong/ts-node/pull/1026 + + testsDirRequire.resolve('ts-node'); + + // only reliably way to ask node for the root path of a dependency is Path.resolve(require.resolve('ts-node/package'), '..') + testsDirRequire.resolve('ts-node/package'); + testsDirRequire.resolve('ts-node/package.json'); + + // All bin entrypoints for people who need to augment our CLI: `node -r otherstuff ./node_modules/ts-node/dist/bin` + testsDirRequire.resolve('ts-node/dist/bin'); + testsDirRequire.resolve('ts-node/dist/bin.js'); + testsDirRequire.resolve('ts-node/dist/bin-transpile'); + testsDirRequire.resolve('ts-node/dist/bin-transpile.js'); + testsDirRequire.resolve('ts-node/dist/bin-script'); + testsDirRequire.resolve('ts-node/dist/bin-script.js'); + testsDirRequire.resolve('ts-node/dist/bin-cwd'); + testsDirRequire.resolve('ts-node/dist/bin-cwd.js'); + + // Must be `require()`able obviously + testsDirRequire.resolve('ts-node/register'); + testsDirRequire.resolve('ts-node/register/files'); + testsDirRequire.resolve('ts-node/register/transpile-only'); + testsDirRequire.resolve('ts-node/register/type-check'); + + // `node --loader ts-node/esm` + testsDirRequire.resolve('ts-node/esm'); + testsDirRequire.resolve('ts-node/esm.mjs'); + testsDirRequire.resolve('ts-node/esm/transpile-only'); + testsDirRequire.resolve('ts-node/esm/transpile-only.mjs'); + + testsDirRequire.resolve('ts-node/transpilers/swc'); + testsDirRequire.resolve('ts-node/transpilers/swc-experimental'); + + testsDirRequire.resolve('ts-node/node14/tsconfig.json'); + testsDirRequire.resolve('ts-node/node16/tsconfig.json'); + testsDirRequire.resolve('ts-node/node18/tsconfig.json'); +}); diff --git a/src/test/regression.spec.ts b/src/test/regression.spec.ts index a2f5c1754..f77319822 100644 --- a/src/test/regression.spec.ts +++ b/src/test/regression.spec.ts @@ -2,9 +2,10 @@ import * as exp from 'expect'; import { join } from 'path'; -import { createExec, createExecTester } from './exec-helpers'; -import { CMD_TS_NODE_WITHOUT_PROJECT_FLAG, ctxTsNode, TEST_DIR } from './helpers'; -import { context } from './testlib'; +import type { CreateOptions } from '..'; +import { createExec, createExecTester } from './helpers/exec'; +import { CMD_TS_NODE_WITHOUT_PROJECT_FLAG, ctxTsNode, DIST_DIR, TEST_DIR, tsSupportsMtsCtsExtensions } from './helpers'; +import { context, ExecutionContext, expect } from './testlib'; const test = context(ctxTsNode); const exec = createExecTester({ @@ -35,3 +36,64 @@ test('#1488 regression test', async () => { exp(r.stdout).toBe('foo\n'); // prove that it ran exp(r.stderr).toBe(''); // prove that no warnings }); + +test.suite('issue #1098', (test) => { + function testAllowedExtensions( + t: ExecutionContext, + compilerOptions: CreateOptions['compilerOptions'], + allowed: string[] + ) { + const disallowed = allExtensions.filter((ext) => !allowed.includes(ext)); + const { ignored } = t.context.tsNodeUnderTest.create({ + compilerOptions, + skipProject: true, + }); + for (const ext of allowed) { + t.log(`Testing that ${ext} files are allowed`); + expect(ignored(join(DIST_DIR, `index${ext}`))).toBe(false); + } + for (const ext of disallowed) { + t.log(`Testing that ${ext} files are ignored`); + expect(ignored(join(DIST_DIR, `index${ext}`))).toBe(true); + } + } + + const allExtensions = [ + '.ts', + '.js', + '.d.ts', + '.mts', + '.cts', + '.d.mts', + '.d.cts', + '.mjs', + '.cjs', + '.tsx', + '.jsx', + '.xyz', + '', + ]; + const mtsCts = tsSupportsMtsCtsExtensions ? ['.mts', '.cts', '.d.mts', '.d.cts'] : []; + const mjsCjs = tsSupportsMtsCtsExtensions ? ['.mjs', '.cjs'] : []; + + test('correctly filters file extensions from the compiler when allowJs=false and jsx=false', (t) => { + testAllowedExtensions(t, {}, ['.ts', '.d.ts', ...mtsCts]); + }); + test('correctly filters file extensions from the compiler when allowJs=true and jsx=false', (t) => { + testAllowedExtensions(t, { allowJs: true }, ['.ts', '.js', '.d.ts', ...mtsCts, ...mjsCjs]); + }); + test('correctly filters file extensions from the compiler when allowJs=false and jsx=true', (t) => { + testAllowedExtensions(t, { allowJs: false, jsx: 'preserve' }, ['.ts', '.tsx', '.d.ts', ...mtsCts]); + }); + test('correctly filters file extensions from the compiler when allowJs=true and jsx=true', (t) => { + testAllowedExtensions(t, { allowJs: true, jsx: 'preserve' }, [ + '.ts', + '.tsx', + '.js', + '.jsx', + '.d.ts', + ...mtsCts, + ...mjsCjs, + ]); + }); +}); diff --git a/src/test/reminders.spec.ts b/src/test/reminders.spec.ts new file mode 100644 index 000000000..1d94dac18 --- /dev/null +++ b/src/test/reminders.spec.ts @@ -0,0 +1,43 @@ +// Reminders about chores to stay up-to-date with the ecosystem + +import { ts, tsSupportsStableNodeNextNode16 } from './helpers'; +import { expect, test } from './testlib'; + +test('Detect when typescript adds new ModuleKind values; flag as a failure so we can update our code flagged [MUST_UPDATE_FOR_NEW_MODULEKIND]', async () => { + // We have marked a few places in our code with MUST_UPDATE_FOR_NEW_MODULEKIND to make it easier to update them when TS adds new ModuleKinds + const foundKeys: string[] = []; + function check(value: number, name: string, required: boolean) { + if (required) expect(ts.ModuleKind[name as any]).toBe(value); + if (ts.ModuleKind[value] === undefined) { + expect(ts.ModuleKind[name as any]).toBeUndefined(); + } else { + expect(ts.ModuleKind[value]).toBe(name); + foundKeys.push(name, `${value}`); + } + } + check(0, 'None', true); + check(1, 'CommonJS', true); + check(2, 'AMD', true); + check(3, 'UMD', true); + check(4, 'System', true); + check(5, 'ES2015', true); + try { + check(6, 'ES2020', false); + check(99, 'ESNext', true); + } catch { + // the value changed: is `99` now, but was `6` in TS 2.7 + check(6, 'ESNext', true); + expect(ts.ModuleKind[99]).toBeUndefined(); + } + check(7, 'ES2022', false); + if (tsSupportsStableNodeNextNode16) { + check(100, 'Node16', true); + } else { + check(100, 'Node12', false); + } + check(199, 'NodeNext', false); + const actualKeys = Object.keys(ts.ModuleKind); + actualKeys.sort(); + foundKeys.sort(); + expect(actualKeys).toEqual(foundKeys); +}); diff --git a/src/test/repl/repl-environment.spec.ts b/src/test/repl/repl-environment.spec.ts index 10ab4f102..0d8f2470b 100644 --- a/src/test/repl/repl-environment.spec.ts +++ b/src/test/repl/repl-environment.spec.ts @@ -7,7 +7,7 @@ import { context, expect } from '../testlib'; import { expectStream } from '@cspotcode/expect-stream'; import { CMD_TS_NODE_WITH_PROJECT_FLAG, ctxTsNode, delay, TEST_DIR } from '../helpers'; import { dirname, join } from 'path'; -import { createExec, createExecTester } from '../exec-helpers'; +import { createExec, createExecTester } from '../helpers/exec'; import { homedir } from 'os'; import { replFile } from './helpers/misc'; import { ctxRepl } from './helpers/ctx-repl'; diff --git a/src/test/repl/repl.spec.ts b/src/test/repl/repl.spec.ts index 5570ba521..99612ac40 100644 --- a/src/test/repl/repl.spec.ts +++ b/src/test/repl/repl.spec.ts @@ -8,7 +8,7 @@ import { } from '../helpers'; import semver = require('semver'); import { CMD_TS_NODE_WITH_PROJECT_FLAG, ctxTsNode, TEST_DIR } from '../helpers'; -import { createExec, createExecTester } from '../exec-helpers'; +import { createExec, createExecTester } from '../helpers/exec'; import { upstreamTopLevelAwaitTests } from './node-repl-tla'; import { replFile } from './helpers/misc'; import { expectStream } from '@cspotcode/expect-stream'; diff --git a/src/test/sourcemaps.spec.ts b/src/test/sourcemaps.spec.ts index 136872b5e..4aae34757 100644 --- a/src/test/sourcemaps.spec.ts +++ b/src/test/sourcemaps.spec.ts @@ -1,6 +1,5 @@ import * as expect from 'expect'; -import { createExec, createExecTester } from './exec-helpers'; -import { CMD_TS_NODE_WITH_PROJECT_FLAG, ctxTsNode, TEST_DIR } from './helpers'; +import { createExec, createExecTester, CMD_TS_NODE_WITH_PROJECT_FLAG, ctxTsNode, TEST_DIR } from './helpers'; import { context } from './testlib'; const test = context(ctxTsNode); diff --git a/src/test/transpile-only.spec.ts b/src/test/transpile-only.spec.ts index 5518f083b..7e99272b6 100644 --- a/src/test/transpile-only.spec.ts +++ b/src/test/transpile-only.spec.ts @@ -1,4 +1,4 @@ -import { createExec } from './exec-helpers'; +import { createExec } from './helpers/exec'; import { ctxTsNode, tsSupportsVerbatimModuleSyntax } from './helpers'; import { CMD_TS_NODE_WITH_PROJECT_FLAG } from './helpers/command-lines'; import { TEST_DIR } from './helpers/paths'; diff --git a/src/test/ts-import-specifiers.spec.ts b/src/test/ts-import-specifiers.spec.ts index 8716e8779..87acb55fc 100644 --- a/src/test/ts-import-specifiers.spec.ts +++ b/src/test/ts-import-specifiers.spec.ts @@ -1,6 +1,6 @@ import { context } from './testlib'; import * as expect from 'expect'; -import { createExec } from './exec-helpers'; +import { createExec } from './helpers/exec'; import { TEST_DIR, ctxTsNode, CMD_TS_NODE_WITHOUT_PROJECT_FLAG, tsSupportsAllowImportingTsExtensions } from './helpers'; import { project as fsProject } from '@TypeStrong/fs-fixture-builder'; import { outdent as o } from 'outdent'; diff --git a/src/test/tsconfig-bases.spec.ts b/src/test/tsconfig-bases.spec.ts index 8744619c8..29b4edc67 100644 --- a/src/test/tsconfig-bases.spec.ts +++ b/src/test/tsconfig-bases.spec.ts @@ -1,5 +1,5 @@ import { join } from 'path'; -import { createExec } from './exec-helpers'; +import { createExec } from './helpers/exec'; import { ctxTmpDirOutsideCheckout } from './helpers/ctx-tmp-dir'; import { ctxTsNode } from './helpers/ctx-ts-node'; import { BIN_PATH, TEST_DIR } from './helpers/paths';