Skip to content

Commit 0b8b848

Browse files
authored
Add test projects for FwLiteMaui and FwLiteShared (#1557)
* Add tests for FwLiteMaui and FwLiteShared * Stabilize performance test * Don't share config instance across tests
1 parent b293dbc commit 0b8b848

File tree

14 files changed

+360
-26
lines changed

14 files changed

+360
-26
lines changed

.github/workflows/fw-lite.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ jobs:
6262
run: task fw-lite:has-pending-model-changes -- --no-build
6363

6464
- name: Dotnet test
65-
run: dotnet test FwLiteOnly.slnf --logger GitHubActions --no-build
65+
run: dotnet test FwLiteOnly.slnf --logger GitHubActions --no-build -p:BuildAndroid=false
6666

6767
frontend:
6868
runs-on: ubuntu-latest

FwLiteOnly.slnf

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,11 @@
55
"backend\\FwLite\\FwDataMiniLcmBridge.Tests\\FwDataMiniLcmBridge.Tests.csproj",
66
"backend\\FwLite\\FwDataMiniLcmBridge\\FwDataMiniLcmBridge.csproj",
77
"backend\\FwLite\\FwLiteMaui\\FwLiteMaui.csproj",
8+
"backend\\FwLite\\FwLiteMaui.Tests\\FwLiteMaui.Tests.csproj",
89
"backend\\FwLite\\FwLiteProjectSync.Tests\\FwLiteProjectSync.Tests.csproj",
910
"backend\\FwLite\\FwLiteProjectSync\\FwLiteProjectSync.csproj",
1011
"backend\\FwLite\\FwLiteShared\\FwLiteShared.csproj",
12+
"backend\\FwLite\\FwLiteShared.Tests\\FwLiteShared.Tests.csproj",
1113
"backend\\FwLite\\FwLiteWeb\\FwLiteWeb.csproj",
1214
"backend\\FwLite\\LcmCrdt.Tests\\LcmCrdt.Tests.csproj",
1315
"backend\\FwLite\\LcmCrdt\\LcmCrdt.csproj",
@@ -18,4 +20,4 @@
1820
"backend\\harmony\\src\\SIL.Harmony\\SIL.Harmony.csproj"
1921
]
2022
}
21-
}
23+
}

LexBox.sln

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Testing", "backend\Testing\
2121
EndProject
2222
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FixFwData", "backend\FixFwData\FixFwData.csproj", "{D7FC8B93-15A1-4D0B-9EAB-45596DB147F4}"
2323
EndProject
24-
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "FwLite", "FwLite", "{7B6E21C4-5AF4-4505-B7D9-59A3886C5090}"
25-
EndProject
24+
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "FwLite", "FwLite", "{7B6E21C4-5AF4-4505-B7D9-59A3886C5090}"
25+
EndProject
2626
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LfClassicData", "backend\LfClassicData\LfClassicData.csproj", "{E8BB768B-C3DC-4BE6-9B9F-82319E05AF86}"
2727
EndProject
2828
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MiniLcm", "backend\FwLite\MiniLcm\MiniLcm.csproj", "{6D4062DC-1B1A-4A24-9C61-0F6A18A39882}"
@@ -57,6 +57,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FwLiteShared", "backend\FwL
5757
EndProject
5858
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WebServiceDefaults", "backend\WebServiceDefaults\WebServiceDefaults.csproj", "{9B71BEF9-6017-4E30-81E0-EB8126B2CF02}"
5959
EndProject
60+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FwLiteMaui.Tests", "backend\FwLite\FwLiteMaui.Tests\FwLiteMaui.Tests.csproj", "{5A277FCE-454F-4956-8C33-7D9726C4E409}"
61+
EndProject
62+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FwLiteShared.Tests", "backend\FwLite\FwLiteShared.Tests\FwLiteShared.Tests.csproj", "{ED3FE7AD-323D-45C5-ABC9-2E2CFDDC4A3D}"
63+
EndProject
6064
Global
6165
GlobalSection(SolutionConfigurationPlatforms) = preSolution
6266
Debug|Any CPU = Debug|Any CPU
@@ -95,6 +99,10 @@ Global
9599
{6D4062DC-1B1A-4A24-9C61-0F6A18A39882}.Debug|Any CPU.Build.0 = Debug|Any CPU
96100
{6D4062DC-1B1A-4A24-9C61-0F6A18A39882}.Release|Any CPU.ActiveCfg = Release|Any CPU
97101
{6D4062DC-1B1A-4A24-9C61-0F6A18A39882}.Release|Any CPU.Build.0 = Release|Any CPU
102+
{2CDF7126-733B-46E8-9B93-7DC31DE39682}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
103+
{2CDF7126-733B-46E8-9B93-7DC31DE39682}.Debug|Any CPU.Build.0 = Debug|Any CPU
104+
{2CDF7126-733B-46E8-9B93-7DC31DE39682}.Release|Any CPU.ActiveCfg = Release|Any CPU
105+
{2CDF7126-733B-46E8-9B93-7DC31DE39682}.Release|Any CPU.Build.0 = Release|Any CPU
98106
{6B857F83-72E3-43E6-91C3-A946F3F988D8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
99107
{6B857F83-72E3-43E6-91C3-A946F3F988D8}.Debug|Any CPU.Build.0 = Debug|Any CPU
100108
{6B857F83-72E3-43E6-91C3-A946F3F988D8}.Release|Any CPU.ActiveCfg = Release|Any CPU
@@ -125,10 +133,6 @@ Global
125133
{9001FE0F-DBBF-4A78-9EB9-9B5042CF8A78}.Release|Any CPU.ActiveCfg = Release|Any CPU
126134
{9001FE0F-DBBF-4A78-9EB9-9B5042CF8A78}.Release|Any CPU.Build.0 = Release|Any CPU
127135
{9001FE0F-DBBF-4A78-9EB9-9B5042CF8A78}.Release|Any CPU.Deploy.0 = Release|Any CPU
128-
{2CDF7126-733B-46E8-9B93-7DC31DE39682}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
129-
{2CDF7126-733B-46E8-9B93-7DC31DE39682}.Debug|Any CPU.Build.0 = Debug|Any CPU
130-
{2CDF7126-733B-46E8-9B93-7DC31DE39682}.Release|Any CPU.ActiveCfg = Release|Any CPU
131-
{2CDF7126-733B-46E8-9B93-7DC31DE39682}.Release|Any CPU.Build.0 = Release|Any CPU
132136
{2245BAB6-753A-48AE-B929-6D8C35CB9804}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
133137
{2245BAB6-753A-48AE-B929-6D8C35CB9804}.Debug|Any CPU.Build.0 = Debug|Any CPU
134138
{2245BAB6-753A-48AE-B929-6D8C35CB9804}.Release|Any CPU.ActiveCfg = Release|Any CPU
@@ -157,6 +161,14 @@ Global
157161
{9B71BEF9-6017-4E30-81E0-EB8126B2CF02}.Debug|Any CPU.Build.0 = Debug|Any CPU
158162
{9B71BEF9-6017-4E30-81E0-EB8126B2CF02}.Release|Any CPU.ActiveCfg = Release|Any CPU
159163
{9B71BEF9-6017-4E30-81E0-EB8126B2CF02}.Release|Any CPU.Build.0 = Release|Any CPU
164+
{5A277FCE-454F-4956-8C33-7D9726C4E409}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
165+
{5A277FCE-454F-4956-8C33-7D9726C4E409}.Debug|Any CPU.Build.0 = Debug|Any CPU
166+
{5A277FCE-454F-4956-8C33-7D9726C4E409}.Release|Any CPU.ActiveCfg = Release|Any CPU
167+
{5A277FCE-454F-4956-8C33-7D9726C4E409}.Release|Any CPU.Build.0 = Release|Any CPU
168+
{ED3FE7AD-323D-45C5-ABC9-2E2CFDDC4A3D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
169+
{ED3FE7AD-323D-45C5-ABC9-2E2CFDDC4A3D}.Debug|Any CPU.Build.0 = Debug|Any CPU
170+
{ED3FE7AD-323D-45C5-ABC9-2E2CFDDC4A3D}.Release|Any CPU.ActiveCfg = Release|Any CPU
171+
{ED3FE7AD-323D-45C5-ABC9-2E2CFDDC4A3D}.Release|Any CPU.Build.0 = Release|Any CPU
160172
EndGlobalSection
161173
GlobalSection(SolutionProperties) = preSolution
162174
HideSolutionNode = FALSE
@@ -178,6 +190,8 @@ Global
178190
{00AE5440-0E36-4488-935B-5B11301BA57D} = {7B6E21C4-5AF4-4505-B7D9-59A3886C5090}
179191
{ECBA46AB-AF87-4D4D-9716-FD77264B817F} = {7B6E21C4-5AF4-4505-B7D9-59A3886C5090}
180192
{73DC604C-C501-410D-B56B-0544AD6EF1C2} = {7B6E21C4-5AF4-4505-B7D9-59A3886C5090}
193+
{5A277FCE-454F-4956-8C33-7D9726C4E409} = {7B6E21C4-5AF4-4505-B7D9-59A3886C5090}
194+
{ED3FE7AD-323D-45C5-ABC9-2E2CFDDC4A3D} = {7B6E21C4-5AF4-4505-B7D9-59A3886C5090}
181195
EndGlobalSection
182196
GlobalSection(ExtensibilityGlobals) = postSolution
183197
SolutionGuid = {440AE83C-6DB0-4F18-B2C1-BCD33F0645B6}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
using FwLiteShared.Events;
2+
using Microsoft.Extensions.Logging;
3+
using Moq;
4+
5+
namespace FwLiteMaui.Tests;
6+
7+
#if WINDOWS
8+
public class AppUpdateServiceTests
9+
{
10+
private readonly AppUpdateService _appUpdateService;
11+
private readonly Mock<IPreferences> _preferencesMock;
12+
13+
public AppUpdateServiceTests()
14+
{
15+
_preferencesMock = new Mock<IPreferences>();
16+
_appUpdateService = new AppUpdateService(
17+
Mock.Of<ILogger<AppUpdateService>>(),
18+
_preferencesMock.Object,
19+
new GlobalEventBus(Mock.Of<ILogger<GlobalEventBus>>()));
20+
}
21+
22+
[Fact]
23+
public void LastUpdateCheck_ReadsFromPreferences()
24+
{
25+
var expectedTime = new DateTime(2024, 6, 15, 10, 30, 0, DateTimeKind.Utc);
26+
_preferencesMock.Setup(p => p.Get(It.IsAny<string>(), It.IsAny<DateTime>(), null))
27+
.Returns(expectedTime);
28+
29+
var result = _appUpdateService.LastUpdateCheck;
30+
31+
result.Should().Be(expectedTime);
32+
}
33+
34+
[Fact]
35+
public void LastUpdateCheck_SetWritesToPreferences()
36+
{
37+
var newTime = new DateTime(2024, 7, 20, 14, 0, 0, DateTimeKind.Utc);
38+
39+
_appUpdateService.LastUpdateCheck = newTime;
40+
41+
_preferencesMock.Verify(p => p.Set("lastUpdateChecked", newTime, null), Times.Once);
42+
}
43+
44+
[Fact]
45+
public void SupportsAutoUpdate_ReturnsTrueForNonPortableApp()
46+
{
47+
var result = _appUpdateService.SupportsAutoUpdate;
48+
49+
result.Should().Be(!FwLiteMauiKernel.IsPortableApp);
50+
}
51+
}
52+
#endif
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<IsPackable>false</IsPackable>
5+
<IsTestProject>true</IsTestProject>
6+
<!-- override the target framework set in Directory.Build.props, we will use what is defined in TargetFrameworks below instead-->
7+
<TargetFramework/>
8+
<TargetFrameworks Condition=" '$(BuildAndroid)' != 'false' ">$(TargetFrameworks);net9.0-android</TargetFrameworks>
9+
<TargetFrameworks Condition="$([MSBuild]::IsOSPlatform('osx')) And '$(BuildApple)' != 'false'">$(TargetFrameworks);net9.0-ios;net9.0-maccatalyst</TargetFrameworks>
10+
<TargetFrameworks Condition="$([MSBuild]::IsOSPlatform('windows'))">$(TargetFrameworks);net9.0-windows10.0.19041.0</TargetFrameworks>
11+
</PropertyGroup>
12+
13+
<ItemGroup>
14+
<PackageReference Include="coverlet.collector">
15+
<PrivateAssets>all</PrivateAssets>
16+
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
17+
</PackageReference>
18+
<PackageReference Include="Microsoft.NET.Test.Sdk"/>
19+
<PackageReference Include="FluentAssertions"/>
20+
<PackageReference Include="Moq" />
21+
<PackageReference Include="xunit"/>
22+
<PackageReference Include="xunit.runner.visualstudio">
23+
<PrivateAssets>all</PrivateAssets>
24+
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
25+
</PackageReference>
26+
<PackageReference Include="GitHubActionsTestLogger">
27+
<PrivateAssets>all</PrivateAssets>
28+
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
29+
</PackageReference>
30+
<PackageReference Include="Microsoft.Extensions.DependencyInjection"/>
31+
</ItemGroup>
32+
33+
<ItemGroup>
34+
<Using Include="Xunit"/>
35+
<Using Include="FluentAssertions"/>
36+
</ItemGroup>
37+
38+
<ItemGroup>
39+
<ProjectReference Include="..\FwLiteMaui\FwLiteMaui.csproj"/>
40+
</ItemGroup>
41+
42+
</Project>
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
using FwLiteMaui.Services;
2+
using Microsoft.Extensions.Logging;
3+
using Microsoft.Extensions.Options;
4+
using Moq;
5+
6+
namespace FwLiteMaui.Tests;
7+
8+
public class MauiTroubleshootingServiceTests
9+
{
10+
private readonly Mock<ILauncher> _launcherMock;
11+
private readonly Mock<IBrowser> _browserMock;
12+
private readonly Mock<IShare> _shareMock;
13+
private readonly Mock<IOptions<FwLiteMauiConfig>> _configMock;
14+
private readonly MauiTroubleshootingService _service;
15+
16+
public MauiTroubleshootingServiceTests()
17+
{
18+
_launcherMock = new Mock<ILauncher>();
19+
_browserMock = new Mock<IBrowser>();
20+
_shareMock = new Mock<IShare>();
21+
_configMock = new Mock<IOptions<FwLiteMauiConfig>>();
22+
23+
var config = new FwLiteMauiConfig
24+
{
25+
BaseDataDir = "test_data_dir"
26+
};
27+
_configMock.Setup(c => c.Value).Returns(config);
28+
29+
_service = new MauiTroubleshootingService(
30+
_configMock.Object,
31+
Mock.Of<ILogger<MauiTroubleshootingService>>(),
32+
null!, // passing null for CrdtProjectsService as we aren't testing ShareCrdtProject yet
33+
_launcherMock.Object,
34+
_browserMock.Object,
35+
_shareMock.Object
36+
);
37+
}
38+
39+
[Fact]
40+
public async Task TryOpenDataDirectory_OpensBrowserWithFileUrl()
41+
{
42+
var result = await _service.TryOpenDataDirectory();
43+
44+
result.Should().BeTrue();
45+
var expectedUri = "file://" + _configMock.Object.Value.BaseDataDir;
46+
_browserMock.Verify(b => b.OpenAsync(It.Is<Uri>(u => u.OriginalString == expectedUri), It.IsAny<BrowserLaunchOptions>()), Times.Once);
47+
}
48+
49+
[Fact]
50+
public async Task OpenLogFile_OpensFileWithLauncher()
51+
{
52+
await _service.OpenLogFile();
53+
54+
_launcherMock.Verify(l => l.OpenAsync(It.Is<OpenFileRequest>(r => r.Title == "Log File" && r.File!.FullPath.Contains("app.log"))), Times.Once);
55+
}
56+
}

backend/FwLite/FwLiteMaui/FwLiteMauiKernel.cs

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
using System.Diagnostics;
2-
using System.Reflection;
31
using FwLiteMaui.Services;
42
using FwLiteShared;
53
using FwLiteShared.Auth;
@@ -28,7 +26,7 @@ public static void AddFwLiteMauiServices(this IServiceCollection services,
2826
environment = "Development";
2927
#endif
3028
IHostEnvironment env = new HostingEnvironment() { EnvironmentName = environment };
31-
services.AddSingleton<IHostEnvironment>(env);
29+
services.AddSingleton(env);
3230
services.AddMauiBlazorWebView();
3331
services.AddBlazorWebViewDeveloperTools();
3432
//must be added after blazor as it modifies IJSRuntime in order to intercept it's constructor
@@ -122,9 +120,13 @@ public static void AddFwLiteMauiServices(this IServiceCollection services,
122120
options.FileSizeLimitBytes = fwLiteMauiConfig.MaxLogFileSize;
123121
options.MaxRollingFiles = fwLiteMauiConfig.MaxLogFileCount;
124122
});
125-
services.AddSingleton<IPreferences>(Preferences.Default);
126-
services.AddSingleton<IVersionTracking>(VersionTracking.Default);
127-
services.AddSingleton<IConnectivity>(Connectivity.Current);
123+
//use factory callbacks so tests can mock
124+
services.AddSingleton(_ => Preferences.Default);
125+
services.AddSingleton(_ => VersionTracking.Default);
126+
services.AddSingleton(_ => Connectivity.Current);
127+
services.AddSingleton(_ => Launcher.Default);
128+
services.AddSingleton(_ => Browser.Default);
129+
services.AddSingleton(_ => Share.Default);
128130
services.AddSingleton<ITroubleshootingService, MauiTroubleshootingService>();
129131
logging.AddConsole();
130132
#if DEBUG

backend/FwLite/FwLiteMaui/Services/MauiTroubleshootingService.cs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,14 @@ namespace FwLiteMaui.Services;
99
public class MauiTroubleshootingService(
1010
IOptions<FwLiteMauiConfig> config,
1111
ILogger<MauiTroubleshootingService> logger,
12-
CrdtProjectsService projectsService) : ITroubleshootingService
12+
CrdtProjectsService projectsService,
13+
ILauncher launcher,
14+
IBrowser browser,
15+
IShare share) : ITroubleshootingService
1316
{
14-
private readonly ILauncher _launcher = Launcher.Default;
15-
private readonly IBrowser _browser = Browser.Default;
16-
private readonly IShare _share = Share.Default;
17+
private readonly ILauncher _launcher = launcher;
18+
private readonly IBrowser _browser = browser;
19+
private readonly IShare _share = share;
1720
private FwLiteMauiConfig Config => config.Value;
1821

1922
[JSInvokable]

0 commit comments

Comments
 (0)