-
-
Notifications
You must be signed in to change notification settings - Fork 739
Integration Tests Everywhere! #931
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
3f10d6b
dfcb234
1a964b4
e4485fd
7558037
17f2474
a30239e
c98ad58
ff1b802
9488576
61476e3
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,209 @@ | ||
| name: Tests | ||
|
|
||
| on: | ||
| push: | ||
| branches: [ develop, main ] | ||
| pull_request: | ||
| branches: [ develop, main ] | ||
|
|
||
| concurrency: | ||
| group: integration-tests-${{ github.ref }} | ||
| cancel-in-progress: true | ||
|
|
||
| jobs: | ||
| tests: | ||
| name: Integration Tests (${{ matrix.os }}) | ||
| runs-on: ${{ matrix.os }} | ||
| strategy: | ||
| fail-fast: false | ||
| matrix: | ||
| include: | ||
| - os: ubuntu-24.04 | ||
| rid: linux-x64 | ||
| - os: windows-2022 | ||
| rid: win-x64 | ||
| - os: macos-14 | ||
| rid: osx-arm64 | ||
|
|
||
| env: | ||
| DOTNET_SKIP_FIRST_TIME_EXPERIENCE: 1 | ||
| DOTNET_NOLOGO: 1 | ||
| CI: true | ||
| ELECTRON_ENABLE_LOGGING: 1 | ||
|
|
||
| steps: | ||
| - name: Checkout | ||
| uses: actions/checkout@v4 | ||
|
|
||
| - name: Setup .NET | ||
| uses: actions/setup-dotnet@v4 | ||
| with: | ||
| dotnet-version: '10.0.x' | ||
|
|
||
| - name: Setup Node.js | ||
| uses: actions/setup-node@v4 | ||
| with: | ||
| node-version: '22' | ||
|
|
||
| - name: Restore | ||
| run: dotnet restore -r ${{ matrix.rid }} -p:RuntimeIdentifier=${{ matrix.rid }} src/ElectronNET.IntegrationTests/ElectronNET.IntegrationTests.csproj | ||
|
|
||
| - name: Build | ||
| run: dotnet build --no-restore -c Release -r ${{ matrix.rid }} -p:RuntimeIdentifier=${{ matrix.rid }} src/ElectronNET.IntegrationTests/ElectronNET.IntegrationTests.csproj | ||
|
|
||
| - name: Install Linux GUI dependencies | ||
| if: runner.os == 'Linux' | ||
| run: | | ||
| set -e | ||
| sudo apt-get update | ||
| # Core Electron dependencies | ||
| sudo apt-get install -y xvfb \ | ||
| libgtk-3-0 libnss3 libgdk-pixbuf-2.0-0 libdrm2 libgbm1 libxss1 libxtst6 libatk-bridge2.0-0 libatk1.0-0 libatspi2.0-0 libx11-xcb1 libasound2t64 | ||
| - name: Run tests (Linux) | ||
| if: runner.os == 'Linux' | ||
| continue-on-error: true | ||
| run: | | ||
| mkdir -p test-results/Ubuntu | ||
| xvfb-run -a dotnet test src/ElectronNET.IntegrationTests/ElectronNET.IntegrationTests.csproj \ | ||
| -c Release --no-build -r ${{ matrix.rid }} -p:RuntimeIdentifier=${{ matrix.rid }} \ | ||
| --logger "trx;LogFileName=Ubuntu.trx" \ | ||
| --logger "console;verbosity=detailed" \ | ||
| --results-directory test-results | ||
| - name: Run tests (Windows) | ||
| if: runner.os == 'Windows' | ||
| continue-on-error: true | ||
| run: | | ||
| New-Item -ItemType Directory -Force -Path test-results/Windows | Out-Null | ||
| dotnet test src/ElectronNET.IntegrationTests/ElectronNET.IntegrationTests.csproj -c Release --no-build -r ${{ matrix.rid }} -p:RuntimeIdentifier=${{ matrix.rid }} --logger "trx;LogFileName=Windows.trx" --logger "console;verbosity=detailed" --results-directory test-results | ||
| - name: Run tests (macOS) | ||
| if: runner.os == 'macOS' | ||
| continue-on-error: true | ||
| run: | | ||
| mkdir -p test-results/macOS | ||
| dotnet test src/ElectronNET.IntegrationTests/ElectronNET.IntegrationTests.csproj -c Release --no-build -r ${{ matrix.rid }} -p:RuntimeIdentifier=${{ matrix.rid }} --logger "trx;LogFileName=macOS.trx" --logger "console;verbosity=detailed" --results-directory test-results | ||
| - name: Upload raw test results | ||
| if: always() | ||
| uses: actions/upload-artifact@v4 | ||
| with: | ||
| name: test-results-${{ matrix.os }} | ||
| path: test-results/*.trx | ||
| retention-days: 7 | ||
|
|
||
| summary: | ||
| name: Test Results | ||
| runs-on: ubuntu-24.04 | ||
| if: always() | ||
| needs: [tests] | ||
|
|
||
| permissions: | ||
| actions: read | ||
| contents: read | ||
| checks: write | ||
| pull-requests: write | ||
|
|
||
| steps: | ||
| - name: Download all test results | ||
| uses: actions/download-artifact@v4 | ||
| with: | ||
| path: test-results | ||
|
|
||
| - name: Setup .NET (for CTRF conversion) | ||
| uses: actions/setup-dotnet@v4 | ||
| with: | ||
| dotnet-version: '10.0.x' | ||
|
|
||
| - name: Install CTRF TRX→CTRF converter (dotnet tool) | ||
| run: | | ||
| dotnet new tool-manifest | ||
| dotnet tool install DotnetCtrfJsonReporter --local | ||
| - name: Convert TRX → CTRF and clean names (keep suites; set filePath=OS) | ||
| shell: bash | ||
| run: | | ||
| set -euo pipefail | ||
| mkdir -p ctrf | ||
| shopt -s globstar nullglob | ||
| conv=0 | ||
| for trx in test-results/**/*.trx; do | ||
| fname="$(basename "$trx")" | ||
| os="${fname%.trx}" | ||
| outdir="ctrf/${os}" | ||
| mkdir -p "$outdir" | ||
| out="${outdir}/ctrf-report.json" | ||
| dotnet tool run DotnetCtrfJsonReporter -p "$trx" -d "$outdir" -f "ctrf-report.json" | ||
| jq --arg os "$os" '.results.tests |= map(.filePath = $os)' "$out" > "${out}.tmp" && mv "${out}.tmp" "$out" | ||
| echo "Converted & normalized $trx -> $out" | ||
| conv=$((conv+1)) | ||
| done | ||
| echo "Processed $conv TRX file(s)" | ||
| - name: Publish Test Report | ||
| if: always() | ||
| uses: ctrf-io/github-test-reporter@v1 | ||
| with: | ||
| report-path: 'ctrf/**/*.json' | ||
|
|
||
| summary: true | ||
| pull-request: false | ||
| status-check: false | ||
| status-check-name: 'Integration Tests' | ||
| use-suite-name: true | ||
| update-comment: true | ||
| always-group-by: true | ||
| overwrite-comment: true | ||
| exit-on-fail: true | ||
| group-by: 'suite' | ||
| upload-artifact: true | ||
| fetch-previous-results: true | ||
|
|
||
| summary-report: false | ||
| summary-delta-report: true | ||
| github-report: true | ||
| test-report: false | ||
| test-list-report: false | ||
| failed-report: true | ||
| failed-folded-report: false | ||
| skipped-report: true | ||
| suite-folded-report: true | ||
| suite-list-report: false | ||
| file-report: true | ||
| previous-results-report: true | ||
| insights-report: true | ||
| flaky-report: true | ||
| flaky-rate-report: true | ||
| fail-rate-report: false | ||
| slowest-report: false | ||
|
|
||
| report-order: 'summary-delta-report,failed-report,skipped-report,suite-folded-report,file-report,previous-results-report,github-report' | ||
| env: | ||
| GITHUB_TOKEN: ${{ github.token }} | ||
|
|
||
|
|
||
| - name: Create PR Comment | ||
| if: always() | ||
| uses: ctrf-io/github-test-reporter@v1 | ||
| with: | ||
| report-path: 'ctrf/**/*.json' | ||
|
|
||
| summary: true | ||
| pull-request: true | ||
| use-suite-name: true | ||
| update-comment: true | ||
| always-group-by: true | ||
| overwrite-comment: true | ||
| upload-artifact: false | ||
|
|
||
| pull-request-report: true | ||
| env: | ||
| GITHUB_TOKEN: ${{ github.token }} | ||
|
|
||
| - name: Summary | ||
| run: echo "All matrix test jobs completed." | ||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -40,7 +40,7 @@ protected override Task StartCore() | |||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||
| var isUnPacked = ElectronNetRuntime.StartupMethod.IsUnpackaged(); | ||||||||||||||||||||||||||||||||||||
| var electronBinaryName = ElectronNetRuntime.ElectronExecutable; | ||||||||||||||||||||||||||||||||||||
| var args = Environment.CommandLine; | ||||||||||||||||||||||||||||||||||||
| var args = string.Format("{0} {1}", ElectronNetRuntime.ElectronExtraArguments, Environment.CommandLine).Trim(); | ||||||||||||||||||||||||||||||||||||
| this.port = ElectronNetRuntime.ElectronSocketPort; | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| if (!this.port.HasValue) | ||||||||||||||||||||||||||||||||||||
|
|
@@ -49,10 +49,15 @@ protected override Task StartCore() | |||||||||||||||||||||||||||||||||||
| ElectronNetRuntime.ElectronSocketPort = this.port; | ||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| Console.Error.WriteLine("[StartCore]: isUnPacked: {0}", isUnPacked); | ||||||||||||||||||||||||||||||||||||
| Console.Error.WriteLine("[StartCore]: electronBinaryName: {0}", electronBinaryName); | ||||||||||||||||||||||||||||||||||||
| Console.Error.WriteLine("[StartCore]: args: {0}", args); | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| this.electronProcess = new ElectronProcessActive(isUnPacked, electronBinaryName, args, this.port.Value); | ||||||||||||||||||||||||||||||||||||
| this.electronProcess.Ready += this.ElectronProcess_Ready; | ||||||||||||||||||||||||||||||||||||
| this.electronProcess.Stopped += this.ElectronProcess_Stopped; | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| Console.Error.WriteLine("[StartCore]: Before Start"); | ||||||||||||||||||||||||||||||||||||
|
Comment on lines
+52
to
+60
|
||||||||||||||||||||||||||||||||||||
| Console.Error.WriteLine("[StartCore]: isUnPacked: {0}", isUnPacked); | |
| Console.Error.WriteLine("[StartCore]: electronBinaryName: {0}", electronBinaryName); | |
| Console.Error.WriteLine("[StartCore]: args: {0}", args); | |
| this.electronProcess = new ElectronProcessActive(isUnPacked, electronBinaryName, args, this.port.Value); | |
| this.electronProcess.Ready += this.ElectronProcess_Ready; | |
| this.electronProcess.Stopped += this.ElectronProcess_Stopped; | |
| Console.Error.WriteLine("[StartCore]: Before Start"); | |
| this.electronProcess = new ElectronProcessActive(isUnPacked, electronBinaryName, args, this.port.Value); | |
| this.electronProcess.Ready += this.ElectronProcess_Ready; | |
| this.electronProcess.Stopped += this.ElectronProcess_Stopped; |
Copilot
AI
Nov 15, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove debugging Console.Error.WriteLine statements before merging to production. These appear to be temporary diagnostic logs that should be removed or replaced with proper logging infrastructure.
| Console.Error.WriteLine("[StartCore]: Before Start"); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -5,6 +5,7 @@ | |
| using System; | ||
| using System.ComponentModel; | ||
| using System.IO; | ||
| using System.Runtime.InteropServices; | ||
| using System.Threading.Tasks; | ||
|
|
||
| /// <summary> | ||
|
|
@@ -42,6 +43,11 @@ protected override Task StartCore() | |
| var electrondir = Path.Combine(dir.FullName, ".electron"); | ||
| startCmd = Path.Combine(electrondir, "node_modules", "electron", "dist", "electron"); | ||
|
|
||
| if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) | ||
| { | ||
| startCmd = Path.Combine(electrondir, "node_modules", "electron", "dist", "Electron.app", "Contents", "MacOS", "Electron"); | ||
| } | ||
|
|
||
| args = $"main.js -unpackeddotnet --trace-warnings -electronforcedport={this.socketPort:D} " + this.extraArguments; | ||
| workingDir = electrondir; | ||
| } | ||
|
|
@@ -68,22 +74,40 @@ protected override Task StopCore() | |
|
|
||
| private async Task StartInternal(string startCmd, string args, string directoriy) | ||
| { | ||
| await Task.Delay(10).ConfigureAwait(false); | ||
| try | ||
| { | ||
| await Task.Delay(10).ConfigureAwait(false); | ||
|
|
||
| this.process = new ProcessRunner("ElectronRunner"); | ||
| this.process.ProcessExited += this.Process_Exited; | ||
| this.process.Run(startCmd, args, directoriy); | ||
| Console.Error.WriteLine("[StartInternal]: startCmd: {0}", startCmd); | ||
| Console.Error.WriteLine("[StartInternal]: args: {0}", args); | ||
|
Comment on lines
+81
to
+82
|
||
|
|
||
| await Task.Delay(500).ConfigureAwait(false); | ||
| this.process = new ProcessRunner("ElectronRunner"); | ||
| this.process.ProcessExited += this.Process_Exited; | ||
| this.process.Run(startCmd, args, directoriy); | ||
|
|
||
| if (!this.process.IsRunning) | ||
| { | ||
| Task.Run(() => this.TransitionState(LifetimeState.Stopped)); | ||
| await Task.Delay(500).ConfigureAwait(false); | ||
|
|
||
| throw new Exception("Failed to launch the Electron process."); | ||
| } | ||
| Console.Error.WriteLine("[StartInternal]: after run:"); | ||
|
||
|
|
||
| if (!this.process.IsRunning) | ||
| { | ||
| Console.Error.WriteLine("[StartInternal]: Process is not running: " + this.process.StandardError); | ||
| Console.Error.WriteLine("[StartInternal]: Process is not running: " + this.process.StandardOutput); | ||
|
Comment on lines
+94
to
+95
|
||
|
|
||
| this.TransitionState(LifetimeState.Ready); | ||
| Task.Run(() => this.TransitionState(LifetimeState.Stopped)); | ||
|
|
||
| throw new Exception("Failed to launch the Electron process."); | ||
| } | ||
|
|
||
| this.TransitionState(LifetimeState.Ready); | ||
| } | ||
| catch (Exception ex) | ||
| { | ||
| Console.Error.WriteLine("[StartInternal]: Exception: " + this.process?.StandardError); | ||
| Console.Error.WriteLine("[StartInternal]: Exception: " + this.process?.StandardOutput); | ||
| Console.Error.WriteLine("[StartInternal]: Exception: " + ex); | ||
|
Comment on lines
+106
to
+108
|
||
| throw; | ||
| } | ||
| } | ||
|
|
||
| private void Process_Exited(object sender, EventArgs e) | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -132,13 +132,19 @@ private BuildInfo GatherBuildInfo() | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (electronAssembly == null) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Console.WriteLine("GatherBuildInfo: Early exit"); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return buildInfo; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (electronAssembly.GetName().Name == "testhost" || electronAssembly.GetName().Name == "ReSharperTestRunner") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Console.WriteLine("GatherBuildInfo: Detected testhost"); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| electronAssembly = AppDomain.CurrentDomain.GetData("ElectronTestAssembly") as Assembly ?? electronAssembly; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| else | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Console.WriteLine("GatherBuildInfo: No testhost detected: " + electronAssembly.GetName().Name); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+135
to
+146
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Console.WriteLine("GatherBuildInfo: Early exit"); | |
| return buildInfo; | |
| } | |
| if (electronAssembly.GetName().Name == "testhost" || electronAssembly.GetName().Name == "ReSharperTestRunner") | |
| { | |
| Console.WriteLine("GatherBuildInfo: Detected testhost"); | |
| electronAssembly = AppDomain.CurrentDomain.GetData("ElectronTestAssembly") as Assembly ?? electronAssembly; | |
| } | |
| else | |
| { | |
| Console.WriteLine("GatherBuildInfo: No testhost detected: " + electronAssembly.GetName().Name); | |
| return buildInfo; | |
| } | |
| if (electronAssembly.GetName().Name == "testhost" || electronAssembly.GetName().Name == "ReSharperTestRunner") | |
| { | |
| electronAssembly = AppDomain.CurrentDomain.GetData("ElectronTestAssembly") as Assembly ?? electronAssembly; | |
| } | |
| else | |
| { | |
| // No testhost detected |
Copilot
AI
Nov 15, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove debugging Console.WriteLine statements before merging to production. These appear to be temporary diagnostic logs that should be removed or replaced with proper logging infrastructure.
| Console.WriteLine("GatherBuildInfo: Early exit"); | |
| return buildInfo; | |
| } | |
| if (electronAssembly.GetName().Name == "testhost" || electronAssembly.GetName().Name == "ReSharperTestRunner") | |
| { | |
| Console.WriteLine("GatherBuildInfo: Detected testhost"); | |
| electronAssembly = AppDomain.CurrentDomain.GetData("ElectronTestAssembly") as Assembly ?? electronAssembly; | |
| } | |
| else | |
| { | |
| Console.WriteLine("GatherBuildInfo: No testhost detected: " + electronAssembly.GetName().Name); | |
| return buildInfo; | |
| } | |
| if (electronAssembly.GetName().Name == "testhost" || electronAssembly.GetName().Name == "ReSharperTestRunner") | |
| { | |
| electronAssembly = AppDomain.CurrentDomain.GetData("ElectronTestAssembly") as Assembly ?? electronAssembly; | |
| } | |
| else | |
| { | |
| // No testhost detected |
Copilot
AI
Nov 15, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove debugging Console.WriteLine statements before merging to production. These appear to be temporary diagnostic logs that should be removed or replaced with proper logging infrastructure.
| Console.WriteLine("GatherBuildInfo: Early exit"); | |
| return buildInfo; | |
| } | |
| if (electronAssembly.GetName().Name == "testhost" || electronAssembly.GetName().Name == "ReSharperTestRunner") | |
| { | |
| Console.WriteLine("GatherBuildInfo: Detected testhost"); | |
| electronAssembly = AppDomain.CurrentDomain.GetData("ElectronTestAssembly") as Assembly ?? electronAssembly; | |
| } | |
| else | |
| { | |
| Console.WriteLine("GatherBuildInfo: No testhost detected: " + electronAssembly.GetName().Name); | |
| return buildInfo; | |
| } | |
| if (electronAssembly.GetName().Name == "testhost" || electronAssembly.GetName().Name == "ReSharperTestRunner") | |
| { | |
| electronAssembly = AppDomain.CurrentDomain.GetData("ElectronTestAssembly") as Assembly ?? electronAssembly; | |
| } | |
| else | |
| { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove the UTF-8 BOM (Byte Order Mark) character at the beginning of the file. YAML files should be UTF-8 without BOM.