Skip to content

Commit

Permalink
docs: transport headless docs.
Browse files Browse the repository at this point in the history
  • Loading branch information
zdpcdt committed Aug 29, 2023
1 parent 1098a75 commit ad78fb9
Show file tree
Hide file tree
Showing 5 changed files with 430 additions and 0 deletions.
4 changes: 4 additions & 0 deletions i18n/zh-Hans/docusaurus-plugin-content-docs/current.json
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,10 @@
"message": "数据模板",
"description": "The label for category Data Templates in sidebar documentationSidebar"
},
"sidebar.documentationSidebar.category.Headless": {
"message": "Headless",
"description": "The label for category Headless Custom in sidebar documentationSidebar"
},
"sidebar.documentationSidebar.category.Input": {
"message": "输入",
"description": "The label for category Input in sidebar documentationSidebar"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
---
id: headless-custom
title: Manual Setup of Headless Platform
---

:::warning
This page explains an advanced usage scenario with the Headless platform.
We recommend using the [XUnit](headless-xunit.md) or [NUnit](headless-nunit.md) testing frameworks instead.
:::

## Install Packages

To set up the Headless platform, you need to install two packages:
- [Avalonia.Headless](https://www.nuget.org/packages/Avalonia.Headless), which also includes Avalonia.
- [Avalonia.Themes.Fluent](https://www.nuget.org/packages/Avalonia.Themes.Fluent), as even headless controls need a theme.

:::tip
The Headless platform doesn't require any specific theme, and it is possible to swap FluentTheme with any other.
:::

## Setup Application

As in any other Avalonia app, an `Application` instance needs to be created, and themes need to be applied. When using the Headless platform, the setup is not much different from a regular Avalonia app and can mostly be reused.

```xml title=App.axaml
<Application xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="Tests.App">
<Application.Styles>
<FluentTheme />
</Application.Styles>
</Application>
```

And the code:

```csharp title=App.axaml.cs
using Avalonia;
using Avalonia.Headless;

public class App : Application
{
public override void Initialize()
{
AvaloniaXamlLoader.Load(this);
}
}
```

## Run Headless Session

```csharp title=Program.cs
using Avalonia.Controls;
using Avalonia.Headless;

// Start Headless session passing Application type.
using var session = HeadlessUnitTestSession.StartNew(typeof(App));

// Since the Headless session has its own thread internally, we need to dispatch actions there:
await session.Dispatch(() =>
{
// Setup controls:
var textBox = new TextBox();
var window = new Window { Content = textBox };

// Open window:
window.Show();

// Focus text box:
textBox.Focus();

// Simulate text input:
window.KeyTextInput("Hello World");

// Assert:
if (textBox.Text != "Hello World")
{
throw new Exception("Assert");
}
}, CancellationToken.None);
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
---
id: headless-nunit
title: Headless Testing with NUnit
---

## Preparation

This page assumes that NUnit project was already created.
If not, please follow NUnit "Getting Started" and "Installation" here https://docs.nunit.org/articles/nunit/getting-started/installation.html.

## Install packages

Aside from NUnit packages, we need to install two more packages:
- [Avalonia.Headless.NUnit](https://www.nuget.org/packages/Avalonia.Headless.NUnit) which also includes Avalonia.
- [Avalonia.Themes.Fluent](https://www.nuget.org/packages/Avalonia.Themes.Fluent) as even headless controls need a theme

:::tip
Headless platform doesn't require any specific theme, and it is possible to swap FluentTheme with any other.
:::

## Setup Application
As in any other Avalonia app, an `Application` instance needs to be created, and themes need to be applied. When using the Headless platform, the setup is not much different from a regular Avalonia app and can mostly be reused.

```xml title=App.axaml
<Application xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="Tests.App">
<Application.Styles>
<FluentTheme />
</Application.Styles>
</Application>
```

And the code:

```csharp title=App.axaml.cs
using Avalonia;
using Avalonia.Headless;

public class App : Application
{
public override void Initialize()
{
AvaloniaXamlLoader.Load(this);
}
}
```

:::note
Usually, the `BuildAvaloniaApp` method is defined in the Program.cs file, but NUnit/XUnit tests don't have it, so it is defined in the `App` file instead.
:::

## Initialize NUnit Tests

The `[AvaloniaTestApplication]` attribute wires the tests in the current project with the specific application. It needs to be defined once per project in any file.

```csharp
[assembly: AvaloniaTestApplication(typeof(TestAppBuilder))]

public class TestAppBuilder
{
public static AppBuilder BuildAvaloniaApp() => AppBuilder.Configure<App>()
.UseHeadless(new AvaloniaHeadlessPlatformOptions());
}
```

## Test Example

```csharp
[AvaloniaTest]
public void Should_Type_Text_Into_TextBox()
{
// Setup controls:
var textBox = new TextBox();
var window = new Window { Content = textBox };

// Open window:
window.Show();

// Focus text box:
textBox.Focus();

// Simulate text input:
window.KeyTextInput("Hello World");

// Assert:
Assert.AreEqual("Hello World", textBox.Text);
}
```

Instead of the typical `[Test]` attribute, we need to use `[AvaloniaTest]` as it sets up the UI thread. Similarly, instead of `[Theory]`, there is a `[AvaloniaTheory]` attribute.
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
---
id: headless-xunit
title: Headless Testing with XUnit
---

## Preparation

This page assumes that XUnit project was already created.
If not, please follow XUnit "Getting Started" and "Installation" here https://xunit.net/docs/getting-started/netfx/visual-studio.

## Install packages

Aside from XUnit packages, we need to install two more packages:
- [Avalonia.Headless.XUnit](https://www.nuget.org/packages/Avalonia.Headless.XUnit) which also includes Avalonia.
- [Avalonia.Themes.Fluent](https://www.nuget.org/packages/Avalonia.Themes.Fluent) as even headless controls need a theme

:::tip
Headless platform doesn't require any specific theme, and it is possible to swap FluentTheme with any other.
:::

## Setup Application
As in any other Avalonia app, an `Application` instance needs to be created, and themes need to be applied. When using the Headless platform, the setup is not much different from a regular Avalonia app and can mostly be reused.

```xml title=App.axaml
<Application xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="Tests.App">
<Application.Styles>
<FluentTheme />
</Application.Styles>
</Application>
```

And the code:

```csharp title=App.axaml.cs
using Avalonia;
using Avalonia.Headless;

public class App : Application
{
public override void Initialize()
{
AvaloniaXamlLoader.Load(this);
}
}
```

:::note
Usually, the `BuildAvaloniaApp` method is defined in the Program.cs file, but NUnit/XUnit tests don't have it, so it is defined in the `App` file instead.
:::

## Initialize XUnit Tests

The `[AvaloniaTestApplication]` attribute wires the tests in the current project with the specific application. It needs to be defined once per project in any file.

```csharp
[assembly: AvaloniaTestApplication(typeof(TestAppBuilder))]

public class TestAppBuilder
{
public static AppBuilder BuildAvaloniaApp() => AppBuilder.Configure<App>()
.UseHeadless(new AvaloniaHeadlessPlatformOptions());
}
```

## Test Example

```csharp
[AvaloniaFact]
public void Should_Type_Text_Into_TextBox()
{
// Setup controls:
var textBox = new TextBox();
var window = new Window { Content = textBox };

// Open window:
window.Show();

// Focus text box:
textBox.Focus();

// Simulate text input:
window.KeyTextInput("Hello World");

// Assert:
Assert.Equal("Hello World", textBox.Text);
}
```

Instead of the typical `[Fact]` attribute, we need to use `[AvaloniaFact]` as it sets up the UI thread. Similarly, instead of `[Theory]`, there is a `[AvaloniaTheory]` attribute.
Loading

0 comments on commit ad78fb9

Please sign in to comment.