-
-
Notifications
You must be signed in to change notification settings - Fork 739
Add 77 IntegrationTests and lots of fixes #913
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
Add 77 IntegrationTests and lots of fixes #913
Conversation
softworkz
commented
Nov 9, 2025
- StartupManager: Add support for running under testhost
- BrowserView.cs: Fix cast exception in Bounds property getter
- App.cs: Fix UserAgentFallbackAsync
- ipc.ts: Add helper method for tests
- browserWindows.ts: Fix SetThumbarButtons
- browserWindows.ts: Add catch for Set/GetRepresentedFilename...
- notification.ts: Fix notificationIsSupported...
- webContents.ts: Fix clearAuthCache invocation...
- main.js: Load api/process import (was missing)
- ProcessMetric: Fix deserialization error for CreationTime
- ApiBase: fix event names for App
- BrowserWindow: Disable SetPosition 'workaround'...
- browserWindowSetParentWindow: Support null parameter
- Add IntegrationTests project
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.
Pull Request Overview
This PR adds comprehensive integration tests for the ElectronNET project and fixes several bugs discovered during test development. Key changes include:
- A new integration test project with extensive test coverage for BrowserWindow, WebContents, App, IPC, and other Electron APIs
- Bug fixes for API compatibility issues (Notification.isSupported, parent window handling, represented filename)
- Improvements to socket event naming consistency and property getter implementation
- Enhanced error handling for platform-specific features
- Process metric type correction from int to double for CreationTime
Reviewed Changes
Copilot reviewed 40 out of 44 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| ElectronNET.sln | Adds integration test project to solution |
| ElectronNET.IntegrationTests/*.cs | Integration tests covering major Electron APIs |
| ElectronFixture.cs | Test fixture for shared Electron runtime |
| notification.ts/js | Fixes isSupported to call as function |
| browserWindows.ts/js | Adds error handling for platform-specific APIs and thumbar button fixes |
| ipc.ts/js | Adds integration test helpers for menu item clicking |
| webContents.ts/js | Adds clearAuthCache overload support |
| StartupManager.cs | Adds testhost detection for assembly resolution |
| ProcessMetric.cs | Changes CreationTime from int to double |
| BrowserWindow.cs | Fixes SetParentWindow null handling and removes Windows 10 position workaround |
| ApiBase.cs | Refactors socket event naming to support multiple patterns |
| App.cs | Fixes UserAgentFallbackAsync property implementation |
| BrowserView.cs | Improves async Bounds property getter |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
src/ElectronNET.IntegrationTests/ElectronNET.IntegrationTests.csproj
Outdated
Show resolved
Hide resolved
92b9dce to
ee1f86a
Compare
|
Note that two tests are failing because of this: #905 (comment) |
|
That is much appreciated - and I'm happy that it already confirms two issues. Only question is - should we fix them in this PR or make a subsequent PR? As it stands we need to have a baseline with all tests working - otherwise future PRs will always have these two failing tests. |
This is a bigger change - not for this PR, I'd say. I'm waiting for a comment from @agracio as I thought it wouildn't be nice to submit a PR which fundamentally changes his contribution, so we should wait for whether he wants to work on fixing it. These options exist: We could do the 3rd one either way, this should fix it.
As long as |
It doesn't make sense to do this adjustment for set only but not for get. Neither is this done for SetBounds, so it should be either fully consistent or left up to the application to deal with it.
The options were no propagated for the overload with RemovePassword options
It's a method, was used like a property
It's not supported on all platforms
9c1b688 to
60a278c
Compare
|
I was under the impression that EDIT: now that I think about it they are always passed as null first so there is no such thing as reference here. Look like I have made a mistake there. Not sure how to fix this particular issue in the context of the code I created. |
I've seen the issue from the code alone before even trying, so I'm pretty sure that it's like that. But you can surely check out this branch and revert your commits on top. Or you don't even have to do that actually, you just need to revert the two events being tested to the older code. That way you won't have any conflicts. Btw, there are more issues in the EventHelper which I haven't mentioend: At two or more places, you do callback+= value only inside the if statement bodies.
Yup, that's total unintuitive - if I wouldn't have known it, I would have made the same assumption. |
Multicast delegates are a very special kind of animal in C# - even the null check is kind-of fake... |
Did you read my comments in your PR? |
|
So even if I remove closures and pass them by ref it will not make a difference, since they are null when they are initially passed I do not believe it will resolve the issue. |
|
Creating a dictionary of delegates, yes that would be possible. |
When you pass them by ref, the receiver is added like when you'd do it on the calling side - i.e. second time it won't be null. |
Yes - same like in case of properties.
Another weirdness: Action and Action<T> do not have a base class, but both can be casted to |
I do not think it is needed in the first place, only one dictionary would store eventName->Action. |
|
You PR should be merged first in my opinion, much easier to work for both of us when there are no competing PRs in the same branch that might be touching the same code. |
You cannot cast Action<T> to Acttion or vice versa, that's what I meant. |
|
As for the rest of the comment you left on my PR: my intention was never to change the existing code - I refactored it as is including string concatenations, no null checks etc... |
Which comment do you mean..? |
A very good point forgot about it. |
That's why I said that both can be cast to delegate - so you can make a single dictionary of eventName->delegate and cast the delegate to Action/ActionT as needed. 😁 |
Sorry meant to say comments - plural
As I said the code was refactored the way it was used before, no improvements or changes of any kind and was never my intention. |
|
Btw having integration tests in Electron.NET is a huge milestone. |
Yea, make it nullable
Ah, now I got it - I didn't look how it has s been before, so it's been a (tiny) bit unfair, but it had been merged already, so I didn't think in terms of what would be a blocker and what not. |
|
See my comment #913 (comment) - I believe this PR should be merged first, as my changes might also touch on so ts/js files and definitely on files that are changed in this RP. Would like to avoid merge complications. |
Agreed. But you can check out this PR and start working on top of it already (if you like).. |
I am already working on a prototype. On a completely off-topic note - every time I open solution in Rider it tells me that Nuke.Common 8.0.0 contains vulnerabilities. |
Definitely. My comment was rather meant as a "we should integrate it into NUKE / the build system ASAP then ...". But then my suggestion is to merge (just did) and integrate once we have all tests succeeding. Until then we can just run tests locally to verify if everything (except the known ones) is still running. Huge milestone! Many thanks. On a sidenote: I should get a chatroom for the two of you @agracio @softworkz :D. Not the conversation is not meaningful (I like it), but definitely a lot to digest before getting into the relevant pieces here. Chatroom may be a good trigger point as right now gitter is still used (but last time I checked the room was inactive & I know that at least @GregorBiswanger and @FlorianRappl are only active on Discord any more - so maybe let's move there, too?). |
|
@softworkz are there any steps that need to be done to run integration tests, they all fail on my PC. private void SetElectronExecutable()
{
string executable = ElectronNetRuntime.BuildInfo.ElectronExecutable;
if (string.IsNullOrEmpty(executable))
{
throw new Exception("AssemblyMetadataAttribute 'ElectronExecutable' could not be found!");
}
if (Environment.OSVersion.Platform == PlatformID.Win32NT)
{
executable += ".exe";
}
ElectronNetRuntime.ElectronExecutable = executable;
}
|
👍
It won't happen regularly, I don't have that much time, but I also hate to be the one having to say that it's all wrong after submission (and effort by a contributor), so I rather tell beforehand when I know the caveats already. |
Look for these lines in StartupInfo: if (electronAssembly.GetName().Name == "testhost")
{
electronAssembly = AppDomain.CurrentDomain.GetData("ElectronTestAssembly") as Assembly ?? electronAssembly;
}If you're not using Visual Studio, your test runner might not be "testhost". Check out what it is and add it to that condition. |
|
It looks like fix is not as straightforward as I initially thought. Even when using dictionary test fails but with a different result. Here is a very basic code change. private static readonly ConcurrentDictionary<string, Delegate> events = new();
internal static void AddEvent(string eventName, object id, Action callback, Action value)
{
var call = (Action)events.GetOrAdd(eventName, callback);
if (call == null)
{
BridgeConnector.Socket.On(eventName + id, () => { call(); });
BridgeConnector.Socket.Emit($"register-{eventName}", id);
}
call += value;
events[eventName] = call;
}Checking in debugger it shows that all 3 listeners are subscribed co h1.TrySetResult();
h2.TrySetResult();
h3.TrySetResult();But only the first event is successful Not all events were fired:
Event1 fired: True
Event2 fired: False
Event3 fired: FalsePretty sure that I am missing something completely obvious. |
|
Figured out the problem internal static void AddEvent(string eventName, object id, Action callback, Action value)
{
var call = (Action)events.GetOrAdd(eventName, callback);
if (call == null)
{
BridgeConnector.Socket.On(eventName + id, () =>
{
((Action)events[eventName])();
});
BridgeConnector.Socket.Emit($"register-{eventName}", id);
}
call += value;
events[eventName] = call;
}@softworkz could you advise whether it requires any locks and if so where. |
|
I am moving events into |
@agracio - please see here: #918 - even though you got it working somehow, my earlier advice was a bit too simplistic, I'm sorry about that. As a remedy, I created a solid pattern that you can use. |