Skip to content

Commit 2cefdce

Browse files
committed
Refactor
1 parent e4cec0d commit 2cefdce

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

50 files changed

+735
-821
lines changed

Directory.build.props

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<Project>
2+
<PropertyGroup>
3+
<BaseTargetFramework>net10.0</BaseTargetFramework>
4+
<ImplicitUsings>enable</ImplicitUsings>
5+
<Nullable>enable</Nullable>
6+
<EnableAotAnalyzer>true</EnableAotAnalyzer>
7+
<EnableTrimAnalyzer>true</EnableTrimAnalyzer>
8+
<EnableSingleFileAnalyzer>true</EnableSingleFileAnalyzer>
9+
10+
<MauiVersion>10.0.41</MauiVersion>
11+
</PropertyGroup>
12+
</Project>

Directory.packages.props

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
<Project>
2+
<PropertyGroup>
3+
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
4+
<ShinyVersion>4.0.0-beta-0095</ShinyVersion>
5+
</PropertyGroup>
6+
7+
<ItemGroup>
8+
<PackageVersion Include="Microsoft.Extensions.Localization" Version="10.0.4"/>
9+
<PackageVersion Include="Microsoft.Maui.Controls" Version="$(MauiVersion)"/>
10+
<PackageVersion Include="Microsoft.Maui.Controls.Maps" Version="$(MauiVersion)"/>
11+
<PackageVersion Include="Microsoft.Extensions.Logging.Debug" Version="10.0.3" Condition="'$(Configuration)' == 'Debug'"/>
12+
<PackageVersion Include="CommunityToolkit.Mvvm" Version="8.4.0"/>
13+
<PackageVersion Include="Sentry.Maui" Version="6.1.0"/>
14+
</ItemGroup>
15+
16+
<ItemGroup>
17+
<PackageVersion Include="Shiny.Extensions.Localization.Generator" Version="2.0.1"/>
18+
<PackageVersion Include="Shiny.Extensions.MauiHosting" Version="2.0.0"/>
19+
<PackageVersion Include="Shiny.Maui.TableView" Version="1.0.2"/>
20+
<PackageVersion Include="Shiny.Maui.Shell" Version="3.1.0"/>
21+
<PackageVersion Include="Shiny.Mediator.Maui" Version="6.2.1"/>
22+
<PackageVersion Include="Shiny.Mediator.Sentry" Version="6.2.1"/>
23+
<PackageVersion Include="Shiny.Locations" Version="$(ShinyVersion)"/>
24+
<PackageVersion Include="Shiny.Jobs" Version="$(ShinyVersion)"/>
25+
<PackageVersion Include="Shiny.Notifications" Version="$(ShinyVersion)"/>
26+
<PackageVersion Include="Shiny.SqliteDocumentDb" Version="1.0.0"/>
27+
<PackageVersion Include="Shiny.Reflector" Version="1.7.1"/>
28+
</ItemGroup>
29+
30+
<ItemGroup>
31+
<PackageVersion Include="Shiny.Hosting.Maui" Version="$(ShinyVersion)"/>
32+
<PackageVersion Include="Shiny.Extensions.Configuration" Version="$(ShinyVersion)"/>
33+
</ItemGroup>
34+
35+
<ItemGroup>
36+
<PackageVersion Include="coverlet.collector" Version="8.0.0"/>
37+
<PackageVersion Include="Microsoft.Extensions.TimeProvider.Testing" Version="10.3.0"/>
38+
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="18.3.0"/>
39+
<PackageVersion Include="NSubstitute" Version="5.3.0"/>
40+
<PackageVersion Include="Shouldly" Version="4.3.0"/>
41+
<PackageVersion Include="xunit" Version="2.9.3"/>
42+
<PackageVersion Include="xunit.runner.visualstudio" Version="3.1.5"/>
43+
</ItemGroup>
44+
</Project>
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<TargetFramework>$(BaseTargetFramework)</TargetFramework>
5+
<RootNamespace>ShinyWonderland</RootNamespace>
6+
</PropertyGroup>
7+
8+
<ItemGroup>
9+
<PackageReference Include="Shiny.Mediator.Maui"/>
10+
11+
<MediatorHttp Include="OpenApiRemote"
12+
Uri="https://api.themeparks.wiki/docs/v1.yaml"
13+
Namespace="ShinyWonderland.ThemeParksApi"
14+
ContractPostfix="HttpRequest"
15+
GenerateJsonConverters="true"
16+
Visible="false"/>
17+
</ItemGroup>
18+
19+
</Project>
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
using Microsoft.Extensions.DependencyInjection;
2+
3+
namespace ShinyWonderland;
4+
5+
public static class Registration
6+
{
7+
public static IServiceCollection AddWonderlandLocalization(this IServiceCollection services)
8+
{
9+
services.AddStronglyTypedLocalizations();
10+
services.AddLocalization();
11+
return services;
12+
}
13+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<TargetFramework>$(BaseTargetFramework)</TargetFramework>
5+
<RootNamespace>ShinyWonderland</RootNamespace>
6+
</PropertyGroup>
7+
8+
<ItemGroup>
9+
<PackageReference Include="Microsoft.Extensions.Localization"/>
10+
<PackageReference Include="Shiny.Extensions.Localization.Generator">
11+
<PrivateAssets>all</PrivateAssets>
12+
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
13+
</PackageReference>
14+
<EmbeddedResource Update="**/*.resx"/>
15+
</ItemGroup>
16+
</Project>
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
namespace ShinyWonderland;
2+
3+
public partial class Strings;
Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
3+
<root>
4+
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
5+
<xsd:element name="root" msdata:IsDataSet="true">
6+
7+
</xsd:element>
8+
</xsd:schema>
9+
<resheader name="resmimetype">
10+
<value>text/microsoft-resx</value>
11+
</resheader>
12+
<resheader name="version">
13+
<value>1.3</value>
14+
</resheader>
15+
<resheader name="reader">
16+
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
17+
</resheader>
18+
<resheader name="writer">
19+
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
20+
</resheader>
21+
<data name="MealTimes" xml:space="preserve">
22+
<value>Meal Times</value>
23+
</data>
24+
<data name="RideTimes" xml:space="preserve">
25+
<value>Ride Times</value>
26+
</data>
27+
<data name="Settings" xml:space="preserve">
28+
<value>Settings</value>
29+
</data>
30+
<data name="Hours" xml:space="preserve">
31+
<value>Hours</value>
32+
</data>
33+
<data name="Parking" xml:space="preserve">
34+
<value>Parking</value>
35+
</data>
36+
<data name="YouAreOffline" xml:space="preserve">
37+
<value>You are currently offline</value>
38+
</data>
39+
<data name="DataFrom" xml:space="preserve">
40+
<value>Data is from</value>
41+
</data>
42+
<data name="Paid" xml:space="preserve">
43+
<value>PAID</value>
44+
</data>
45+
<data name="LastRide" xml:space="preserve">
46+
<value>Last Ride</value>
47+
</data>
48+
<data name="RideHistory" xml:space="preserve">
49+
<value>Ride History</value>
50+
</data>
51+
<data name="UnknownDistance" xml:space="preserve">
52+
<value>Unknown Distance</value>
53+
</data>
54+
<data name="Closed" xml:space="preserve">
55+
<value>CLOSED</value>
56+
</data>
57+
<data name="AddRide" xml:space="preserve">
58+
<value>Add Ride</value>
59+
</data>
60+
<data name="History" xml:space="preserve">
61+
<value>History</value>
62+
</data>
63+
<data name="HistoryDialogTitle" xml:space="preserve">
64+
<value>History?</value>
65+
</data>
66+
<data name="AddRideHistoryQuestion" xml:space="preserve">
67+
<value>Add a new ride history for '{0}'?</value>
68+
</data>
69+
<data name="Error" xml:space="preserve">
70+
<value>Error</value>
71+
</data>
72+
<data name="GeneralError" xml:space="preserve">
73+
<value>There was an error loading the data</value>
74+
</data>
75+
<data name="Ok" xml:space="preserve">
76+
<value>Ok</value>
77+
</data>
78+
<data name="Mins" xml:space="preserve">
79+
<value>mins</value>
80+
</data>
81+
<data name="Reset" xml:space="preserve">
82+
<value>Reset?</value>
83+
</data>
84+
<data name="ConfirmReset" xml:space="preserve">
85+
<value>Are you sure you want to reset the parking location?</value>
86+
</data>
87+
<data name="PermissionDenied" xml:space="preserve">
88+
<value>Permission Denied</value>
89+
</data>
90+
<data name="OpenSettings" xml:space="preserve">
91+
<value>Do you wish to open app settings to change to the necessary permissions?</value>
92+
</data>
93+
<data name="SetParking" xml:space="preserve">
94+
<value>Set Parking Location to Current Location</value>
95+
</data>
96+
<data name="RemoveParking" xml:space="preserve">
97+
<value>Remove Parking Location</value>
98+
</data>
99+
<data name="NotCloseEnough" xml:space="preserve">
100+
<value>You aren't close enough to the park to use the parking function</value>
101+
</data>
102+
<data name="ErrorRetrievingLocation" xml:space="preserve">
103+
<value>Error retrieving current position</value>
104+
</data>
105+
<data name="TakePhoto" xml:space="preserve">
106+
<value>Take Photo</value>
107+
</data>
108+
<data name="HoursOfOperation" xml:space="preserve">
109+
<value>Hours of Operation</value>
110+
</data>
111+
<data name="ParkClosed" xml:space="preserve">
112+
<value>Park Closed</value>
113+
</data>
114+
<data name="Today" xml:space="preserve">
115+
<value>Today</value>
116+
</data>
117+
<data name="Never" xml:space="preserve">
118+
<value>Never</value>
119+
</data>
120+
<data name="Minutes" xml:space="preserve">
121+
<value>minutes ago</value>
122+
</data>
123+
<data name="Now" xml:space="preserve">
124+
<value>now</value>
125+
</data>
126+
<data name="Seconds" xml:space="preserve">
127+
<value>seconds ago</value>
128+
</data>
129+
<data name="Minute" xml:space="preserve">
130+
<value>minute ago</value>
131+
</data>
132+
<data name="Second" xml:space="preserve">
133+
<value>second ago</value>
134+
</data>
135+
<data name="Days" xml:space="preserve">
136+
<value>days ago</value>
137+
</data>
138+
<data name="Day" xml:space="preserve">
139+
<value>day ago</value>
140+
</data>
141+
<data name="Month" xml:space="preserve">
142+
<value>month ago</value>
143+
</data>
144+
<data name="Months" xml:space="preserve">
145+
<value>months ago</value>
146+
</data>
147+
<data name="Year" xml:space="preserve">
148+
<value>year ago</value>
149+
</data>
150+
<data name="Years" xml:space="preserve">
151+
<value>years ago</value>
152+
</data>
153+
<data name="Hour" xml:space="preserve">
154+
<value>hour ago</value>
155+
</data>
156+
<data name="Reminder" xml:space="preserve">
157+
<value>Reminder</value>
158+
</data>
159+
<data name="EnterParkNotificationMessage" xml:space="preserve">
160+
<value>Don't forget to turn on the app for real time ride notifications and set your parking</value>
161+
</data>
162+
<data name="RideTime" xml:space="preserve">
163+
<value>Ride Time</value>
164+
</data>
165+
<data name="RideTimeNotificationMessageFormat" xml:space="preserve">
166+
<value>{0} is now a {1} minute wait. Down {2} minutes</value>
167+
</data>
168+
<data name="LeaveParkNotificationMessage" xml:space="preserve">
169+
<value>Hope you had fun. GPS has been turned off to save battery, you will not receive real time ride updates, and parking has been cleared</value>
170+
</data>
171+
</root>

ShinyWonderland.Tests/Delegates/MyGeofenceDelegateTests.cs

Lines changed: 23 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -2,30 +2,29 @@ namespace ShinyWonderland.Tests.Delegates;
22

33
public class MyGeofenceDelegateTests
44
{
5-
readonly ILogger<MyGeofenceDelegate> logger;
65
readonly AppSettings appSettings;
7-
readonly MyGeofenceDelegateLocalized localized;
8-
readonly IOptions<ParkOptions> parkOptions;
96
readonly INotificationManager notifications;
107
readonly MyGeofenceDelegate geofenceDelegate;
118

129
public MyGeofenceDelegateTests()
1310
{
14-
logger = Substitute.For<ILogger<MyGeofenceDelegate>>();
11+
var logger = Substitute.For<ILogger<MyGeofenceDelegate>>();
1512
appSettings = new AppSettings();
16-
localized = Substitute.For<MyGeofenceDelegateLocalized>();
17-
localized.Reminder.Returns("Reminder");
18-
localized.NotificationMessage.Returns("Welcome to the park!");
1913

20-
var options = new ParkOptions
14+
var localized = TestLocalization.Create(new Dictionary<string, string>
15+
{
16+
["Reminder"] = "Reminder",
17+
["EnterParkNotificationMessage"] = "Welcome to the park!"
18+
});
19+
20+
var parkOptions = Options.Create(new ParkOptions
2121
{
2222
Name = "Wonderland",
2323
EntityId = "test-park",
2424
Latitude = 33.8121,
2525
Longitude = -117.9190,
2626
NotificationDistanceMeters = 1000
27-
};
28-
parkOptions = Options.Create(options);
27+
});
2928

3029
notifications = Substitute.For<INotificationManager>();
3130

@@ -48,11 +47,12 @@ public async Task OnStatusChanged_WhenEntered_AndNotificationsEnabled_ShouldSend
4847
// Act
4948
await geofenceDelegate.OnStatusChanged(GeofenceState.Entered, region);
5049

51-
// Assert
52-
await notifications.Received(1).Send(
53-
Arg.Is<string>(t => t.Contains("Wonderland") && t.Contains("Reminder")),
54-
Arg.Is<string>(m => m == "Welcome to the park!")
55-
);
50+
// Assert - Send(string, string) is an extension method; assert on the interface method Send(Notification)
51+
await notifications.Received(1).Send(Arg.Is<Notification>(n =>
52+
n.Title!.Contains("Wonderland") &&
53+
n.Title!.Contains("Reminder") &&
54+
n.Message == "Welcome to the park!"
55+
));
5656
}
5757

5858
[Fact]
@@ -66,7 +66,7 @@ public async Task OnStatusChanged_WhenEntered_AndNotificationsDisabled_ShouldNot
6666
await geofenceDelegate.OnStatusChanged(GeofenceState.Entered, region);
6767

6868
// Assert
69-
await notifications.DidNotReceive().Send(Arg.Any<string>(), Arg.Any<string>());
69+
await notifications.DidNotReceive().Send(Arg.Any<Notification>());
7070
}
7171

7272
[Fact]
@@ -80,7 +80,7 @@ public async Task OnStatusChanged_WhenExited_ShouldNotSendNotification()
8080
await geofenceDelegate.OnStatusChanged(GeofenceState.Exited, region);
8181

8282
// Assert
83-
await notifications.DidNotReceive().Send(Arg.Any<string>(), Arg.Any<string>());
83+
await notifications.DidNotReceive().Send(Arg.Any<Notification>());
8484
}
8585

8686
[Fact]
@@ -94,7 +94,7 @@ public async Task OnStatusChanged_WithUnknownStatus_ShouldNotSendNotification()
9494
await geofenceDelegate.OnStatusChanged(GeofenceState.Unknown, region);
9595

9696
// Assert
97-
await notifications.DidNotReceive().Send(Arg.Any<string>(), Arg.Any<string>());
97+
await notifications.DidNotReceive().Send(Arg.Any<Notification>());
9898
}
9999

100100
[Fact]
@@ -103,17 +103,16 @@ public async Task OnStatusChanged_NotificationTitle_ShouldContainParkNameAndRemi
103103
// Arrange
104104
appSettings.EnableGeofenceNotifications = true;
105105
var region = new GeofenceRegion("test", new Position(33.8121, -117.9190), Distance.FromMeters(1000));
106-
string? capturedTitle = null;
106+
Notification? captured = null;
107107

108-
notifications.Send(Arg.Do<string>(t => capturedTitle = t), Arg.Any<string>())
109-
.Returns(Task.CompletedTask);
108+
notifications.Send(Arg.Do<Notification>(n => captured = n));
110109

111110
// Act
112111
await geofenceDelegate.OnStatusChanged(GeofenceState.Entered, region);
113112

114113
// Assert
115-
capturedTitle.ShouldNotBeNull();
116-
capturedTitle.ShouldContain("Wonderland");
117-
capturedTitle.ShouldContain("Reminder");
114+
captured.ShouldNotBeNull();
115+
captured.Title!.ShouldContain("Wonderland");
116+
captured.Title!.ShouldContain("Reminder");
118117
}
119118
}

0 commit comments

Comments
 (0)