You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Jest测试ContentEditable类时无法获取目标DOM元素的问题

Why contentEditable.editables is Always Empty in Your Jest Test?

Ah, I spot the key mistake here! You've created your div element correctly, but you haven't added it to the DOM tree—and that's why document.querySelectorAll can't find it.

The Root Cause

When you use document.createElement("div"), the element only exists in memory; it's not attached to any part of the active document. document.querySelectorAll searches through elements that are actually part of the page's DOM, so your in-memory element is invisible to it.

Fix 1: Add the Element to the DOM (and Clean Up After)

Modify your test to append the element to document.body before instantiating ContentEditable, then remove it afterward to avoid polluting other tests:

test('editables of kind text', () => { 
  let element = document.createElement("div"); 
  element.dataset.editablekind = 'text';

  // Attach the element to the DOM so querySelectorAll can find it
  document.body.appendChild(element);

  const contentEditable = new ContentEditable('text'); 
  expect([...contentEditable.editables].length).toEqual(1); 

  // Clean up: remove the element to prevent side effects for other tests
  document.body.removeChild(element);
});

Fix 2: Use a Test Container for Cleaner Cleanup

For better organization, you can create a dedicated container for test elements and manage it with Jest's hooks:

let testContainer;

// Set up the container before each test
beforeEach(() => {
  testContainer = document.createElement('div');
  document.body.appendChild(testContainer);
});

// Clean up the container after each test
afterEach(() => {
  document.body.removeChild(testContainer);
});

test('editables of kind text', () => { 
  let element = document.createElement("div"); 
  element.dataset.editablekind = 'text';
  testContainer.appendChild(element);

  const contentEditable = new ContentEditable('text'); 
  expect([...contentEditable.editables].length).toEqual(1); 
});

Bonus: Optional Class Enhancement (For Better Testability)

If you want to avoid touching the global DOM in tests entirely, you could modify your ContentEditable class to accept an optional root element for querying. This makes testing more isolated:

class ContentEditable { 
  constructor(editableKind, root = document){ 
    this.editables = root.querySelectorAll(`[data-editablekind='${editableKind}']`); 
    this.editionStrategy = this.getStrategy(editableKind) 
  } 
}

Then in your test, you can use an in-memory container without attaching it to the body:

test('editables of kind text', () => { 
  const testContainer = document.createElement('div');
  let element = document.createElement("div"); 
  element.dataset.editablekind = 'text';
  testContainer.appendChild(element);

  // Pass the test container as the root for querying
  const contentEditable = new ContentEditable('text', testContainer); 
  expect([...contentEditable.editables].length).toEqual(1); 
});

This keeps your tests self-contained and avoids any global DOM changes.

内容的提问来源于stack exchange,提问作者David Geismar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.08 23:02:46