@tkeron/html-parser 0.1.1 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,688 @@
1
+ import { describe, it, expect } from "bun:test";
2
+ import { parseHTML } from "../index";
3
+ import { NodeType } from "../src/dom-simulator";
4
+
5
+ describe("DOM Manipulation - insertBefore", () => {
6
+ describe("Basic insertBefore functionality", () => {
7
+ it("should insert a node before another node in the middle", () => {
8
+ const doc = parseHTML("<div><span>First</span><span>Third</span></div>");
9
+ const div = doc.querySelector("div");
10
+ const firstSpan = div.childNodes[0];
11
+ const thirdSpan = div.childNodes[1];
12
+
13
+ const newSpan = doc.createElement("span");
14
+ newSpan.textContent = "Second";
15
+
16
+ div.insertBefore(newSpan, thirdSpan);
17
+
18
+ expect(div.childNodes.length).toBe(3);
19
+ expect(div.childNodes[0]).toBe(firstSpan);
20
+ expect(div.childNodes[1]).toBe(newSpan);
21
+ expect(div.childNodes[2]).toBe(thirdSpan);
22
+ });
23
+
24
+ it("should insert a node at the beginning", () => {
25
+ const doc = parseHTML("<div><span>Second</span><span>Third</span></div>");
26
+ const div = doc.querySelector("div");
27
+ const secondSpan = div.childNodes[0];
28
+
29
+ const newSpan = doc.createElement("span");
30
+ newSpan.textContent = "First";
31
+
32
+ div.insertBefore(newSpan, secondSpan);
33
+
34
+ expect(div.childNodes.length).toBe(3);
35
+ expect(div.childNodes[0]).toBe(newSpan);
36
+ expect(div.childNodes[1]).toBe(secondSpan);
37
+ expect(div.firstChild).toBe(newSpan);
38
+ });
39
+
40
+ it("should append when reference node is null", () => {
41
+ const doc = parseHTML("<div><span>First</span></div>");
42
+ const div = doc.querySelector("div");
43
+
44
+ const newSpan = doc.createElement("span");
45
+ newSpan.textContent = "Last";
46
+
47
+ div.insertBefore(newSpan, null);
48
+
49
+ expect(div.childNodes.length).toBe(2);
50
+ expect(div.childNodes[1]).toBe(newSpan);
51
+ expect(div.lastChild).toBe(newSpan);
52
+ });
53
+
54
+ it("should throw error when reference node is not a child", () => {
55
+ const doc = parseHTML("<div><span>Child</span></div>");
56
+ const div = doc.querySelector("div");
57
+ const otherSpan = doc.createElement("span");
58
+ const newSpan = doc.createElement("span");
59
+
60
+ expect(() => {
61
+ div.insertBefore(newSpan, otherSpan);
62
+ }).toThrow("Reference node is not a child of this node");
63
+ });
64
+ });
65
+
66
+ describe("insertBefore with text nodes", () => {
67
+ it("should insert text node before element node", () => {
68
+ const doc = parseHTML("<div><span>Element</span></div>");
69
+ const div = doc.querySelector("div");
70
+ const span = div.childNodes[0];
71
+
72
+ const textNode = doc.createTextNode("Text before ");
73
+
74
+ div.insertBefore(textNode, span);
75
+
76
+ expect(div.childNodes.length).toBe(2);
77
+ expect(div.childNodes[0]).toBe(textNode);
78
+ expect(div.childNodes[1]).toBe(span);
79
+ expect(div.firstChild).toBe(textNode);
80
+ });
81
+
82
+ it("should insert element node before text node", () => {
83
+ const doc = parseHTML("<div>Some text</div>");
84
+ const div = doc.querySelector("div");
85
+ const textNode = div.childNodes[0];
86
+
87
+ const span = doc.createElement("span");
88
+ span.textContent = "Element";
89
+
90
+ div.insertBefore(span, textNode);
91
+
92
+ expect(div.childNodes.length).toBe(2);
93
+ expect(div.childNodes[0]).toBe(span);
94
+ expect(div.childNodes[1]).toBe(textNode);
95
+ });
96
+ });
97
+
98
+ describe("insertBefore sibling relationships", () => {
99
+ it("should update nextSibling and previousSibling correctly", () => {
100
+ const doc = parseHTML("<div><span>A</span><span>C</span></div>");
101
+ const div = doc.querySelector("div");
102
+ const spanA = div.childNodes[0];
103
+ const spanC = div.childNodes[1];
104
+
105
+ const spanB = doc.createElement("span");
106
+ spanB.textContent = "B";
107
+
108
+ div.insertBefore(spanB, spanC);
109
+
110
+ expect(spanA.nextSibling).toBe(spanB);
111
+ expect(spanB.previousSibling).toBe(spanA);
112
+ expect(spanB.nextSibling).toBe(spanC);
113
+ expect(spanC.previousSibling).toBe(spanB);
114
+ });
115
+
116
+ it("should update firstChild when inserting at beginning", () => {
117
+ const doc = parseHTML("<div><span>Second</span></div>");
118
+ const div = doc.querySelector("div");
119
+ const secondSpan = div.childNodes[0];
120
+
121
+ const firstSpan = doc.createElement("span");
122
+ firstSpan.textContent = "First";
123
+
124
+ div.insertBefore(firstSpan, secondSpan);
125
+
126
+ expect(div.firstChild).toBe(firstSpan);
127
+ expect(firstSpan.previousSibling).toBeNull();
128
+ expect(firstSpan.nextSibling).toBe(secondSpan);
129
+ });
130
+
131
+ it("should not change lastChild when inserting before last", () => {
132
+ const doc = parseHTML("<div><span>A</span><span>C</span></div>");
133
+ const div = doc.querySelector("div");
134
+ const spanC = div.childNodes[1];
135
+
136
+ const spanB = doc.createElement("span");
137
+ div.insertBefore(spanB, spanC);
138
+
139
+ expect(div.lastChild).toBe(spanC);
140
+ });
141
+ });
142
+
143
+ describe("insertBefore element-specific relationships", () => {
144
+ it("should update children array correctly", () => {
145
+ const doc = parseHTML("<div><span>A</span><span>C</span></div>");
146
+ const div = doc.querySelector("div");
147
+ const spanC = div.children[1];
148
+
149
+ const spanB = doc.createElement("span");
150
+ spanB.textContent = "B";
151
+
152
+ div.insertBefore(spanB, spanC);
153
+
154
+ expect(div.children.length).toBe(3);
155
+ expect(div.children[0].textContent).toBe("A");
156
+ expect(div.children[1]).toBe(spanB);
157
+ expect(div.children[2]).toBe(spanC);
158
+ });
159
+
160
+ it("should update nextElementSibling and previousElementSibling", () => {
161
+ const doc = parseHTML("<div><span>A</span><span>C</span></div>");
162
+ const div = doc.querySelector("div");
163
+ const spanA = div.children[0];
164
+ const spanC = div.children[1];
165
+
166
+ const spanB = doc.createElement("span");
167
+ div.insertBefore(spanB, spanC);
168
+
169
+ expect(spanA.nextElementSibling).toBe(spanB);
170
+ expect(spanB.previousElementSibling).toBe(spanA);
171
+ expect(spanB.nextElementSibling).toBe(spanC);
172
+ expect(spanC.previousElementSibling).toBe(spanB);
173
+ });
174
+
175
+ it("should update firstElementChild when inserting element at beginning", () => {
176
+ const doc = parseHTML("<div><span>Second</span></div>");
177
+ const div = doc.querySelector("div");
178
+ const secondSpan = div.childNodes[0];
179
+
180
+ const firstSpan = doc.createElement("span");
181
+ div.insertBefore(firstSpan, secondSpan);
182
+
183
+ expect(div.firstElementChild).toBe(firstSpan);
184
+ });
185
+
186
+ it("should handle inserting element before text node", () => {
187
+ const doc = parseHTML("<div>Text<span>After</span></div>");
188
+ const div = doc.querySelector("div");
189
+ const textNode = div.childNodes[0];
190
+ const spanAfter = div.childNodes[1];
191
+
192
+ const spanBefore = doc.createElement("span");
193
+ spanBefore.textContent = "Before";
194
+
195
+ div.insertBefore(spanBefore, textNode);
196
+
197
+ expect(div.children.length).toBe(2);
198
+ expect(div.children[0]).toBe(spanBefore);
199
+ expect(div.children[1]).toBe(spanAfter);
200
+ expect(div.firstElementChild).toBe(spanBefore);
201
+ expect(spanBefore.nextElementSibling).toBe(spanAfter);
202
+ });
203
+ });
204
+
205
+ describe("insertBefore synchronization", () => {
206
+ it("should update innerHTML after inserting node", () => {
207
+ const doc = parseHTML("<div><span>A</span><span>C</span></div>");
208
+ const div = doc.querySelector("div");
209
+ const spanC = div.childNodes[1];
210
+
211
+ const spanB = doc.createElement("span");
212
+ spanB.textContent = "B";
213
+
214
+ div.insertBefore(spanB, spanC);
215
+
216
+ expect(div.innerHTML).toBe("<span>A</span><span>B</span><span>C</span>");
217
+ });
218
+
219
+ it("should update outerHTML of parent after inserting node", () => {
220
+ const doc = parseHTML("<div><span>A</span></div>");
221
+ const div = doc.querySelector("div");
222
+ const spanA = div.childNodes[0];
223
+
224
+ const spanB = doc.createElement("span");
225
+ spanB.textContent = "B";
226
+
227
+ div.insertBefore(spanB, spanA);
228
+
229
+ expect(div.outerHTML).toBe("<div><span>B</span><span>A</span></div>");
230
+ });
231
+
232
+ it("should update textContent correctly", () => {
233
+ const doc = parseHTML("<div><span>World</span></div>");
234
+ const div = doc.querySelector("div");
235
+ const spanWorld = div.childNodes[0];
236
+
237
+ const textNode = doc.createTextNode("Hello ");
238
+ div.insertBefore(textNode, spanWorld);
239
+
240
+ expect(div.textContent).toBe("Hello World");
241
+ });
242
+
243
+ it("should set parentNode correctly", () => {
244
+ const doc = parseHTML("<div></div>");
245
+ const div = doc.querySelector("div");
246
+
247
+ const span = doc.createElement("span");
248
+ div.insertBefore(span, null);
249
+
250
+ expect(span.parentNode).toBe(div);
251
+ expect(span.parentElement).toBe(div);
252
+ });
253
+ });
254
+
255
+ describe("insertBefore with node relocation", () => {
256
+ it("should remove node from previous parent when inserting", () => {
257
+ const doc = parseHTML(
258
+ "<div id='parent1'><span>Child</span></div><div id='parent2'></div>"
259
+ );
260
+ const parent1 = doc.querySelector("#parent1");
261
+ const parent2 = doc.querySelector("#parent2");
262
+ const child = parent1.querySelector("span");
263
+
264
+ parent2.insertBefore(child, null);
265
+
266
+ expect(parent1.childNodes.length).toBe(0);
267
+ expect(parent2.childNodes.length).toBe(1);
268
+ expect(child.parentNode).toBe(parent2);
269
+ });
270
+
271
+ it("should update all relationships when moving node between parents", () => {
272
+ const doc = parseHTML(
273
+ "<div id='p1'><span>A</span><span>B</span></div><div id='p2'><span>C</span></div>"
274
+ );
275
+ const parent1 = doc.querySelector("#p1");
276
+ const parent2 = doc.querySelector("#p2");
277
+ const spanB = parent1.children[1];
278
+ const spanC = parent2.children[0];
279
+
280
+ parent2.insertBefore(spanB, spanC);
281
+
282
+ expect(parent1.children.length).toBe(1);
283
+ expect(parent2.children.length).toBe(2);
284
+ expect(spanB.parentNode).toBe(parent2);
285
+ expect(spanB.nextElementSibling).toBe(spanC);
286
+ expect(spanC.previousElementSibling).toBe(spanB);
287
+ });
288
+ });
289
+ });
290
+
291
+ describe("DOM Manipulation - replaceChild", () => {
292
+ describe("Basic replaceChild functionality", () => {
293
+ it("should replace a child node with a new node", () => {
294
+ const doc = parseHTML("<div><span>Old</span></div>");
295
+ const div = doc.querySelector("div");
296
+ const oldSpan = div.childNodes[0];
297
+
298
+ const newSpan = doc.createElement("span");
299
+ newSpan.textContent = "New";
300
+
301
+ const returned = div.replaceChild(newSpan, oldSpan);
302
+
303
+ expect(returned).toBe(oldSpan);
304
+ expect(div.childNodes.length).toBe(1);
305
+ expect(div.childNodes[0]).toBe(newSpan);
306
+ expect(div.childNodes[0]).not.toBe(oldSpan);
307
+ });
308
+
309
+ it("should throw error when old child is not a child of parent", () => {
310
+ const doc = parseHTML("<div><span>Child</span></div>");
311
+ const div = doc.querySelector("div");
312
+ const notAChild = doc.createElement("span");
313
+ const newSpan = doc.createElement("span");
314
+
315
+ expect(() => {
316
+ div.replaceChild(newSpan, notAChild);
317
+ }).toThrow("Old child is not a child of this node");
318
+ });
319
+
320
+ it("should replace middle child in multiple children", () => {
321
+ const doc = parseHTML(
322
+ "<div><span>First</span><span>Old</span><span>Third</span></div>"
323
+ );
324
+ const div = doc.querySelector("div");
325
+ const oldSpan = div.childNodes[1];
326
+
327
+ const newSpan = doc.createElement("span");
328
+ newSpan.textContent = "New";
329
+
330
+ div.replaceChild(newSpan, oldSpan);
331
+
332
+ expect(div.childNodes.length).toBe(3);
333
+ expect(div.childNodes[1]).toBe(newSpan);
334
+ expect(div.childNodes[1].textContent).toBe("New");
335
+ });
336
+ });
337
+
338
+ describe("replaceChild with different node types", () => {
339
+ it("should replace element with text node", () => {
340
+ const doc = parseHTML("<div><span>Element</span></div>");
341
+ const div = doc.querySelector("div");
342
+ const span = div.childNodes[0];
343
+
344
+ const textNode = doc.createTextNode("Just text");
345
+ div.replaceChild(textNode, span);
346
+
347
+ expect(div.childNodes.length).toBe(1);
348
+ expect(div.childNodes[0].nodeType).toBe(NodeType.TEXT_NODE);
349
+ expect(div.childNodes[0].textContent).toBe("Just text");
350
+ expect(div.children.length).toBe(0);
351
+ });
352
+
353
+ it("should replace text node with element", () => {
354
+ const doc = parseHTML("<div>Text</div>");
355
+ const div = doc.querySelector("div");
356
+ const textNode = div.childNodes[0];
357
+
358
+ const span = doc.createElement("span");
359
+ span.textContent = "Element";
360
+
361
+ div.replaceChild(span, textNode);
362
+
363
+ expect(div.childNodes.length).toBe(1);
364
+ expect(div.childNodes[0].nodeType).toBe(NodeType.ELEMENT_NODE);
365
+ expect(div.children.length).toBe(1);
366
+ expect(div.children[0]).toBe(span);
367
+ });
368
+
369
+ it("should replace text node with text node", () => {
370
+ const doc = parseHTML("<div>Old text</div>");
371
+ const div = doc.querySelector("div");
372
+ const oldText = div.childNodes[0];
373
+
374
+ const newText = doc.createTextNode("New text");
375
+ div.replaceChild(newText, oldText);
376
+
377
+ expect(div.childNodes.length).toBe(1);
378
+ expect(div.childNodes[0]).toBe(newText);
379
+ expect(div.textContent).toBe("New text");
380
+ });
381
+ });
382
+
383
+ describe("replaceChild sibling relationships", () => {
384
+ it("should transfer sibling relationships to new node", () => {
385
+ const doc = parseHTML(
386
+ "<div><span>A</span><span>Old</span><span>C</span></div>"
387
+ );
388
+ const div = doc.querySelector("div");
389
+ const spanA = div.childNodes[0];
390
+ const oldSpan = div.childNodes[1];
391
+ const spanC = div.childNodes[2];
392
+
393
+ const newSpan = doc.createElement("span");
394
+ newSpan.textContent = "B";
395
+
396
+ div.replaceChild(newSpan, oldSpan);
397
+
398
+ expect(spanA.nextSibling).toBe(newSpan);
399
+ expect(newSpan.previousSibling).toBe(spanA);
400
+ expect(newSpan.nextSibling).toBe(spanC);
401
+ expect(spanC.previousSibling).toBe(newSpan);
402
+ });
403
+
404
+ it("should update firstChild when replacing first child", () => {
405
+ const doc = parseHTML("<div><span>Old</span><span>Second</span></div>");
406
+ const div = doc.querySelector("div");
407
+ const oldSpan = div.childNodes[0];
408
+
409
+ const newSpan = doc.createElement("span");
410
+ newSpan.textContent = "New";
411
+
412
+ div.replaceChild(newSpan, oldSpan);
413
+
414
+ expect(div.firstChild).toBe(newSpan);
415
+ expect(newSpan.previousSibling).toBeNull();
416
+ });
417
+
418
+ it("should update lastChild when replacing last child", () => {
419
+ const doc = parseHTML("<div><span>First</span><span>Old</span></div>");
420
+ const div = doc.querySelector("div");
421
+ const oldSpan = div.childNodes[1];
422
+
423
+ const newSpan = doc.createElement("span");
424
+ newSpan.textContent = "New";
425
+
426
+ div.replaceChild(newSpan, oldSpan);
427
+
428
+ expect(div.lastChild).toBe(newSpan);
429
+ expect(newSpan.nextSibling).toBeNull();
430
+ });
431
+
432
+ it("should clear old child's relationships", () => {
433
+ const doc = parseHTML("<div><span>A</span><span>Old</span><span>C</span></div>");
434
+ const div = doc.querySelector("div");
435
+ const oldSpan = div.childNodes[1];
436
+
437
+ const newSpan = doc.createElement("span");
438
+ div.replaceChild(newSpan, oldSpan);
439
+
440
+ expect(oldSpan.parentNode).toBeNull();
441
+ expect(oldSpan.parentElement).toBeNull();
442
+ expect(oldSpan.previousSibling).toBeNull();
443
+ expect(oldSpan.nextSibling).toBeNull();
444
+ });
445
+ });
446
+
447
+ describe("replaceChild element-specific relationships", () => {
448
+ it("should update children array when replacing element with element", () => {
449
+ const doc = parseHTML(
450
+ "<div><span>A</span><span>Old</span><span>C</span></div>"
451
+ );
452
+ const div = doc.querySelector("div");
453
+ const oldSpan = div.children[1];
454
+
455
+ const newSpan = doc.createElement("span");
456
+ newSpan.textContent = "B";
457
+
458
+ div.replaceChild(newSpan, oldSpan);
459
+
460
+ expect(div.children.length).toBe(3);
461
+ expect(div.children[1]).toBe(newSpan);
462
+ expect(div.children[1].textContent).toBe("B");
463
+ });
464
+
465
+ it("should update element sibling relationships", () => {
466
+ const doc = parseHTML(
467
+ "<div><span>A</span><span>Old</span><span>C</span></div>"
468
+ );
469
+ const div = doc.querySelector("div");
470
+ const spanA = div.children[0];
471
+ const oldSpan = div.children[1];
472
+ const spanC = div.children[2];
473
+
474
+ const newSpan = doc.createElement("span");
475
+ div.replaceChild(newSpan, oldSpan);
476
+
477
+ expect(spanA.nextElementSibling).toBe(newSpan);
478
+ expect(newSpan.previousElementSibling).toBe(spanA);
479
+ expect(newSpan.nextElementSibling).toBe(spanC);
480
+ expect(spanC.previousElementSibling).toBe(newSpan);
481
+ });
482
+
483
+ it("should update firstElementChild when replacing first element", () => {
484
+ const doc = parseHTML("<div><span>Old</span><span>Second</span></div>");
485
+ const div = doc.querySelector("div");
486
+ const oldSpan = div.children[0];
487
+
488
+ const newSpan = doc.createElement("span");
489
+ div.replaceChild(newSpan, oldSpan);
490
+
491
+ expect(div.firstElementChild).toBe(newSpan);
492
+ });
493
+
494
+ it("should update lastElementChild when replacing last element", () => {
495
+ const doc = parseHTML("<div><span>First</span><span>Old</span></div>");
496
+ const div = doc.querySelector("div");
497
+ const oldSpan = div.children[1];
498
+
499
+ const newSpan = doc.createElement("span");
500
+ div.replaceChild(newSpan, oldSpan);
501
+
502
+ expect(div.lastElementChild).toBe(newSpan);
503
+ });
504
+
505
+ it("should remove from children array when replacing element with text", () => {
506
+ const doc = parseHTML(
507
+ "<div><span>A</span><span>Old</span><span>C</span></div>"
508
+ );
509
+ const div = doc.querySelector("div");
510
+ const spanA = div.children[0];
511
+ const oldSpan = div.children[1];
512
+ const spanC = div.children[2];
513
+
514
+ const textNode = doc.createTextNode("Text");
515
+ div.replaceChild(textNode, oldSpan);
516
+
517
+ expect(div.children.length).toBe(2);
518
+ expect(div.children[0]).toBe(spanA);
519
+ expect(div.children[1]).toBe(spanC);
520
+ expect(spanA.nextElementSibling).toBe(spanC);
521
+ expect(spanC.previousElementSibling).toBe(spanA);
522
+ });
523
+
524
+ it("should add to children array when replacing text with element", () => {
525
+ const doc = parseHTML("<div><span>A</span>Text<span>C</span></div>");
526
+ const div = doc.querySelector("div");
527
+ const textNode = div.childNodes[1];
528
+
529
+ const newSpan = doc.createElement("span");
530
+ newSpan.textContent = "B";
531
+
532
+ div.replaceChild(newSpan, textNode);
533
+
534
+ expect(div.children.length).toBe(3);
535
+ expect(div.children[1]).toBe(newSpan);
536
+ expect(div.children[0].nextElementSibling).toBe(newSpan);
537
+ expect(div.children[2].previousElementSibling).toBe(newSpan);
538
+ });
539
+ });
540
+
541
+ describe("replaceChild synchronization", () => {
542
+ it("should update innerHTML after replacement", () => {
543
+ const doc = parseHTML("<div><span>Old</span></div>");
544
+ const div = doc.querySelector("div");
545
+ const oldSpan = div.childNodes[0];
546
+
547
+ const newSpan = doc.createElement("span");
548
+ newSpan.textContent = "New";
549
+
550
+ div.replaceChild(newSpan, oldSpan);
551
+
552
+ expect(div.innerHTML).toBe("<span>New</span>");
553
+ });
554
+
555
+ it("should update outerHTML after replacement", () => {
556
+ const doc = parseHTML("<div><span>Old</span></div>");
557
+ const div = doc.querySelector("div");
558
+ const oldSpan = div.childNodes[0];
559
+
560
+ const newSpan = doc.createElement("b");
561
+ newSpan.textContent = "Bold";
562
+
563
+ div.replaceChild(newSpan, oldSpan);
564
+
565
+ expect(div.outerHTML).toBe("<div><b>Bold</b></div>");
566
+ });
567
+
568
+ it("should update textContent correctly", () => {
569
+ const doc = parseHTML("<div><span>Old</span></div>");
570
+ const div = doc.querySelector("div");
571
+ const oldSpan = div.childNodes[0];
572
+
573
+ const newSpan = doc.createElement("span");
574
+ newSpan.textContent = "New Text";
575
+
576
+ div.replaceChild(newSpan, oldSpan);
577
+
578
+ expect(div.textContent).toBe("New Text");
579
+ });
580
+ });
581
+
582
+ describe("replaceChild with node relocation", () => {
583
+ it("should remove node from previous parent before replacing", () => {
584
+ const doc = parseHTML(
585
+ "<div id='p1'><span>Moving</span></div><div id='p2'><span>Old</span></div>"
586
+ );
587
+ const parent1 = doc.querySelector("#p1");
588
+ const parent2 = doc.querySelector("#p2");
589
+ const movingSpan = parent1.querySelector("span");
590
+ const oldSpan = parent2.querySelector("span");
591
+
592
+ parent2.replaceChild(movingSpan, oldSpan);
593
+
594
+ expect(parent1.childNodes.length).toBe(0);
595
+ expect(parent2.childNodes.length).toBe(1);
596
+ expect(movingSpan.parentNode).toBe(parent2);
597
+ });
598
+ });
599
+ });
600
+
601
+ describe("DOM Manipulation - insertAfter", () => {
602
+ describe("Basic insertAfter functionality", () => {
603
+ it("should insert node after reference node", () => {
604
+ const doc = parseHTML("<div><span>First</span><span>Third</span></div>");
605
+ const div = doc.querySelector("div");
606
+ const firstSpan = div.childNodes[0];
607
+
608
+ const secondSpan = doc.createElement("span");
609
+ secondSpan.textContent = "Second";
610
+
611
+ div.insertAfter(secondSpan, firstSpan);
612
+
613
+ expect(div.childNodes.length).toBe(3);
614
+ expect(div.childNodes[0]).toBe(firstSpan);
615
+ expect(div.childNodes[1]).toBe(secondSpan);
616
+ expect(firstSpan.nextSibling).toBe(secondSpan);
617
+ });
618
+
619
+ it("should insert at end when reference node is last child", () => {
620
+ const doc = parseHTML("<div><span>First</span></div>");
621
+ const div = doc.querySelector("div");
622
+ const firstSpan = div.childNodes[0];
623
+
624
+ const secondSpan = doc.createElement("span");
625
+ secondSpan.textContent = "Second";
626
+
627
+ div.insertAfter(secondSpan, firstSpan);
628
+
629
+ expect(div.childNodes.length).toBe(2);
630
+ expect(div.lastChild).toBe(secondSpan);
631
+ expect(firstSpan.nextSibling).toBe(secondSpan);
632
+ });
633
+
634
+ it("should insert at beginning when reference node is null", () => {
635
+ const doc = parseHTML("<div><span>Second</span></div>");
636
+ const div = doc.querySelector("div");
637
+
638
+ const firstSpan = doc.createElement("span");
639
+ firstSpan.textContent = "First";
640
+
641
+ div.insertAfter(firstSpan, null);
642
+
643
+ expect(div.childNodes.length).toBe(2);
644
+ expect(div.firstChild).toBe(firstSpan);
645
+ });
646
+
647
+ it("should throw error when reference node is not a child", () => {
648
+ const doc = parseHTML("<div><span>Child</span></div>");
649
+ const div = doc.querySelector("div");
650
+ const notAChild = doc.createElement("span");
651
+ const newSpan = doc.createElement("span");
652
+
653
+ expect(() => {
654
+ div.insertAfter(newSpan, notAChild);
655
+ }).toThrow("Reference node is not a child of this node");
656
+ });
657
+ });
658
+
659
+ describe("insertAfter synchronization", () => {
660
+ it("should update innerHTML correctly", () => {
661
+ const doc = parseHTML("<div><span>A</span><span>C</span></div>");
662
+ const div = doc.querySelector("div");
663
+ const spanA = div.childNodes[0];
664
+
665
+ const spanB = doc.createElement("span");
666
+ spanB.textContent = "B";
667
+
668
+ div.insertAfter(spanB, spanA);
669
+
670
+ expect(div.innerHTML).toBe("<span>A</span><span>B</span><span>C</span>");
671
+ });
672
+
673
+ it("should update sibling relationships correctly", () => {
674
+ const doc = parseHTML("<div><span>A</span><span>C</span></div>");
675
+ const div = doc.querySelector("div");
676
+ const spanA = div.childNodes[0];
677
+ const spanC = div.childNodes[1];
678
+
679
+ const spanB = doc.createElement("span");
680
+ div.insertAfter(spanB, spanA);
681
+
682
+ expect(spanA.nextSibling).toBe(spanB);
683
+ expect(spanB.previousSibling).toBe(spanA);
684
+ expect(spanB.nextSibling).toBe(spanC);
685
+ expect(spanC.previousSibling).toBe(spanB);
686
+ });
687
+ });
688
+ });