Skip to content

Commit 066f273

Browse files
committed
[lexical] Test: Use using for the #8563 regression editor
Manage the editor lifecycle with `using` and move root-element setup/teardown into a test extension's register function (setRootElement + document.body cleanup), matching the idiom used by the other reconciler repro tests. The editor's dispose also calls setRootElement(null), so the whole fixture tears down at end of scope without an afterEach. https://claude.ai/code/session_01EAeZ6geVH74SpUrRhY6Z8h
1 parent 4d6cdcb commit 066f273

1 file changed

Lines changed: 25 additions & 23 deletions

File tree

packages/lexical/src/__tests__/unit/Issue8563Repro.test.ts

Lines changed: 25 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,26 @@
66
*
77
*/
88

9-
import {buildEditorFromExtensions} from '@lexical/extension';
9+
import {buildEditorFromExtensions, defineExtension} from '@lexical/extension';
1010
import {RichTextExtension} from '@lexical/rich-text';
1111
import {$createParagraphNode, $createTextNode, $getRoot} from 'lexical';
12-
import {afterEach, describe, expect, test} from 'vitest';
12+
import {describe, expect, test} from 'vitest';
13+
14+
// Attaches a root element so DOM reconciliation runs, and returns a dispose
15+
// that detaches it. `buildEditorFromExtensions` disposal calls both this
16+
// cleanup and `editor.setRootElement(null)`, so a `using` editor tears the
17+
// whole thing down at end of scope.
18+
const TestRootElementExtension = defineExtension({
19+
name: 'issue-8563-root',
20+
register(editor) {
21+
const root = document.createElement('div');
22+
document.body.appendChild(root);
23+
editor.setRootElement(root);
24+
return () => {
25+
document.body.removeChild(root);
26+
};
27+
},
28+
});
1329

1430
// Regression test for https://github.com/facebook/lexical/issues/8563
1531
//
@@ -24,39 +40,25 @@ import {afterEach, describe, expect, test} from 'vitest';
2440
// pointers and reached a key that only exists in the next state, throwing
2541
// `reconcileNode: prevNode or nextNode does not exist in nodeMap`.
2642
describe('Issue #8563: full reconcile with same-size child key swap', () => {
27-
let cleanup: (() => void) | null = null;
28-
afterEach(() => {
29-
if (cleanup) {
30-
cleanup();
31-
cleanup = null;
32-
}
33-
});
34-
3543
test('undo (setEditorState) does not crash when a child is replaced by a different-key child of equal count', () => {
3644
const errors: Error[] = [];
37-
const editor = buildEditorFromExtensions({
38-
dependencies: [RichTextExtension],
45+
using editor = buildEditorFromExtensions({
46+
dependencies: [RichTextExtension, TestRootElementExtension],
3947
name: 'issue-8563-repro',
4048
onError: e => {
4149
errors.push(e);
4250
},
4351
});
44-
const root = document.createElement('div');
45-
document.body.appendChild(root);
46-
editor.setRootElement(root);
47-
cleanup = () => {
48-
editor.setRootElement(null);
49-
document.body.removeChild(root);
50-
editor.dispose();
51-
};
5252

5353
// State A: enough children to engage the fast path (>= 4).
5454
editor.update(
5555
() => {
56-
const r = $getRoot();
57-
r.clear();
56+
const root = $getRoot();
57+
root.clear();
5858
for (let i = 0; i < 5; i++) {
59-
r.append($createParagraphNode().append($createTextNode(`line ${i}`)));
59+
root.append(
60+
$createParagraphNode().append($createTextNode(`line ${i}`)),
61+
);
6062
}
6163
},
6264
{discrete: true},

0 commit comments

Comments
 (0)