using AngleSharp.Dom; using XFESystem.Desktop; namespace XFESystem.Browser.Tests; public sealed class PreviewWorkReuseTests { private sealed class Transport(string html) : IWebTransport { public WebResponse Get(Uri address,BrowserLimits limits)=>new(address,200,"text/html",html); } private static BrowserService Page(string body,string css="") { var browser=new BrowserService(new Transport(""+body)); browser.Navigate("http://example.test/");browser.Layout(new(300,100));return browser; } [Fact] public void VerticalScrollReusesBoxesAndKeepsOldSnapshotGeometryAndCanvasBackground() { var browser=Page("

one

two

three

four

","body{background:#102538}"); var node=browser.Document!.GetElementById("B")!;var first=browser.Layout(new(300,100));long passes=browser.LayoutPassCount; var next=browser.Layout(new(300,100,0,20)); Assert.Equal(passes,browser.LayoutPassCount);Assert.Equal(1,browser.ScrollLayoutReuseCount); Assert.Equal(40,first.GetBoundingClientRect(node).Y);Assert.Equal(20,next.GetBoundingClientRect(node).Y); Assert.Equal(next.GetBoundingClientRect(node).Y,next.HitTest(10,25)!.BorderBox.Y-20); Assert.All(next.Commands.Where(c=>c.ViewportPinned),c=>Assert.Equal(20,c.Bounds.Y)); Assert.All(first.Commands.Where(c=>c.ViewportPinned),c=>Assert.Equal(0,c.Bounds.Y)); } [Theory][InlineData("fixed;top:0",0,20,false)][InlineData("sticky;top:0",0,20,false)] [InlineData("sticky;left:0",0,20,true)][InlineData("sticky;left:0",20,0,false)] public void PositionedScrollFallbackDependsOnAffectedAxis(string position,double x,double y,bool reuse) { var browser=Page("

one

two

three

","#A{position:"+position+"}");long passes=browser.LayoutPassCount; browser.Layout(new(300,100,x,y));Assert.Equal(passes+(reuse?0:1),browser.LayoutPassCount); } [Fact] public void MutationAndResizeStillRebuildAfterAReusedScroll() { var browser=Page("

one

two

three

");browser.Layout(new(300,100,0,20));long passes=browser.LayoutPassCount; browser.ExecuteJavaScript("document.getElementById('A').style.height='80px'"); var changed=browser.Layout(new(300,100,0,20));Assert.Equal(80,changed.GetBoundingClientRect(browser.Document!.GetElementById("A")!).Height); Assert.True(browser.LayoutPassCount>passes);passes=browser.LayoutPassCount; browser.Layout(new(200,100,0,20));Assert.Equal(passes+1,browser.LayoutPassCount); } [Fact] public void MovingAcrossPlainParagraphsDoesNotRebuildForUnrelatedButtonHoverRules() { var browser=Page("

one

two

","button:hover{color:red}"); long passes=browser.LayoutPassCount,revision=browser.Revision; browser.Pointer(new("mousemove",10,10));browser.Pointer(new("mousemove",10,50));browser.Layout(new(300,100)); Assert.Equal(passes,browser.LayoutPassCount);Assert.Equal(revision,browser.Revision); } [Fact] public void HoverAncestorDescendantAndNotSelectorsStillRebuildAndApplyStyles() { var browser=Page("

one

two

","#P:hover #A{color:#ff0000}#P:not(:hover) #A{color:#0000ff}"); browser.Pointer(new("mousemove",10,10));var list=browser.Layout(new(300,100)); Assert.Equal(0xff0000u,list.GetComputedStyle(browser.Document!.GetElementById("A")!)!.Color.Rgb); browser.Pointer(new("mousemove",10,50));list=browser.Layout(new(300,100)); Assert.Equal(0x0000ffu,list.GetComputedStyle(browser.Document!.GetElementById("A")!)!.Color.Rgb); } [Fact] public void IndexedSimpleClassRulesKeepSpecificityOrderAndGeneratedContent() { var browser=Page("

one

",".Target{color:red}#A{color:green}.Target{color:blue!important}.Target::before{content:'icon'}"); var list=browser.Layout(new(300,100));var node=browser.Document!.GetElementById("A")!; Assert.Equal(0x0000ffu,list.GetComputedStyle(node)!.Color.Rgb); Assert.Contains(list.Commands,c=>c.Kind==BrowserDrawKind.Text&&c.Text=="icon"); browser.ExecuteJavaScript("document.getElementById('A').className='Other'");list=browser.Layout(new(300,100)); Assert.Equal(0x008000u,list.GetComputedStyle(node)!.Color.Rgb); Assert.DoesNotContain(list.Commands,c=>c.Kind==BrowserDrawKind.Text&&c.Text=="icon"); } [Fact] public void ComplexClassSelectorsStayOnTheFullMatcherPath() { var browser=Page("

one

",".Parent .Target{color:red}:is(.Target){color:blue}.Parent:not(.Missing) .Target{color:#123456}"); var list=browser.Layout(new(300,100));Assert.Equal(0x123456u,list.GetComputedStyle(browser.Document!.GetElementById("A")!)!.Color.Rgb); } }