UNPKG

textlint-tester

Version:
345 lines (341 loc) 13.5 kB
// LICENSE : MIT "use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.TextLintTester = exports.createTestLinter = exports.createTextlintKernelDescriptor = void 0; const assert = __importStar(require("assert")); const test_util_1 = require("./test-util"); const kernel_1 = require("@textlint/kernel"); const feature_flag_1 = require("@textlint/feature-flag"); const textlint_plugin_text_1 = __importDefault(require("@textlint/textlint-plugin-text")); const textlint_plugin_markdown_1 = __importDefault(require("@textlint/textlint-plugin-markdown")); const promises_1 = __importDefault(require("fs/promises")); const path_1 = __importDefault(require("path")); const hasOwnProperty = Object.prototype.hasOwnProperty; const globalObject = globalThis; // Type guard helper function isObjectWithProperty(obj, property) { return typeof obj === "object" && obj !== null && property in obj; } const describe = typeof globalObject.describe === "function" ? globalObject.describe : function (_text, method) { return method.apply(this); }; const it = typeof globalObject.it === "function" ? globalObject.it : function (_text, method) { return method.apply(this); }; /** * get fixer function from ruleCreator * if not found, throw error * @param {((...args: any[]) => any)|Object} ruleCreator * @param {string} ruleName */ function assertHasFixer(ruleCreator, ruleName) { if (isObjectWithProperty(ruleCreator, "fixer") && typeof ruleCreator.fixer === "function") { return; } if (typeof ruleCreator === "function") { return; } throw new Error(`Not found \`fixer\` function in the ruleCreator: ${ruleName}`); } function assertTestConfig(testConfig) { assert.notEqual(testConfig, null, "TestConfig is null"); assert.notEqual(Object.keys(testConfig).length === 0 && testConfig.constructor === Object, true, "TestConfig is empty"); assert.ok(Array.isArray(testConfig.rules), "TestConfig.rules should be an array"); assert.ok(testConfig.rules.length > 0, "TestConfig.rules should have at least one rule"); testConfig.rules.forEach((rule) => { assert.ok(hasOwnProperty.call(rule, "ruleId"), "ruleId property not found"); assert.ok(hasOwnProperty.call(rule, "rule"), "rule property not found"); }); if (typeof testConfig.plugins !== "undefined") { assert.ok(Array.isArray(testConfig.plugins), "TestConfig.plugins should be an array"); testConfig.plugins.forEach((plugin) => { assert.ok(hasOwnProperty.call(plugin, "pluginId"), "pluginId property not found"); assert.ok(hasOwnProperty.call(plugin, "plugin"), "plugin property not found"); }); } } function isTestConfig(arg) { if (hasOwnProperty.call(arg, "rules")) { return true; } if ((isObjectWithProperty(arg, "fixer") && typeof arg.fixer === "function") || typeof arg === "function") { return false; } return true; } function createTestPluginSet(testConfigPlugins) { const testPluginSet = { plugins: {}, pluginOptions: {} }; testConfigPlugins.forEach((plugin) => { var _a; const pluginName = plugin.pluginId; const pluginOptions = (_a = plugin.options) !== null && _a !== void 0 ? _a : true; testPluginSet.plugins[pluginName] = plugin.plugin; testPluginSet.pluginOptions[pluginName] = pluginOptions; }); return testPluginSet; } const builtInPlugins = [ { pluginId: "@textlint/textlint-plugin-text", plugin: textlint_plugin_text_1.default, options: true }, { pluginId: "@textlint/textlint-plugin-markdown", plugin: textlint_plugin_markdown_1.default, options: true } ]; const createTextlintKernelDescriptor = ({ testName, testRuleDefinition, testCaseOptions }) => { if (isTestConfig(testRuleDefinition)) { const testConfig = testRuleDefinition; assertTestConfig(testConfig); // Note: testCaseOptions is not supported and it will be just ignored. // Assertion check it // > Could not specify options property in valid object when TestConfig was passed. Use TestConfig.rules.options. const testPluginSet = createTestPluginSet(testConfig.plugins || []); const plugins = [ ...builtInPlugins, ...Object.keys(testPluginSet.plugins).map((pluginId) => { return { pluginId, plugin: testPluginSet.plugins[pluginId], options: testPluginSet.pluginOptions[pluginId] }; }) ]; return new kernel_1.TextlintKernelDescriptor({ rules: testConfig.rules, filterRules: [], plugins }); } else { return new kernel_1.TextlintKernelDescriptor({ rules: [ { ruleId: testName, rule: testRuleDefinition, options: testCaseOptions } ], filterRules: [], plugins: builtInPlugins }); } }; exports.createTextlintKernelDescriptor = createTextlintKernelDescriptor; const createTestLinter = (textlintKernelDescriptor) => { const kernel = new kernel_1.TextlintKernel(); return { async lintText(text, ext) { return kernel.lintText(text, { ext, ...textlintKernelDescriptor.toKernelOptions() }); }, async lintFile(filePath) { const text = await promises_1.default.readFile(filePath, "utf-8"); const ext = path_1.default.extname(filePath); return kernel.lintText(text, { ext, filePath, ...textlintKernelDescriptor.toKernelOptions() }); }, async fixText(text, ext) { return kernel.fixText(text, { ext, ...textlintKernelDescriptor.toKernelOptions() }); }, async fixFile(filePath) { const text = await promises_1.default.readFile(filePath, "utf-8"); const ext = path_1.default.extname(filePath); return kernel.fixText(text, { ext, filePath, ...textlintKernelDescriptor.toKernelOptions() }); } }; }; exports.createTestLinter = createTestLinter; class TextLintTester { constructor() { if (typeof feature_flag_1.coreFlags === "object") { feature_flag_1.coreFlags.runningTester = true; } } testValidPattern(testName, param, valid) { const text = typeof valid === "object" ? valid.text : valid; const inputPath = typeof valid === "object" ? valid.inputPath : undefined; const ext = typeof valid === "object" && valid.ext !== undefined ? valid.ext : ".md"; const options = typeof valid === "object" && valid.options !== undefined ? valid.options : undefined; const description = typeof valid === "object" && valid.description !== undefined ? valid.description : undefined; const textlint = (0, exports.createTestLinter)((0, exports.createTextlintKernelDescriptor)({ testName, testRuleDefinition: param, testCaseOptions: options })); const textCaseName = `${inputPath || text}`; it(textCaseName, () => { if (inputPath) { return (0, test_util_1.testValid)({ textlint, inputPath, description }); } else if (text !== undefined && ext) { return (0, test_util_1.testValid)({ textlint, text, ext, description }); } throw new Error(`valid should have text or inputPath property. valid: [ "text", { text: "text" }, { inputPath: "path/to/file" } ] `); }); } testInvalidPattern(testName, param, invalid) { const errors = invalid.errors; const inputPath = invalid.inputPath; const text = invalid.text; const ext = invalid.ext !== undefined ? invalid.ext : ".md"; const options = invalid.options; const description = invalid.description; const textlint = (0, exports.createTestLinter)((0, exports.createTextlintKernelDescriptor)({ testName, testRuleDefinition: param, testCaseOptions: options })); const testCaseName = `${inputPath || text}`; it(testCaseName, () => { if (inputPath) { return (0, test_util_1.testInvalid)({ textlint, inputPath, errors, description }); } else if (text !== undefined && ext) { return (0, test_util_1.testInvalid)({ textlint, text, ext, errors, description }); } throw new Error(`invalid should have { text } or { inputPath } property. invalid: [ { text: "text", errors: [...] }, { inputPath: "path/to/file", errors: [...] } ] `); }); // --fix if (hasOwnProperty.call(invalid, "output")) { it(`Fixer: ${testCaseName}`, () => { if (isTestConfig(param)) { param.rules.forEach((rule) => { assertHasFixer(rule.rule, rule.ruleId); }); } else { assertHasFixer(param, testName); } let promise; if (inputPath !== undefined) { promise = textlint.fixFile(inputPath); } else if (text !== undefined) { promise = textlint.fixText(text, ext); } else { throw new Error("Should set `text` or `inputPath`"); } return promise.then((result) => { const output = invalid.output; assert.strictEqual(result.output, output); }); }); } } /** * run test for textlint rule. * @param {string} name name is name of the test or rule * @param {TextlintRuleModule|TestConfig} testRuleDefinition param is TextlintRuleCreator or TestConfig * @param {string[]|object[]} [valid] * @param {object[]} [invalid] */ run(name, testRuleDefinition, { valid = [], invalid = [] }) { if (isTestConfig(testRuleDefinition)) { assertTestConfig(testRuleDefinition); if (valid) { valid.forEach((validCase) => { assert.ok(!hasOwnProperty.call(validCase, "options"), "Could not specify options property in valid object when TestConfig was passed. Use TestConfig.rules.options."); }); } if (invalid) { invalid.forEach((invalidCase) => { assert.ok(!hasOwnProperty.call(invalidCase, "options"), "Could not specify options property in invalid object when TestConfig was passed. Use TestConfig.rules.options."); }); } } describe(name, () => { invalid.forEach((state) => { this.testInvalidPattern(name, testRuleDefinition, state); }); valid.forEach((state) => { this.testValidPattern(name, testRuleDefinition, state); }); }); } } exports.TextLintTester = TextLintTester; //# sourceMappingURL=textlint-tester.js.map