Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
becb170
Add sample test infrastructure for PR validation
nmetulev Mar 7, 2026
4edbf3b
Extend sample tests with guide-first workflows and packaging-cli test
nmetulev Mar 7, 2026
ffeb3ea
Fix test bugs, simplify electron test, update naming to Sample & Guide
nmetulev Mar 7, 2026
ab58630
Migrate sample & guide tests to Pester 5.x framework
nmetulev Mar 7, 2026
f757d50
Fix review findings: standardize Invoke-WinappCommand usage across al…
nmetulev Mar 7, 2026
16b1a76
Consolidate Electron e2e test into Pester sample test framework
nmetulev Mar 9, 2026
355fa72
Add pull_request trigger to sample tests workflow
nmetulev Mar 9, 2026
1fc047a
Merge branch 'main' into nm/sample-tests
nmetulev Mar 30, 2026
9c17a1a
Changes to the packaging cli guide
Jaylyn-Barbee Apr 7, 2026
c1be139
dotnet tests improved and added winapp run tests for dotnet apps
Jaylyn-Barbee Apr 8, 2026
8ab4c9d
Wpf tests
Jaylyn-Barbee Apr 9, 2026
33a21cf
merging main
Jaylyn-Barbee Apr 9, 2026
5fa970b
improvements to the rust guide, winapp run tests for rust and wpf + e…
Jaylyn-Barbee Apr 9, 2026
839b480
moving the step to add alias before we create the debug idenity
Jaylyn-Barbee Apr 9, 2026
59814af
fixing dotnet test ordering
Jaylyn-Barbee Apr 9, 2026
636c4d8
working on dotnet test
Jaylyn-Barbee Apr 9, 2026
f6f77a1
Improvements to the c++ guide and test
Jaylyn-Barbee Apr 10, 2026
8d250a8
Improve Flutter guide, restructure test into individual
Jaylyn-Barbee Apr 10, 2026
158ec58
Improved Tauri guide and tests
Jaylyn-Barbee Apr 10, 2026
7e4160b
Changes to electron setup and winml addon guide
Jaylyn-Barbee Apr 13, 2026
b1f7303
Fixes for PhiSilica guide
Jaylyn-Barbee Apr 13, 2026
839385c
electron improvements
Jaylyn-Barbee Apr 14, 2026
56aaf76
merging main
Jaylyn-Barbee Apr 14, 2026
12399e2
More verbose logs
Jaylyn-Barbee Apr 14, 2026
5f1f732
attempt to fix electron tests
Jaylyn-Barbee Apr 14, 2026
3fe4181
More verbose logs for debugging
Jaylyn-Barbee Apr 15, 2026
7b1b52b
Debugging path issue
Jaylyn-Barbee Apr 15, 2026
07d8819
Merge branch 'main' into nm/sample-tests
nmetulev Apr 15, 2026
55e56a2
Merge main into nm/sample-tests and resolve conflict
Copilot Apr 16, 2026
21b10c5
Fix test failures: update manifest filename from appxmanifest.xml to …
Jaylyn-Barbee Apr 16, 2026
9a4c36f
Fix tauri test: use appxmanifest.xml since init preserves existing ma…
Jaylyn-Barbee Apr 16, 2026
60cd7f0
Merge branch 'main' into nm/sample-tests
nmetulev Apr 17, 2026
6571306
Address PR #351 review comments
nmetulev Apr 17, 2026
c0bc7b5
Merge branch 'main' into nm/sample-tests
nmetulev Apr 17, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 0 additions & 28 deletions .github/workflows/build-package.yml
Original file line number Diff line number Diff line change
Expand Up @@ -173,34 +173,6 @@ jobs:
});
core.info(`Marked comment ${existing.id} as stale.`);

# E2E test for Electron workflow - runs after build completes
e2e-test:
runs-on: windows-latest
needs: build-and-package
steps:
- name: Checkout
uses: actions/checkout@v5

- name: Enable Windows Developer Mode
run: |
# Registry key to enable Developer Mode
reg add "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\AppModelUnlock" /t REG_DWORD /v "AllowDevelopmentWithoutDevLicense" /d 1 /f

- name: Setup Node.js
uses: actions/setup-node@v5
with:
node-version: '24'

- name: Download npm package artifact
uses: actions/download-artifact@v4
with:
name: npm-package
path: artifacts/npm

- name: Run E2E Electron test
run: |
.\scripts\test-e2e-electron.ps1 -ArtifactsPath "artifacts/npm" -Verbose

# E2E test for winapp ui commands against WinUI 3 sample app
e2e-test-ui:
runs-on: windows-latest
Expand Down
190 changes: 190 additions & 0 deletions .github/workflows/test-samples.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
name: Test Samples & Guides

on:
pull_request:
branches: [ "main" ]
workflow_dispatch:
inputs:
sample:
description: 'Specific sample to test (or "all")'
required: false
default: 'all'
type: choice
options:
- all
- cpp-app
- dotnet-app
- electron
- flutter-app
- packaging-cli
- rust-app
- tauri-app
- wpf-app

permissions:
contents: read

jobs:
# Build npm (and NuGet) package for pull_request and workflow_dispatch events.
# This makes the workflow self-contained — no cross-workflow artifact chaining.
build:
if: github.event_name == 'pull_request' || github.event_name == 'workflow_dispatch'
runs-on: windows-latest
steps:
- uses: actions/checkout@v5
- uses: actions/setup-dotnet@v5
with:
dotnet-version: '10.0.x'
- uses: actions/setup-node@v5
with:
node-version: '24'
- name: Build npm package
shell: pwsh
run: .\scripts\build-cli.ps1 -SkipTests -SkipMsix
- uses: actions/upload-artifact@v4
with:
name: npm-package
path: artifacts/*.tgz
- uses: actions/upload-artifact@v4
with:
name: nuget-package
path: artifacts/nuget/*.nupkg
if-no-files-found: ignore

test-sample:
needs: [build]
if: needs.build.result == 'success'
strategy:
fail-fast: false
matrix:
sample: [cpp-app, dotnet-app, electron, flutter-app, packaging-cli, rust-app, tauri-app, wpf-app]
runs-on: windows-latest
name: ${{ matrix.sample }}

steps:
- name: Check if sample should run
id: check
shell: pwsh
run: |
$requested = '${{ github.event.inputs.sample || 'all' }}'
if ($requested -ne 'all' -and $requested -ne '${{ matrix.sample }}') {
echo "skip=true" >> $env:GITHUB_OUTPUT
} else {
echo "skip=false" >> $env:GITHUB_OUTPUT
}

- name: Checkout
if: steps.check.outputs.skip != 'true'
uses: actions/checkout@v5

# Download the npm package artifact built by the `build` job above
- name: Download npm package
if: steps.check.outputs.skip != 'true'
uses: actions/download-artifact@v4
with:
name: npm-package
path: artifacts/npm

# Download NuGet package for .NET samples
- name: Download NuGet package
if: >-
steps.check.outputs.skip != 'true' &&
contains(fromJson('["dotnet-app", "wpf-app"]'), matrix.sample)
uses: actions/download-artifact@v4
with:
name: nuget-package
path: artifacts/nuget
continue-on-error: true

- name: Add local NuGet source
if: >-
steps.check.outputs.skip != 'true' &&
contains(fromJson('["dotnet-app", "wpf-app"]'), matrix.sample)
shell: pwsh
run: |
$nugetPath = "artifacts/nuget"
if (Test-Path $nugetPath) {
$resolvedPath = (Resolve-Path $nugetPath).Path
dotnet nuget add source $resolvedPath --name WinAppLocal
Write-Host "Added local NuGet source: $resolvedPath"
} else {
Write-Warning "No NuGet artifacts found — .NET samples may fail to restore"
}

# --- Toolchain setup (conditional per sample) ---

- name: Setup .NET
if: >-
steps.check.outputs.skip != 'true' &&
contains(fromJson('["dotnet-app", "wpf-app", "packaging-cli", "electron"]'), matrix.sample)
uses: actions/setup-dotnet@v5
with:
dotnet-version: '10.0.x'

- name: Setup Node.js
if: >-
steps.check.outputs.skip != 'true' &&
contains(fromJson('["electron", "tauri-app", "cpp-app", "dotnet-app", "wpf-app", "rust-app", "flutter-app", "packaging-cli"]'), matrix.sample)
uses: actions/setup-node@v5
with:
node-version: '24'

- name: Setup Flutter
if: >-
steps.check.outputs.skip != 'true' &&
matrix.sample == 'flutter-app'
uses: subosito/flutter-action@v2
with:
channel: stable

- name: Setup Rust
if: >-
steps.check.outputs.skip != 'true' &&
contains(fromJson('["rust-app", "tauri-app"]'), matrix.sample)
uses: dtolnay/rust-toolchain@stable

# --- Run the sample's self-contained Pester test ---

- name: Install Pester
if: steps.check.outputs.skip != 'true'
shell: pwsh
run: |
Install-Module -Name Pester -Force -SkipPublisherCheck -Scope CurrentUser -MinimumVersion 5.0

- name: Run ${{ matrix.sample }} test
if: steps.check.outputs.skip != 'true'
shell: pwsh
run: |
$container = New-PesterContainer -Path "samples/${{ matrix.sample }}/test.Tests.ps1" -Data @{
WinappPath = "artifacts/npm"
}
$config = New-PesterConfiguration
$config.Run.Container = $container
$config.Run.Exit = $true
$config.Output.Verbosity = 'Detailed'
$config.TestResult.Enabled = $true
$config.TestResult.OutputPath = "test-results-${{ matrix.sample }}.xml"
$config.TestResult.OutputFormat = 'JUnitXml'
Invoke-Pester -Configuration $config

- name: Upload test results
if: always() && steps.check.outputs.skip != 'true'
uses: actions/upload-artifact@v4
with:
name: test-results-${{ matrix.sample }}
path: test-results-${{ matrix.sample }}.xml
if-no-files-found: ignore

# Summary job to provide a single check status for branch protection
test-samples-result:
if: always()
needs: [build, test-sample]
runs-on: ubuntu-latest
steps:
- name: Check results
run: |
if [ "${{ needs.test-sample.result }}" = "failure" ]; then
echo "::error::One or more sample tests failed"
exit 1
fi
echo "All sample tests passed (or were skipped)"
41 changes: 41 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,47 @@ When adding or changing public facing features, ensure all documentation is also

If a feature is big enough and requires its own docs page, add it under docs\

## Sample & guide testing

Each sample under `samples/` has a self-contained **Pester 5.x** test file (`test.Tests.ps1`) that validates the corresponding guide workflow from scratch (Phase 1) and verifies the existing sample code still builds (Phase 2). Tests share infrastructure via `samples/SampleTestHelpers.psm1`.

### Running sample & guide tests locally

```powershell
# Run all sample tests
.\scripts\test-samples.ps1

# Run a specific sample
.\scripts\test-samples.ps1 -Samples dotnet-app

# Run with a locally built winapp npm tarball (package-npm.ps1 outputs to .\artifacts\)
.\scripts\test-samples.ps1 -WinappPath .\artifacts -Verbose

# Or pass a specific .tgz / a directory containing one (e.g., a CI artifact download)
.\scripts\test-samples.ps1 -WinappPath .\artifacts\npm -Verbose
```

### Writing a new sample & guide test

1. Create `test.Tests.ps1` in the sample directory (Pester naming convention)
2. Use `BeforeDiscovery` for skip logic (prerequisite checks run at discovery time)
3. Import shared helpers in `BeforeAll`: `Import-Module "$PSScriptRoot\..\SampleTestHelpers.psm1" -Force`
4. Accept `$WinappPath` and `$SkipCleanup` parameters via `param()` block
5. Phase 1 (`Context`): from-scratch guide workflow in a temp directory (scaffold, winapp init, build, cert, pack)
6. Phase 2 (`Context`): quick build of existing sample code to verify freshness
7. Add the sample name to the matrix in `.github/workflows/test-samples.yml`

#### Pester conventions for sample tests

- **`BeforeDiscovery`**: Set `$script:skip` using inline `Get-Command` checks (no module import). Pester evaluates `-Skip:$variable` during discovery, before `BeforeAll` runs.
- **`BeforeAll`**: Import `SampleTestHelpers.psm1`, install winapp, create temp directories. Guard with `if ($script:skip) { return }`.
- **`AfterAll`**: Clean up temp directories using `Remove-TempTestDirectory`.
- **`It` blocks**: Use `-Skip:$script:skip` for prerequisite gating. Use Pester `Should` assertions (`Should -Be 0`, `Should -Exist`, `Should -Not -BeNullOrEmpty`). When all setup happens in `BeforeAll` and depends on the prerequisite, you may apply `-Skip:$script:skip` to the enclosing `Context` instead.
- **Shared helpers**: `Invoke-WinappCommand` (throws on failure), `Test-Prerequisite` (returns bool), `New-TempTestDirectory`, `Remove-TempTestDirectory`, `Install-WinappGlobal`.

### CI integration

Sample & guide tests run via `.github/workflows/test-samples.yml` using a GitHub Actions matrix strategy. Each sample runs in its own parallel job after the main build completes. The workflow downloads the npm package artifact from the `Build and Package` workflow. Test results are uploaded as JUnit XML via `Invoke-Pester` with `TestResult` configuration.

## Where to look first

Expand Down
Loading
Loading