test-dom-shim.js 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. /* eslint-disable no-empty-function */
  2. // Minimal DOM-like globals for Node test runtime.
  3. if (typeof globalThis.window === "undefined") {
  4. globalThis.window = globalThis;
  5. }
  6. if (typeof globalThis.self === "undefined") {
  7. globalThis.self = globalThis;
  8. }
  9. if (typeof globalThis.postMessage === "undefined") {
  10. globalThis.postMessage = function postMessage() {};
  11. }
  12. if (typeof globalThis.self.postMessage === "undefined") {
  13. globalThis.self.postMessage = globalThis.postMessage;
  14. }
  15. if (typeof globalThis.self.addEventListener === "undefined") {
  16. globalThis.self.addEventListener = function addEventListener() {};
  17. }
  18. if (typeof globalThis.self.removeEventListener === "undefined") {
  19. globalThis.self.removeEventListener = function removeEventListener() {};
  20. }
  21. if (typeof globalThis.navigator === "undefined") {
  22. globalThis.navigator = { userAgent: "node.js" };
  23. }
  24. const createNoopElement = (tagName = "div") => ({
  25. tagName: String(tagName).toUpperCase(),
  26. style: {},
  27. dataset: {},
  28. classList: { add() {}, remove() {}, contains() { return false; } },
  29. children: [],
  30. childNodes: [],
  31. appendChild() {},
  32. removeChild() {},
  33. setAttribute() {},
  34. getAttribute() { return null; },
  35. addEventListener() {},
  36. removeEventListener() {},
  37. dispatchEvent() { return false; },
  38. querySelector() { return null; },
  39. querySelectorAll() { return []; },
  40. getBoundingClientRect() {
  41. return { x: 0, y: 0, top: 0, left: 0, right: 0, bottom: 0, width: 0, height: 0 };
  42. }
  43. });
  44. if (typeof globalThis.document === "undefined") {
  45. const body = createNoopElement("body");
  46. const head = createNoopElement("head");
  47. const documentElement = createNoopElement("html");
  48. globalThis.document = {
  49. documentElement,
  50. body,
  51. head,
  52. activeElement: body,
  53. createElement: createNoopElement,
  54. createElementNS(_ns, tagName) { return createNoopElement(tagName); },
  55. createTextNode(text) { return { textContent: String(text) }; },
  56. getElementById() { return null; },
  57. getElementsByClassName() { return []; },
  58. querySelector() { return null; },
  59. querySelectorAll() { return []; },
  60. addEventListener() {},
  61. removeEventListener() {},
  62. hasFocus() { return false; },
  63. execCommand() { return false; }
  64. };
  65. }
  66. if (typeof globalThis.HTMLElement === "undefined") {
  67. globalThis.HTMLElement = function HTMLElement() {};
  68. }
  69. if (typeof globalThis.Element === "undefined") {
  70. globalThis.Element = globalThis.HTMLElement;
  71. }
  72. if (typeof globalThis.Node === "undefined") {
  73. globalThis.Node = function Node() {};
  74. }
  75. if (typeof globalThis.MutationObserver === "undefined") {
  76. globalThis.MutationObserver = class MutationObserver {
  77. disconnect() {}
  78. observe() {}
  79. takeRecords() { return []; }
  80. };
  81. }
  82. if (typeof globalThis.ResizeObserver === "undefined") {
  83. globalThis.ResizeObserver = class ResizeObserver {
  84. disconnect() {}
  85. observe() {}
  86. unobserve() {}
  87. };
  88. }
  89. if (typeof globalThis.getComputedStyle === "undefined") {
  90. globalThis.getComputedStyle = () => ({ overflow: "visible" });
  91. }
  92. if (typeof globalThis.requestAnimationFrame === "undefined") {
  93. globalThis.requestAnimationFrame = (cb) => setTimeout(() => cb(Date.now()), 0);
  94. }
  95. if (typeof globalThis.cancelAnimationFrame === "undefined") {
  96. globalThis.cancelAnimationFrame = (id) => clearTimeout(id);
  97. }
  98. if (typeof globalThis.customElements === "undefined") {
  99. globalThis.customElements = {
  100. define() {},
  101. get() { return undefined; }
  102. };
  103. }
  104. // Some optional runtime provider SDKs are not present in local test env.
  105. // Stub them only when module resolution fails.
  106. const Module = require("module");
  107. const originalLoad = Module._load;
  108. const optionalModuleStubs = {
  109. "@cloudflare/sandbox": {
  110. getSandbox() {
  111. return {};
  112. }
  113. },
  114. "@vercel/sandbox": {
  115. Sandbox: {
  116. create: async () => ({}),
  117. get: async () => ({})
  118. }
  119. }
  120. };
  121. Module._load = function patchedModuleLoad(request, parent, isMain) {
  122. if (Object.prototype.hasOwnProperty.call(optionalModuleStubs, request)) {
  123. try {
  124. return originalLoad.call(this, request, parent, isMain);
  125. } catch (error) {
  126. if (error && error.code === "MODULE_NOT_FOUND") {
  127. return optionalModuleStubs[request];
  128. }
  129. throw error;
  130. }
  131. }
  132. return originalLoad.call(this, request, parent, isMain);
  133. };