Skip to content
Open
Show file tree
Hide file tree
Changes from 26 commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
1c5f2f6
updated Appium in desktop module
teo-nikolov Nov 19, 2023
3901b9a
fixed warning messages in IDE
teo-nikolov Nov 19, 2023
f7a056c
Desktop Module Update
teo-nikolov Feb 13, 2024
b61128d
Updates to the desktop module
teo-nikolov Apr 12, 2024
f80b0d1
Merge remote-tracking branch 'origin/desktop-module-update' into desk…
teo-nikolov Apr 12, 2024
cb102c4
reverted click default action
teo-nikolov Apr 12, 2024
c29358e
updated azure dependencies
teo-nikolov Apr 12, 2024
7766b3f
added SelectOption method to Menu component
teo-nikolov Apr 18, 2024
6d8a2a6
removed case-sensitive folder
teo-nikolov Apr 24, 2024
40f1938
Fixed CheckBox.cs filename casing
teo-nikolov Apr 24, 2024
71c7256
made WindowHandle virtual
teo-nikolov Apr 30, 2024
a051ee9
fixes for appium auto start
teo-nikolov May 2, 2024
83bb762
revert changes to process closing method
teo-nikolov May 2, 2024
738adc2
Added experimental appium driver support
teo-nikolov Jun 24, 2024
937a76d
Merge branch 'master' of github.com:AutomateThePlanet/BELLATRIX into …
teo-nikolov Nov 11, 2025
8e210fb
fix warnings
teo-nikolov Nov 11, 2025
210ba1f
fix errors
teo-nikolov Nov 11, 2025
c7311de
updates for Appium NovaWindows Driver installing
teo-nikolov Nov 11, 2025
e39c4db
Fixed possible null reference excepton
teo-nikolov Nov 11, 2025
b86237f
Updated packages
teo-nikolov Nov 11, 2025
71a1a84
Fixed for desktop module
teo-nikolov Nov 12, 2025
6ec910d
Updated Desktop Components and Find Strategies
teo-nikolov Nov 12, 2025
d772e21
fixed prompt find strategies
teo-nikolov Nov 12, 2025
3065bc0
NovaWindows driver preview version bump
teo-nikolov Nov 12, 2025
fecb2d6
Disable self-healing locators and smart failure analysis by default
teo-nikolov Nov 13, 2025
7af0882
Fix errors when LLM settings not exist in config
Nov 18, 2025
5d5ff67
update nuget packages
angelovstanton Dec 16, 2025
11d1ac4
fix build errors caused by automapper and appium upgrades
angelovstanton Dec 16, 2025
047d93b
update nugets
angelovstanton Dec 16, 2025
19d16c9
upgrade .net version and language to .net 10
angelovstanton Dec 16, 2025
69a811b
update MS related nugets
angelovstanton Dec 16, 2025
5bd4566
fix build errors related to mstest upgrade
angelovstanton Dec 16, 2025
5cf9add
Fixed AppiumOptions initialization
teo-nikolov Dec 17, 2025
ff42f02
Merge remote-tracking branch 'origin/experimental-desktop-driver' int…
teo-nikolov Dec 17, 2025
3b6300d
Comment fixes
teo-nikolov Dec 18, 2025
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
37 changes: 19 additions & 18 deletions Bellatrix.LLM/Bellatrix.LLM.csproj
Original file line number Diff line number Diff line change
@@ -1,23 +1,24 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\src\Bellatrix.Core\Bellatrix.Core.csproj" />
<ProjectReference Include="..\src\Bellatrix.KeyVault\Bellatrix.KeyVault.csproj" />
<ProjectReference Include="..\src\Bellatrix.Plugins.Screenshots\Bellatrix.Plugins.Screenshots.csproj" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\src\Bellatrix.Core\Bellatrix.Core.csproj" />
<ProjectReference Include="..\src\Bellatrix.KeyVault\Bellatrix.KeyVault.csproj" />
<ProjectReference Include="..\src\Bellatrix.Plugins.Screenshots\Bellatrix.Plugins.Screenshots.csproj" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="9.0.5" />
<PackageReference Include="Microsoft.SemanticKernel" Version="1.50.0" />
<PackageReference Include="Microsoft.KernelMemory" Version="0.98.250508.3" />
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="9.0.4" />
<PackageReference Include="NUnit" Version="4.3.2" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="9.0.5" />
<PackageReference Include="Microsoft.SemanticKernel" Version="1.50.0" />
<!-- DO NOT update Microsoft.KernelMemory unless we move to .NET 9 -->
<PackageReference Include="Microsoft.KernelMemory" Version="0.97.250211.1" />
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="9.0.4" />
<PackageReference Include="NUnit" Version="4.3.2" />
</ItemGroup>

</Project>
</Project>
4 changes: 3 additions & 1 deletion Bellatrix.LLM/SemanticKernelService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,9 @@ private static void EnsureInitialized()
return;

var llmSettings = ConfigurationService.GetSection<LargeLanguageModelsSettings>();

if (llmSettings == null)
return;

var genSettings = llmSettings.ModelSettings[0];
var embedSettings = llmSettings.ModelSettings[1];

Expand Down
9 changes: 7 additions & 2 deletions Bellatrix.LLM/plugins/SmartFailureAnalysisPlugin .cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
// The architecture and agent logic are original contributions by Anton Angelov, forming the foundation for a PhD dissertation.
// Please cite or credit appropriately if reusing in academic or commercial work.</note>

using Bellatrix.LLM.Settings;
using Bellatrix.Plugins.Screenshots.Contracts;
using Bellatrix.Plugins;
using Bellatrix.Plugins.Screenshots.Plugins;
Expand All @@ -26,12 +27,15 @@ public class SmartFailureAnalysisPlugin : Plugin, IScreenshotPlugin
private readonly IScreenshotOutputProvider _screenshotOutputProvider;
private readonly IViewSnapshotProvider _viewSnapshotProvider;
private static ThreadLocal<string> _screenshotPath = new ThreadLocal<string>();
private readonly bool _isEnabled;


public SmartFailureAnalysisPlugin()
{
_screenshotOutputProvider = ServicesCollection.Current.Resolve<IScreenshotOutputProvider>();
_viewSnapshotProvider = ServicesCollection.Main.Resolve<IViewSnapshotProvider>();
var largeLanguageModelsSettings = ConfigurationService.GetSection<LargeLanguageModelsSettings>();
_isEnabled = largeLanguageModelsSettings?.EnableSmartFailureAnalysis ?? false;
}

public static void Add()
Expand Down Expand Up @@ -60,6 +64,7 @@ public void ScreenshotGenerated(object sender, ScreenshotPluginEventArgs args)

protected override void PreTestCleanup(object sender, PluginEventArgs e)
{
if (!_isEnabled) return;
if (e.TestOutcome == TestOutcome.Passed)
{
var log = Logger.GetLogs();
Expand Down Expand Up @@ -87,7 +92,7 @@ private void RunFailureAnalysisAsync(PluginEventArgs e)
snapshot,
_screenshotPath.Value ?? string.Empty);


}
catch (Exception ex)
{
Expand All @@ -112,4 +117,4 @@ private void RunFailureAnalysisAsync(PluginEventArgs e)
//{extended}
//""");
}
}
}
2 changes: 1 addition & 1 deletion shared/SharedAssemblyInfo.targets
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
<RunAnalyzers>true</RunAnalyzers>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<WarningsAsErrors />
<NoWarn>NU1701;NU1702;NU1705;NU1608;</NoWarn>
<NoWarn>NU1701;NU1702;NU1705;NU1608;NU1903;NU1902;NU1904;</NoWarn>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
<Optimize>true</Optimize>
Expand Down
2 changes: 1 addition & 1 deletion src/Bellatrix.Core/utilities/WindowsProcessExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ public static IEnumerable<Process> GetChildProcesses(this Process process)

return children;
}

public static Process GetParentProcess(this Process process)
{
int parentPid = 0;
Expand Down
17 changes: 6 additions & 11 deletions src/Bellatrix.Desktop/Bellatrix.Desktop.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,15 @@
<Import Project="..\..\shared\SharedAssemblyInfo.targets" />

<ItemGroup>
<!--<PackageReference Include="Appium.WebDriver" Version="4.3.1" />-->
<PackageReference Include="Appium.WebDriver" Version="8.0.1" />
<PackageReference Include="Microsoft.CSharp" Version="4.7.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="9.0.5" />
<PackageReference Include="Microsoft.Extensions.Configuration" Version="9.0.5" />
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="9.0.5" />
<PackageReference Include="Microsoft.WinAppDriver.Appium.WebDriver" Version="1.0.1-Preview" />
<PackageReference Include="MSTest" Version="3.8.3" />
<PackageReference Include="NUnit" Version="4.3.2" />

<!--Do not Update to 3.14.0, it has bugs incompatible with Appium.WebDriver 3.0.0.1-->
<!--<PackageReference Include="Selenium.WebDriver" Version="3.141.0" />-->
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="10.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration" Version="10.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="10.0.0" />
<PackageReference Include="MSTest" Version="3.8.3" />
<PackageReference Include="NUnit" Version="4.3.2" />
<PackageReference Include="System.Drawing.Primitives" Version="4.3.0" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\..\Bellatrix.LLM\Bellatrix.LLM.csproj" />
<ProjectReference Include="..\Bellatrix.Allure\Bellatrix.Results.Allure.csproj" />
Expand Down
2 changes: 1 addition & 1 deletion src/Bellatrix.Desktop/DesktopPluginsConfiguration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ public static void ConfigureLLM()
{
if (ConfigurationService.GetSection<LargeLanguageModelsSettings>() == null)
{
throw new ArgumentException("Could not load LargeLanguageModelsSettings section from testFrameworkSettings.json");
return;
}

try
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,15 +31,33 @@ public virtual void Check(bool isChecked = true)
{
if (isChecked && !WrappedElement.Selected || !isChecked && WrappedElement.Selected)
{
Click(Checking, Checked);
Checking?.Invoke(this, new ComponentActionEventArgs(this));
try
{
WrappedDriver.ExecuteScript("windows: toggle", WrappedElement);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will all of these JavaScript commands work across all desktop applications?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are appium platform-specific extensions and are implemented in NovaWindows driver.

Whether they should work or not depends on if the component implements the correct Pattern (e.g. TogglePattern). If it does not, there's a fallback to the previous method.

}
catch
{
Click(null, null);
}
Checked?.Invoke(this, new ComponentActionEventArgs(this));
}
}

public virtual void Uncheck()
{
if (WrappedElement.Selected)
{
Click(Unchecking, Unchecked);
Unchecking?.Invoke(this, new ComponentActionEventArgs(this));
try
{
WrappedDriver.ExecuteScript("windows: toggle", WrappedElement);
}
catch
{
Click(null, null);
}
Unchecked?.Invoke(this, new ComponentActionEventArgs(this));
}
}

Expand Down
58 changes: 55 additions & 3 deletions src/Bellatrix.Desktop/components/ComboBox.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,11 @@
// <site>https://bellatrix.solutions/</site>
using System;
using System.Diagnostics;
using System.Linq;
using Bellatrix.Desktop.Contracts;
using Bellatrix.Desktop.Events;
using Bellatrix.Desktop.Services;
using OpenQA.Selenium.Appium;

namespace Bellatrix.Desktop;

Expand All @@ -34,16 +37,65 @@ public virtual void SelectByText(string value)
{
Selecting?.Invoke(this, new ComponentActionEventArgs(this, value));

if (WrappedElement.Text != value)
try
{
WrappedElement.SendKeys(value);
var itemToSelect = this.CreateAllByTag<ListItem>("ListItem")
.FirstOrDefault(x => x.CreateByTag<Label>("Text").InnerText == value);

WrappedDriver.ExecuteScript("windows: select", itemToSelect);
}
catch
{
if (WrappedElement.Text != value)
{
WrappedElement.SendKeys(value);
}
}

Selected?.Invoke(this, new ComponentActionEventArgs(this, value));
}

public virtual ListItem SelectedItem
{
get
{
var retryCount = 3;

while (retryCount-- > 0)
{
try
{
WrappedDriver.ExecuteScript("windows: expand", WrappedElement);
var result = new ComponentsRepository().CreateComponentThatIsFound<ListItem>(null,
(AppiumElement)WrappedDriver.ExecuteScript("windows: selectedItem", WrappedElement));
WrappedDriver.ExecuteScript("windows: collapse", WrappedElement);
return result;
}
catch
{
// ignore
}
}

return null;
}
}

[DebuggerBrowsable(DebuggerBrowsableState.Never)]
public virtual string InnerText => GetInnerText();
public virtual string InnerText
{
get
{
try
{
return SelectedItem?.CreateByTag<Label>("Text").InnerText ?? string.Empty;
}
catch
{
return GetInnerText();
}
}
}

[DebuggerBrowsable(DebuggerBrowsableState.Never)]
public virtual bool IsDisabled => GetIsDisabled();
Expand Down
67 changes: 61 additions & 6 deletions src/Bellatrix.Desktop/components/Core/Component.DefaultActions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,13 @@
// </copyright>
// <author>Anton Angelov</author>
// <site>https://bellatrix.solutions/</site>

using System;
using System.Collections.Generic;
using Bellatrix.Desktop.Contracts;
using Bellatrix.Desktop.Events;
using Bellatrix.Layout;
using OpenQA.Selenium;
using OpenQA.Selenium.Remote;
using OpenQA.Selenium.Interactions;

namespace Bellatrix.Desktop;

Expand All @@ -25,8 +26,39 @@ public partial class Component : IComponentVisible, IComponent, ILayoutComponent
internal virtual void Click(EventHandler<ComponentActionEventArgs> clicking, EventHandler<ComponentActionEventArgs> clicked)
{
clicking?.Invoke(this, new ComponentActionEventArgs(this));
var clickSuccess = false;

try
{
WrappedDriver.ExecuteScript("windows: invoke", WrappedElement);
clickSuccess = true;
}
catch
{
// ignore
}

if (!clickSuccess)
{
try
{
this.ToBeVisible().WrappedElement.Click();
clickSuccess = true;
}
catch
{
Logger.LogWarning($"Could not click component {ComponentName}." +
$"Component location: X={Location.X}, Y={Location.Y}" +
$"Component size: Width={Size.Width}, Height={Size.Height}");
}
}

WrappedElement.Click();
if (!clickSuccess)
{
new Actions(WrappedDriver, TimeSpan.Zero)
.MoveToElement(WrappedElement)
.Click().Perform();
}

clicked?.Invoke(this, new ComponentActionEventArgs(this));
}
Expand All @@ -35,7 +67,19 @@ internal virtual void Hover(EventHandler<ComponentActionEventArgs> hovering, Eve
{
hovering?.Invoke(this, new ComponentActionEventArgs(this));

WrappedDriver.Mouse.MouseMove(WrappedElement.Coordinates);
try
{
WrappedDriver.ExecuteScript("windows: hover", new Dictionary<string, object>
{
{ "startElementId", WrappedElement.Id },
{ "endElementId", WrappedElement.Id },
{ "durationMs", 0 }
});
}
catch
{
new Actions(WrappedDriver).MoveToElement(WrappedElement).Perform();
}

hovered?.Invoke(this, new ComponentActionEventArgs(this));
}
Expand All @@ -53,8 +97,19 @@ internal virtual bool GetIsDisabled()
internal virtual void SetText(EventHandler<ComponentActionEventArgs> settingValue, EventHandler<ComponentActionEventArgs> valueSet, string value)
{
settingValue?.Invoke(this, new ComponentActionEventArgs(this, value));
WrappedElement.Clear();
WrappedElement.SendKeys(value);
var element = WrappedElement;

try
{
WrappedDriver.ExecuteScript("windows: setValue", element, value);
valueSet?.Invoke(this, new ComponentActionEventArgs(this, value));
}
catch
{
WrappedElement.Clear();
WrappedElement.SendKeys(value);
}

valueSet?.Invoke(this, new ComponentActionEventArgs(this, value));
}
}
Loading
Loading