runFixtureTests.js 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. import { multiple as getFixtures } from "@babel/helper-fixtures";
  2. export function runFixtureTests(fixturesPath, parseFunction) {
  3. const fixtures = getFixtures(fixturesPath);
  4. Object.keys(fixtures).forEach(function(name) {
  5. fixtures[name].forEach(function(testSuite) {
  6. testSuite.tests.forEach(function(task) {
  7. const testFn = task.disabled ? it.skip : it;
  8. testFn(name + "/" + testSuite.title + "/" + task.title, function() {
  9. try {
  10. runTest(task, parseFunction);
  11. } catch (err) {
  12. err.message =
  13. name + "/" + task.actual.filename + ": " + err.message;
  14. throw err;
  15. }
  16. });
  17. });
  18. });
  19. });
  20. }
  21. export function runThrowTestsWithEstree(fixturesPath, parseFunction) {
  22. const fixtures = getFixtures(fixturesPath);
  23. Object.keys(fixtures).forEach(function(name) {
  24. fixtures[name].forEach(function(testSuite) {
  25. testSuite.tests.forEach(function(task) {
  26. if (!task.options.throws) return;
  27. task.options.plugins = task.options.plugins || [];
  28. task.options.plugins.push("estree");
  29. const testFn = task.disabled ? it.skip : it;
  30. testFn(name + "/" + testSuite.title + "/" + task.title, function() {
  31. try {
  32. runTest(task, parseFunction);
  33. } catch (err) {
  34. err.message =
  35. name + "/" + task.actual.filename + ": " + err.message;
  36. throw err;
  37. }
  38. });
  39. });
  40. });
  41. });
  42. }
  43. function save(test, ast) {
  44. // Ensure that RegExp are serialized as strings
  45. const toJSON = RegExp.prototype.toJSON;
  46. RegExp.prototype.toJSON = RegExp.prototype.toString;
  47. require("fs").writeFileSync(test.expect.loc, JSON.stringify(ast, null, " "));
  48. RegExp.prototype.toJSON = toJSON;
  49. }
  50. function runTest(test, parseFunction) {
  51. const opts = test.options;
  52. if (opts.throws && test.expect.code) {
  53. throw new Error(
  54. "File expected.json exists although options specify throws. Remove expected.json.",
  55. );
  56. }
  57. let ast;
  58. try {
  59. ast = parseFunction(test.actual.code, opts);
  60. } catch (err) {
  61. if (opts.throws) {
  62. if (err.message === opts.throws) {
  63. return;
  64. } else {
  65. err.message =
  66. "Expected error message: " +
  67. opts.throws +
  68. ". Got error message: " +
  69. err.message;
  70. throw err;
  71. }
  72. }
  73. throw err;
  74. }
  75. if (ast.comments && !ast.comments.length) delete ast.comments;
  76. if (!test.expect.code && !opts.throws && !process.env.CI) {
  77. test.expect.loc += "on";
  78. return save(test, ast);
  79. }
  80. if (opts.throws) {
  81. throw new Error(
  82. "Expected error message: " + opts.throws + ". But parsing succeeded.",
  83. );
  84. } else {
  85. const mis = misMatch(JSON.parse(test.expect.code), ast);
  86. if (mis) {
  87. throw new Error(mis);
  88. }
  89. }
  90. }
  91. function ppJSON(v) {
  92. v = v instanceof RegExp ? v.toString() : v;
  93. return JSON.stringify(v, null, 2);
  94. }
  95. function addPath(str, pt) {
  96. if (str.charAt(str.length - 1) == ")") {
  97. return str.slice(0, str.length - 1) + "/" + pt + ")";
  98. } else {
  99. return str + " (" + pt + ")";
  100. }
  101. }
  102. function misMatch(exp, act) {
  103. if (exp instanceof RegExp || act instanceof RegExp) {
  104. const left = ppJSON(exp);
  105. const right = ppJSON(act);
  106. if (left !== right) return left + " !== " + right;
  107. } else if (Array.isArray(exp)) {
  108. if (!Array.isArray(act)) return ppJSON(exp) + " != " + ppJSON(act);
  109. if (act.length != exp.length) {
  110. return "array length mismatch " + exp.length + " != " + act.length;
  111. }
  112. for (let i = 0; i < act.length; ++i) {
  113. const mis = misMatch(exp[i], act[i]);
  114. if (mis) return addPath(mis, i);
  115. }
  116. } else if (!exp || !act || typeof exp != "object" || typeof act != "object") {
  117. if (exp !== act && typeof exp != "function") {
  118. return ppJSON(exp) + " !== " + ppJSON(act);
  119. }
  120. } else {
  121. for (const prop in exp) {
  122. const mis = misMatch(exp[prop], act[prop]);
  123. if (mis) return addPath(mis, prop);
  124. }
  125. for (const prop in act) {
  126. if (typeof act[prop] === "function") {
  127. continue;
  128. }
  129. if (!(prop in exp) && act[prop] !== undefined) {
  130. return `Did not expect a property '${prop}'`;
  131. }
  132. }
  133. }
  134. }