using AngleSharp.Html.Parser;
namespace XFESystem.Browser.Tests;
public sealed class BrowserChildMutationTests
{
[Fact]
public void ReplaceChildrenMovesRealNodesAndExpandsFragments()
{
Run("""
const parent=document.querySelector('div'),first=parent.firstChild,fragment=document.createDocumentFragment();
fragment.append('tail',document.createElement('i'));parent.replaceChildren('new',first,fragment,null,undefined);
if(parent.childNodes.length!==6||first.parentNode!==parent||fragment.childNodes.length!==0||parent.textContent!=='newAtailnullundefined')throw Error('replaceChildren');
parent.replaceChildren();if(parent.childNodes.length!==0)throw Error('clear');
""");
}
[Fact]
public void BeforeAfterAndReplaceWithPreserveRealSiblingOrder()
{
Run("""
const parent=document.querySelector('div'),a=parent.firstChild,b=parent.lastChild;
a.before('start');b.after('end');a.replaceWith('replacement');
if(parent.textContent!=='startreplacementBend'||a.parentNode!==null)throw Error('order');
b.before(b,'X');b.after('Y',b);if(parent.textContent!=='startreplacementYBXend')throw Error('receiver move');
const text=parent.firstChild;text.replaceWith('s','t');if(parent.textContent!=='streplacementYBXend')throw Error('text node');
""");
}
[Fact]
public void ReplacementRejectsCyclesAndDetachedChildNodeOperationsAreInert()
{
Run("""
const parent=document.querySelector('div'),child=parent.firstChild;let errors=0;
try{parent.replaceChildren(parent);}catch{errors++;}try{child.replaceWith(parent);}catch{errors++;}
if(errors!==2||parent.textContent!=='AB')throw Error('cycle');
const detached=document.createElement('p');detached.before('x');detached.after('x');detached.replaceWith('x');
if(detached.parentNode!==null||detached.textContent!=='')throw Error('detached');
""");
}
private static void Run(string code)
{
var runtime = new JavaScriptRuntime();
var doc = new HtmlParser().ParseDocument("<div><b>A</b><b>B</b></div>");
_ = new DomBridge(runtime, doc, new("http://xfesystem.local/"), new());
var result = runtime.Evaluate(code);
Assert.True(result.Success, result.Error);
}
}
using AngleSharp.Html.Parser;
namespace XFESystem.Browser.Tests;
public sealed class BrowserChildMutationTests
{
[Fact]
public void ReplaceChildrenMovesRealNodesAndExpandsFragments()
{
Run("""
const parent=document.querySelector('div'),first=parent.firstChild,fragment=document.createDocumentFragment();
fragment.append('tail',document.createElement('i'));parent.replaceChildren('new',first,fragment,null,undefined);
if(parent.childNodes.length!==6||first.parentNode!==parent||fragment.childNodes.length!==0||parent.textContent!=='newAtailnullundefined')throw Error('replaceChildren');
parent.replaceChildren();if(parent.childNodes.length!==0)throw Error('clear');
""");
}
[Fact]
public void BeforeAfterAndReplaceWithPreserveRealSiblingOrder()
{
Run("""
const parent=document.querySelector('div'),a=parent.firstChild,b=parent.lastChild;
a.before('start');b.after('end');a.replaceWith('replacement');
if(parent.textContent!=='startreplacementBend'||a.parentNode!==null)throw Error('order');
b.before(b,'X');b.after('Y',b);if(parent.textContent!=='startreplacementYBXend')throw Error('receiver move');
const text=parent.firstChild;text.replaceWith('s','t');if(parent.textContent!=='streplacementYBXend')throw Error('text node');
""");
}
[Fact]
public void ReplacementRejectsCyclesAndDetachedChildNodeOperationsAreInert()
{
Run("""
const parent=document.querySelector('div'),child=parent.firstChild;let errors=0;
try{parent.replaceChildren(parent);}catch{errors++;}try{child.replaceWith(parent);}catch{errors++;}
if(errors!==2||parent.textContent!=='AB')throw Error('cycle');
const detached=document.createElement('p');detached.before('x');detached.after('x');detached.replaceWith('x');
if(detached.parentNode!==null||detached.textContent!=='')throw Error('detached');
""");
}
private static void Run(string code)
{
var runtime = new JavaScriptRuntime();
var doc = new HtmlParser().ParseDocument("<div><b>A</b><b>B</b></div>");
_ = new DomBridge(runtime, doc, new("http://xfesystem.local/"), new());
var result = runtime.Evaluate(code);
Assert.True(result.Success, result.Error);
}
}