node/test/es-module/test-typescript.mjs
Antoine du Hamel f98d9c125c
process: fix process.features.typescript when Amaro is unavailable
PR-URL: https://github.com/nodejs/node/pull/55323
Reviewed-By: Marco Ippolito <marcoippolito54@gmail.com>
Reviewed-By: Richard Lau <rlau@redhat.com>
2024-10-11 11:27:16 +00:00

417 lines
14 KiB
JavaScript

import { skip, spawnPromisified, isWindows } from '../common/index.mjs';
import * as fixtures from '../common/fixtures.mjs';
import { match, strictEqual } from 'node:assert';
import { test } from 'node:test';
test('expect process.features.typescript to be \'strip\' when --experimental-strip-types', async () => {
const result = await spawnPromisified(process.execPath, [
'--no-warnings',
'--experimental-strip-types',
fixtures.path('typescript/echo-process-features-typescript.cjs'),
]);
strictEqual(result.stderr, '');
strictEqual(result.stdout, process.config.variables.node_use_amaro ? 'strip\n' : 'false\n');
strictEqual(result.code, 0);
});
test('expect process.features.typescript to be \'transform\' when --experimental-transform-types', async () => {
const result = await spawnPromisified(process.execPath, [
'--no-warnings',
'--experimental-transform-types',
fixtures.path('typescript/echo-process-features-typescript.cjs'),
]);
strictEqual(result.stderr, '');
strictEqual(result.stdout, process.config.variables.node_use_amaro ? 'transform\n' : 'false\n');
strictEqual(result.code, 0);
});
if (!process.config.variables.node_use_amaro) skip('Requires Amaro');
test('execute a TypeScript file', async () => {
const result = await spawnPromisified(process.execPath, [
'--experimental-strip-types',
fixtures.path('typescript/ts/test-typescript.ts'),
]);
match(result.stderr, /Type Stripping is an experimental feature and might change at any time/);
match(result.stdout, /Hello, TypeScript!/);
strictEqual(result.code, 0);
});
test('execute a TypeScript file with imports', async () => {
const result = await spawnPromisified(process.execPath, [
'--experimental-strip-types',
'--no-warnings',
fixtures.path('typescript/ts/test-import-foo.ts'),
]);
strictEqual(result.stderr, '');
match(result.stdout, /Hello, TypeScript!/);
strictEqual(result.code, 0);
});
test('execute a TypeScript file with imports', async () => {
const result = await spawnPromisified(process.execPath, [
'--no-warnings',
'--eval',
`require(${JSON.stringify(fixtures.path('typescript/ts/test-import-fs.ts'))})`,
]);
strictEqual(result.stderr, '');
match(result.stdout, /Hello, TypeScript!/);
strictEqual(result.code, 0);
});
test('execute a TypeScript file with imports with default-type module', async () => {
const result = await spawnPromisified(process.execPath, [
'--experimental-strip-types',
'--experimental-default-type=module',
'--no-warnings',
fixtures.path('typescript/ts/test-import-foo.ts'),
]);
strictEqual(result.stderr, '');
match(result.stdout, /Hello, TypeScript!/);
strictEqual(result.code, 0);
});
test('execute a TypeScript file with node_modules', async () => {
const result = await spawnPromisified(process.execPath, [
'--experimental-strip-types',
'--no-warnings',
fixtures.path('typescript/ts/test-typescript-node-modules.ts'),
]);
strictEqual(result.stderr, '');
match(result.stdout, /Hello, TypeScript!/);
strictEqual(result.code, 0);
});
test('execute a TypeScript file with node_modules with default-type module', async () => {
const result = await spawnPromisified(process.execPath, [
'--experimental-strip-types',
'--experimental-default-type=module',
'--no-warnings',
fixtures.path('typescript/ts/test-typescript-node-modules.ts'),
]);
strictEqual(result.stderr, '');
match(result.stdout, /Hello, TypeScript!/);
strictEqual(result.code, 0);
});
test('expect error when executing a TypeScript file with imports with no extensions', async () => {
const result = await spawnPromisified(process.execPath, [
'--experimental-strip-types',
fixtures.path('typescript/ts/test-import-no-extension.ts'),
]);
match(result.stderr, /Error \[ERR_MODULE_NOT_FOUND\]:/);
strictEqual(result.stdout, '');
strictEqual(result.code, 1);
});
test('expect error when executing a TypeScript file with imports with no extensions with default-type module',
async () => {
const result = await spawnPromisified(process.execPath, [
'--experimental-strip-types',
'--experimental-default-type=module',
fixtures.path('typescript/ts/test-import-no-extension.ts'),
]);
match(result.stderr, /Error \[ERR_MODULE_NOT_FOUND\]:/);
strictEqual(result.stdout, '');
strictEqual(result.code, 1);
});
test('expect error when executing a TypeScript file with enum', async () => {
const result = await spawnPromisified(process.execPath, [
'--experimental-strip-types',
fixtures.path('typescript/ts/test-enums.ts'),
]);
// This error should be thrown during transformation
match(result.stderr, /TypeScript enum is not supported in strip-only mode/);
strictEqual(result.stdout, '');
strictEqual(result.code, 1);
});
test('expect error when executing a TypeScript file with experimental decorators', async () => {
const result = await spawnPromisified(process.execPath, [
'--experimental-strip-types',
fixtures.path('typescript/ts/test-experimental-decorators.ts'),
]);
// This error should be thrown at runtime
match(result.stderr, /Invalid or unexpected token/);
strictEqual(result.stdout, '');
strictEqual(result.code, 1);
});
test('expect error when executing a TypeScript file with namespaces', async () => {
const result = await spawnPromisified(process.execPath, [
'--experimental-strip-types',
fixtures.path('typescript/ts/test-namespaces.ts'),
]);
// This error should be thrown during transformation
match(result.stderr, /TypeScript namespace declaration is not supported in strip-only mode/);
strictEqual(result.stdout, '');
strictEqual(result.code, 1);
});
test('execute a TypeScript file with type definition', async () => {
const result = await spawnPromisified(process.execPath, [
'--experimental-strip-types',
'--no-warnings',
fixtures.path('typescript/ts/test-import-types.ts'),
]);
strictEqual(result.stderr, '');
match(result.stdout, /Hello, TypeScript!/);
strictEqual(result.code, 0);
});
test('execute a TypeScript file with type definition but no type keyword', async () => {
const result = await spawnPromisified(process.execPath, [
'--experimental-strip-types',
fixtures.path('typescript/ts/test-import-no-type-keyword.ts'),
]);
match(result.stderr, /does not provide an export named 'MyType'/);
strictEqual(result.stdout, '');
strictEqual(result.code, 1);
});
test('execute a TypeScript file with type definition but no type keyword with default-type modue', async () => {
const result = await spawnPromisified(process.execPath, [
'--experimental-strip-types',
'--experimental-default-type=module',
fixtures.path('typescript/ts/test-import-no-type-keyword.ts'),
]);
match(result.stderr, /does not provide an export named 'MyType'/);
strictEqual(result.stdout, '');
strictEqual(result.code, 1);
});
test('execute a TypeScript file with CommonJS syntax', async () => {
const result = await spawnPromisified(process.execPath, [
'--experimental-strip-types',
'--no-warnings',
fixtures.path('typescript/ts/test-commonjs-parsing.ts'),
]);
strictEqual(result.stderr, '');
match(result.stdout, /Hello, TypeScript!/);
strictEqual(result.code, 0);
});
test('execute a TypeScript file with ES module syntax', async () => {
const result = await spawnPromisified(process.execPath, [
'--experimental-strip-types',
'--no-warnings',
fixtures.path('typescript/ts/test-module-typescript.ts'),
]);
strictEqual(result.stderr, '');
match(result.stdout, /Hello, TypeScript!/);
strictEqual(result.code, 0);
});
test('execute a TypeScript file with ES module syntax with default-type module', async () => {
const result = await spawnPromisified(process.execPath, [
'--experimental-strip-types',
'--experimental-default-type=module',
'--no-warnings',
fixtures.path('typescript/ts/test-module-typescript.ts'),
]);
strictEqual(result.stderr, '');
match(result.stdout, /Hello, TypeScript!/);
strictEqual(result.code, 0);
});
test('expect failure of a TypeScript file requiring ES module syntax', async () => {
const result = await spawnPromisified(process.execPath, [
'--experimental-strip-types',
'--experimental-require-module',
fixtures.path('typescript/ts/test-require-module.ts'),
]);
match(result.stderr, /Support for loading ES Module in require\(\) is an experimental feature and might change at any time/);
match(result.stdout, /Hello, TypeScript!/);
strictEqual(result.code, 0);
});
test('expect stack trace of a TypeScript file to be correct', async () => {
const result = await spawnPromisified(process.execPath, [
'--experimental-strip-types',
fixtures.path('typescript/ts/test-whitespacing.ts'),
]);
strictEqual(result.stdout, '');
match(result.stderr, /test-whitespacing\.ts:5:7/);
strictEqual(result.code, 1);
});
test('execute CommonJS TypeScript file from node_modules with require-module', async () => {
const result = await spawnPromisified(process.execPath, [
'--experimental-strip-types',
fixtures.path('typescript/ts/test-import-ts-node-modules.ts'),
]);
match(result.stderr, /ERR_UNSUPPORTED_NODE_MODULES_TYPE_STRIPPING/);
strictEqual(result.stdout, '');
strictEqual(result.code, 1);
});
test('execute CommonJS TypeScript file from node_modules with require-module and default-type module',
async () => {
const result = await spawnPromisified(process.execPath, [
'--experimental-strip-types',
'--experimental-default-type=module',
fixtures.path('typescript/ts/test-import-ts-node-modules.ts'),
]);
match(result.stderr, /ERR_UNSUPPORTED_NODE_MODULES_TYPE_STRIPPING/);
strictEqual(result.stdout, '');
strictEqual(result.code, 1);
});
test('execute a TypeScript file with CommonJS syntax but default type module', async () => {
const result = await spawnPromisified(process.execPath, [
'--experimental-strip-types',
'--experimental-default-type=module',
fixtures.path('typescript/ts/test-commonjs-parsing.ts'),
]);
strictEqual(result.stdout, '');
match(result.stderr, /require is not defined in ES module scope, you can use import instead/);
strictEqual(result.code, 1);
});
test('execute a TypeScript file with CommonJS syntax requiring .cts', async () => {
const result = await spawnPromisified(process.execPath, [
'--experimental-strip-types',
'--no-warnings',
fixtures.path('typescript/ts/test-require-cts.ts'),
]);
strictEqual(result.stderr, '');
match(result.stdout, /Hello, TypeScript!/);
strictEqual(result.code, 0);
});
test('execute a TypeScript file with CommonJS syntax requiring .mts', async () => {
const result = await spawnPromisified(process.execPath, [
'--experimental-strip-types',
fixtures.path('typescript/ts/test-require-mts.ts'),
]);
match(result.stdout, /Hello, TypeScript!/);
strictEqual(result.code, 0);
});
test('execute a TypeScript file with CommonJS syntax requiring .mts using require-module', async () => {
const result = await spawnPromisified(process.execPath, [
'--experimental-strip-types',
'--experimental-require-module',
fixtures.path('typescript/ts/test-require-mts.ts'),
]);
match(result.stderr, /Support for loading ES Module in require\(\) is an experimental feature and might change at any time/);
match(result.stdout, /Hello, TypeScript!/);
strictEqual(result.code, 0);
});
test('execute a TypeScript file with CommonJS syntax requiring .cts using commonjs', async () => {
const result = await spawnPromisified(process.execPath, [
'--experimental-strip-types',
'--no-warnings',
fixtures.path('typescript/ts/test-require-cts.ts'),
]);
strictEqual(result.stderr, '');
match(result.stdout, /Hello, TypeScript!/);
strictEqual(result.code, 0);
});
test('execute a TypeScript file with CommonJS syntax requiring .mts with require-module with default-type commonjs',
async () => {
const result = await spawnPromisified(process.execPath, [
'--experimental-strip-types',
'--experimental-default-type=commonjs',
'--no-warnings',
fixtures.path('typescript/ts/test-require-cts.ts'),
]);
strictEqual(result.stderr, '');
match(result.stdout, /Hello, TypeScript!/);
strictEqual(result.code, 0);
});
test('execute a JavaScript file importing a cjs TypeScript file', async () => {
const result = await spawnPromisified(process.execPath, [
'--experimental-strip-types',
'--no-warnings',
fixtures.path('typescript/ts/issue-54457.mjs'),
]);
strictEqual(result.stderr, '');
match(result.stdout, /Hello, TypeScript!/);
strictEqual(result.code, 0);
});
// TODO(marco-ippolito) Due to a bug in SWC, the TypeScript loader
// does not work on Windows arm64. This test should be re-enabled
// when https://github.com/nodejs/node/issues/54645 is fixed
test('execute a TypeScript test mocking module', { skip: isWindows && process.arch === 'arm64' }, async () => {
const result = await spawnPromisified(process.execPath, [
'--test',
'--experimental-test-module-mocks',
'--experimental-strip-types',
'--no-warnings',
fixtures.path('typescript/ts/test-mock-module.ts'),
]);
strictEqual(result.stderr, '');
match(result.stdout, /Hello, TypeScript-Module!/);
match(result.stdout, /Hello, TypeScript-CommonJS!/);
strictEqual(result.code, 0);
});
test('expect process.features.typescript to be false without type-stripping', async () => {
strictEqual(process.features.typescript, false);
});
test('execute a TypeScript file with union types', async () => {
const result = await spawnPromisified(process.execPath, [
'--experimental-strip-types',
'--no-warnings',
fixtures.path('typescript/ts/test-union-types.ts'),
]);
strictEqual(result.stderr, '');
strictEqual(result.stdout,
'{' +
" name: 'Hello, TypeScript!' }\n" +
'{ role: \'admin\', permission: \'all\' }\n' +
'{\n foo: \'Testing Partial Type\',\n bar: 42,\n' +
' zoo: true,\n metadata: undefined\n' +
'}\n');
strictEqual(result.code, 0);
});
test('expect error when executing a TypeScript file with generics', async () => {
const result = await spawnPromisified(process.execPath, [
'--experimental-strip-types',
fixtures.path('typescript/ts/test-parameter-properties.ts'),
]);
// This error should be thrown during transformation
match(
result.stderr,
/TypeScript parameter property is not supported in strip-only mode/
);
strictEqual(result.stdout, '');
strictEqual(result.code, 1);
});