aboutsummaryrefslogtreecommitdiff
path: root/js/test.js
blob: 3f1b6ff54d789d089c1d364158956dc7034f912f (plain)
  1. #!/usr/bin/env node
  2. "use strict";
  3. var fs = require('fs');
  4. var commonmark = require('./lib/index.js');
  5. // Home made mini-version of the npm ansi module:
  6. var escSeq = function(s) {
  7. return function (){
  8. process.stdout.write('\u001b' + s);
  9. return this;
  10. };
  11. };
  12. var repeat = function(pattern, count) {
  13. if (count < 1) {
  14. return '';
  15. }
  16. var result = '';
  17. while (count > 1) {
  18. if (count & 1) {
  19. result += pattern;
  20. }
  21. count >>= 1;
  22. pattern += pattern;
  23. }
  24. return result + pattern;
  25. };
  26. var cursor = {
  27. write: function (s) {
  28. process.stdout.write(s);
  29. return this;
  30. },
  31. green: escSeq('[0;32m'),
  32. red: escSeq('[0;31m'),
  33. cyan: escSeq('[0;36m'),
  34. reset: escSeq('[0m')
  35. };
  36. var writer = new commonmark.HtmlRenderer();
  37. var reader = new commonmark.DocParser();
  38. var results = {
  39. passed: 0,
  40. failed: 0
  41. };
  42. var showSpaces = function(s) {
  43. var t = s;
  44. return t.replace(/\t/g, '→')
  45. .replace(/ /g, '␣');
  46. };
  47. var pathologicalTest = function(testcase, results) {
  48. cursor.write(testcase.name + ' ');
  49. console.time(' elapsed time');
  50. var actual = writer.render(reader.parse(testcase.input));
  51. if (actual === testcase.expected) {
  52. cursor.green().write('✓\n').reset();
  53. results.passed += 1;
  54. } else {
  55. cursor.red().write('✘\n');
  56. cursor.cyan();
  57. cursor.write('=== markdown ===============\n');
  58. cursor.write(showSpaces(testcase.input));
  59. cursor.write('=== expected ===============\n');
  60. cursor.write(showSpaces(testcase.expected));
  61. cursor.write('=== got ====================\n');
  62. cursor.write(showSpaces(actual));
  63. cursor.write('\n');
  64. cursor.reset();
  65. results.failed += 1;
  66. }
  67. console.timeEnd(' elapsed time');
  68. };
  69. fs.readFile('spec.txt', 'utf8', function(err, data) {
  70. if (err) {
  71. return console.log(err);
  72. }
  73. var i;
  74. var examples = [];
  75. var current_section = "";
  76. var example_number = 0;
  77. var tests = data
  78. .replace(/\r\n?/g, "\n") // Normalize newlines for platform independence
  79. .replace(/^<!-- END TESTS -->(.|[\n])*/m, '');
  80. tests.replace(/^\.\n([\s\S]*?)^\.\n([\s\S]*?)^\.$|^#{1,6} *(.*)$/gm,
  81. function(_, markdownSubmatch, htmlSubmatch, sectionSubmatch){
  82. if (sectionSubmatch) {
  83. current_section = sectionSubmatch;
  84. } else {
  85. example_number++;
  86. examples.push({markdown: markdownSubmatch,
  87. html: htmlSubmatch,
  88. section: current_section,
  89. number: example_number});
  90. }
  91. });
  92. current_section = "";
  93. cursor.write('Spec tests:\n\n');
  94. console.time("Elapsed time");
  95. for (i = 0; i < examples.length; i++) {
  96. var example = examples[i];
  97. if (example.section !== current_section) {
  98. if (current_section !== '') {
  99. cursor.write('\n');
  100. }
  101. current_section = example.section;
  102. cursor.reset().write(current_section).reset().write(' ');
  103. }
  104. var actual = writer.render(reader.parse(example.markdown.replace(/→/g, '\t')));
  105. if (actual === example.html) {
  106. results.passed++;
  107. cursor.green().write('✓').reset();
  108. } else {
  109. results.failed++;
  110. cursor.write('\n');
  111. cursor.red().write('✘ Example ' + example.number + '\n');
  112. cursor.cyan();
  113. cursor.write('=== markdown ===============\n');
  114. cursor.write(showSpaces(example.markdown));
  115. cursor.write('=== expected ===============\n');
  116. cursor.write(showSpaces(example.html));
  117. cursor.write('=== got ====================\n');
  118. cursor.write(showSpaces(actual));
  119. cursor.reset();
  120. }
  121. }
  122. cursor.write('\n');
  123. console.timeEnd("Elapsed time");
  124. // pathological cases
  125. cursor.write('\nPathological cases:\n');
  126. var cases = [
  127. { name: 'U+0000 in input',
  128. input: 'abc\u0000xyz\u0000\n',
  129. expected: '<p>abc\ufffdxyz\ufffd</p>\n' },
  130. { name: 'nested strong emph 10000 deep',
  131. input: repeat('*a **a ', 10000) + 'b' + repeat(' a** a*', 10000),
  132. expected: '<p>' + repeat('<em>a <strong>a ', 10000) + 'b' +
  133. repeat(' a</strong> a</em>', 10000) + '</p>\n' },
  134. { name: 'nested brackets 10000 deep',
  135. input: repeat('[', 10000) + 'a' + repeat(']', 10000),
  136. expected: '<p>' + repeat('[', 10000) + 'a' + repeat(']', 10000) +
  137. '</p>\n' },
  138. { name: 'nested block quote 10000 deep',
  139. input: repeat('> ', 10000) + 'a\n',
  140. expected: repeat('<blockquote>\n', 10000) + '<p>a</p>\n' +
  141. repeat('</blockquote>\n', 10000) }
  142. ];
  143. for (i = 0; i < cases.length; i++) {
  144. pathologicalTest(cases[i], results);
  145. }
  146. cursor.write('\n');
  147. cursor.write(results.passed.toString() + ' tests passed, ' +
  148. results.failed.toString() + ' failed.\n');
  149. });