Skip to content

Commit 9cf2115

Browse files
committed
test: refactor organize fixtures
1 parent a71c437 commit 9cf2115

File tree

3 files changed

+333
-333
lines changed

3 files changed

+333
-333
lines changed

tests/fixtures.ts

Lines changed: 330 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,330 @@
1+
const cjsContextCheck = 'typeof module !== \'undefined\'';
2+
const tsCheck = '1 as number';
3+
4+
const declareReact = `
5+
const React = {
6+
createElement: (...args) => Array.from(args),
7+
};
8+
`;
9+
const jsxCheck = '<><div>JSX</div></>';
10+
11+
const preserveName = `
12+
assert(
13+
(function functionName() {}).name === 'functionName',
14+
'Name should be preserved'
15+
);
16+
`;
17+
18+
const syntaxLowering = `
19+
// es2016 - Exponentiation operator
20+
10 ** 4;
21+
22+
// es2017 - Async functions
23+
(async () => {});
24+
25+
// es2018 - Spread properties
26+
({...Object});
27+
28+
// es2018 - Rest properties
29+
const {...x} = Object;
30+
31+
// es2019 - Optional catch binding
32+
try {} catch {}
33+
34+
// es2020 - Optional chaining
35+
Object?.keys;
36+
37+
// es2020 - Nullish coalescing
38+
Object ?? true
39+
40+
// es2020 - import.meta
41+
// import.meta
42+
43+
// es2021 - Logical assignment operators
44+
// let a = false; a ??= true; a ||= true; a &&= true;
45+
46+
// es2022 - Class instance fields
47+
(class { x });
48+
49+
// es2022 - Static class fields
50+
(class { static x });
51+
52+
// es2022 - Private instance methods
53+
(class { #x() {} });
54+
55+
// es2022 - Private instance fields
56+
(class { #x });
57+
58+
// es2022 - Private static methods
59+
(class { static #x() {} });
60+
61+
// es2022 - Private static fields
62+
(class { static #x });
63+
64+
// es2022 - Class static blocks
65+
(class { static {} });
66+
67+
export const named = 2;
68+
export default 1;
69+
`;
70+
71+
const sourcemap = {
72+
// Adding the dynamic import helps test the import transformation's source map
73+
test: (
74+
extension: string,
75+
) => `import ('node:fs');\nconst { stack } = new Error(); const searchString = 'index.${extension}:SOURCEMAP_LINE'; assert(stack.includes(searchString), \`Expected \${searchString} in stack: \${stack}\`)`,
76+
tag: (
77+
strings: TemplateStringsArray,
78+
...values: string[]
79+
) => {
80+
const finalString = String.raw({ raw: strings }, ...values);
81+
const lineNumber = finalString.split('\n').findIndex(line => line.includes('SOURCEMAP_LINE')) + 1;
82+
return finalString.replaceAll('SOURCEMAP_LINE', lineNumber.toString());
83+
},
84+
};
85+
86+
export const files = {
87+
'js/index.js': `
88+
import assert from 'assert';
89+
${syntaxLowering}
90+
${preserveName}
91+
export const cjsContext = ${cjsContextCheck};
92+
`,
93+
94+
'json/index.json': JSON.stringify({ loaded: 'json' }),
95+
96+
'cjs/index.cjs': sourcemap.tag`
97+
const assert = require('node:assert');
98+
assert(${cjsContextCheck}, 'Should have CJS context');
99+
${preserveName}
100+
${sourcemap.test('cjs')}
101+
102+
// Assert __esModule is unwrapped
103+
import ('../ts/index.ts').then((m) => assert(
104+
!(typeof m.default === 'object' && ('default' in m.default)),
105+
));
106+
exports.named = 'named';
107+
`,
108+
109+
'mjs/index.mjs': `
110+
import assert from 'assert';
111+
export const mjsHasCjsContext = ${cjsContextCheck};
112+
113+
import ('pkg-commonjs').then((m) => assert(
114+
!(typeof m.default === 'object' && ('default' in m.default)),
115+
));
116+
`,
117+
118+
'ts/index.ts': sourcemap.tag`
119+
import assert from 'assert';
120+
import type {Type} from 'resolved-by-tsc'
121+
122+
interface Foo {}
123+
124+
type Foo = number
125+
126+
declare module 'foo' {}
127+
128+
enum BasicEnum {
129+
Left,
130+
Right,
131+
}
132+
133+
enum NamedEnum {
134+
SomeEnum = 'some-value',
135+
}
136+
137+
export const a = BasicEnum.Left;
138+
139+
export const b = NamedEnum.SomeEnum;
140+
141+
export default function foo(): string {
142+
return 'foo'
143+
}
144+
145+
// For "ts as tsx" test
146+
const bar = <T>(value: T) => fn<T>();
147+
148+
${preserveName}
149+
${sourcemap.test('ts')}
150+
export const cjsContext = ${cjsContextCheck};
151+
${tsCheck};
152+
`,
153+
154+
// TODO: test resolution priority for files 'index.tsx` & 'index.tsx.ts` via 'index.tsx'
155+
156+
'jsx/index.jsx': sourcemap.tag`
157+
import assert from 'assert';
158+
export const cjsContext = ${cjsContextCheck};
159+
${declareReact}
160+
export const jsx = ${jsxCheck};
161+
${preserveName}
162+
${sourcemap.test('jsx')}
163+
`,
164+
165+
'tsx/index.tsx': sourcemap.tag`
166+
import assert from 'assert';
167+
export const cjsContext = ${cjsContextCheck};
168+
${tsCheck};
169+
${declareReact}
170+
export const jsx = ${jsxCheck};
171+
${preserveName}
172+
${sourcemap.test('tsx')}
173+
`,
174+
175+
'mts/index.mts': sourcemap.tag`
176+
import assert from 'assert';
177+
export const mjsHasCjsContext = ${cjsContextCheck};
178+
${tsCheck};
179+
${preserveName}
180+
${sourcemap.test('mts')}
181+
`,
182+
183+
'cts/index.cts': sourcemap.tag`
184+
const assert = require('assert');
185+
assert(${cjsContextCheck}, 'Should have CJS context');
186+
${tsCheck};
187+
${preserveName}
188+
${sourcemap.test('cts')}
189+
`,
190+
191+
'expect-errors.js': `
192+
export const expectErrors = async (...assertions) => {
193+
let errors = await Promise.all(
194+
assertions.map(async ([fn, expectedError]) => {
195+
let thrown;
196+
try {
197+
await fn();
198+
} catch (error) {
199+
thrown = error;
200+
}
201+
202+
if (!thrown) {
203+
return new Error('No error thrown');
204+
} else if (!thrown.message.includes(expectedError)) {
205+
return new Error(\`Message \${JSON.stringify(expectedError)} not found in \${JSON.stringify(thrown.message)}\n\${thrown.stack}\`);
206+
}
207+
}),
208+
);
209+
210+
errors = errors.filter(Boolean);
211+
212+
if (errors.length > 0) {
213+
console.error(errors);
214+
process.exitCode = 1;
215+
}
216+
};
217+
`,
218+
219+
'file.txt': 'hello',
220+
221+
'import-typescript-parent.js': sourcemap.tag`
222+
import './import-typescript-child.js';
223+
`,
224+
225+
'import-typescript-child.ts': sourcemap.tag`
226+
console.log('imported');
227+
`,
228+
229+
'broken-syntax.ts': 'if',
230+
231+
node_modules: {
232+
'pkg-commonjs': {
233+
'package.json': JSON.stringify({
234+
type: 'commonjs',
235+
}),
236+
'index.js': syntaxLowering,
237+
},
238+
'pkg-module': {
239+
'package.json': JSON.stringify({
240+
type: 'module',
241+
main: './index.js',
242+
}),
243+
'index.js': `${syntaxLowering}\nexport * from "./empty-export"`,
244+
'empty-export/index.js': 'export {}',
245+
},
246+
},
247+
248+
tsconfig: {
249+
'file.ts': '',
250+
251+
'jsx.jsx': `
252+
// tsconfig not applied to jsx because allowJs is not set
253+
import { expectErrors } from '../expect-errors';
254+
expectErrors(
255+
[() => ${jsxCheck}, 'React is not defined'],
256+
257+
// These should throw unless allowJs is set
258+
// [() => import ('prefix/file'), "Cannot find package 'prefix'"],
259+
// [() => import ('paths-exact-match'), "Cannot find package 'paths-exact-match'"],
260+
// [() => import ('file'), "Cannot find package 'file'"],
261+
);
262+
`,
263+
264+
'node_modules/tsconfig-should-not-apply': {
265+
'package.json': JSON.stringify({
266+
exports: {
267+
import: './index.mjs',
268+
default: './index.cjs',
269+
},
270+
}),
271+
'index.mjs': `
272+
import { expectErrors } from '../../../expect-errors';
273+
expectErrors(
274+
[() => import ('prefix/file'), "Cannot find package 'prefix'"],
275+
[() => import ('paths-exact-match'), "Cannot find package 'paths-exact-match'"],
276+
[() => import ('file'), "Cannot find package 'file'"],
277+
);
278+
`,
279+
'index.cjs': `
280+
const { expectErrors } = require('../../../expect-errors');
281+
expectErrors(
282+
[() => require('prefix/file'), "Cannot find module"],
283+
[() => require('paths-exact-match'), "Cannot find module"],
284+
[() => require('file'), "Cannot find module"],
285+
);
286+
`,
287+
},
288+
289+
'index.tsx': `
290+
${jsxCheck};
291+
292+
import './jsx';
293+
294+
// Resolves relative to baseUrl
295+
import 'file';
296+
297+
// Resolves paths - exact match
298+
import 'paths-exact-match';
299+
300+
// Resolves paths - prefix match
301+
import 'prefix/file';
302+
303+
// Resolves paths - suffix match
304+
import 'file/suffix';
305+
306+
// tsconfig should not apply to dependency
307+
import "tsconfig-should-not-apply";
308+
`,
309+
310+
'tsconfig.json': JSON.stringify({
311+
compilerOptions: {
312+
jsxFactory: 'Array',
313+
jsxFragmentFactory: 'null',
314+
baseUrl: '.',
315+
paths: {
316+
'paths-exact-match': ['file'],
317+
'prefix/*': ['*'],
318+
'*/suffix': ['*'],
319+
},
320+
},
321+
}),
322+
323+
'tsconfig-allowJs.json': JSON.stringify({
324+
extends: './tsconfig.json',
325+
compilerOptions: {
326+
allowJs: true,
327+
},
328+
}),
329+
},
330+
};

0 commit comments

Comments
 (0)