Skip to content

Commit b11a297

Browse files
test: use ts compiler in cli tests (freeCodeCamp#62783)
1 parent c3dcec1 commit b11a297

File tree

6 files changed

+146
-70
lines changed

6 files changed

+146
-70
lines changed

curriculum/package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
"@types/js-yaml": "4.0.5",
5050
"@types/polka": "^0.5.7",
5151
"@types/string-similarity": "^4.0.2",
52+
"@typescript/vfs-1.6.1": "npm:@typescript/[email protected]",
5253
"@vitest/ui": "^3.2.4",
5354
"eslint": "^9.39.1",
5455
"glob": "8.1.0",
@@ -64,6 +65,7 @@
6465
"puppeteer": "22.12.1",
6566
"sirv": "^3.0.2",
6667
"string-similarity": "4.0.4",
68+
"typescript-5.9.2": "npm:[email protected]",
6769
"vitest": "^3.2.4"
6870
}
6971
}

curriculum/src/test/test-challenges.js

Lines changed: 41 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,8 @@
1-
import { describe, it, beforeAll, expect } from 'vitest';
1+
import { describe, it, beforeAll, expect, vi } from 'vitest';
2+
23
import jsdom from 'jsdom';
34
import lodash from 'lodash';
45

5-
import {
6-
buildChallenge,
7-
runnerTypes
8-
} from '../../../client/src/templates/Challenges/utils/build';
96
import {
107
challengeTypes,
118
hasNoSolution
@@ -28,6 +25,32 @@ import { sortChallenges } from './utils/sort-challenges.js';
2825

2926
const { flatten, isEmpty, cloneDeep } = lodash;
3027

28+
vi.mock(
29+
'../../../client/src/templates/Challenges/utils/typescript-worker-handler',
30+
async importOriginal => {
31+
const actual = await importOriginal();
32+
33+
// ts and tsvfs must match the versions used in the typescript-worker.
34+
const tsvfs = await import('@typescript/vfs-1.6.1');
35+
const ts = await import('typescript-5.9.2');
36+
// use the same TS compiler as the client
37+
const tsCompiler = await import(
38+
'../../../tools/client-plugins/browser-scripts/modules/typescript-compiler'
39+
);
40+
const compiler = new tsCompiler.Compiler(ts, tsvfs);
41+
await compiler.setup({ useNodeModules: true });
42+
return {
43+
...actual,
44+
checkTSServiceIsReady: () => Promise.resolve(true),
45+
compileTypeScriptCode: code => {
46+
const { result, error } = compiler.compile(code, 'index.tsx');
47+
if (error) throw error;
48+
return result;
49+
}
50+
};
51+
}
52+
);
53+
3154
const dom = new jsdom.JSDOM('');
3255
global.document = dom.window.document;
3356
global.DOMParser = dom.window.DOMParser;
@@ -86,13 +109,13 @@ export async function defineTestsForBlock(testFilter) {
86109

87110
const challengeData = { meta, challenges, lang };
88111

89-
describe('Check challenges', () => {
112+
describe('Check challenges', async () => {
90113
beforeAll(async () => {
91114
page = await newPageContext();
92115
global.Worker = createPseudoWorker(page);
93116
});
94117

95-
populateTestsForLang(challengeData, () => page);
118+
await populateTestsForLang(challengeData, () => page);
96119
});
97120
}
98121

@@ -123,7 +146,13 @@ export async function getChallenges(lang, filters) {
123146
return sortChallenges(challenges);
124147
}
125148

126-
function populateTestsForLang({ lang, challenges, meta }) {
149+
async function populateTestsForLang({ lang, challenges, meta }) {
150+
// We have to dynamically import this because otherwise it will not be mocked.
151+
// Presumably this is because we import from_this file in the generated block
152+
// test files and that happens before the mock is applied.
153+
const { buildChallenge } = await import(
154+
'../../../client/src/templates/Challenges/utils/build'
155+
);
127156
const validateChallenge = challengeSchemaValidator();
128157

129158
describe(`Language: ${lang}`, function () {
@@ -341,6 +370,10 @@ async function createTestRunner(
341370
buildChallenge,
342371
solutionFromNext
343372
) {
373+
const { runnerTypes } = await import(
374+
'../../../client/src/templates/Challenges/utils/build'
375+
);
376+
344377
const challengeFiles = replaceChallengeFilesContentsWithSolutions(
345378
challenge.challengeFiles,
346379
solutionFiles

0 commit comments

Comments
 (0)