tapFormatter.cjs 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. // NOTICE: This file is generated by Rollup. To modify it,
  2. // please instead edit the ESM counterpart and rebuild with Rollup (npm run build).
  3. 'use strict';
  4. const validateTypes = require('../utils/validateTypes.cjs');
  5. const preprocessWarnings = require('./preprocessWarnings.cjs');
  6. /** @import {Warning, Formatter} from 'stylelint' */
  7. /** @typedef {Array<Omit<Warning, 'rule'>>} Warnings */
  8. /** @type {Formatter} */
  9. function tapFormatter(results) {
  10. const lines = ['TAP version 14', `1..${results.length}`];
  11. for (const [index, result] of results.entries()) {
  12. preprocessWarnings(result);
  13. // SKIP indicates "that a test was not run, or if it was,
  14. // that its success or failure is being temporarily ignored."
  15. // skipped tests must not be treated as test failures though
  16. // if a file is ignored, errored is currently always false
  17. const ignored = result.ignored ? ' # SKIP ignored' : '';
  18. const error = result.errored ? 'not ' : '';
  19. lines.push(`${error}ok ${index + 1} - ${getEscapedSource(result.source)}${ignored}`);
  20. if (error) {
  21. lines.push(' ---');
  22. /** @type {Record<string, Warnings>} */
  23. const rules = {};
  24. for (const { rule, ...rest } of result.warnings) {
  25. const name = rule || 'unknown';
  26. const warnings = (rules[name] ??= []);
  27. warnings.push(rest);
  28. }
  29. for (const [ruleName, warnings] of Object.entries(rules)) {
  30. lines.push(` ${ruleName}:`);
  31. for (const { text, severity, line, column, endLine, endColumn } of warnings) {
  32. lines.push(
  33. ` - message: ${JSON.stringify(text)}`,
  34. ` severity: ${severity}`,
  35. ` line: ${line}`,
  36. ` column: ${column}`,
  37. );
  38. if (validateTypes.isNumber(endLine)) lines.push(` endLine: ${endLine}`);
  39. if (validateTypes.isNumber(endColumn)) lines.push(` endColumn: ${endColumn}`);
  40. }
  41. }
  42. lines.push(' ...');
  43. }
  44. }
  45. lines.push('');
  46. return lines.join('\n');
  47. }
  48. /**
  49. * Apply TAP escaping to the source that is part of the test point description
  50. * @see {@link https://testanything.org/tap-version-14-specification.html#escaping TAP 14 specification}
  51. * @param {string} [source]
  52. */
  53. function getEscapedSource(source) {
  54. if (!source) return source;
  55. let output = '';
  56. for (const char of source) {
  57. switch (char.codePointAt(0)) {
  58. case 0x005c: // `\`
  59. case 0x0023: // `#`
  60. output += '\\';
  61. output += char;
  62. break;
  63. default:
  64. output += char;
  65. break;
  66. }
  67. }
  68. return output;
  69. }
  70. module.exports = tapFormatter;