using System.Text.Json;
namespace XFESystem.Browser.Tests;
public sealed class RemotePageProofTests
{
private const string Hash = "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef";
[Fact]
public void PublishedProofBindsActualLayoutSourceAndSnapshotWithoutInvalidatingPaint()
{
var page = new BrowserService(new Fixture()); page.Navigate("https://example.test/");
page.Layout(new(800, 500)); long passes = page.LayoutPassCount, revision = page.Revision;
using var proof = JsonDocument.Parse(page.ReadRemotePageProof(12)); var value = proof.RootElement;
Assert.Equal(Hash, value.GetProperty("BodySha256").GetString());
Assert.Equal(12, value.GetProperty("SnapshotSequence").GetInt64());
Assert.Equal("Remote fixture", value.GetProperty("Title").GetString());
Assert.Contains(value.GetProperty("TextRuns").EnumerateArray(), item => item.GetProperty("Text").GetString()!.Contains("Actual"));
Assert.Contains(value.GetProperty("SearchInputs").EnumerateArray(), item => item.GetProperty("Name").GetString() == "q" && item.GetProperty("Bounds").GetProperty("Width").GetDouble() > 0);
Assert.Single(value.GetProperty("LoadedStyles").EnumerateArray());
Assert.Single(value.GetProperty("DeclaredStyleLinks").EnumerateArray());
Assert.Equal(passes, page.LayoutPassCount); Assert.Equal(revision, page.Revision);
}
[Fact]
public void OfflineNavigationNeverReusesPreviousRemoteEvidence()
{
var page = new BrowserService(new Fixture()); page.Navigate("https://example.test/"); page.Layout(new(800, 500));
Assert.NotEqual("{}", page.ReadRemotePageProof());
page.Navigate("about:Start"); page.Layout(new(800, 500)); Assert.Equal("{}", page.ReadRemotePageProof());
}
[Fact]
public void MissingCertificateOrBodyEvidenceCannotBecomeRemoteProof()
{
var page = new BrowserService(new Fixture(verified: false));
Assert.Equal("Navigation failed", page.Navigate("https://example.test/").Title);
Assert.Equal("{}", page.ReadRemotePageProof());
page = new(new Fixture(hash: null)); page.Navigate("https://example.test/"); page.Layout(new(800, 500));
Assert.Equal("{}", page.ReadRemotePageProof());
}
[Theory]
[InlineData(false)]
[InlineData(true)]
public void ActualStylePaintAndProofRetainRequestedAndFinalUrls(bool redirectStyle)
{
var page = new BrowserService(new Fixture(redirectStyle: redirectStyle));
page.Navigate("https://example.test/");
var layout = page.Layout(new(800, 500));
Assert.Contains(layout.Commands, command => command.Kind == BrowserDrawKind.Text &&
command.Text.Contains("Actual", StringComparison.Ordinal) && command.Color == 0x123456);
var receipt = Assert.Single(page.LoadedResources, item => item.Kind == "style");
string final = redirectStyle ? "https://cdn.example.test/FinalStyle.css" : "https://example.test/Style.css";
Assert.Equal("https://example.test/Style.css", receipt.RequestedAddress);
Assert.Equal(final, receipt.Address);
using var proof = JsonDocument.Parse(page.ReadRemotePageProof(14));
var style = Assert.Single(proof.RootElement.GetProperty("LoadedStyles").EnumerateArray());
Assert.Equal("https://example.test/Style.css", style.GetProperty("RequestedAddress").GetString());
Assert.Equal(final, style.GetProperty("Address").GetString());
Assert.Equal(final, style.GetProperty("FinalAddress").GetString());
Assert.Equal(style.GetProperty("RequestedAddress").GetString(),
Assert.Single(proof.RootElement.GetProperty("DeclaredStyleLinks").EnumerateArray()).GetString());
}
[Fact]
public void RedirectedStylesheetWithInvalidTlsDoesNotBecomeLoadedProof()
{
var page = new BrowserService(new Fixture(redirectStyle: true, styleVerified: false));
page.Navigate("https://example.test/"); page.Layout(new(800, 500));
Assert.DoesNotContain(page.LoadedResources, item => item.Kind == "style");
using var proof = JsonDocument.Parse(page.ReadRemotePageProof(15));
Assert.Empty(proof.RootElement.GetProperty("LoadedStyles").EnumerateArray());
Assert.Single(proof.RootElement.GetProperty("DeclaredStyleLinks").EnumerateArray());
}
[Fact]
public void VisibleMissingImageCannotBeHiddenByClippedOrOffscreenTelemetry()
{
var page = new BrowserService(new GeometryFixture("![]()
Actual remote text
", verified, BodySha256: hash); } }