diff --git a/.github/workflows/continuous-integration.yml b/.github/workflows/continuous-integration.yml index fba007e2d..dc4f034ab 100644 --- a/.github/workflows/continuous-integration.yml +++ b/.github/workflows/continuous-integration.yml @@ -173,6 +173,7 @@ jobs: - run: | npm config set cache "$( node -p "process.cwd()" )/temp/npm-cache" - name: Cache dependencies + if: ${{ matrix.os != 'windows' }} uses: actions/cache@v2 with: path: temp/npm-cache diff --git a/src/test/helpers.ts b/src/test/helpers.ts index 2750528d6..39e9f3e9f 100644 --- a/src/test/helpers.ts +++ b/src/test/helpers.ts @@ -22,6 +22,10 @@ export const ROOT_DIR = resolve(__dirname, '../..'); export const DIST_DIR = resolve(__dirname, '..'); export const TEST_DIR = join(__dirname, '../../tests'); export const PROJECT = join(TEST_DIR, 'tsconfig.json'); +export const PROJECT_TRANSPILE_ONLY = join( + TEST_DIR, + 'tsconfig-transpile-only.json' +); export const BIN_PATH = join(TEST_DIR, 'node_modules/.bin/ts-node'); export const BIN_PATH_JS = join(TEST_DIR, 'node_modules/ts-node/dist/bin.js'); export const BIN_SCRIPT_PATH = join( @@ -35,6 +39,8 @@ export const BIN_ESM_PATH = join(TEST_DIR, 'node_modules/.bin/ts-node-esm'); //#region command lines /** Default `ts-node --project` invocation */ export const CMD_TS_NODE_WITH_PROJECT_FLAG = `"${BIN_PATH}" --project "${PROJECT}"`; +/** Default `ts-node --project` invocation with transpile-only */ +export const CMD_TS_NODE_WITH_PROJECT_TRANSPILE_ONLY_FLAG = `"${BIN_PATH}" --project "${PROJECT_TRANSPILE_ONLY}"`; /** Default `ts-node` invocation without `--project` */ export const CMD_TS_NODE_WITHOUT_PROJECT_FLAG = `"${BIN_PATH}"`; export const EXPERIMENTAL_MODULES_FLAG = semver.gte(process.version, '12.17.0') diff --git a/src/test/index.spec.ts b/src/test/index.spec.ts index 72faf86ea..ca5e957ae 100644 --- a/src/test/index.spec.ts +++ b/src/test/index.spec.ts @@ -5,6 +5,7 @@ import { tmpdir } from 'os'; import semver = require('semver'); import { BIN_PATH_JS, + CMD_TS_NODE_WITH_PROJECT_TRANSPILE_ONLY_FLAG, nodeSupportsEsmHooks, ts, tsSupportsShowConfig, @@ -143,7 +144,10 @@ test.suite('ts-node', (test) => { test('should execute cli with absolute path', async () => { const { err, stdout } = await exec( - `${CMD_TS_NODE_WITH_PROJECT_FLAG} "${join(TEST_DIR, 'hello-world')}"` + `${CMD_TS_NODE_WITH_PROJECT_TRANSPILE_ONLY_FLAG} "${join( + TEST_DIR, + 'hello-world' + )}"` ); expect(err).toBe(null); expect(stdout).toBe('Hello, world!\n'); @@ -157,26 +161,18 @@ test.suite('ts-node', (test) => { expect(stdout).toBe('example\n'); }); - test('should provide registered information globally', async () => { + test("should expose ts-node Service as a symbol property on Node's `process` object", async () => { const { err, stdout } = await exec( - `${CMD_TS_NODE_WITH_PROJECT_FLAG} env` + `${CMD_TS_NODE_WITH_PROJECT_TRANSPILE_ONLY_FLAG} env` ); expect(err).toBe(null); expect(stdout).toBe('object\n'); }); - test('should provide registered information on register', async () => { - const { err, stdout } = await exec(`node -r ts-node/register env.ts`, { - cwd: TEST_DIR, - }); - expect(err).toBe(null); - expect(stdout).toBe('object\n'); - }); - test('should allow js', async () => { const { err, stdout } = await exec( [ - CMD_TS_NODE_WITH_PROJECT_FLAG, + CMD_TS_NODE_WITH_PROJECT_TRANSPILE_ONLY_FLAG, '-O "{\\"allowJs\\":true}"', '-pe "import { main } from \'./allow-js/run\';main()"', ].join(' ') @@ -188,7 +184,7 @@ test.suite('ts-node', (test) => { test('should include jsx when `allow-js` true', async () => { const { err, stdout } = await exec( [ - CMD_TS_NODE_WITH_PROJECT_FLAG, + CMD_TS_NODE_WITH_PROJECT_TRANSPILE_ONLY_FLAG, '-O "{\\"allowJs\\":true}"', '-pe "import { Foo2 } from \'./allow-js/with-jsx\'; Foo2.sayHi()"', ].join(' ') @@ -199,7 +195,7 @@ test.suite('ts-node', (test) => { test('should eval code', async () => { const { err, stdout } = await exec( - `${CMD_TS_NODE_WITH_PROJECT_FLAG} -e "import * as m from './module';console.log(m.example('test'))"` + `${CMD_TS_NODE_WITH_PROJECT_TRANSPILE_ONLY_FLAG} -e "import * as m from './module';console.log(m.example('test'))"` ); expect(err).toBe(null); expect(stdout).toBe('TEST\n'); @@ -207,13 +203,13 @@ test.suite('ts-node', (test) => { test('should import empty files', async () => { const { err, stdout } = await exec( - `${CMD_TS_NODE_WITH_PROJECT_FLAG} -e "import './empty'"` + `${CMD_TS_NODE_WITH_PROJECT_TRANSPILE_ONLY_FLAG} -e "import './empty'"` ); expect(err).toBe(null); expect(stdout).toBe(''); }); - test('should throw errors', async () => { + test('should throw typechecking errors', async () => { const { err } = await exec( `${CMD_TS_NODE_WITH_PROJECT_FLAG} -e "import * as m from './module';console.log(m.example(123))"` ); @@ -377,7 +373,7 @@ test.suite('ts-node', (test) => { } test('should pipe into `ts-node` and evaluate', async () => { - const execPromise = exec(CMD_TS_NODE_WITH_PROJECT_FLAG); + const execPromise = exec(CMD_TS_NODE_WITH_PROJECT_TRANSPILE_ONLY_FLAG); execPromise.child.stdin!.end("console.log('hello')"); const { err, stdout } = await execPromise; expect(err).toBe(null); @@ -385,7 +381,9 @@ test.suite('ts-node', (test) => { }); test('should pipe into `ts-node`', async () => { - const execPromise = exec(`${CMD_TS_NODE_WITH_PROJECT_FLAG} -p`); + const execPromise = exec( + `${CMD_TS_NODE_WITH_PROJECT_TRANSPILE_ONLY_FLAG} -p` + ); execPromise.child.stdin!.end('true'); const { err, stdout } = await execPromise; expect(err).toBe(null); @@ -404,7 +402,7 @@ test.suite('ts-node', (test) => { test('should support require flags', async () => { const { err, stdout } = await exec( - `${CMD_TS_NODE_WITH_PROJECT_FLAG} -r ./hello-world -pe "console.log('success')"` + `${CMD_TS_NODE_WITH_PROJECT_TRANSPILE_ONLY_FLAG} -r ./hello-world -pe "console.log('success')"` ); expect(err).toBe(null); expect(stdout).toBe('Hello, world!\nsuccess\nundefined\n'); @@ -412,7 +410,7 @@ test.suite('ts-node', (test) => { test('should support require from node modules', async () => { const { err, stdout } = await exec( - `${CMD_TS_NODE_WITH_PROJECT_FLAG} -r typescript -e "console.log('success')"` + `${CMD_TS_NODE_WITH_PROJECT_TRANSPILE_ONLY_FLAG} -r typescript -e "console.log('success')"` ); expect(err).toBe(null); expect(stdout).toBe('success\n'); @@ -458,28 +456,17 @@ test.suite('ts-node', (test) => { ); }); - test('should preserve `ts-node` context with child process', async () => { - const { err, stdout } = await exec( - `${CMD_TS_NODE_WITH_PROJECT_FLAG} child-process` - ); - expect(err).toBe(null); - expect(stdout).toBe('Hello, world!\n'); - }); - test('should import js before ts by default', async () => { const { err, stdout } = await exec( - `${CMD_TS_NODE_WITH_PROJECT_FLAG} import-order/compiled` + `${CMD_TS_NODE_WITH_PROJECT_TRANSPILE_ONLY_FLAG} import-order/compiled` ); expect(err).toBe(null); expect(stdout).toBe('Hello, JavaScript!\n'); }); - const preferTsExtsEntrypoint = semver.gte(process.version, '12.0.0') - ? 'import-order/compiled' - : 'import-order/require-compiled'; test('should import ts before js when --prefer-ts-exts flag is present', async () => { const { err, stdout } = await exec( - `${CMD_TS_NODE_WITH_PROJECT_FLAG} --prefer-ts-exts ${preferTsExtsEntrypoint}` + `${CMD_TS_NODE_WITH_PROJECT_TRANSPILE_ONLY_FLAG} --prefer-ts-exts import-order/compiled` ); expect(err).toBe(null); expect(stdout).toBe('Hello, TypeScript!\n'); @@ -487,7 +474,7 @@ test.suite('ts-node', (test) => { test('should import ts before js when TS_NODE_PREFER_TS_EXTS env is present', async () => { const { err, stdout } = await exec( - `${CMD_TS_NODE_WITH_PROJECT_FLAG} ${preferTsExtsEntrypoint}`, + `${CMD_TS_NODE_WITH_PROJECT_TRANSPILE_ONLY_FLAG} import-order/compiled`, { env: { ...process.env, TS_NODE_PREFER_TS_EXTS: 'true' }, } @@ -498,7 +485,7 @@ test.suite('ts-node', (test) => { test('should ignore .d.ts files', async () => { const { err, stdout } = await exec( - `${CMD_TS_NODE_WITH_PROJECT_FLAG} import-order/importer` + `${CMD_TS_NODE_WITH_PROJECT_TRANSPILE_ONLY_FLAG} import-order/importer` ); expect(err).toBe(null); expect(stdout).toBe('Hello, World!\n'); @@ -538,63 +525,60 @@ test.suite('ts-node', (test) => { }); }); - if (semver.gte(ts.version, '2.7.0')) { - test('should locate tsconfig relative to entry-point by default', async () => { - const { err, stdout } = await exec(`${BIN_PATH} ../a/index`, { - cwd: join(TEST_DIR, 'cwd-and-script-mode/b'), - }); - expect(err).toBe(null); - expect(stdout).toMatch(/plugin-a/); + test('should locate tsconfig relative to entry-point by default', async () => { + const { err, stdout } = await exec(`${BIN_PATH} ../a/index`, { + cwd: join(TEST_DIR, 'cwd-and-script-mode/b'), }); - test('should locate tsconfig relative to entry-point via ts-node-script', async () => { - const { err, stdout } = await exec(`${BIN_SCRIPT_PATH} ../a/index`, { - cwd: join(TEST_DIR, 'cwd-and-script-mode/b'), - }); - expect(err).toBe(null); - expect(stdout).toMatch(/plugin-a/); - }); - test('should locate tsconfig relative to entry-point with --script-mode', async () => { - const { err, stdout } = await exec( - `${BIN_PATH} --script-mode ../a/index`, - { - cwd: join(TEST_DIR, 'cwd-and-script-mode/b'), - } - ); - expect(err).toBe(null); - expect(stdout).toMatch(/plugin-a/); + expect(err).toBe(null); + expect(stdout).toMatch(/plugin-a/); + }); + test('should locate tsconfig relative to entry-point via ts-node-script', async () => { + const { err, stdout } = await exec(`${BIN_SCRIPT_PATH} ../a/index`, { + cwd: join(TEST_DIR, 'cwd-and-script-mode/b'), }); - test('should locate tsconfig relative to cwd via ts-node-cwd', async () => { - const { err, stdout } = await exec(`${BIN_CWD_PATH} ../a/index`, { + expect(err).toBe(null); + expect(stdout).toMatch(/plugin-a/); + }); + test('should locate tsconfig relative to entry-point with --script-mode', async () => { + const { err, stdout } = await exec( + `${BIN_PATH} --script-mode ../a/index`, + { cwd: join(TEST_DIR, 'cwd-and-script-mode/b'), - }); - expect(err).toBe(null); - expect(stdout).toMatch(/plugin-b/); + } + ); + expect(err).toBe(null); + expect(stdout).toMatch(/plugin-a/); + }); + test('should locate tsconfig relative to cwd via ts-node-cwd', async () => { + const { err, stdout } = await exec(`${BIN_CWD_PATH} ../a/index`, { + cwd: join(TEST_DIR, 'cwd-and-script-mode/b'), }); - test('should locate tsconfig relative to cwd in --cwd-mode', async () => { + expect(err).toBe(null); + expect(stdout).toMatch(/plugin-b/); + }); + test('should locate tsconfig relative to cwd in --cwd-mode', async () => { + const { err, stdout } = await exec(`${BIN_PATH} --cwd-mode ../a/index`, { + cwd: join(TEST_DIR, 'cwd-and-script-mode/b'), + }); + expect(err).toBe(null); + expect(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 { err, stdout } = await exec( - `${BIN_PATH} --cwd-mode ../a/index`, - { cwd: join(TEST_DIR, 'cwd-and-script-mode/b') } + `${BIN_PATH} main-realpath/symlink/symlink.tsx` ); expect(err).toBe(null); - expect(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 { err, stdout } = await exec( - `${BIN_PATH} main-realpath/symlink/symlink.tsx` - ); - expect(err).toBe(null); - expect(stdout).toBe(''); - } else { - t.log('Skipping'); - return; - } - }); - } + expect(stdout).toBe(''); + } else { + t.log('Skipping'); + return; + } + }); test.suite('should read ts-node options from tsconfig.json', (test) => { const BIN_EXEC = `"${BIN_PATH}" --project tsconfig-options/tsconfig.json`; diff --git a/src/test/register.spec.ts b/src/test/register.spec.ts index 97769283c..f81809b29 100644 --- a/src/test/register.spec.ts +++ b/src/test/register.spec.ts @@ -1,7 +1,7 @@ import { once } from 'lodash'; import { contextTsNodeUnderTest, - PROJECT, + PROJECT_TRANSPILE_ONLY, resetNodeEnvironment, TEST_DIR, tsNodeTypes, @@ -16,7 +16,7 @@ const SOURCE_MAP_REGEXP = /\/\/# sourceMappingURL=data:application\/json;charset=utf\-8;base64,[\w\+]+=*$/; const createOptions: tsNodeTypes.CreateOptions = { - project: PROJECT, + project: PROJECT_TRANSPILE_ONLY, compilerOptions: { jsx: 'preserve', }, diff --git a/tests/cwd-and-script-mode/a/tsconfig.json b/tests/cwd-and-script-mode/a/tsconfig.json index 196e2b444..377a86016 100644 --- a/tests/cwd-and-script-mode/a/tsconfig.json +++ b/tests/cwd-and-script-mode/a/tsconfig.json @@ -1,4 +1,7 @@ { + "ts-node": { + "transpileOnly": true + }, "compilerOptions": { "plugins": [ { diff --git a/tests/cwd-and-script-mode/b/tsconfig.json b/tests/cwd-and-script-mode/b/tsconfig.json index 3b22d468d..dd98865c1 100644 --- a/tests/cwd-and-script-mode/b/tsconfig.json +++ b/tests/cwd-and-script-mode/b/tsconfig.json @@ -1,4 +1,7 @@ { + "ts-node": { + "transpileOnly": true + }, "compilerOptions": { "plugins": [ { diff --git a/tests/esm-import-assertions/tsconfig.json b/tests/esm-import-assertions/tsconfig.json index d626b9278..731778e97 100644 --- a/tests/esm-import-assertions/tsconfig.json +++ b/tests/esm-import-assertions/tsconfig.json @@ -1,4 +1,7 @@ { + "ts-node": { + "transpileOnly": true + }, "compilerOptions": { "module": "ESNext", "target": "ESNext", diff --git a/tests/import-order/require-compiled.js b/tests/import-order/require-compiled.js deleted file mode 100644 index b73d5a376..000000000 --- a/tests/import-order/require-compiled.js +++ /dev/null @@ -1,2 +0,0 @@ -// indirectly load ./compiled in node < 12 (soon to be end-of-life'd) -require('./compiled'); diff --git a/tests/main-realpath/target/tsconfig.json b/tests/main-realpath/target/tsconfig.json index 986627de2..93d434ff5 100644 --- a/tests/main-realpath/target/tsconfig.json +++ b/tests/main-realpath/target/tsconfig.json @@ -1,4 +1,7 @@ { + "ts-node": { + "transpileOnly": true + }, "compilerOptions": { "jsx": "react" } diff --git a/tests/recursive-fork/index.ts b/tests/recursive-fork/index.ts index ed68a2080..b426d29bd 100644 --- a/tests/recursive-fork/index.ts +++ b/tests/recursive-fork/index.ts @@ -1,5 +1,9 @@ import { fork } from 'child_process'; +// Type syntax to prove its compiled, though the import above should also +// prove the same +const a = null as any; + console.log(JSON.stringify({ execArgv: process.execArgv, argv: process.argv })); if (process.env.generation !== 'grandchild') { const nextGeneration = diff --git a/tests/tsconfig-transpile-only.json b/tests/tsconfig-transpile-only.json new file mode 100644 index 000000000..1a80ab281 --- /dev/null +++ b/tests/tsconfig-transpile-only.json @@ -0,0 +1,13 @@ +{ + "ts-node": { + "transpileOnly": true + }, + "compilerOptions": { + "target": "es2015", + "jsx": "react", + "noEmit": true, + "strict": true, + // Global type definitions. + "typeRoots": ["./typings", "../node_modules/@types"] + } +}