diff --git a/lib/rules/__tests__/index.test.js b/lib/rules/__tests__/index.test.mjs similarity index 54% rename from lib/rules/__tests__/index.test.js rename to lib/rules/__tests__/index.test.mjs index a2031de379..4ed741c302 100644 --- a/lib/rules/__tests__/index.test.js +++ b/lib/rules/__tests__/index.test.mjs @@ -1,16 +1,20 @@ -'use strict'; +import { mkdirSync, rmSync, writeFileSync } from 'node:fs'; +import { createRequire } from 'node:module'; +import { execSync } from 'node:child_process'; +import { fileURLToPath } from 'node:url'; +import path from 'node:path'; +import { readFile } from 'node:fs/promises'; -const cp = require('child_process'); -const fs = require('fs'); -const path = require('path'); +import rules from '../index.js'; -const rules = require('..'); -const ruleEntries = Object.entries(rules); +const require = createRequire(import.meta.url); +const __dirname = fileURLToPath(new URL('.', import.meta.url)); +const ruleEntries = Object.entries(rules); let rulesListDoc; beforeAll(async () => { - rulesListDoc = await fs.promises.readFile( + rulesListDoc = await readFile( path.join(__dirname, '..', '..', '..', 'docs', 'user-guide', 'rules.md'), 'utf8', ); @@ -32,13 +36,13 @@ describe('fixable rules', () => { const fixableRules = ruleEntries.filter(([, rule]) => rule.meta.fixable); test.each(fixableRules)('"%s" should describe fixable in the rules doc', async (name) => { - const doc = await fs.promises.readFile(path.join(__dirname, '..', name, 'README.md'), 'utf8'); + const doc = await readFile(path.join(__dirname, '..', name, 'README.md'), 'utf8'); expect(doc).toMatch('`fix` option'); }); test.each(fixableRules)('"%s" should describe fixable in the rules doc', (name) => { - expect(rulesListDoc).toMatch(new RegExp(`^.+\\b${name}\\b.+\\|.+\\|\\s+🔧\\s+\\|$`, 'm')); + expect(rulesListDoc).toMatch(new RegExp(`^.+\`${name}\`.+\\|.+\\|\\s+🔧\\s+\\|$`, 'm')); }); }); @@ -46,7 +50,7 @@ describe('deprecated rules', () => { const deprecatedRules = ruleEntries.filter(([, rule]) => rule.meta.deprecated); test.each(deprecatedRules)('"%s" should describe deprecation in the rules doc', async (name) => { - const doc = await fs.promises.readFile(path.join(__dirname, '..', name, 'README.md'), 'utf8'); + const doc = await readFile(path.join(__dirname, '..', name, 'README.md'), 'utf8'); expect(doc).toMatch('> **Warning**'); }); @@ -57,12 +61,12 @@ describe('custom message option', () => { '"%s" should describe a custom message option in its doc', async (ruleName) => { const jsFile = path.join(__dirname, '..', ruleName, 'index.js'); - const jsCode = await fs.promises.readFile(jsFile, 'utf8'); + const jsCode = await readFile(jsFile, 'utf8'); // NOTE: If all rules support a custom message option, we should remove this `if` statement. if (!jsCode.includes('\tmessageArgs: [')) return; - const doc = await fs.promises.readFile(jsFile.replace('index.js', 'README.md'), 'utf8'); + const doc = await readFile(jsFile.replace('index.js', 'README.md'), 'utf8'); expect(doc).toContain('`message` secondary option'); }, @@ -70,27 +74,36 @@ describe('custom message option', () => { }); describe('standard config', () => { - const cwd = path.join(__dirname, 'tmp'); + const tmpDir = path.join(__dirname, 'tmp'); - fs.rmSync(cwd, { recursive: true, force: true }); - fs.mkdirSync(cwd, { recursive: true }); - fs.writeFileSync(path.join(cwd, 'package.json'), '{}'); - cp.execSync( + // NOTE: The use of Promised-based APIs may cause flaky test on CI. + rmSync(tmpDir, { recursive: true, force: true }); + mkdirSync(tmpDir, { recursive: true }); + writeFileSync(path.join(tmpDir, 'package.json'), '{}'); + execSync( 'npm install --silent --no-package-lock --no-audit --omit=peer stylelint-config-standard', - { cwd }, + { cwd: tmpDir }, ); - const configRules = (name) => Object.keys(require(path.join(cwd, 'node_modules', name)).rules); + const configRules = (name) => { + const config = require(path.join(tmpDir, 'node_modules', name)); + + return Object.keys(config.rules); + }; + const standardRules = configRules('stylelint-config-standard'); - test('standard config is not empty', () => { + standardRules.push(...configRules('stylelint-config-recommended')); + + afterAll(() => { + rmSync(tmpDir, { recursive: true, force: true }); + }); + + test('the rules are not empty', () => { expect(standardRules).not.toHaveLength(0); }); - test.each(standardRules)( - '"%s" should be included in the standard config in the rules doc', - (name) => { - expect(rulesListDoc).toMatch(new RegExp(`^.+\\b${name}\\b.+\\|\\s+✅\\s+\\|.+\\|$`, 'm')); - }, - ); + test.each(standardRules)('the rule "%s" are present in the rules doc', (name) => { + expect(rulesListDoc).toMatch(new RegExp(`^.+\`${name}\`.+\\|\\s+✅\\s+\\|.+\\|$`, 'm')); + }); }); diff --git a/lib/utils/__tests__/blurComments.test.js b/lib/utils/__tests__/blurComments.test.js deleted file mode 100644 index 750ab14d34..0000000000 --- a/lib/utils/__tests__/blurComments.test.js +++ /dev/null @@ -1,9 +0,0 @@ -'use strict'; - -const blurComments = require('../blurComments'); - -it('blurComments', () => { - expect(blurComments('abc')).toBe('abc'); - expect(blurComments('/* abc */')).toBe('`'); - expect(blurComments('a { b:c } /*abc*/', '#')).toBe('a { b:c } #'); -}); diff --git a/lib/utils/__tests__/blurFunctionArguments.test.js b/lib/utils/__tests__/blurFunctionArguments.test.js deleted file mode 100644 index f644abbaf8..0000000000 --- a/lib/utils/__tests__/blurFunctionArguments.test.js +++ /dev/null @@ -1,11 +0,0 @@ -'use strict'; - -const blurFunctionArguments = require('../blurFunctionArguments'); - -it('blurFunctionArguments', () => { - expect(blurFunctionArguments('abc abc', 'url')).toBe('abc abc'); - expect(blurFunctionArguments('abc url(abc) abc', 'url')).toBe('abc url(```) abc'); - expect(blurFunctionArguments('abc uRl(abc) abc', 'url')).toBe('abc uRl(```) abc'); - expect(blurFunctionArguments('abc URL(abc) abc', 'url')).toBe('abc URL(```) abc'); - expect(blurFunctionArguments('abc url(abc) url(xx)', 'url', '#')).toBe('abc url(###) url(##)'); -}); diff --git a/lib/utils/blurComments.js b/lib/utils/blurComments.js deleted file mode 100644 index bcc6d5b188..0000000000 --- a/lib/utils/blurComments.js +++ /dev/null @@ -1,10 +0,0 @@ -'use strict'; - -/** - * @param {string} source - * - * @returns {string} - */ -module.exports = function blurComments(source, blurChar = '`') { - return source.replace(/\/\*.*\*\//g, blurChar); -}; diff --git a/lib/utils/blurFunctionArguments.js b/lib/utils/blurFunctionArguments.js deleted file mode 100644 index 520e0f20c9..0000000000 --- a/lib/utils/blurFunctionArguments.js +++ /dev/null @@ -1,53 +0,0 @@ -'use strict'; - -const balancedMatch = require('balanced-match'); - -/** - * Replace all of the characters that are arguments to a certain - * CSS function with some innocuous character. - * - * This is useful if you need to use a RegExp to find a string - * but want to ignore matches in certain functions (e.g. `url()`, - * which might contain all kinds of false positives). - * - * For example: - * blurFunctionArguments("abc url(abc) abc", "url") === "abc url(```) abc" - * - * @param {string} source - * @param {string} functionName - * @return {string} - The result string, with the function arguments "blurred" - */ -module.exports = function blurFunctionArguments(source, functionName, blurChar = '`') { - const nameWithParen = `${functionName.toLowerCase()}(`; - const lowerCaseSource = source.toLowerCase(); - - if (!lowerCaseSource.includes(nameWithParen)) { - return source; - } - - const functionNameLength = functionName.length; - - let result = source; - let searchStartIndex = 0; - - while (lowerCaseSource.includes(nameWithParen, searchStartIndex)) { - const openingParenIndex = - lowerCaseSource.indexOf(nameWithParen, searchStartIndex) + functionNameLength; - const parensMatch = balancedMatch('(', ')', lowerCaseSource.slice(openingParenIndex)); - - if (!parensMatch) { - throw new Error(`No parens match: "${source}"`); - } - - const closingParenIndex = parensMatch.end + openingParenIndex; - const argumentsLength = closingParenIndex - openingParenIndex - 1; - - result = - result.slice(0, openingParenIndex + 1) + - blurChar.repeat(argumentsLength) + - result.slice(closingParenIndex); - searchStartIndex = closingParenIndex; - } - - return result; -}; diff --git a/package.json b/package.json index baca0b2b4e..0dc042bc2f 100644 --- a/package.json +++ b/package.json @@ -47,6 +47,7 @@ "pretest": "npm run lint", "test": "node --experimental-vm-modules node_modules/jest/bin/jest.js", "test-coverage": "npm test --ignore-scripts -- --coverage", + "test-only": "npm test --ignore-scripts", "version": "changeset version", "postversion": "git restore package.json", "watch": "npm test --ignore-scripts -- --watch",