diff --git a/.github/skills/mtp-test-running/SKILL.md b/.github/skills/mtp-test-running/SKILL.md new file mode 100644 index 0000000000..2be3c96151 --- /dev/null +++ b/.github/skills/mtp-test-running/SKILL.md @@ -0,0 +1,72 @@ +--- +name: mtp-test-running +description: Run MaterialDesignInXamlToolkit tests correctly with dotnet test, TUnit, and Microsoft Testing Platform. Use when validating changes, choosing a safe test scope, or filtering to the exact affected tests. +--- + +# Test running with MTP + +Use this skill when you need to run or suggest test commands in this repository. + +## Repository-specific runner setup + +1. Test projects use `UseMicrosoftTestingPlatformRunner=true`. +2. Test projects also set `TestingPlatformDotnetTestSupport=true`. +3. `global.json` does **not** opt into `test.runner = Microsoft.Testing.Platform`. +4. That means this repo currently uses `dotnet test` in the legacy CLI mode while delegating execution to MTP-backed test applications. +5. Runner-specific arguments must therefore be passed after an extra `--`. +6. Do **not** rely on top-level `dotnet test --filter ...` for these projects. + +## Strong preferences + +1. Start with the smallest non-UI test scope that covers the change. +2. Avoid `MaterialDesignThemes.UITests` unless the change is inherently runtime WPF behavior. +3. Only run UI tests after the user explicitly asks or grants permission. +4. When UI tests are necessary, run only the affected tests, never the whole UI suite. + +## TUnit filter syntax + +TUnit uses `--treenode-filter`. + +Format: + +`////` + +- Use `*` as a wildcard within a segment. +- Use `(A)|(B)` inside a segment for OR. +- Prefer exact class and test names over namespace-wide filters. +- Add `--minimum-expected-tests ` so an empty selection fails loudly. + +## Command patterns + +### Example targeted non-UI test run + +```powershell +dotnet test tests\MaterialDesignThemes.Wpf.Tests\MaterialDesignThemes.Wpf.Tests.csproj -c Release --no-build -- --treenode-filter "/*/*/AutomationPropertiesNameConverterTests/*" --minimum-expected-tests 1 --no-ansi --no-progress +``` + +### Example targeted UI validation + +```powershell +dotnet test tests\MaterialDesignThemes.UITests\MaterialDesignThemes.UITests.csproj -c Release --no-build -- --treenode-filter "/*/*/DecimalUpDownTests/(NumericButtons_WithMaximum_DisablesPlusButton)|(NumericButtons_WithMinimum_DisablesMinusButton)" --minimum-expected-tests 2 --no-ansi --no-progress +``` + +### Verify a UI filter before running + +```powershell +tests\MaterialDesignThemes.UITests\bin\Release\net10.0-windows\MaterialDesignThemes.UITests.exe --list-tests --no-ansi --treenode-filter "/*/*/DecimalUpDownTests/(NumericButtons_WithMaximum_DisablesPlusButton)|(NumericButtons_WithMinimum_DisablesMinusButton)" +``` + +## Mistakes to avoid + +- Using top-level `dotnet test --filter ...` for these MTP-backed projects. +- Passing runner-specific flags before the extra `--`. +- Running broad UI suites when one or two targeted tests are enough. +- Forgetting `--minimum-expected-tests`, which can hide a bad filter. + +## Useful references + +- `global.json` +- `tests/MaterialDesignThemes.Wpf.Tests/MaterialDesignThemes.Wpf.Tests.csproj` +- `tests/MaterialDesignThemes.UITests/MaterialDesignThemes.UITests.csproj` +- https://learn.microsoft.com/dotnet/core/testing/unit-testing-with-dotnet-test +- https://tunit.dev/docs/execution/test-filters diff --git a/.github/skills/xamltest-ui-tests/SKILL.md b/.github/skills/xamltest-ui-tests/SKILL.md new file mode 100644 index 0000000000..5513d06a6c --- /dev/null +++ b/.github/skills/xamltest-ui-tests/SKILL.md @@ -0,0 +1,77 @@ +--- +name: xamltest-ui-tests +description: Write and update WPF UI tests in MaterialDesignThemes.UITests using XAMLTest. Use when template, layout, focus, interaction, or visual behavior needs coverage, or when a reviewer asks to move runtime UI checks out of MaterialDesignThemes.Wpf.Tests. +--- + +# XAMLTest UI tests + +Use this skill when working on runtime WPF behavior in this repository. + +## When to use it + +- A change touches templates, visual states, focus behavior, layout, coordinates, or input handling. +- You need to inspect named template parts such as `PART_TextBox` or `PART_IncreaseButton`. +- A reviewer asks to use XAMLTest instead of regular unit tests. +- You need to assert WPF-only properties like `Padding`, `Visibility`, `ActualWidth`, or `DataContext` state after layout. + +## Repository-specific rules + +1. Put runtime UI behavior tests in `tests/MaterialDesignThemes.UITests`. +2. Do **not** add visual-tree or layout interaction tests to `tests/MaterialDesignThemes.Wpf.Tests`. +3. Prefer extending the existing feature file under `tests/MaterialDesignThemes.UITests/WPF//` instead of creating a generic catch-all test file. +4. Match the existing file's result-recording pattern; many current UI tests use `TestRecorder`, but it should not be treated as a blanket requirement. +5. Ask permission before running UI tests, and only run the affected ones. + +## Standard pattern + +1. Inherit from `TestBase`. +2. Use `LoadXaml()` for focused control scenarios. +3. Use `LoadUserControl()` when you need a sample view model, bindings, or additional focus targets. +4. Get named parts with `GetElement("PART_Name")`. +5. Use `RemoteExecute` with static methods for properties that helpers do not expose directly. +6. Use `Wait.For(...)` for layout-sensitive assertions. + +## What to prefer + +- `GetCoordinates()` for alignment and spacing assertions. +- `RemoteExecute` for `Padding`, `Visibility`, `ActualWidth`, `Margin`, or `DataContext` inspection. +- Keyboard and mouse helpers such as `MoveKeyboardFocus`, `SendKeyboardInput`, and `LeftClick` for interaction. + +## What to avoid + +- Inspecting the visual tree from `MaterialDesignThemes.Wpf.Tests` for runtime template behavior. +- Overly broad UI suites when a single targeted XAMLTest scenario will do. +- Repeating helper code inline when a small static local or private helper method is enough. + +## Example + +```csharp +[Test] +public async Task DecimalUpDown_WithMaximum_DisablesPlusButton() +{ + await using var recorder = new TestRecorder(App); + + var decimalUpDown = await LoadXaml(""" + + """); + var plusButton = await decimalUpDown.GetElement("PART_IncreaseButton"); + var textBox = await decimalUpDown.GetElement("PART_TextBox"); + + await plusButton.LeftClick(); + await Wait.For(async () => + { + await Assert.That(await textBox.GetText()).IsEqualTo("2"); + await Assert.That(await decimalUpDown.GetValue()).IsEqualTo(2); + }); + + await Assert.That(await plusButton.GetIsEnabled()).IsFalse(); + + recorder.Success(); +} +``` + +## Useful local references + +- `tests/MaterialDesignThemes.UITests/TestBase.cs` +- `tests/MaterialDesignThemes.UITests/XamlTestExtensions.cs` +- Existing feature tests under `tests/MaterialDesignThemes.UITests/WPF/`