Skip to content

Testing Examples

Common testing patterns for Hermes applications.

Basic Window Tests

Testing Window Configuration

csharp
[Fact]
public void Window_AppliesConfiguration()
{
    using var testWindow = new TestableHermesWindow()
        .SetTitle("My Application")
        .SetSize(1280, 720)
        .SetPosition(100, 100)
        .SetResizable(true);

    testWindow.Show();

    HermesAssert.HasTitle(testWindow.Backend, "My Application");
    HermesAssert.HasSize(testWindow.Backend, 1280, 720);
    HermesAssert.HasPosition(testWindow.Backend, 100, 100);
    HermesAssert.WasShown(testWindow.Backend);
}

Testing Window Lifecycle

csharp
[Fact]
public void Window_LifecycleEventsFireCorrectly()
{
    var closingCalled = false;

    using var testWindow = new TestableHermesWindow()
        .OnClosing(() => closingCalled = true);

    testWindow.Show();
    testWindow.Close();

    Assert.True(closingCalled);
    HermesAssert.WasClosed(testWindow.Backend);
}

Event Handler Tests

Testing Maximize/Restore

csharp
[Fact]
public void Window_MaximizeRestoreCycle()
{
    var events = new List<string>();

    using var testWindow = new TestableHermesWindow()
        .OnMaximized(() => events.Add("maximized"))
        .OnRestored(() => events.Add("restored"));

    testWindow.Show();

    testWindow.SimulateMaximize();
    Assert.True(testWindow.Backend.IsMaximized);

    testWindow.SimulateRestore();
    Assert.False(testWindow.Backend.IsMaximized);

    Assert.Equal(["maximized", "restored"], events);
}

Testing Resize Handler

csharp
[Fact]
public void Window_TracksResizeEvents()
{
    var resizeHistory = new List<(int W, int H)>();

    using var testWindow = new TestableHermesWindow()
        .SetSize(800, 600)
        .OnResized((w, h) => resizeHistory.Add((w, h)));

    testWindow.Show();

    testWindow.SimulateResize(1024, 768);
    testWindow.SimulateResize(1920, 1080);

    Assert.Equal([(1024, 768), (1920, 1080)], resizeHistory);
    HermesAssert.HasSize(testWindow.Backend, 1920, 1080);
}

WebView Communication Tests

Testing Message Receipt

csharp
[Fact]
public void Window_ProcessesWebMessages()
{
    var processedCommands = new List<string>();

    using var testWindow = new TestableHermesWindow()
        .OnWebMessage(msg =>
        {
            var json = JsonDocument.Parse(msg);
            var type = json.RootElement.GetProperty("type").GetString();
            processedCommands.Add(type!);
        });

    testWindow.Show();

    testWindow.SimulateWebMessage("""{"type":"save"}""");
    testWindow.SimulateWebMessage("""{"type":"load"}""");

    Assert.Equal(["save", "load"], processedCommands);
}

Testing Bidirectional Communication

csharp
[Fact]
public void Window_SendsResponseToWebView()
{
    using var testWindow = new TestableHermesWindow()
        .OnWebMessage(msg =>
        {
            if (msg.Contains("ping"))
            {
                testWindow.Window.SendWebMessage("""{"type":"pong"}""");
            }
        });

    testWindow.Show();
    testWindow.SimulateWebMessage("""{"type":"ping"}""");

    HermesAssert.SentWebMessageMatching(testWindow.Recording, "pong");
}

Custom Titlebar Tests

Testing Drag Region Detection

csharp
[Fact]
public void CustomTitlebar_DetectsDragRegions()
{
    using var testWindow = new TestableHermesWindow()
        .SetCustomTitleBar(true)
        .SetChromeless(true);

    testWindow.Show();

    // User clicks on draggable titlebar area
    testWindow.SimulateDragRegionClick();
    HermesAssert.DetectedDragRegionClick(testWindow.Recording);

    testWindow.Recording.Clear();

    // User clicks on a button in the titlebar
    testWindow.SimulateNonDragRegionClick();
    HermesAssert.DetectedNonDragRegionClick(testWindow.Recording);
}

Testing Double-Click to Maximize

csharp
[Fact]
public void CustomTitlebar_DoubleClickMaximizes()
{
    var maximizeCalled = false;

    using var testWindow = new TestableHermesWindow()
        .SetCustomTitleBar(true)
        .OnMaximized(() => maximizeCalled = true);

    testWindow.Show();
    testWindow.SimulateDragRegionDoubleClick();

    HermesAssert.DetectedDragRegionDoubleClick(testWindow.Recording);
    // Note: The actual maximize behavior depends on your app's handler
}

Testing URL Loading

csharp
[Fact]
public void Window_NavigatesToUrl()
{
    using var testWindow = new TestableHermesWindow()
        .Load("https://app.example.com/dashboard");

    testWindow.Show();

    HermesAssert.NavigatedTo(testWindow.Recording, "https://app.example.com/dashboard");
}

Testing Navigation Sequence

csharp
[Fact]
public void Window_TracksNavigationHistory()
{
    using var testWindow = new TestableHermesWindow();

    testWindow.Load("https://example.com/page1");
    testWindow.Show();

    // Simulate navigation via web message
    testWindow.Window.Load("https://example.com/page2");

    Assert.Contains("page1", testWindow.Recording.Navigations);
    Assert.Contains("page2", testWindow.Recording.Navigations);
}

Custom Scheme Tests

csharp
[Fact]
public void Window_RegistersCustomScheme()
{
    using var testWindow = new TestableHermesWindow();

    testWindow.Window.RegisterCustomScheme("myapp", url =>
    {
        if (url.EndsWith(".css"))
        {
            var css = "body { background: #fff; }";
            return (new MemoryStream(Encoding.UTF8.GetBytes(css)), "text/css");
        }
        return (null, null);
    });

    HermesAssert.CustomSchemeRegistered(testWindow.Backend, "myapp");

    // Test the handler
    var result = testWindow.Backend.TestCustomScheme("myapp", "myapp://styles/main.css");
    Assert.NotNull(result);
    Assert.Equal("text/css", result.Value.ContentType);
}

Platform-Specific Tests

csharp
[Theory]
[InlineData(HermesPlatform.Windows)]
[InlineData(HermesPlatform.macOS)]
[InlineData(HermesPlatform.Linux)]
public void Window_BehavesCorrectlyOnPlatform(HermesPlatform platform)
{
    var backend = new RecordingWindowBackend { Platform = platform };
    using var testWindow = new TestableHermesWindow(backend);

    testWindow.Show();

    // Test platform-specific behavior
    Assert.Equal(platform, testWindow.Backend.Platform);
}

Testing with Recording Queries

csharp
[Fact]
public void Recording_QueriesWorkCorrectly()
{
    using var testWindow = new TestableHermesWindow();
    testWindow.Show();
    testWindow.SimulateWebMessage("""{"action":"test"}""");

    var recording = testWindow.Recording;

    // Query methods
    Assert.True(recording.MethodWasCalled("Show"));
    Assert.True(recording.ReceivedWebMessageMatching("action"));
    Assert.True(recording.EventWasRaised("WebMessageReceived"));

    // Direct collection access
    Assert.Single(recording.WebMessagesReceived);
    Assert.NotEmpty(recording.MethodCalls);
}

Clearing Between Test Phases

csharp
[Fact]
public void Window_MultiPhaseTest()
{
    using var testWindow = new TestableHermesWindow();
    testWindow.Show();

    // Phase 1: Initial setup
    testWindow.SimulateWebMessage("""{"phase":1}""");
    HermesAssert.ReceivedWebMessageMatching(testWindow.Recording, "phase\":1");

    // Clear recordings for phase 2
    testWindow.Recording.Clear();

    // Phase 2: Different behavior
    testWindow.SimulateWebMessage("""{"phase":2}""");

    // Only phase 2 messages are recorded
    Assert.Single(testWindow.Recording.WebMessagesReceived);
    HermesAssert.ReceivedWebMessageMatching(testWindow.Recording, "phase\":2");
}