rebase.js 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. "use strict";
  2. var __create = Object.create;
  3. var __defProp = Object.defineProperty;
  4. var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
  5. var __getOwnPropNames = Object.getOwnPropertyNames;
  6. var __getProtoOf = Object.getPrototypeOf;
  7. var __hasOwnProp = Object.prototype.hasOwnProperty;
  8. var __export = (target, all) => {
  9. for (var name in all)
  10. __defProp(target, name, { get: all[name], enumerable: true });
  11. };
  12. var __copyProps = (to, from, except, desc) => {
  13. if (from && typeof from === "object" || typeof from === "function") {
  14. for (let key of __getOwnPropNames(from))
  15. if (!__hasOwnProp.call(to, key) && key !== except)
  16. __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
  17. }
  18. return to;
  19. };
  20. var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
  21. // If the importer is in node compatibility mode or this is not an ESM
  22. // file that has been converted to a CommonJS file using a Babel-
  23. // compatible transform (i.e. "__esModule" has not been set), then set
  24. // "default" to the CommonJS "module.exports" for node compatibility.
  25. isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
  26. mod
  27. ));
  28. var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
  29. var rebase_exports = {};
  30. __export(rebase_exports, {
  31. addSuggestedRebaseline: () => addSuggestedRebaseline,
  32. applySuggestedRebaselines: () => applySuggestedRebaselines,
  33. clearSuggestedRebaselines: () => clearSuggestedRebaselines
  34. });
  35. module.exports = __toCommonJS(rebase_exports);
  36. var import_fs = __toESM(require("fs"));
  37. var import_path = __toESM(require("path"));
  38. var import_utils = require("playwright-core/lib/utils");
  39. var import_utils2 = require("playwright-core/lib/utils");
  40. var import_utilsBundle = require("playwright-core/lib/utilsBundle");
  41. var import_projectUtils = require("./projectUtils");
  42. var import_babelBundle = require("../transform/babelBundle");
  43. const t = import_babelBundle.types;
  44. const suggestedRebaselines = new import_utils.MultiMap();
  45. function addSuggestedRebaseline(location, suggestedRebaseline) {
  46. suggestedRebaselines.set(location.file, { location, code: suggestedRebaseline });
  47. }
  48. function clearSuggestedRebaselines() {
  49. suggestedRebaselines.clear();
  50. }
  51. async function applySuggestedRebaselines(config, reporter) {
  52. if (config.config.updateSnapshots === "none")
  53. return;
  54. if (!suggestedRebaselines.size)
  55. return;
  56. const [project] = (0, import_projectUtils.filterProjects)(config.projects, config.cliProjectFilter);
  57. if (!project)
  58. return;
  59. const patches = [];
  60. const files = [];
  61. const gitCache = /* @__PURE__ */ new Map();
  62. const patchFile = import_path.default.join(project.project.outputDir, "rebaselines.patch");
  63. for (const fileName of [...suggestedRebaselines.keys()].sort()) {
  64. const source = await import_fs.default.promises.readFile(fileName, "utf8");
  65. const lines = source.split("\n");
  66. const replacements = suggestedRebaselines.get(fileName);
  67. const fileNode = (0, import_babelBundle.babelParse)(source, fileName, true);
  68. const ranges = [];
  69. (0, import_babelBundle.traverse)(fileNode, {
  70. CallExpression: (path2) => {
  71. const node = path2.node;
  72. if (node.arguments.length < 1)
  73. return;
  74. if (!t.isMemberExpression(node.callee))
  75. return;
  76. const argument = node.arguments[0];
  77. if (!t.isStringLiteral(argument) && !t.isTemplateLiteral(argument))
  78. return;
  79. const prop = node.callee.property;
  80. if (!prop.loc || !argument.start || !argument.end)
  81. return;
  82. for (const replacement of replacements) {
  83. if (prop.loc.start.line !== replacement.location.line)
  84. continue;
  85. if (prop.loc.start.column + 1 !== replacement.location.column)
  86. continue;
  87. const indent = lines[prop.loc.start.line - 1].match(/^\s*/)[0];
  88. const newText = replacement.code.replace(/\{indent\}/g, indent);
  89. ranges.push({ start: argument.start, end: argument.end, oldText: source.substring(argument.start, argument.end), newText });
  90. break;
  91. }
  92. }
  93. });
  94. ranges.sort((a, b) => b.start - a.start);
  95. let result = source;
  96. for (const range of ranges)
  97. result = result.substring(0, range.start) + range.newText + result.substring(range.end);
  98. const relativeName = import_path.default.relative(process.cwd(), fileName);
  99. files.push(relativeName);
  100. if (config.config.updateSourceMethod === "overwrite") {
  101. await import_fs.default.promises.writeFile(fileName, result);
  102. } else if (config.config.updateSourceMethod === "3way") {
  103. await import_fs.default.promises.writeFile(fileName, applyPatchWithConflictMarkers(source, result));
  104. } else {
  105. const gitFolder = findGitRoot(import_path.default.dirname(fileName), gitCache);
  106. const relativeToGit = import_path.default.relative(gitFolder || process.cwd(), fileName);
  107. patches.push(createPatch(relativeToGit, source, result));
  108. }
  109. }
  110. const fileList = files.map((file) => " " + import_utils2.colors.dim(file)).join("\n");
  111. reporter.onStdErr(`
  112. New baselines created for:
  113. ${fileList}
  114. `);
  115. if (config.config.updateSourceMethod === "patch") {
  116. await import_fs.default.promises.mkdir(import_path.default.dirname(patchFile), { recursive: true });
  117. await import_fs.default.promises.writeFile(patchFile, patches.join("\n"));
  118. reporter.onStdErr(`
  119. ` + import_utils2.colors.cyan("git apply " + import_path.default.relative(process.cwd(), patchFile)) + "\n");
  120. }
  121. }
  122. function createPatch(fileName, before, after) {
  123. const file = fileName.replace(/\\/g, "/");
  124. const text = import_utilsBundle.diff.createPatch(file, before, after, void 0, void 0, { context: 3 });
  125. return [
  126. "diff --git a/" + file + " b/" + file,
  127. "--- a/" + file,
  128. "+++ b/" + file,
  129. ...text.split("\n").slice(4)
  130. ].join("\n");
  131. }
  132. function findGitRoot(dir, cache) {
  133. const result = cache.get(dir);
  134. if (result !== void 0)
  135. return result;
  136. const gitPath = import_path.default.join(dir, ".git");
  137. if (import_fs.default.existsSync(gitPath) && import_fs.default.lstatSync(gitPath).isDirectory()) {
  138. cache.set(dir, dir);
  139. return dir;
  140. }
  141. const parentDir = import_path.default.dirname(dir);
  142. if (dir === parentDir) {
  143. cache.set(dir, null);
  144. return null;
  145. }
  146. const parentResult = findGitRoot(parentDir, cache);
  147. cache.set(dir, parentResult);
  148. return parentResult;
  149. }
  150. function applyPatchWithConflictMarkers(oldText, newText) {
  151. const diffResult = import_utilsBundle.diff.diffLines(oldText, newText);
  152. let result = "";
  153. let conflict = false;
  154. diffResult.forEach((part) => {
  155. if (part.added) {
  156. if (conflict) {
  157. result += part.value;
  158. result += ">>>>>>> SNAPSHOT\n";
  159. conflict = false;
  160. } else {
  161. result += "<<<<<<< HEAD\n";
  162. result += part.value;
  163. result += "=======\n";
  164. conflict = true;
  165. }
  166. } else if (part.removed) {
  167. result += "<<<<<<< HEAD\n";
  168. result += part.value;
  169. result += "=======\n";
  170. conflict = true;
  171. } else {
  172. if (conflict) {
  173. result += ">>>>>>> SNAPSHOT\n";
  174. conflict = false;
  175. }
  176. result += part.value;
  177. }
  178. });
  179. if (conflict)
  180. result += ">>>>>>> SNAPSHOT\n";
  181. return result;
  182. }
  183. // Annotate the CommonJS export names for ESM import in node:
  184. 0 && (module.exports = {
  185. addSuggestedRebaseline,
  186. applySuggestedRebaselines,
  187. clearSuggestedRebaselines
  188. });