UNPKG

@jhae/stylelint-config-verifier

Version:

A Stylelint configuration tester for Jest that helps you verify your defined rules.

147 lines (146 loc) 4.65 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.ConfigVerifier = void 0; const stylelint_1 = __importDefault(require("stylelint")); /** * The `ConfigVerifier` class verifies the rules of a Stylelint configuration. It runs Stylelint for a given test case * and compares the linter result with the expected result. The test case contains the code that should be linted and * the expected result. The expected result contains the expected error status, messages, and severities. * * @example * ```typescript * new ConfigVerifier().verify( * 'at-rule-disallowed-list', * { * name: 'Disallow @debug rule', * code: '@debug "";', * expect: { * errored: true, * messages: ['Unexpected at-rule "debug"'], * severities: ['error'], * }, * }, * { * name: 'Allow @use rule', * code: '@use "test.scss";', * }, * ); * `` */ class ConfigVerifier { configFile; /** * The default test case expectation * * This expectation occurs if Stylelint reports no problems and is used if no expectation was defined in a test case. * * @type {TestCaseExpectation} * * @internal */ defaultExpectation = { errored: false, messages: [], severities: [], }; /** * Creates a new `ConfigVerifier` object. * * @param {string} configFile The path to the Stylelint config file whose rules should be verified */ constructor(configFile = '.stylelintrc.yaml') { this.configFile = configFile; } /** * Verifies a rule configuration. * * @param {string} ruleName The name of the rule * @param {TestCase[]} testCases The test cases */ verify(ruleName, ...testCases) { describe(`Rule '${ruleName}'`, () => { test.each(testCases)('$name', async (testCase) => { const warnings = this.getWarnings(ruleName, await this.getLinterResult(testCase)); const { expect: expectation = this.defaultExpectation } = testCase; expect(this.getErrored(warnings)).toBe(expectation.errored); expect(this.getMessages(warnings)).toStrictEqual(expectation.messages.map((message) => `${message} (${ruleName})`)); expect(this.getSeverities(warnings)).toStrictEqual(expectation.severities); }); }); } /** * Runs Stylelint for the given test case and returns a Promise that resolves to the linter result. * * @internal * * @param {TestCase} testCase The test case * * @return {Promise<LinterResult>} */ getLinterResult({ file, code }) { if ([file, code].filter((value) => value === undefined).length !== 1) { throw new Error('Though both "file" and "code" are optional, you must have one and cannot have both.'); } return stylelint_1.default.lint({ configFile: this.configFile, files: file, code, }); } /** * Returns the warnings for a rule from the given linter result. * * @internal * * @param {string} ruleName The name of the rule * @param {LinterResult} linterResult The linter result * * @return {Warning[]} */ getWarnings(ruleName, { results: lintResults }) { return lintResults .map(({ warnings }) => warnings) .reduce((previous, current) => previous.concat(current), []) .filter((warning) => warning.rule === ruleName); } /** * Returns true if the given lint warnings contain an error, otherwise false. * * @internal * * @param {Warning[]} warnings The lint warnings * * @return {boolean} */ getErrored(warnings) { return this.getSeverities(warnings).some((severity) => severity === 'error'); } /** * Returns the messages of the given lint warnings. * * @internal * * @param {Warning[]} warnings The lint warnings * * @return {string[]} */ getMessages(warnings) { return warnings.map(({ text }) => text); } /** * Returns the severities of the given lint warnings. * * @internal * * @param {Warning[]} warnings The lint warnings * * @return {Severity[]} */ getSeverities(warnings) { return warnings.map(({ severity }) => severity); } } exports.ConfigVerifier = ConfigVerifier;