/
githubmirror
/
preact
Обзор
Документация
Войти
/
githubmirror
/
preact
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
10.29.4
test/browser/replaceNode.test.jsx
239 строк
6 KB
Marvin Hagemeister
chore: rename *.js -> *.jsx when JSX is used
21 мар 2026, 21:21
21 мар 2026, 21:21
cd1c4af
Код
Авторство
О чём код?
import { createElement, render, Component } from 'preact'; import { setupScratch, teardown, serializeHtml, sortAttributes } from '../_util/helpers'; /** @jsx createElement */ describe('replaceNode parameter in render()', () => { let scratch; /** * @param {HTMLDivElement} container * @returns {HTMLDivElement[]} */ function setupABCDom(container) { return ['a', 'b', 'c'].map(id => { const child = document.createElement('div'); child.id = id; container.appendChild(child); return child; }); } beforeEach(() => { scratch = setupScratch(); }); afterEach(() => { teardown(scratch); }); it('should use replaceNode as render root and not inject into it', () => { setupABCDom(scratch); const childA = scratch.querySelector('#a'); render(<div id="a">contents</div>, scratch, childA); expect(scratch.querySelector('#a')).to.equalNode(childA); expect(childA.innerHTML).to.equal('contents'); }); it('should not remove siblings of replaceNode', () => { setupABCDom(scratch); const childA = scratch.querySelector('#a'); render(<div id="a" />, scratch, childA); expect(scratch.innerHTML).to.equal( '<div id="a"></div><div id="b"></div><div id="c"></div>' ); }); it('should notice prop changes on replaceNode', () => { setupABCDom(scratch); const childA = scratch.querySelector('#a'); render(<div id="a" className="b" />, scratch, childA); expect(sortAttributes(String(scratch.innerHTML))).to.equal( sortAttributes( '<div id="a" class="b"></div><div id="b"></div><div id="c"></div>' ) ); }); it('should unmount existing components', () => { const unmount = sinon.spy(); const mount = sinon.spy(); class App extends Component { componentDidMount() { mount(); } componentWillUnmount() { unmount(); } render() { return <div>App</div>; } } render( <div id="a"> <App /> </div>, scratch ); expect(scratch.innerHTML).to.equal('<div id="a"><div>App</div></div>'); expect(mount).to.be.calledOnce; render(<div id="a">new</div>, scratch, scratch.querySelector('#a')); expect(scratch.innerHTML).to.equal('<div id="a">new</div>'); expect(unmount).to.be.calledOnce; }); it('should unmount existing components in prerendered HTML', () => { const unmount = sinon.spy(); const mount = sinon.spy(); class App extends Component { componentDidMount() { mount(); } componentWillUnmount() { unmount(); } render() { return <span>App</span>; } } scratch.innerHTML = `<div id="child"></div>`; const childContainer = scratch.querySelector('#child'); render(<App />, childContainer); expect(serializeHtml(childContainer)).to.equal('<span>App</span>'); expect(mount).to.be.calledOnce; render(<div />, scratch, scratch.firstElementChild); expect(serializeHtml(scratch)).to.equal('<div id=""></div>'); expect(unmount).to.be.calledOnce; }); it('should render multiple render roots in one parentDom', () => { setupABCDom(scratch); const childA = scratch.querySelector('#a'); const childB = scratch.querySelector('#b'); const childC = scratch.querySelector('#c'); const expectedA = '<div id="a">childA</div>'; const expectedB = '<div id="b">childB</div>'; const expectedC = '<div id="c">childC</div>'; render(<div id="a">childA</div>, scratch, childA); render(<div id="b">childB</div>, scratch, childB); render(<div id="c">childC</div>, scratch, childC); expect(scratch.innerHTML).to.equal(`${expectedA}${expectedB}${expectedC}`); }); it('should call unmount when working with replaceNode', () => { const mountSpy = sinon.spy(); const unmountSpy = sinon.spy(); class MyComponent extends Component { componentDidMount() { mountSpy(); } componentWillUnmount() { unmountSpy(); } render() { return <div>My Component</div>; } } const container = document.createElement('div'); scratch.appendChild(container); render(<MyComponent />, scratch, container); expect(mountSpy).to.be.calledOnce; render(<div>Not my component</div>, document.body, container); expect(unmountSpy).to.be.calledOnce; }); it('should double replace', () => { const container = document.createElement('div'); scratch.appendChild(container); render(<div>Hello</div>, scratch, scratch.firstElementChild); expect(scratch.innerHTML).to.equal('<div>Hello</div>'); render(<div>Hello</div>, scratch, scratch.firstElementChild); expect(scratch.innerHTML).to.equal('<div>Hello</div>'); }); it('should replaceNode after rendering', () => { function App({ i }) { return <p>{i}</p>; } render(<App i={2} />, scratch); expect(scratch.innerHTML).to.equal('<p>2</p>'); render(<App i={3} />, scratch, scratch.firstChild); expect(scratch.innerHTML).to.equal('<p>3</p>'); }); it("shouldn't remove elements on subsequent renders with replaceNode", () => { const placeholder = document.createElement('div'); scratch.appendChild(placeholder); const App = () => ( <div> New content <button>Update</button> </div> ); render(<App />, scratch, placeholder); expect(scratch.innerHTML).to.equal( '<div>New content<button>Update</button></div>' ); render(<App />, scratch, placeholder); expect(scratch.innerHTML).to.equal( '<div>New content<button>Update</button></div>' ); }); it('should remove redundant elements on subsequent renders with replaceNode', () => { const placeholder = document.createElement('div'); scratch.appendChild(placeholder); const App = () => ( <div> New content <button>Update</button> </div> ); render(<App />, scratch, placeholder); expect(scratch.innerHTML).to.equal( '<div>New content<button>Update</button></div>' ); placeholder.appendChild(document.createElement('span')); expect(scratch.innerHTML).to.equal( '<div>New content<button>Update</button><span></span></div>' ); render(<App />, scratch, placeholder); expect(scratch.innerHTML).to.equal( '<div>New content<button>Update</button></div>' ); }); });