From 68614b43a98e98344c35914a783c357554e40018 Mon Sep 17 00:00:00 2001 From: Huyen Nguyen <25715018+huyenltnguyen@users.noreply.github.com> Date: Fri, 19 Sep 2025 14:46:06 +0700 Subject: [PATCH] chore(tools): migrate scripts/lint test to vitest (#62265) Co-authored-by: Sem Bauke Co-authored-by: Oliver Eyton-Williams --- jest.config.js | 1 + package.json | 2 +- pnpm-lock.yaml | 9 +++++ pnpm-workspace.yaml | 1 + tools/scripts/lint/index.test.js | 61 +++++++++++++------------------- tools/scripts/lint/package.json | 24 +++++++++++++ 6 files changed, 61 insertions(+), 37 deletions(-) create mode 100644 tools/scripts/lint/package.json diff --git a/jest.config.js b/jest.config.js index 8b76533673a..0c9aa39cd07 100644 --- a/jest.config.js +++ b/jest.config.js @@ -6,6 +6,7 @@ module.exports = { 'tools/challenge-helper-scripts/', 'tools/challenge-parser/', 'tools/scripts/build/', + 'tools/scripts/lint/', 'curriculum', 'client' ], diff --git a/package.json b/package.json index 4a03191426c..d64e7fa46d5 100644 --- a/package.json +++ b/package.json @@ -74,13 +74,13 @@ "test:api": "cd api && pnpm test", "test:tools:challenge-helper-scripts": "cd ./tools/challenge-helper-scripts && pnpm test run", "test:tools:scripts-build": "cd ./tools/scripts/build && pnpm test run", + "test:tools:scripts-lint": "cd ./tools/scripts/lint && pnpm test run", "test:tools:challenge-parser": "cd ./tools/challenge-parser && pnpm test run", "test:curriculum:content": "cd ./curriculum && pnpm test run", "test:curriculum:tooling": "cd ./curriculum && pnpm vitest run", "test-curriculum-full-output": "cd ./curriculum && pnpm run test:full-output run", "test:client": "cd ./client && pnpm test run", "test-config": "jest config", - "test-tools": "jest tools", "test-utils": "jest utils", "prepare": "husky", "playwright:run": "playwright test", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f98b84bf62c..ed161ad5ec7 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1079,6 +1079,15 @@ importers: specifier: ^3.2.4 version: 3.2.4(@types/node@20.12.8)(@vitest/ui@3.2.4)(jsdom@26.1.0)(msw@2.8.7(@types/node@20.12.8)(typescript@5.8.2))(terser@5.28.1)(tsx@4.19.1)(yaml@2.8.0) + tools/scripts/lint: + devDependencies: + '@vitest/ui': + specifier: ^3.2.4 + version: 3.2.4(vitest@3.2.4) + vitest: + specifier: ^3.2.4 + version: 3.2.4(@types/node@20.12.8)(@vitest/ui@3.2.4)(jsdom@26.1.0)(msw@2.8.7(@types/node@20.12.8)(typescript@5.8.2))(terser@5.28.1)(tsx@4.19.1)(yaml@2.8.0) + tools/scripts/seed: devDependencies: debug: diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 3d29885ab9b..4e8a62d9509 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -11,6 +11,7 @@ packages: - 'tools/crowdin' - 'tools/daily-challenges' - 'tools/scripts/build' + - 'tools/scripts/lint' - 'tools/scripts/seed' - 'tools/scripts/seed-exams' diff --git a/tools/scripts/lint/index.test.js b/tools/scripts/lint/index.test.js index 7f38da6eeee..72c7948d6a5 100644 --- a/tools/scripts/lint/index.test.js +++ b/tools/scripts/lint/index.test.js @@ -1,13 +1,13 @@ -const path = require('path'); - -const lint = require('.'); +import path from 'path'; +import { describe, it, beforeEach, afterEach, expect, vi } from 'vitest'; +import lint from '.'; describe('markdown linter', () => { - let good = { path: path.join(__dirname, './fixtures/good.md') }; - let badYML = { path: path.join(__dirname, './fixtures/badYML.md') }; - let badFencing = { path: path.join(__dirname, './fixtures/badFencing.md') }; + const good = { path: path.join(__dirname, './fixtures/good.md') }; + const badYML = { path: path.join(__dirname, './fixtures/badYML.md') }; + const badFencing = { path: path.join(__dirname, './fixtures/badFencing.md') }; beforeEach(() => { - console.log = jest.fn(); + console.log = vi.fn(); // the linter signals that a file failed by setting // exitCode to 1, so it needs (re)setting to 0 process.exitCode = 0; @@ -16,40 +16,29 @@ describe('markdown linter', () => { process.exitCode = 0; }); - it('should pass `good` markdown', done => { - function callback() { - expect(process.exitCode).toBe(0); - done(); - } - lint(good, callback); + it('should pass `good` markdown', async () => { + await new Promise(resolve => lint(good, resolve)); + expect(process.exitCode).toBe(0); }); - it('should fail invalid YML blocks', done => { - function callback() { - expect(process.exitCode).toBe(1); - done(); - } - lint(badYML, callback); + it('should fail invalid YML blocks', async () => { + await new Promise(resolve => lint(badYML, resolve)); + expect(process.exitCode).toBe(1); }); - it('should fail when code fences are not surrounded by newlines', done => { - function callback() { - expect(process.exitCode).toBe(1); - done(); - } - lint(badFencing, callback); + it('should fail when code fences are not surrounded by newlines', async () => { + await new Promise(resolve => lint(badFencing, resolve)); + expect(process.exitCode).toBe(1); }); - it('should write to the console describing the problem', done => { - function callback() { - const expected = - 'badYML.md: 19: yaml-linter YAML code blocks should be valid [bad indentation of a mapping entry at line 3, column 17:\n testString: testString\n ^] [Context: "```yml"]'; - expect(console.log.mock.calls.length).toBe(1); - expect(console.log.mock.calls[0][0]).toEqual( - expect.stringContaining(expected) - ); - done(); - } - lint(badYML, callback); + it('should write to the console describing the problem', async () => { + await new Promise(resolve => lint(badYML, resolve)); + + const expected = + 'badYML.md: 19: yaml-linter YAML code blocks should be valid [bad indentation of a mapping entry at line 3, column 17:\n testString: testString\n ^] [Context: "```yml"]'; + expect(console.log.mock.calls.length).toBe(1); + expect(console.log.mock.calls[0][0]).toEqual( + expect.stringContaining(expected) + ); }); }); diff --git a/tools/scripts/lint/package.json b/tools/scripts/lint/package.json new file mode 100644 index 00000000000..4dbad4ce75d --- /dev/null +++ b/tools/scripts/lint/package.json @@ -0,0 +1,24 @@ +{ + "name": "@freecodecamp/scripts-lint", + "version": "0.0.1", + "description": "The freeCodeCamp.org open-source codebase and curriculum", + "license": "BSD-3-Clause", + "private": true, + "main": "none", + "repository": { + "type": "git", + "url": "git+https://github.com/freeCodeCamp/freeCodeCamp.git" + }, + "bugs": { + "url": "https://github.com/freeCodeCamp/freeCodeCamp/issues" + }, + "homepage": "https://github.com/freeCodeCamp/freeCodeCamp#readme", + "author": "freeCodeCamp ", + "scripts": { + "test": "vitest" + }, + "devDependencies": { + "@vitest/ui": "^3.2.4", + "vitest": "^3.2.4" + } +}