UNPKG

stylelint-tape

Version:
160 lines (151 loc) 5.33 kB
import logUpdate from 'log-update'; import path from 'path'; import stylelint from 'stylelint'; const colors = { reset: '\x1b[0m', bold: '\x1b[1m', dim: '\x1b[2m', underline: '\x1b[4m', blink: '\x1b[5m', reverse: '\x1b[7m', hidden: '\x1b[8m', black: '\x1b[30m', red: '\x1b[31m', green: '\x1b[32m', yellow: '\x1b[33m', blue: '\x1b[34m', magenta: '\x1b[35m', cyan: '\x1b[36m', white: '\x1b[37m', bgBlack: '\x1b[40m', bgRed: '\x1b[41m', bgGreen: '\x1b[42m', bgYellow: '\x1b[43m', bgBlue: '\x1b[44m', bgMagenta: '\x1b[45m', bgCyan: '\x1b[46m', bgWhite: '\x1b[47m' }; const getColorFn = key => string => `${colors[key]}${String(string).replace(colors.reset, `${colors.reset}${colors[key]}`)}${colors.reset}`; const bold = getColorFn('bold'); const dim = getColorFn('dim'); const red = getColorFn('red'); const green = getColorFn('green'); const yellow = getColorFn('yellow'); const cyan = getColorFn('cyan'); const white = getColorFn('white'); const trim = string => String(string).trim().replace(/\s+/g, ' '); const json = object => { try { // trimmed, stringified object with raw-formatted RegExp return trim(JSON.stringify(object, (key, value) => value instanceof RegExp ? `__REGEX_START${value}__REGEX_END` : value, ' ')).replace(/"__REGEX_START([\W\w]+)__REGEX_END"/g, '$1').replace(/^\[\s*([\W\w]*)\s*\]$/, '$1'); } catch (error) { return ''; } }; const done = process.platform === 'win32' ? '√' : '✔'; const fail = process.platform === 'win32' ? '×' : '✖'; const wait = '…'; const cwd = process.cwd(); var nodeOptions = { cwd, defaultArgs: [true] }; async function stylelintTape(options, testsByRuleName) { let errorsCount = 0; const normalizedopts = Object.assign({}, nodeOptions, options === Object(options) ? options : { plugin: options }); normalizedopts.plugin = path.resolve(normalizedopts.cwd, normalizedopts.plugin || ''); for (const ruleName in testsByRuleName) { const tests = testsByRuleName[ruleName]; for (const test of tests) { const title = getTitleByTest(test); // update log for pending test logUpdate(`${dim(wait)} ${title}`); // run test and update log with results await runTest(ruleName, test, normalizedopts).then(() => { logUpdate(`${green(done)} ${white(title)}`); }, error => { // update error count in case there is errors errorsCount++; logUpdate(`${red(fail)} ${bold(title)}\n ${yellow(trim(error.message))}`); }).then(() => { logUpdate.done(); }); } } if (errorsCount === 0) { return Promise.resolve(); } return Promise.reject(Error('Tests failed.')); } function runTest(ruleName, test, opts) { return stylelint.lint({ code: test.source, config: { plugins: [path.resolve(opts.cwd, opts.plugin)], rules: { [ruleName]: test.args || opts.defaultArgs } }, fix: Boolean(test.expect) }).then(results => { const warnings = results.results.reduce((array, result) => { return array.concat(result.warnings); }, []); if (typeof test.warnings === 'number' && test.warnings !== warnings.length) { // throw when the warning length by number does not match throw new Error(`Expected ${test.warnings} warnings\nReceived ${warnings.length} warnings`); } if (Array.isArray(test.warnings)) { if (test.warnings.length !== warnings.length) { // throw when the warning length by array does not match throw new Error(`Expected ${test.warnings.length} warnings\nReceived ${warnings.length} warnings`); } test.warnings.forEach((warningEntry, warningIndex) => { if (typeof warningEntry === 'string' && warningEntry !== warnings[warningIndex].text) { // throw when the warning text does not match throw new Error(`Expected warning: "${warningEntry}"\nReceived warning: "${warnings[warningIndex].text}"`); } Object.keys(Object(warningEntry)).forEach(warningKey => { if (warnings[warningIndex][warningKey] === warningEntry[warningKey]) { // throw when the warning key-value pair does not match throw new Error(`Expected: "${warningKey}" as ${warnings[warningIndex][warningKey]}\nReceived: ${warningEntry[warningKey]}`); } }); }); } if (test.expect && results.code !== test.expect) { throw new Error(`Expected: ${test.expect}\nReceived: ${results.code}`); } }); } function getWarningsByTest(test) { if (test.warnings instanceof Array) { return test.warnings.length; } if (typeof test.warnings === 'number') { return test.warnings; } return 0; } function getargsByTest(test) { if (test.args) { return ` with ${green(json(test.args))}`; } return ''; } function getTitleByTest(test) { if ('title' in test) { return test.title; } if ('expect' in test) { return `${cyan(test.source)}${getargsByTest(test)} becomes ${cyan(test.expect)}`; } const numberOfWarnings = getWarningsByTest(test); const warnings = numberOfWarnings === 1 ? 'warning' : 'warnings'; return `${cyan(test.source)}${getargsByTest(test)} reports ${yellow(String(numberOfWarnings))} ${warnings}`; } export { stylelintTape as default }; //# sourceMappingURL=index.mjs.map